Skip to content

Commit c0447b4

Browse files
committed
fix #103435, unused lint won't produce invalid code
1 parent 9be2f35 commit c0447b4

File tree

4 files changed

+106
-13
lines changed

4 files changed

+106
-13
lines changed

compiler/rustc_lint/src/unused.rs

+31-13
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,26 @@ trait UnusedDelimLint {
565565
lint.set_arg("delim", Self::DELIM_STR);
566566
lint.set_arg("item", msg);
567567
if let Some((lo, hi)) = spans {
568-
let replacement = vec![
569-
(lo, if keep_space.0 { " ".into() } else { "".into() }),
570-
(hi, if keep_space.1 { " ".into() } else { "".into() }),
571-
];
568+
let sm = cx.sess().source_map();
569+
let lo_replace =
570+
if keep_space.0 &&
571+
let Ok(snip) = sm.span_to_snippet(lo.with_lo(lo.lo() - BytePos(1))) &&
572+
!snip.starts_with(" ") {
573+
" ".to_string()
574+
} else {
575+
"".to_string()
576+
};
577+
578+
let hi_replace =
579+
if keep_space.1 &&
580+
let Ok(snip) = sm.span_to_snippet(sm.next_point(hi)) &&
581+
!snip.starts_with(" ") {
582+
" ".to_string()
583+
} else {
584+
"".to_string()
585+
};
586+
587+
let replacement = vec![(lo, lo_replace), (hi, hi_replace)];
572588
lint.multipart_suggestion(
573589
fluent::suggestion,
574590
replacement,
@@ -765,6 +781,7 @@ impl UnusedParens {
765781
value: &ast::Pat,
766782
avoid_or: bool,
767783
avoid_mut: bool,
784+
keep_space: (bool, bool),
768785
) {
769786
use ast::{BindingAnnotation, PatKind};
770787

@@ -789,7 +806,7 @@ impl UnusedParens {
789806
} else {
790807
None
791808
};
792-
self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
809+
self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
793810
}
794811
}
795812
}
@@ -798,7 +815,7 @@ impl EarlyLintPass for UnusedParens {
798815
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
799816
match e.kind {
800817
ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
801-
self.check_unused_parens_pat(cx, pat, false, false);
818+
self.check_unused_parens_pat(cx, pat, false, false, (true, true));
802819
}
803820
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
804821
// handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
@@ -842,40 +859,41 @@ impl EarlyLintPass for UnusedParens {
842859

843860
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
844861
use ast::{Mutability, PatKind::*};
862+
let keep_space = (false, false);
845863
match &p.kind {
846864
// Do not lint on `(..)` as that will result in the other arms being useless.
847865
Paren(_)
848866
// The other cases do not contain sub-patterns.
849867
| Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
850868
// These are list-like patterns; parens can always be removed.
851869
TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
852-
self.check_unused_parens_pat(cx, p, false, false);
870+
self.check_unused_parens_pat(cx, p, false, false, keep_space);
853871
},
854872
Struct(_, _, fps, _) => for f in fps {
855-
self.check_unused_parens_pat(cx, &f.pat, false, false);
873+
self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
856874
},
857875
// Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
858-
Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false),
876+
Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
859877
// Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
860878
// Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
861-
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not),
879+
Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
862880
}
863881
}
864882

865883
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
866884
if let StmtKind::Local(ref local) = s.kind {
867-
self.check_unused_parens_pat(cx, &local.pat, true, false);
885+
self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
868886
}
869887

870888
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
871889
}
872890

873891
fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
874-
self.check_unused_parens_pat(cx, &param.pat, true, false);
892+
self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
875893
}
876894

877895
fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
878-
self.check_unused_parens_pat(cx, &arm.pat, false, false);
896+
self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
879897
}
880898

881899
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
#![deny(unused_parens)]
3+
4+
fn main() {
5+
if let Some(_) = Some(1) {}
6+
//~^ ERROR unnecessary parentheses around pattern
7+
8+
for _x in 1..10 {}
9+
//~^ ERROR unnecessary parentheses around pattern
10+
11+
if 2 == 1 {}
12+
//~^ ERROR unnecessary parentheses around `if` condition
13+
14+
// FIXME, auto recover from this one?
15+
// for(_x in 1..10) {}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
#![deny(unused_parens)]
3+
4+
fn main() {
5+
if let(Some(_))= Some(1) {}
6+
//~^ ERROR unnecessary parentheses around pattern
7+
8+
for(_x)in 1..10 {}
9+
//~^ ERROR unnecessary parentheses around pattern
10+
11+
if(2 == 1){}
12+
//~^ ERROR unnecessary parentheses around `if` condition
13+
14+
// FIXME, auto recover from this one?
15+
// for(_x in 1..10) {}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: unnecessary parentheses around pattern
2+
--> $DIR/issue-103435-extra-parentheses.rs:5:11
3+
|
4+
LL | if let(Some(_))= Some(1) {}
5+
| ^ ^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/issue-103435-extra-parentheses.rs:2:9
9+
|
10+
LL | #![deny(unused_parens)]
11+
| ^^^^^^^^^^^^^
12+
help: remove these parentheses
13+
|
14+
LL - if let(Some(_))= Some(1) {}
15+
LL + if let Some(_) = Some(1) {}
16+
|
17+
18+
error: unnecessary parentheses around pattern
19+
--> $DIR/issue-103435-extra-parentheses.rs:8:8
20+
|
21+
LL | for(_x)in 1..10 {}
22+
| ^ ^
23+
|
24+
help: remove these parentheses
25+
|
26+
LL - for(_x)in 1..10 {}
27+
LL + for _x in 1..10 {}
28+
|
29+
30+
error: unnecessary parentheses around `if` condition
31+
--> $DIR/issue-103435-extra-parentheses.rs:11:7
32+
|
33+
LL | if(2 == 1){}
34+
| ^ ^
35+
|
36+
help: remove these parentheses
37+
|
38+
LL - if(2 == 1){}
39+
LL + if 2 == 1 {}
40+
|
41+
42+
error: aborting due to 3 previous errors
43+

0 commit comments

Comments
 (0)