fix #103435, unused lint won't produce invalid code

This commit is contained in:
yukang 2022-10-24 16:48:28 +08:00
parent 9be2f35a4c
commit c0447b489b
4 changed files with 106 additions and 13 deletions

View File

@ -565,10 +565,26 @@ fn emit_unused_delims(
lint.set_arg("delim", Self::DELIM_STR);
lint.set_arg("item", msg);
if let Some((lo, hi)) = spans {
let replacement = vec![
(lo, if keep_space.0 { " ".into() } else { "".into() }),
(hi, if keep_space.1 { " ".into() } else { "".into() }),
];
let sm = cx.sess().source_map();
let lo_replace =
if keep_space.0 &&
let Ok(snip) = sm.span_to_snippet(lo.with_lo(lo.lo() - BytePos(1))) &&
!snip.starts_with(" ") {
" ".to_string()
} else {
"".to_string()
};
let hi_replace =
if keep_space.1 &&
let Ok(snip) = sm.span_to_snippet(sm.next_point(hi)) &&
!snip.starts_with(" ") {
" ".to_string()
} else {
"".to_string()
};
let replacement = vec![(lo, lo_replace), (hi, hi_replace)];
lint.multipart_suggestion(
fluent::suggestion,
replacement,
@ -765,6 +781,7 @@ fn check_unused_parens_pat(
value: &ast::Pat,
avoid_or: bool,
avoid_mut: bool,
keep_space: (bool, bool),
) {
use ast::{BindingAnnotation, PatKind};
@ -789,7 +806,7 @@ fn check_unused_parens_pat(
} else {
None
};
self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
}
}
}
@ -798,7 +815,7 @@ impl EarlyLintPass for UnusedParens {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
match e.kind {
ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
self.check_unused_parens_pat(cx, pat, false, false);
self.check_unused_parens_pat(cx, pat, false, false, (true, true));
}
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
// handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
@ -842,6 +859,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
use ast::{Mutability, PatKind::*};
let keep_space = (false, false);
match &p.kind {
// Do not lint on `(..)` as that will result in the other arms being useless.
Paren(_)
@ -849,33 +867,33 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
| Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
// These are list-like patterns; parens can always be removed.
TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
self.check_unused_parens_pat(cx, p, false, false);
self.check_unused_parens_pat(cx, p, false, false, keep_space);
},
Struct(_, _, fps, _) => for f in fps {
self.check_unused_parens_pat(cx, &f.pat, false, false);
self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
},
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false),
Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
// Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
// Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not),
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
}
}
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
if let StmtKind::Local(ref local) = s.kind {
self.check_unused_parens_pat(cx, &local.pat, true, false);
self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
}
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
}
fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
self.check_unused_parens_pat(cx, &param.pat, true, false);
self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
}
fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
self.check_unused_parens_pat(cx, &arm.pat, false, false);
self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
}
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {

View File

@ -0,0 +1,16 @@
// run-rustfix
#![deny(unused_parens)]
fn main() {
if let Some(_) = Some(1) {}
//~^ ERROR unnecessary parentheses around pattern
for _x in 1..10 {}
//~^ ERROR unnecessary parentheses around pattern
if 2 == 1 {}
//~^ ERROR unnecessary parentheses around `if` condition
// FIXME, auto recover from this one?
// for(_x in 1..10) {}
}

View File

@ -0,0 +1,16 @@
// run-rustfix
#![deny(unused_parens)]
fn main() {
if let(Some(_))= Some(1) {}
//~^ ERROR unnecessary parentheses around pattern
for(_x)in 1..10 {}
//~^ ERROR unnecessary parentheses around pattern
if(2 == 1){}
//~^ ERROR unnecessary parentheses around `if` condition
// FIXME, auto recover from this one?
// for(_x in 1..10) {}
}

View File

@ -0,0 +1,43 @@
error: unnecessary parentheses around pattern
--> $DIR/issue-103435-extra-parentheses.rs:5:11
|
LL | if let(Some(_))= Some(1) {}
| ^ ^
|
note: the lint level is defined here
--> $DIR/issue-103435-extra-parentheses.rs:2:9
|
LL | #![deny(unused_parens)]
| ^^^^^^^^^^^^^
help: remove these parentheses
|
LL - if let(Some(_))= Some(1) {}
LL + if let Some(_) = Some(1) {}
|
error: unnecessary parentheses around pattern
--> $DIR/issue-103435-extra-parentheses.rs:8:8
|
LL | for(_x)in 1..10 {}
| ^ ^
|
help: remove these parentheses
|
LL - for(_x)in 1..10 {}
LL + for _x in 1..10 {}
|
error: unnecessary parentheses around `if` condition
--> $DIR/issue-103435-extra-parentheses.rs:11:7
|
LL | if(2 == 1){}
| ^ ^
|
help: remove these parentheses
|
LL - if(2 == 1){}
LL + if 2 == 1 {}
|
error: aborting due to 3 previous errors