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

`+

}

`