Don't declare variables in ExprKind::Let in invalid positions
This commit is contained in:
parent
ec28ae9454
commit
d2d0f62f78
3 changed files with 51 additions and 1 deletions
|
|
@ -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);
|
||||
|
|
|
|||
14
tests/ui/destructuring-assignment/bad-let-in-destructure.rs
Normal file
14
tests/ui/destructuring-assignment/bad-let-in-destructure.rs
Normal 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
|
||||
}
|
||||
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue