Skip to content

Commit 8863848

Browse files
committed
Silence resolve errors on missing let in let-chain
1 parent 83f747d commit 8863848

File tree

7 files changed

+76
-63
lines changed

7 files changed

+76
-63
lines changed

Diff for: compiler/rustc_parse/src/parser/expr.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -2478,7 +2478,12 @@ impl<'a> Parser<'a> {
24782478
let mut cond =
24792479
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
24802480

2481-
CondChecker::new(self).visit_expr(&mut cond);
2481+
let mut checker = CondChecker::new(self);
2482+
checker.visit_expr(&mut cond);
2483+
if checker.seen_missing_let {
2484+
// Avoid unnecessary resolve errors as we know we'll have some.
2485+
*self.sess.silence_resolve_errors.borrow_mut() = true;
2486+
}
24822487

24832488
if let ExprKind::Let(_, _, _, None) = cond.kind {
24842489
// Remove the last feature gating of a `let` expression since it's stable.
@@ -3556,12 +3561,19 @@ struct CondChecker<'a> {
35563561
parser: &'a Parser<'a>,
35573562
forbid_let_reason: Option<ForbiddenLetReason>,
35583563
missing_let: Option<errors::MaybeMissingLet>,
3564+
seen_missing_let: bool,
35593565
comparison: Option<errors::MaybeComparison>,
35603566
}
35613567

35623568
impl<'a> CondChecker<'a> {
35633569
fn new(parser: &'a Parser<'a>) -> Self {
3564-
CondChecker { parser, forbid_let_reason: None, missing_let: None, comparison: None }
3570+
CondChecker {
3571+
parser,
3572+
forbid_let_reason: None,
3573+
missing_let: None,
3574+
seen_missing_let: false,
3575+
comparison: None,
3576+
}
35653577
}
35663578
}
35673579

@@ -3613,6 +3625,7 @@ impl MutVisitor for CondChecker<'_> {
36133625
| ExprKind::Call(_, _)
36143626
| ExprKind::Array(_) = rhs.kind
36153627
{
3628+
self.seen_missing_let = true;
36163629
self.missing_let =
36173630
Some(errors::MaybeMissingLet { span: rhs.span.shrink_to_lo() });
36183631
}

Diff for: compiler/rustc_resolve/src/late/diagnostics.rs

+5
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
435435
code,
436436
);
437437

438+
if *self.r.tcx.sess.parse_sess.silence_resolve_errors.borrow() {
439+
// Silence redundant resolve errors that will be caused due to mis-parse fallout.
440+
err.delay_as_bug();
441+
}
442+
438443
self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
439444
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
440445

Diff for: compiler/rustc_session/src/parse.rs

+4
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ pub struct ParseSess {
217217
pub proc_macro_quoted_spans: AppendOnlyVec<Span>,
218218
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
219219
pub attr_id_generator: AttrIdGenerator,
220+
/// Track parse errors that will cause unnecessary resolve errors. This is a crude mechanism,
221+
/// we should do something that is scope-based, instead of crate-global.
222+
pub silence_resolve_errors: Lock<bool>,
220223
}
221224

222225
impl ParseSess {
@@ -247,6 +250,7 @@ impl ParseSess {
247250
assume_incomplete_release: false,
248251
proc_macro_quoted_spans: Default::default(),
249252
attr_id_generator: AttrIdGenerator::new(),
253+
silence_resolve_errors: Default::default(),
250254
}
251255
}
252256

Diff for: tests/ui/expr/if/bad-if-let-suggestion-2.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// FIXME(compiler-errors): This really should suggest `let` on the RHS of the
2+
// `&&` operator, but that's kinda hard to do because of precedence.
3+
// Instead, for now we just make sure not to suggest `if let let`.
4+
fn a() {
5+
if let x = 1 && i = 2 {}
6+
//~^ ERROR expected expression, found `let` statement
7+
//~| ERROR mismatched types
8+
}
9+
10+
fn main() {}

Diff for: tests/ui/expr/if/bad-if-let-suggestion-2.stderr

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error: expected expression, found `let` statement
2+
--> $DIR/bad-if-let-suggestion-2.rs:5:8
3+
|
4+
LL | if let x = 1 && i = 2 {}
5+
| ^^^^^^^^^
6+
|
7+
= note: only supported directly in conditions of `if` and `while` expressions
8+
help: you might have meant to continue the let-chain
9+
|
10+
LL | if let x = 1 && let i = 2 {}
11+
| +++
12+
help: you might have meant to compare for equality
13+
|
14+
LL | if let x = 1 && i == 2 {}
15+
| +
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/bad-if-let-suggestion-2.rs:5:8
19+
|
20+
LL | if let x = 1 && i = 2 {}
21+
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
22+
|
23+
help: you might have meant to compare for equality
24+
|
25+
LL | if let x = 1 && i == 2 {}
26+
| +
27+
28+
error: aborting due to 2 previous errors
29+
30+
For more information about this error, try `rustc --explain E0308`.

