1
Fork 0

Auto merge of #89841 - cormacrelf:let-else-typed, r=nagisa

Implement let-else type annotations natively

Tracking issue: #87335

Fixes #89688, fixes #89807, edit: fixes  #89960 as well

As explained in https://github.com/rust-lang/rust/issues/89688#issuecomment-940405082, the previous desugaring moved the let-else scrutinee into a dummy variable, which meant if you wanted to refer to it again in the else block, it had moved.

This introduces a new hir type, ~~`hir::LetExpr`~~ `hir::Let`, which takes over all the fields of `hir::ExprKind::Let(...)` and adds an optional type annotation. The `hir::Let` is then treated like a `hir::Local` when type checking a function body, specifically:

* `GatherLocalsVisitor` overrides a new `Visitor::visit_let_expr` and does pretty much exactly what it does for `visit_local`, assigning a local type to the `hir::Let` ~~(they could be deduplicated but they are right next to each other, so at least we know they're the same)~~
* It reuses the code in `check_decl_local` to typecheck the `hir::Let`, simply returning 'bool' for the expression type after doing that.

* ~~`FnCtxt::check_expr_let` passes this local type in to `demand_scrutinee_type`, and then imitates check_decl_local's pattern checking~~
* ~~`demand_scrutinee_type` (the blindest change for me, please give this extra scrutiny) uses this local type instead of of creating a new one~~
    * ~~Just realised the `check_expr_with_needs` was passing NoExpectation further down, need to pass the type there too. And apparently this Expectation API already exists.~~

Some other misc notes:

* ~~Is the clippy code supposed to be autoformatted? I tried not to give huge diffs but maybe some rustfmt changes simply haven't hit it yet.~~
* in `rustc_ast_lowering/src/block.rs`, I noticed some existing `self.alias_attrs()` calls in `LoweringContext::lower_stmts` seem to be copying attributes from the lowered locals/etc to the statements. Is that right? I'm new at this, I don't know.
This commit is contained in:
bors 2021-12-17 22:12:34 +00:00
commit dde825db46
46 changed files with 900 additions and 142 deletions

View file

@ -429,8 +429,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Let(ref pat, ..) => {
self.add_from_pat(pat);
hir::ExprKind::Let(let_expr) => {
self.add_from_pat(let_expr.pat);
intravisit::walk_expr(self, expr);
}
@ -856,9 +856,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
})
}
hir::ExprKind::Let(ref pat, ref scrutinee, _) => {
let succ = self.propagate_through_expr(scrutinee, succ);
self.define_bindings_in_pat(pat, succ)
hir::ExprKind::Let(let_expr) => {
let succ = self.propagate_through_expr(let_expr.init, succ);
self.define_bindings_in_pat(let_expr.pat, succ)
}
// Note that labels have been resolved, so we don't need to look
@ -1401,8 +1401,8 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
}
}
hir::ExprKind::Let(ref pat, ..) => {
this.check_unused_vars_in_pat(pat, None, |_, _, _, _| {});
hir::ExprKind::Let(let_expr) => {
this.check_unused_vars_in_pat(let_expr.pat, None, |_, _, _, _| {});
}
// no correctness conditions related to liveness