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:
commit
dde825db46
46 changed files with 900 additions and 142 deletions
|
@ -605,9 +605,10 @@ impl<'tcx> Cx<'tcx> {
|
|||
},
|
||||
Err(err) => bug!("invalid loop id for continue: {}", err),
|
||||
},
|
||||
hir::ExprKind::Let(ref pat, ref expr, _) => {
|
||||
ExprKind::Let { expr: self.mirror_expr(expr), pat: self.pattern_from_hir(pat) }
|
||||
}
|
||||
hir::ExprKind::Let(let_expr) => ExprKind::Let {
|
||||
expr: self.mirror_expr(let_expr.init),
|
||||
pat: self.pattern_from_hir(let_expr.pat),
|
||||
},
|
||||
hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
|
||||
if_then_scope: region::Scope {
|
||||
id: then.hir_id.local_id,
|
||||
|
|
|
@ -64,7 +64,9 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
|
|||
intravisit::walk_expr(self, ex);
|
||||
match &ex.kind {
|
||||
hir::ExprKind::Match(scrut, arms, source) => self.check_match(scrut, arms, *source),
|
||||
hir::ExprKind::Let(pat, scrut, span) => self.check_let(pat, scrut, *span),
|
||||
hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => {
|
||||
self.check_let(pat, init, *span)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -148,9 +150,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) {
|
||||
fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, scrutinee: &hir::Expr<'_>, span: Span) {
|
||||
self.check_patterns(pat, Refutable);
|
||||
let mut cx = self.new_cx(expr.hir_id);
|
||||
let mut cx = self.new_cx(scrutinee.hir_id);
|
||||
let tpat = self.lower_pattern(&mut cx, pat, &mut false);
|
||||
check_let_reachability(&mut cx, pat.hir_id, tpat, span);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue