Skip to main content

rustc_attr_parsing/
synthetic.rs

1use rustc_ast::SyntheticAttr;
2use rustc_ast::attr::data_structures::CfgEntry;
3use rustc_hir::Attribute;
4use rustc_hir::attrs::AttributeKind;
5use rustc_span::Span;
6use thin_vec::ThinVec;
7
8/// This struct contains the state necessary to convert synthetic attributes to hir attributes
9/// The only conversion that really happens here is that multiple synthetic attributes are
10/// merged into a single hir attribute, representing their combined state.
11/// FIXME: We should make this a nice and extendable system if this is going to be used more often
12#[derive(#[automatically_derived]
impl ::core::default::Default for SyntheticAttrState {
    #[inline]
    fn default() -> SyntheticAttrState {
        SyntheticAttrState {
            cfg_trace: ::core::default::Default::default(),
            cfg_attr_trace: ::core::default::Default::default(),
        }
    }
}Default)]
13pub(crate) struct SyntheticAttrState {
14    /// Attribute state for `SyntheticAttr::CfgTrace` attributes.
15    cfg_trace: ThinVec<(CfgEntry, Span)>,
16
17    /// Attribute state for `SyntheticAttr::CfgAttrTrace` attributes.
18    /// The arguments of these attributes is no longer relevant for any later passes, only their
19    /// presence. So we discard the arguments here.
20    cfg_attr_trace: bool,
21}
22
23impl SyntheticAttrState {
24    pub(crate) fn accept_synthetic_attr(
25        &mut self,
26        attr_span: Span,
27        lower_span: impl Copy + Fn(Span) -> Span,
28        synthetic: &SyntheticAttr,
29    ) {
30        match synthetic {
31            SyntheticAttr::CfgTrace(cfg) => {
32                let mut cfg = cfg.clone();
33                cfg.lower_spans(lower_span);
34                self.cfg_trace.push((cfg, attr_span));
35            }
36            SyntheticAttr::CfgAttrTrace => {
37                self.cfg_attr_trace = true;
38            }
39        }
40    }
41
42    pub(crate) fn finalize_synthetic_attrs(self, attributes: &mut Vec<Attribute>) {
43        if !self.cfg_trace.is_empty() {
44            attributes.push(Attribute::Parsed(AttributeKind::CfgTrace(self.cfg_trace)));
45        }
46        if self.cfg_attr_trace {
47            attributes.push(Attribute::Parsed(AttributeKind::CfgAttrTrace));
48        }
49    }
50}