Skip to main content

rustc_attr_parsing/
synthetic.rs

1use rustc_ast::SyntheticAttr;
2use rustc_ast::attr::data_structures::CfgEntry;
3use rustc_attr_ir::{Attribute, AttributeKind};
4use rustc_span::Span;
5use thin_vec::ThinVec;
6
7/// Contains the state necessary to convert synthetic attributes to parsed attributes.
8///
9/// The only conversion that really happens here is that multiple synthetic attributes are
10/// merged into a single `rustc_attr_ir::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    cfg_attr_trace: ThinVec<(CfgEntry, Span)>,
19}
20
21impl SyntheticAttrState {
22    pub(crate) fn accept_synthetic_attr(
23        &mut self,
24        attr_span: Span,
25        lower_span: impl Copy + Fn(Span) -> Span,
26        synthetic: &SyntheticAttr,
27    ) {
28        match synthetic {
29            SyntheticAttr::CfgTrace(cfg) => {
30                let mut cfg = cfg.clone();
31                cfg.lower_spans(lower_span);
32                self.cfg_trace.push((cfg, attr_span));
33            }
34            SyntheticAttr::CfgAttrTrace(cfg) => {
35                let mut cfg = cfg.clone();
36                cfg.lower_spans(lower_span);
37                self.cfg_attr_trace.push((cfg, attr_span));
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.is_empty() {
47            attributes.push(Attribute::Parsed(AttributeKind::CfgAttrTrace(self.cfg_attr_trace)));
48        }
49    }
50}