Merge from rustc · rust-lang/rust@f1ffb8d

@@ -81,8 +81,17 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {

8181

}

8282

}

838384+

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+8493

/// 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<'_>> {

8695

loop {

8796

match &expr.kind {

8897

AddrOf(_, _, e)

@@ -111,10 +120,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {

111120

| Struct(..)

112121

| TryBlock(..)

113122

| 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+

}

115128116129

MacCall(mac) => {

117-

break (mac.args.delim == Delimiter::Brace).then_some(expr);

130+

break (mac.args.delim == Delimiter::Brace).then_some(TrailingBrace::MacCall(mac));

118131

}

119132120133

InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {

@@ -131,7 +144,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {

131144

| MethodCall(_)

132145

| Tup(_)

133146

| Lit(_)

134-

| Cast(_, _)

135147

| Type(_, _)

136148

| Await(_, _)

137149

| Field(_, _)

@@ -148,3 +160,78 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {

148160

}

149161

}

150162

}

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+

}