Merge from rustc · rust-lang/rust@f1ffb8d (original) (raw)
`@@ -81,8 +81,17 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
`
81
81
`}
`
82
82
`}
`
83
83
``
``
84
`+
pub enum TrailingBrace<'a> {
`
``
85
`` +
/// Trailing brace in a macro call, like the one in x as *const brace! {}
.
``
``
86
`+
/// We will suggest changing the macro call to a different delimiter.
`
``
87
`+
MacCall(&'a ast::MacCall),
`
``
88
`` +
/// Trailing brace in any other expression, such as a + B {}
. We will
``
``
89
`` +
/// suggest wrapping the innermost expression in parentheses: a + (B {})
.
``
``
90
`+
Expr(&'a ast::Expr),
`
``
91
`+
}
`
``
92
+
84
93
`` /// If an expression ends with }
, returns the innermost expression ending in the }
``
85
``
`-
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
`
``
94
`+
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
`
86
95
`loop {
`
87
96
`match &expr.kind {
`
88
97
`AddrOf(_, _, e)
`
`@@ -111,10 +120,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
`
111
120
` | Struct(..)
`
112
121
` | TryBlock(..)
`
113
122
` | While(..)
`
114
``
`-
| ConstBlock(_) => break Some(expr),
`
``
123
`+
| ConstBlock(_) => break Some(TrailingBrace::Expr(expr)),
`
``
124
+
``
125
`+
Cast(_, ty) => {
`
``
126
`+
break type_trailing_braced_mac_call(ty).map(TrailingBrace::MacCall);
`
``
127
`+
}
`
115
128
``
116
129
`MacCall(mac) => {
`
117
``
`-
break (mac.args.delim == Delimiter::Brace).then_some(expr);
`
``
130
`+
break (mac.args.delim == Delimiter::Brace).then_some(TrailingBrace::MacCall(mac));
`
118
131
`}
`
119
132
``
120
133
`InlineAsm() | OffsetOf(, ) | IncludedBytes() | FormatArgs(_) => {
`
`@@ -131,7 +144,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
`
131
144
` | MethodCall(_)
`
132
145
` | Tup(_)
`
133
146
` | Lit(_)
`
134
``
`-
| Cast(_, _)
`
135
147
` | Type(_, _)
`
136
148
` | Await(_, _)
`
137
149
` | Field(_, _)
`
`@@ -148,3 +160,78 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
`
148
160
`}
`
149
161
`}
`
150
162
`}
`
``
163
+
``
164
`` +
/// If the type's last token is }
, it must be due to a braced macro call, such
``
``
165
`` +
/// as in *const brace! { ... }
. Returns that trailing macro call.
``
``
166
`+
fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
`
``
167
`+
loop {
`
``
168
`+
match &ty.kind {
`
``
169
`+
ast::TyKind::MacCall(mac) => {
`
``
170
`+
break (mac.args.delim == Delimiter::Brace).then_some(mac);
`
``
171
`+
}
`
``
172
+
``
173
`+
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
`
``
174
`+
ty = &mut_ty.ty;
`
``
175
`+
}
`
``
176
+
``
177
`+
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
`
``
178
`+
ast::FnRetTy::Default(_) => break None,
`
``
179
`+
ast::FnRetTy::Ty(ret) => ty = ret,
`
``
180
`+
},
`
``
181
+
``
182
`+
ast::TyKind::Path(_, path) => match path_return_type(path) {
`
``
183
`+
Some(trailing_ty) => ty = trailing_ty,
`
``
184
`+
None => break None,
`
``
185
`+
},
`
``
186
+
``
187
`+
ast::TyKind::TraitObject(bounds, ) | ast::TyKind::ImplTrait(, bounds, _) => {
`
``
188
`+
match bounds.last() {
`
``
189
`+
Some(ast::GenericBound::Trait(bound, _)) => {
`
``
190
`+
match path_return_type(&bound.trait_ref.path) {
`
``
191
`+
Some(trailing_ty) => ty = trailing_ty,
`
``
192
`+
None => break None,
`
``
193
`+
}
`
``
194
`+
}
`
``
195
`+
Some(ast::GenericBound::Outlives(_)) | None => break None,
`
``
196
`+
}
`
``
197
`+
}
`
``
198
+
``
199
`+
ast::TyKind::Slice(..)
`
``
200
`+
| ast::TyKind::Array(..)
`
``
201
`+
| ast::TyKind::Never
`
``
202
`+
| ast::TyKind::Tup(..)
`
``
203
`+
| ast::TyKind::Paren(..)
`
``
204
`+
| ast::TyKind::Typeof(..)
`
``
205
`+
| ast::TyKind::Infer
`
``
206
`+
| ast::TyKind::ImplicitSelf
`
``
207
`+
| ast::TyKind::CVarArgs
`
``
208
`+
| ast::TyKind::Pat(..)
`
``
209
`+
| ast::TyKind::Dummy
`
``
210
`+
| ast::TyKind::Err(..) => break None,
`
``
211
+
``
212
`+
// These end in brace, but cannot occur in a let-else statement.
`
``
213
`+
// They are only parsed as fields of a data structure. For the
`
``
214
`+
// purpose of denying trailing braces in the expression of a
`
``
215
`+
// let-else, we can disregard these.
`
``
216
`+
ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None,
`
``
217
`+
}
`
``
218
`+
}
`
``
219
`+
}
`
``
220
+
``
221
`+
/// Returns the trailing return type in the given path, if it has one.
`
``
222
`+
///
`
``
223
/// ```ignore (illustrative)
``
224
`+
/// ::std::ops::FnOnce(&str) -> fn() -> *const c_void
`
``
225
`+
/// ^^^^^^^^^^^^^^^^^^^^^
`
``
226
/// ```
``
227
`+
fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
`
``
228
`+
let last_segment = path.segments.last()?;
`
``
229
`+
let args = last_segment.args.as_ref()?;
`
``
230
`+
match &**args {
`
``
231
`+
ast::GenericArgs::Parenthesized(args) => match &args.output {
`
``
232
`+
ast::FnRetTy::Default(_) => None,
`
``
233
`+
ast::FnRetTy::Ty(ret) => Some(ret),
`
``
234
`+
},
`
``
235
`+
ast::GenericArgs::AngleBracketed(_) => None,
`
``
236
`+
}
`
``
237
`+
}
`