Skip to content

Commit 7a62eed

Browse files
authored
Unrolled build for #141876
Rollup merge of #141876 - compiler-errors:missing-let-ty, r=SparrowLii Don't declare variables in `ExprKind::Let` in invalid positions Handle `let` expressions in invalid positions specially during resolve in order to avoid making destructuring-assignment expressions that reference (invalid) variables that have not yet been delcared yet. See further explanation in test and comment in the source. Fixes #141844
2 parents b17dba4 + 4a803d2 commit 7a62eed

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2370,6 +2370,10 @@ impl Expr<'_> {
23702370
// Lang item paths cannot currently be local variables or statics.
23712371
ExprKind::Path(QPath::LangItem(..)) => false,
23722372

2373+
// Suppress errors for bad expressions.
2374+
ExprKind::Err(_guar)
2375+
| ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true,
2376+
23732377
// Partially qualified paths in expressions can only legally
23742378
// refer to associated items which are always rvalues.
23752379
ExprKind::Path(QPath::TypeRelative(..))
@@ -2401,8 +2405,7 @@ impl Expr<'_> {
24012405
| ExprKind::Binary(..)
24022406
| ExprKind::Yield(..)
24032407
| ExprKind::Cast(..)
2404-
| ExprKind::DropTemps(..)
2405-
| ExprKind::Err(_) => false,
2408+
| ExprKind::DropTemps(..) => false,
24062409
}
24072410
}
24082411

compiler/rustc_resolve/src/late.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4898,11 +4898,28 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
48984898
self.resolve_expr(e, Some(expr));
48994899
}
49004900

4901-
ExprKind::Let(ref pat, ref scrutinee, _, _) => {
4901+
ExprKind::Let(ref pat, ref scrutinee, _, Recovered::No) => {
49024902
self.visit_expr(scrutinee);
49034903
self.resolve_pattern_top(pat, PatternSource::Let);
49044904
}
49054905

4906+
ExprKind::Let(ref pat, ref scrutinee, _, Recovered::Yes(_)) => {
4907+
self.visit_expr(scrutinee);
4908+
// This is basically a tweaked, inlined `resolve_pattern_top`.
4909+
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
4910+
self.resolve_pattern(pat, PatternSource::Let, &mut bindings);
4911+
// We still collect the bindings in this `let` expression which is in
4912+
// an invalid position (and therefore shouldn't declare variables into
4913+
// its parent scope). To avoid unnecessary errors though, we do just
4914+
// reassign the resolutions to `Res::Err`.
4915+
for (_, bindings) in &mut bindings {
4916+
for (_, binding) in bindings {
4917+
*binding = Res::Err;
4918+
}
4919+
}
4920+
self.apply_pattern_bindings(bindings);
4921+
}
4922+
49064923
ExprKind::If(ref cond, ref then, ref opt_else) => {
49074924
self.with_rib(ValueNS, RibKind::Normal, |this| {
49084925
let old = this.diag_metadata.in_if_condition.replace(cond);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/141844>.
2+
3+
fn main() {
4+
// The following expression gets desugared into something like:
5+
// ```
6+
// let (lhs,) = x; (let x = 1) = lhs;
7+
// ```
8+
// This used to ICE since we haven't yet declared the type for `x` when
9+
// checking the first desugared statement, whose RHS resolved to `x` since
10+
// in the AST, the `let` expression was visited first.
11+
(let x = 1,) = x;
12+
//~^ ERROR expected expression, found `let` statement
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: expected expression, found `let` statement
2+
--> $DIR/bad-let-in-destructure.rs:11:4
3+
|
4+
LL | (let x = 1,) = x;
5+
| ^^^
6+
|
7+
= note: only supported directly in conditions of `if` and `while` expressions
8+
9+
error: aborting due to 1 previous error
10+

0 commit comments

Comments
 (0)