Don't declare variables in ExprKind::Let in invalid positions

This commit is contained in:
Michael Goulet 2025-06-02 02:14:32 +00:00
parent ec28ae9454
commit d2d0f62f78
3 changed files with 51 additions and 1 deletions

View file

@ -4891,11 +4891,28 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
self.resolve_expr(e, Some(expr));
}
ExprKind::Let(ref pat, ref scrutinee, _, _) => {
ExprKind::Let(ref pat, ref scrutinee, _, Recovered::No) => {
self.visit_expr(scrutinee);
self.resolve_pattern_top(pat, PatternSource::Let);
}
ExprKind::Let(ref pat, ref scrutinee, _, Recovered::Yes(_)) => {
self.visit_expr(scrutinee);
// This is basically a tweaked, inlined `resolve_pattern_top`.
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
self.resolve_pattern(pat, PatternSource::Let, &mut bindings);
// We still collect the bindings in this `let` expression which is in
// an invalid position (and therefore shouldn't declare variables into
// its parent scope). To avoid unnecessary errors though, we do just
// reassign the resolutions to `Res::Err`.
for (_, bindings) in &mut bindings {
for (_, binding) in bindings {
*binding = Res::Err;
}
}
self.apply_pattern_bindings(bindings);
}
ExprKind::If(ref cond, ref then, ref opt_else) => {
self.with_rib(ValueNS, RibKind::Normal, |this| {
let old = this.diag_metadata.in_if_condition.replace(cond);

View file

@ -0,0 +1,14 @@
// Regression test for <https://github.com/rust-lang/rust/issues/141844>.
fn main() {
// The following expression gets desugared into something like:
// ```
// let (lhs,) = x; (let x = 1) = lhs;
// ```
// This used to ICE since we haven't yet declared the type for `x` when
// checking the first desugared statement, whose RHS resolved to `x` since
// in the AST, the `let` expression was visited first.
(let x = 1,) = x;
//~^ ERROR expected expression, found `let` statement
//~| ERROR invalid left-hand side of assignment
}

View file

@ -0,0 +1,19 @@
error: expected expression, found `let` statement
--> $DIR/bad-let-in-destructure.rs:10:4
|
LL | (let x = 1,) = x;
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
error[E0070]: invalid left-hand side of assignment
--> $DIR/bad-let-in-destructure.rs:10:16
|
LL | (let x = 1,) = x;
| --------- ^
| |
| cannot assign to this expression
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0070`.