Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/classify.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
#[cfg(feature = "full")]
4
use crate::expr::Expr;
5
#[cfg(any(feature = "printing", feature = "full"))]
6
use crate::generics::TypeParamBound;
7
#[cfg(any(feature = "printing", feature = "full"))]
8
use crate::path::{Path, PathArguments};
9
#[cfg(any(feature = "printing", feature = "full"))]
10
use crate::punctuated::Punctuated;
11
#[cfg(any(feature = "printing", feature = "full"))]
12
use crate::ty::{ReturnType, Type};
13
#[cfg(feature = "full")]
14
use proc_macro2::{Delimiter, TokenStream, TokenTree};
15
#[cfg(any(feature = "printing", feature = "full"))]
16
use std::ops::ControlFlow;
17
18
#[cfg(feature = "full")]
19
pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool {
20
match expr {
21
Expr::Macro(expr) => !expr.mac.delimiter.is_brace(),
22
_ => requires_comma_to_be_match_arm(expr),
23
}
24
}
25
26
#[cfg(feature = "full")]
27
pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
28
match expr {
29
Expr::If(_)
30
| Expr::Match(_)
31
| Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc
32
| Expr::While(_)
33
| Expr::Loop(_)
34
| Expr::ForLoop(_)
35
| Expr::TryBlock(_)
36
| Expr::Const(_) => false,
37
38
Expr::Array(_)
39
| Expr::Assign(_)
40
| Expr::Async(_)
41
| Expr::Await(_)
42
| Expr::Binary(_)
43
| Expr::Break(_)
44
| Expr::Call(_)
45
| Expr::Cast(_)
46
| Expr::Closure(_)
47
| Expr::Continue(_)
48
| Expr::Field(_)
49
| Expr::Group(_)
50
| Expr::Index(_)
51
| Expr::Infer(_)
52
| Expr::Let(_)
53
| Expr::Lit(_)
54
| Expr::Macro(_)
55
| Expr::MethodCall(_)
56
| Expr::Paren(_)
57
| Expr::Path(_)
58
| Expr::Range(_)
59
| Expr::RawAddr(_)
60
| Expr::Reference(_)
61
| Expr::Repeat(_)
62
| Expr::Return(_)
63
| Expr::Struct(_)
64
| Expr::Try(_)
65
| Expr::Tuple(_)
66
| Expr::Unary(_)
67
| Expr::Yield(_)
68
| Expr::Verbatim(_) => true,
69
}
70
}
71
72
#[cfg(feature = "printing")]
73
pub(crate) fn trailing_unparameterized_path(mut ty: &Type) -> bool {
74
loop {
75
match ty {
76
Type::BareFn(t) => match &t.output {
77
ReturnType::Default => return false,
78
ReturnType::Type(_, ret) => ty = ret,
79
},
80
Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
81
ControlFlow::Break(trailing_path) => return trailing_path,
82
ControlFlow::Continue(t) => ty = t,
83
},
84
Type::Path(t) => match last_type_in_path(&t.path) {
85
ControlFlow::Break(trailing_path) => return trailing_path,
86
ControlFlow::Continue(t) => ty = t,
87
},
88
Type::Ptr(t) => ty = &t.elem,
89
Type::Reference(t) => ty = &t.elem,
90
Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
91
ControlFlow::Break(trailing_path) => return trailing_path,
92
ControlFlow::Continue(t) => ty = t,
93
},
94
95
Type::Array(_)
96
| Type::Group(_)
97
| Type::Infer(_)
98
| Type::Macro(_)
99
| Type::Never(_)
100
| Type::Paren(_)
101
| Type::Slice(_)
102
| Type::Tuple(_)
103
| Type::Verbatim(_) => return false,
104
}
105
}
106
107
fn last_type_in_path(path: &Path) -> ControlFlow<bool, &Type> {
108
match &path.segments.last().unwrap().arguments {
109
PathArguments::None => ControlFlow::Break(true),
110
PathArguments::AngleBracketed(_) => ControlFlow::Break(false),
111
PathArguments::Parenthesized(arg) => match &arg.output {
112
ReturnType::Default => ControlFlow::Break(false),
113
ReturnType::Type(_, ret) => ControlFlow::Continue(ret),
114
},
115
}
116
}
117
118
fn last_type_in_bounds(
119
bounds: &Punctuated<TypeParamBound, Token![+]>,
120
) -> ControlFlow<bool, &Type> {
121
match bounds.last().unwrap() {
122
TypeParamBound::Trait(t) => last_type_in_path(&t.path),
123
TypeParamBound::Lifetime(_)
124
| TypeParamBound::PreciseCapture(_)
125
| TypeParamBound::Verbatim(_) => ControlFlow::Break(false),
126
}
127
}
128
}
129
130
/// Whether the expression's first token is the label of a loop/block.
131
#[cfg(all(feature = "printing", feature = "full"))]
132
pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool {
133
loop {
134
match expr {
135
Expr::Block(e) => return e.label.is_some(),
136
Expr::ForLoop(e) => return e.label.is_some(),
137
Expr::Loop(e) => return e.label.is_some(),
138
Expr::While(e) => return e.label.is_some(),
139
140
Expr::Assign(e) => expr = &e.left,
141
Expr::Await(e) => expr = &e.base,
142
Expr::Binary(e) => expr = &e.left,
143
Expr::Call(e) => expr = &e.func,
144
Expr::Cast(e) => expr = &e.expr,
145
Expr::Field(e) => expr = &e.base,
146
Expr::Index(e) => expr = &e.expr,
147
Expr::MethodCall(e) => expr = &e.receiver,
148
Expr::Range(e) => match &e.start {
149
Some(start) => expr = start,
150
None => return false,
151
},
152
Expr::Try(e) => expr = &e.expr,
153
154
Expr::Array(_)
155
| Expr::Async(_)
156
| Expr::Break(_)
157
| Expr::Closure(_)
158
| Expr::Const(_)
159
| Expr::Continue(_)
160
| Expr::Group(_)
161
| Expr::If(_)
162
| Expr::Infer(_)
163
| Expr::Let(_)
164
| Expr::Lit(_)
165
| Expr::Macro(_)
166
| Expr::Match(_)
167
| Expr::Paren(_)
168
| Expr::Path(_)
169
| Expr::RawAddr(_)
170
| Expr::Reference(_)
171
| Expr::Repeat(_)
172
| Expr::Return(_)
173
| Expr::Struct(_)
174
| Expr::TryBlock(_)
175
| Expr::Tuple(_)
176
| Expr::Unary(_)
177
| Expr::Unsafe(_)
178
| Expr::Verbatim(_)
179
| Expr::Yield(_) => return false,
180
}
181
}
182
}
183
184
/// Whether the expression's last token is `}`.
185
#[cfg(feature = "full")]
186
pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool {
187
loop {
188
match expr {
189
Expr::Async(_)
190
| Expr::Block(_)
191
| Expr::Const(_)
192
| Expr::ForLoop(_)
193
| Expr::If(_)
194
| Expr::Loop(_)
195
| Expr::Match(_)
196
| Expr::Struct(_)
197
| Expr::TryBlock(_)
198
| Expr::Unsafe(_)
199
| Expr::While(_) => return true,
200
201
Expr::Assign(e) => expr = &e.right,
202
Expr::Binary(e) => expr = &e.right,
203
Expr::Break(e) => match &e.expr {
204
Some(e) => expr = e,
205
None => return false,
206
},
207
Expr::Cast(e) => return type_trailing_brace(&e.ty),
208
Expr::Closure(e) => expr = &e.body,
209
Expr::Let(e) => expr = &e.expr,
210
Expr::Macro(e) => return e.mac.delimiter.is_brace(),
211
Expr::Range(e) => match &e.end {
212
Some(end) => expr = end,
213
None => return false,
214
},
215
Expr::RawAddr(e) => expr = &e.expr,
216
Expr::Reference(e) => expr = &e.expr,
217
Expr::Return(e) => match &e.expr {
218
Some(e) => expr = e,
219
None => return false,
220
},
221
Expr::Unary(e) => expr = &e.expr,
222
Expr::Verbatim(e) => return tokens_trailing_brace(e),
223
Expr::Yield(e) => match &e.expr {
224
Some(e) => expr = e,
225
None => return false,
226
},
227
228
Expr::Array(_)
229
| Expr::Await(_)
230
| Expr::Call(_)
231
| Expr::Continue(_)
232
| Expr::Field(_)
233
| Expr::Group(_)
234
| Expr::Index(_)
235
| Expr::Infer(_)
236
| Expr::Lit(_)
237
| Expr::MethodCall(_)
238
| Expr::Paren(_)
239
| Expr::Path(_)
240
| Expr::Repeat(_)
241
| Expr::Try(_)
242
| Expr::Tuple(_) => return false,
243
}
244
}
245
246
fn type_trailing_brace(mut ty: &Type) -> bool {
247
loop {
248
match ty {
249
Type::BareFn(t) => match &t.output {
250
ReturnType::Default => return false,
251
ReturnType::Type(_, ret) => ty = ret,
252
},
253
Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
254
ControlFlow::Break(trailing_brace) => return trailing_brace,
255
ControlFlow::Continue(t) => ty = t,
256
},
257
Type::Macro(t) => return t.mac.delimiter.is_brace(),
258
Type::Path(t) => match last_type_in_path(&t.path) {
259
Some(t) => ty = t,
260
None => return false,
261
},
262
Type::Ptr(t) => ty = &t.elem,
263
Type::Reference(t) => ty = &t.elem,
264
Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
265
ControlFlow::Break(trailing_brace) => return trailing_brace,
266
ControlFlow::Continue(t) => ty = t,
267
},
268
Type::Verbatim(t) => return tokens_trailing_brace(t),
269
270
Type::Array(_)
271
| Type::Group(_)
272
| Type::Infer(_)
273
| Type::Never(_)
274
| Type::Paren(_)
275
| Type::Slice(_)
276
| Type::Tuple(_) => return false,
277
}
278
}
279
}
280
281
fn last_type_in_path(path: &Path) -> Option<&Type> {
282
match &path.segments.last().unwrap().arguments {
283
PathArguments::None | PathArguments::AngleBracketed(_) => None,
284
PathArguments::Parenthesized(arg) => match &arg.output {
285
ReturnType::Default => None,
286
ReturnType::Type(_, ret) => Some(ret),
287
},
288
}
289
}
290
291
fn last_type_in_bounds(
292
bounds: &Punctuated<TypeParamBound, Token![+]>,
293
) -> ControlFlow<bool, &Type> {
294
match bounds.last().unwrap() {
295
TypeParamBound::Trait(t) => match last_type_in_path(&t.path) {
296
Some(t) => ControlFlow::Continue(t),
297
None => ControlFlow::Break(false),
298
},
299
TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) => {
300
ControlFlow::Break(false)
301
}
302
TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)),
303
}
304
}
305
306
fn tokens_trailing_brace(tokens: &TokenStream) -> bool {
307
if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() {
308
last.delimiter() == Delimiter::Brace
309
} else {
310
false
311
}
312
}
313
}
314
315