Diff for: tests/ui/expr/if/bad-if-let-suggestion.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
// FIXME(compiler-errors): This really should suggest `let` on the RHS of the
22
// `&&` operator, but that's kinda hard to do because of precedence.
33
// Instead, for now we just make sure not to suggest `if let let`.
4-
fn a() {
5-
if let x = 1 && i = 2 {}
6-
//~^ ERROR cannot find value `i` in this scope
7-
//~| ERROR mismatched types
8-
//~| ERROR expected expression, found `let` statement
9-
}
104

115
fn b() {
126
if (i + j) = i {}

Diff for: tests/ui/expr/if/bad-if-let-suggestion.stderr

+12-55
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,30 @@
1-
error: expected expression, found `let` statement
2-
--> $DIR/bad-if-let-suggestion.rs:5:8
3-
|
4-
LL | if let x = 1 && i = 2 {}
5-
| ^^^^^^^^^
6-
|
7-
= note: only supported directly in conditions of `if` and `while` expressions
8-
help: you might have meant to continue the let-chain
9-
|
10-
LL | if let x = 1 && let i = 2 {}
11-
| +++
12-
help: you might have meant to compare for equality
13-
|
14-
LL | if let x = 1 && i == 2 {}
15-
| +
16-
17-
error[E0425]: cannot find value `i` in this scope
18-
--> $DIR/bad-if-let-suggestion.rs:5:21
19-
|
20-
LL | if let x = 1 && i = 2 {}
21-
| ^ not found in this scope
22-
231
error[E0425]: cannot find value `i` in this scope
24-
--> $DIR/bad-if-let-suggestion.rs:12:9
2+
--> $DIR/bad-if-let-suggestion.rs:6:9
253
|
26-
LL | fn a() {
27-
| ------ similarly named function `a` defined here
28-
...
294
LL | if (i + j) = i {}
30-
| ^ help: a function with a similar name exists: `a`
5+
| ^ not found in this scope
316

327
error[E0425]: cannot find value `j` in this scope
33-
--> $DIR/bad-if-let-suggestion.rs:12:13
8+
--> $DIR/bad-if-let-suggestion.rs:6:13
349
|
35-
LL | fn a() {
36-
| ------ similarly named function `a` defined here
37-
...
3810
LL | if (i + j) = i {}
39-
| ^ help: a function with a similar name exists: `a`
11+
| ^ not found in this scope
4012

4113
error[E0425]: cannot find value `i` in this scope
42-
--> $DIR/bad-if-let-suggestion.rs:12:18
14+
--> $DIR/bad-if-let-suggestion.rs:6:18
4315
|
44-
LL | fn a() {
45-
| ------ similarly named function `a` defined here
46-
...
4716
LL | if (i + j) = i {}
48-
| ^ help: a function with a similar name exists: `a`
17+
| ^ not found in this scope
4918

5019
error[E0425]: cannot find value `x` in this scope
51-
--> $DIR/bad-if-let-suggestion.rs:19:8
20+
--> $DIR/bad-if-let-suggestion.rs:13:8
5221
|
53-
LL | fn a() {
54-
| ------ similarly named function `a` defined here
22+
LL | fn b() {
23+
| ------ similarly named function `b` defined here
5524
...
5625
LL | if x[0] = 1 {}
57-
| ^ help: a function with a similar name exists: `a`
58-
59-
error[E0308]: mismatched types
60-
--> $DIR/bad-if-let-suggestion.rs:5:8
61-
|
62-
LL | if let x = 1 && i = 2 {}
63-
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
64-
|
65-
help: you might have meant to compare for equality
66-
|
67-
LL | if let x = 1 && i == 2 {}
68-
| +
26+
| ^ help: a function with a similar name exists: `b`
6927

70-
error: aborting due to 7 previous errors
28+
error: aborting due to 4 previous errors
7129

72-
Some errors have detailed explanations: E0308, E0425.
73-
For more information about an error, try `rustc --explain E0308`.
30+
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)