@@ -15,7 +15,7 @@ use syntax::print::pprust;
1515use syntax:: symbol:: { kw, sym} ;
1616use syntax:: symbol:: Symbol ;
1717use syntax:: util:: parser;
18- use syntax_pos:: Span ;
18+ use syntax_pos:: { Span , BytePos } ;
1919
2020use rustc:: hir;
2121
@@ -353,31 +353,41 @@ declare_lint! {
353353declare_lint_pass ! ( UnusedParens => [ UNUSED_PARENS ] ) ;
354354
355355impl UnusedParens {
356+
357+ fn is_expr_parens_necessary ( inner : & ast:: Expr , followed_by_block : bool ) -> bool {
358+ followed_by_block && match inner. node {
359+ ast:: ExprKind :: Ret ( _) | ast:: ExprKind :: Break ( ..) => true ,
360+ _ => parser:: contains_exterior_struct_lit ( & inner) ,
361+ }
362+ }
363+
356364 fn check_unused_parens_expr ( & self ,
357- cx : & EarlyContext < ' _ > ,
358- value : & ast:: Expr ,
359- msg : & str ,
360- followed_by_block : bool ) {
365+ cx : & EarlyContext < ' _ > ,
366+ value : & ast:: Expr ,
367+ msg : & str ,
368+ followed_by_block : bool ,
369+ left_pos : Option < BytePos > ,
370+ right_pos : Option < BytePos > ) {
361371 match value. node {
362372 ast:: ExprKind :: Paren ( ref inner) => {
363- let necessary = followed_by_block && match inner. node {
364- ast:: ExprKind :: Ret ( _) | ast:: ExprKind :: Break ( ..) => true ,
365- _ => parser:: contains_exterior_struct_lit ( & inner) ,
366- } ;
367- if !necessary {
373+ if !Self :: is_expr_parens_necessary ( inner, followed_by_block) {
368374 let expr_text = if let Ok ( snippet) = cx. sess ( ) . source_map ( )
369375 . span_to_snippet ( value. span ) {
370376 snippet
371377 } else {
372378 pprust:: expr_to_string ( value)
373379 } ;
374- Self :: remove_outer_parens ( cx, value. span , & expr_text, msg) ;
380+ let keep_space = (
381+ left_pos. map ( |s| s >= value. span . lo ( ) ) . unwrap_or ( false ) ,
382+ right_pos. map ( |s| s <= value. span . hi ( ) ) . unwrap_or ( false ) ,
383+ ) ;
384+ Self :: remove_outer_parens ( cx, value. span , & expr_text, msg, keep_space) ;
375385 }
376386 }
377387 ast:: ExprKind :: Let ( _, ref expr) => {
378388 // FIXME(#60336): Properly handle `let true = (false && true)`
379389 // actually needing the parenthesis.
380- self . check_unused_parens_expr ( cx, expr, "`let` head expression" , followed_by_block) ;
390+ self . check_unused_parens_expr ( cx, expr, "`let` head expression" , followed_by_block, None , None ) ;
381391 }
382392 _ => { }
383393 }
@@ -394,11 +404,11 @@ impl UnusedParens {
394404 } else {
395405 pprust:: pat_to_string ( value)
396406 } ;
397- Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg) ;
407+ Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg, ( false , false ) ) ;
398408 }
399409 }
400410
401- fn remove_outer_parens ( cx : & EarlyContext < ' _ > , span : Span , pattern : & str , msg : & str ) {
411+ fn remove_outer_parens ( cx : & EarlyContext < ' _ > , span : Span , pattern : & str , msg : & str , keep_space : ( bool , bool ) ) {
402412 let span_msg = format ! ( "unnecessary parentheses around {}" , msg) ;
403413 let mut err = cx. struct_span_lint ( UNUSED_PARENS , span, & span_msg) ;
404414 let mut ate_left_paren = false ;
@@ -427,9 +437,17 @@ impl UnusedParens {
427437 } ) ;
428438
429439 let replace = {
430- let mut replace = String :: from ( " " ) ;
431- replace. push_str ( parens_removed) ;
432- replace. push ( ' ' ) ;
440+ let mut replace = if keep_space. 0 {
441+ let mut s = String :: from ( " " ) ;
442+ s. push_str ( parens_removed) ;
443+ s
444+ } else {
445+ String :: from ( parens_removed)
446+ } ;
447+
448+ if keep_space. 1 {
449+ replace. push ( ' ' ) ;
450+ }
433451 replace
434452 } ;
435453
@@ -446,14 +464,35 @@ impl UnusedParens {
446464impl EarlyLintPass for UnusedParens {
447465 fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , e : & ast:: Expr ) {
448466 use syntax:: ast:: ExprKind :: * ;
449- let ( value, msg, followed_by_block) = match e. node {
450- If ( ref cond, ..) => ( cond, "`if` condition" , true ) ,
451- While ( ref cond, ..) => ( cond, "`while` condition" , true ) ,
452- ForLoop ( _, ref cond, ..) => ( cond, "`for` head expression" , true ) ,
453- Match ( ref head, _) => ( head, "`match` head expression" , true ) ,
454- Ret ( Some ( ref value) ) => ( value, "`return` value" , false ) ,
455- Assign ( _, ref value) => ( value, "assigned value" , false ) ,
456- AssignOp ( .., ref value) => ( value, "assigned value" , false ) ,
467+ let ( value, msg, followed_by_block, left_pos, right_pos) = match e. node {
468+ If ( ref cond, ref block, ..) => {
469+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 2 ) ;
470+ let right = block. span . lo ( ) ;
471+ ( cond, "`if` condition" , true , Some ( left) , Some ( right) )
472+ }
473+
474+ While ( ref cond, ref block, ..) => {
475+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
476+ let right = block. span . lo ( ) ;
477+ ( cond, "`while` condition" , true , Some ( left) , Some ( right) )
478+ } ,
479+
480+ ForLoop ( _, ref cond, ref block, ..) => {
481+ ( cond, "`for` head expression" , true , None , Some ( block. span . lo ( ) ) )
482+ }
483+
484+ Match ( ref head, _) => {
485+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
486+ ( head, "`match` head expression" , true , Some ( left) , None )
487+ }
488+
489+ Ret ( Some ( ref value) ) => {
490+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 3 ) ;
491+ ( value, "`return` value" , false , Some ( left) , None )
492+ }
493+
494+ Assign ( _, ref value) => ( value, "assigned value" , false , None , None ) ,
495+ AssignOp ( .., ref value) => ( value, "assigned value" , false , None , None ) ,
457496 // either function/method call, or something this lint doesn't care about
458497 ref call_or_other => {
459498 let ( args_to_check, call_kind) = match * call_or_other {
@@ -475,12 +514,12 @@ impl EarlyLintPass for UnusedParens {
475514 }
476515 let msg = format ! ( "{} argument" , call_kind) ;
477516 for arg in args_to_check {
478- self . check_unused_parens_expr ( cx, arg, & msg, false ) ;
517+ self . check_unused_parens_expr ( cx, arg, & msg, false , None , None ) ;
479518 }
480519 return ;
481520 }
482521 } ;
483- self . check_unused_parens_expr ( cx, & value, msg, followed_by_block) ;
522+ self . check_unused_parens_expr ( cx, & value, msg, followed_by_block, left_pos , right_pos ) ;
484523 }
485524
486525 fn check_pat ( & mut self , cx : & EarlyContext < ' _ > , p : & ast:: Pat ) {
@@ -500,7 +539,7 @@ impl EarlyLintPass for UnusedParens {
500539 fn check_stmt ( & mut self , cx : & EarlyContext < ' _ > , s : & ast:: Stmt ) {
501540 if let ast:: StmtKind :: Local ( ref local) = s. node {
502541 if let Some ( ref value) = local. init {
503- self . check_unused_parens_expr ( cx, & value, "assigned value" , false ) ;
542+ self . check_unused_parens_expr ( cx, & value, "assigned value" , false , None , None ) ;
504543 }
505544 }
506545 }
0 commit comments