11use crate :: Lint ;
22use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
33use rustc_ast as ast;
4- use rustc_ast:: util:: parser;
4+ use rustc_ast:: util:: { classify , parser} ;
55use rustc_ast:: { ExprKind , StmtKind } ;
66use rustc_ast_pretty:: pprust;
77use rustc_errors:: { pluralize, Applicability } ;
@@ -382,6 +382,7 @@ enum UnusedDelimsCtx {
382382 FunctionArg ,
383383 MethodArg ,
384384 AssignedValue ,
385+ AssignedValueLetElse ,
385386 IfCond ,
386387 WhileCond ,
387388 ForIterExpr ,
@@ -398,7 +399,9 @@ impl From<UnusedDelimsCtx> for &'static str {
398399 match ctx {
399400 UnusedDelimsCtx :: FunctionArg => "function argument" ,
400401 UnusedDelimsCtx :: MethodArg => "method argument" ,
401- UnusedDelimsCtx :: AssignedValue => "assigned value" ,
402+ UnusedDelimsCtx :: AssignedValue | UnusedDelimsCtx :: AssignedValueLetElse => {
403+ "assigned value"
404+ }
402405 UnusedDelimsCtx :: IfCond => "`if` condition" ,
403406 UnusedDelimsCtx :: WhileCond => "`while` condition" ,
404407 UnusedDelimsCtx :: ForIterExpr => "`for` iterator expression" ,
@@ -441,14 +444,26 @@ trait UnusedDelimLint {
441444 right_pos : Option < BytePos > ,
442445 ) ;
443446
444- fn is_expr_delims_necessary ( inner : & ast:: Expr , followed_by_block : bool ) -> bool {
447+ fn is_expr_delims_necessary (
448+ inner : & ast:: Expr ,
449+ followed_by_block : bool ,
450+ followed_by_else : bool ,
451+ ) -> bool {
452+ if followed_by_else {
453+ match inner. kind {
454+ ast:: ExprKind :: Binary ( op, ..) if op. node . lazy ( ) => return true ,
455+ _ if classify:: expr_trailing_brace ( inner) . is_some ( ) => return true ,
456+ _ => { }
457+ }
458+ }
459+
445460 // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
446461 let lhs_needs_parens = {
447462 let mut innermost = inner;
448463 loop {
449464 if let ExprKind :: Binary ( _, lhs, _rhs) = & innermost. kind {
450465 innermost = lhs;
451- if !rustc_ast :: util :: classify:: expr_requires_semi_to_be_stmt ( innermost) {
466+ if !classify:: expr_requires_semi_to_be_stmt ( innermost) {
452467 break true ;
453468 }
454469 } else {
@@ -618,15 +633,12 @@ trait UnusedDelimLint {
618633 fn check_stmt ( & mut self , cx : & EarlyContext < ' _ > , s : & ast:: Stmt ) {
619634 match s. kind {
620635 StmtKind :: Local ( ref local) if Self :: LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
621- if let Some ( value) = local. kind . init ( ) {
622- self . check_unused_delims_expr (
623- cx,
624- & value,
625- UnusedDelimsCtx :: AssignedValue ,
626- false ,
627- None ,
628- None ,
629- ) ;
636+ if let Some ( ( init, els) ) = local. kind . init_else_opt ( ) {
637+ let ctx = match els {
638+ None => UnusedDelimsCtx :: AssignedValue ,
639+ Some ( _) => UnusedDelimsCtx :: AssignedValueLetElse ,
640+ } ;
641+ self . check_unused_delims_expr ( cx, init, ctx, false , None , None ) ;
630642 }
631643 }
632644 StmtKind :: Expr ( ref expr) => {
@@ -702,7 +714,8 @@ impl UnusedDelimLint for UnusedParens {
702714 ) {
703715 match value. kind {
704716 ast:: ExprKind :: Paren ( ref inner) => {
705- if !Self :: is_expr_delims_necessary ( inner, followed_by_block)
717+ let followed_by_else = ctx == UnusedDelimsCtx :: AssignedValueLetElse ;
718+ if !Self :: is_expr_delims_necessary ( inner, followed_by_block, followed_by_else)
706719 && value. attrs . is_empty ( )
707720 && !value. span . from_expansion ( )
708721 && ( ctx != UnusedDelimsCtx :: LetScrutineeExpr
@@ -941,7 +954,7 @@ impl UnusedDelimLint for UnusedBraces {
941954 // FIXME(const_generics): handle paths when #67075 is fixed.
942955 if let [ stmt] = inner. stmts . as_slice ( ) {
943956 if let ast:: StmtKind :: Expr ( ref expr) = stmt. kind {
944- if !Self :: is_expr_delims_necessary ( expr, followed_by_block)
957+ if !Self :: is_expr_delims_necessary ( expr, followed_by_block, false )
945958 && ( ctx != UnusedDelimsCtx :: AnonConst
946959 || matches ! ( expr. kind, ast:: ExprKind :: Lit ( _) ) )
947960 && !cx. sess ( ) . source_map ( ) . is_multiline ( value. span )
0 commit comments