]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast/src/ast_like.rs
Rollup merge of #83270 - steffahn:missing_word_in_skip_while_doc, r=joshtriplett
[rust.git] / compiler / rustc_ast / src / ast_like.rs
1 use super::ptr::P;
2 use super::tokenstream::LazyTokenStream;
3 use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
4 use super::{AssocItem, Expr, ForeignItem, Item, Local};
5 use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
6 use super::{AttrVec, Attribute, Stmt, StmtKind};
7
8 /// An `AstLike` represents an AST node (or some wrapper around
9 /// and AST node) which stores some combination of attributes
10 /// and tokens.
11 pub trait AstLike: Sized {
12     fn attrs(&self) -> &[Attribute];
13     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
14     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
15 }
16
17 impl<T: AstLike + 'static> AstLike for P<T> {
18     fn attrs(&self) -> &[Attribute] {
19         (**self).attrs()
20     }
21     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
22         (**self).visit_attrs(f);
23     }
24     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
25         (**self).tokens_mut()
26     }
27 }
28
29 fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) {
30     crate::mut_visit::visit_clobber(attrs, |attrs| {
31         let mut vec = attrs.into();
32         f(&mut vec);
33         vec.into()
34     });
35 }
36
37 impl AstLike for StmtKind {
38     fn attrs(&self) -> &[Attribute] {
39         match self {
40             StmtKind::Local(local) => local.attrs(),
41             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(),
42             StmtKind::Item(item) => item.attrs(),
43             StmtKind::Empty => &[],
44             StmtKind::MacCall(mac) => &mac.attrs,
45         }
46     }
47
48     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
49         match self {
50             StmtKind::Local(local) => local.visit_attrs(f),
51             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
52             StmtKind::Item(item) => item.visit_attrs(f),
53             StmtKind::Empty => {}
54             StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
55         }
56     }
57     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
58         Some(match self {
59             StmtKind::Local(local) => &mut local.tokens,
60             StmtKind::Item(item) => &mut item.tokens,
61             StmtKind::Expr(expr) | StmtKind::Semi(expr) => &mut expr.tokens,
62             StmtKind::Empty => return None,
63             StmtKind::MacCall(mac) => &mut mac.tokens,
64         })
65     }
66 }
67
68 impl AstLike for Stmt {
69     fn attrs(&self) -> &[Attribute] {
70         self.kind.attrs()
71     }
72
73     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
74         self.kind.visit_attrs(f);
75     }
76     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
77         self.kind.tokens_mut()
78     }
79 }
80
81 impl AstLike for Attribute {
82     fn attrs(&self) -> &[Attribute] {
83         &[]
84     }
85     fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
86     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
87         Some(match &mut self.kind {
88             AttrKind::Normal(_, tokens) => tokens,
89             kind @ AttrKind::DocComment(..) => {
90                 panic!("Called tokens_mut on doc comment attr {:?}", kind)
91             }
92         })
93     }
94 }
95
96 impl<T: AstLike> AstLike for Option<T> {
97     fn attrs(&self) -> &[Attribute] {
98         self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[])
99     }
100     fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
101         if let Some(inner) = self.as_mut() {
102             inner.visit_attrs(f);
103         }
104     }
105     fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
106         self.as_mut().and_then(|inner| inner.tokens_mut())
107     }
108 }
109
110 /// Helper trait for the macros below. Abstracts over
111 /// the two types of attribute fields that AST nodes
112 /// may have (`Vec<Attribute>` or `AttrVec`)
113 trait VecOrAttrVec {
114     fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
115 }
116
117 impl VecOrAttrVec for Vec<Attribute> {
118     fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
119         f(self)
120     }
121 }
122
123 impl VecOrAttrVec for AttrVec {
124     fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
125         visit_attrvec(self, f)
126     }
127 }
128
129 macro_rules! derive_has_tokens_and_attrs {
130     ($($ty:path),*) => { $(
131         impl AstLike for $ty {
132             fn attrs(&self) -> &[Attribute] {
133                 &self.attrs
134             }
135
136             fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
137                 VecOrAttrVec::visit(&mut self.attrs, f)
138             }
139
140             fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
141                 Some(&mut self.tokens)
142             }
143         }
144     )* }
145 }
146
147 macro_rules! derive_has_attrs_no_tokens {
148     ($($ty:path),*) => { $(
149         impl AstLike for $ty {
150             fn attrs(&self) -> &[Attribute] {
151                 &self.attrs
152             }
153
154             fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
155                 VecOrAttrVec::visit(&mut self.attrs, f)
156             }
157
158             fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
159                 None
160             }
161         }
162     )* }
163 }
164
165 macro_rules! derive_has_tokens_no_attrs {
166     ($($ty:path),*) => { $(
167         impl AstLike for $ty {
168             fn attrs(&self) -> &[Attribute] {
169                 &[]
170             }
171
172             fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
173
174             fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
175                 Some(&mut self.tokens)
176             }
177         }
178     )* }
179 }
180
181 // These AST nodes support both inert and active
182 // attributes, so they also have tokens.
183 derive_has_tokens_and_attrs! {
184     Item, Expr, Local, AssocItem, ForeignItem
185 }
186
187 // These ast nodes only support inert attributes, so they don't
188 // store tokens (since nothing can observe them)
189 derive_has_attrs_no_tokens! {
190     FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam
191 }
192
193 // These AST nodes don't support attributes, but can
194 // be captured by a `macro_rules!` matcher. Therefore,
195 // they need to store tokens.
196 derive_has_tokens_no_attrs! {
197     Ty, Block, AttrItem, Pat, Path, Visibility
198 }