Skip to main content

rustc_builtin_macros/
cfg_accessible.rs

1//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
2
3use rustc_ast as ast;
4use rustc_attr_parsing::{AttributeTemplate, validate_attr};
5use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
6use rustc_span::{Span, sym};
7
8use crate::diagnostics;
9
10pub(crate) struct Expander;
11
12fn validate_input<'a>(ecx: &ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
13    use diagnostics::CfgAccessibleInvalid::*;
14    match mi.meta_item_list() {
15        None => {}
16        Some([]) => {
17            ecx.dcx().emit_err(UnspecifiedPath(mi.span));
18        }
19        Some([_, .., l]) => {
20            ecx.dcx().emit_err(MultiplePaths(l.span()));
21        }
22        Some([nmi]) => match nmi.meta_item() {
23            None => {
24                ecx.dcx().emit_err(LiteralPath(nmi.span()));
25            }
26            Some(mi) => {
27                if !mi.is_word() {
28                    ecx.dcx().emit_err(HasArguments(mi.span));
29                }
30                return Some(&mi.path);
31            }
32        },
33    }
34    None
35}
36
37impl MultiItemModifier for Expander {
38    fn expand(
39        &self,
40        ecx: &mut ExtCtxt<'_>,
41        span: Span,
42        meta_item: &ast::MetaItem,
43        item: Annotatable,
44        _is_derive_const: bool,
45    ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
46        let template = AttributeTemplate { list: Some(&["path"]), ..Default::default() };
47        validate_attr::check_builtin_meta_item(
48            &ecx.sess.psess,
49            meta_item,
50            ast::AttrStyle::Outer,
51            sym::cfg_accessible,
52            template,
53            true,
54        );
55
56        let Some(path) = validate_input(ecx, meta_item) else {
57            return ExpandResult::Ready(Vec::new());
58        };
59
60        match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
61            Ok(true) => ExpandResult::Ready(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [item]))vec![item]),
62            Ok(false) => ExpandResult::Ready(Vec::new()),
63            Err(Indeterminate) if ecx.force_mode => {
64                ecx.dcx().emit_err(diagnostics::CfgAccessibleIndeterminate { span });
65                ExpandResult::Ready(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [item]))vec![item])
66            }
67            Err(Indeterminate) => ExpandResult::Retry(item),
68        }
69    }
70}