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