1
Fork 0

use hir::Let in hir::Guard

This commit is contained in:
SparrowLii 2022-05-09 20:35:58 +08:00
parent 4799baa70d
commit 5251a80c0a
13 changed files with 41 additions and 45 deletions

View file

@ -505,8 +505,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
let pat = self.lower_pat(&arm.pat); let pat = self.lower_pat(&arm.pat);
let guard = arm.guard.as_ref().map(|cond| { let guard = arm.guard.as_ref().map(|cond| {
if let ExprKind::Let(ref pat, ref scrutinee, _) = cond.kind { if let ExprKind::Let(ref pat, ref scrutinee, span) = cond.kind {
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee)) hir::Guard::IfLet(self.arena.alloc(hir::Let {
hir_id: self.next_id(),
span: self.lower_span(span),
pat: self.lower_pat(pat),
ty: None,
init: self.lower_expr(scrutinee),
}))
} else { } else {
hir::Guard::If(self.lower_expr(cond)) hir::Guard::If(self.lower_expr(cond))
} }

View file

@ -1312,8 +1312,7 @@ pub struct Let<'hir> {
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub enum Guard<'hir> { pub enum Guard<'hir> {
If(&'hir Expr<'hir>), If(&'hir Expr<'hir>),
// FIXME use hir::Let for this. IfLet(&'hir Let<'hir>),
IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
} }
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]

View file

@ -1233,9 +1233,8 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
if let Some(ref g) = arm.guard { if let Some(ref g) = arm.guard {
match g { match g {
Guard::If(ref e) => visitor.visit_expr(e), Guard::If(ref e) => visitor.visit_expr(e),
Guard::IfLet(ref pat, ref e) => { Guard::IfLet(ref l) => {
visitor.visit_pat(pat); visitor.visit_let_expr(l);
visitor.visit_expr(e);
} }
} }
} }

View file

@ -1915,14 +1915,9 @@ impl<'a> State<'a> {
self.print_expr(&e); self.print_expr(&e);
self.space(); self.space();
} }
hir::Guard::IfLet(pat, e) => { hir::Guard::IfLet(hir::Let { pat, ty, init, .. }) => {
self.word_nbsp("if"); self.word_nbsp("if");
self.word_nbsp("let"); self.print_let(pat, *ty, init);
self.print_pat(&pat);
self.space();
self.word_space("=");
self.print_expr(&e);
self.space();
} }
} }
} }

View file

@ -798,8 +798,8 @@ impl<'tcx> Cx<'tcx> {
pattern: self.pattern_from_hir(&arm.pat), pattern: self.pattern_from_hir(&arm.pat),
guard: arm.guard.as_ref().map(|g| match g { guard: arm.guard.as_ref().map(|g| match g {
hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)), hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
hir::Guard::IfLet(ref pat, ref e) => { hir::Guard::IfLet(ref l) => {
Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr(e)) Guard::IfLet(self.pattern_from_hir(l.pat), self.mirror_expr(l.init))
} }
}), }),
body: self.mirror_expr(arm.body), body: self.mirror_expr(arm.body),

View file

@ -173,10 +173,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
for arm in hir_arms { for arm in hir_arms {
// Check the arm for some things unrelated to exhaustiveness. // Check the arm for some things unrelated to exhaustiveness.
self.check_patterns(&arm.pat, Refutable); self.check_patterns(&arm.pat, Refutable);
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard { if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
self.check_patterns(pat, Refutable); self.check_patterns(let_expr.pat, Refutable);
let tpat = self.lower_pattern(&mut cx, pat, &mut false); let tpat = self.lower_pattern(&mut cx, let_expr.pat, &mut false);
self.check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span()); self.check_let_reachability(&mut cx, let_expr.pat.hir_id, tpat, tpat.span());
} }
} }
@ -1108,9 +1108,9 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> L
match parent_node { match parent_node {
hir::Node::Arm(hir::Arm { hir::Node::Arm(hir::Arm {
guard: Some(hir::Guard::IfLet(&hir::Pat { hir_id, .. }, _)), guard: Some(hir::Guard::IfLet(&hir::Let { pat: hir::Pat { hir_id, .. }, .. })),
.. ..
}) if Some(hir_id) == pat_id => { }) if Some(*hir_id) == pat_id => {
return LetSource::IfLetGuard; return LetSource::IfLetGuard;
} }
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => { hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {

View file

@ -373,8 +373,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
self.add_from_pat(&arm.pat); self.add_from_pat(&arm.pat);
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard { if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
self.add_from_pat(pat); self.add_from_pat(let_expr.pat);
} }
intravisit::walk_arm(self, arm); intravisit::walk_arm(self, arm);
} }
@ -914,9 +914,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g { let guard_succ = arm.guard.as_ref().map_or(body_succ, |g| match g {
hir::Guard::If(e) => self.propagate_through_expr(e, body_succ), hir::Guard::If(e) => self.propagate_through_expr(e, body_succ),
hir::Guard::IfLet(pat, e) => { hir::Guard::IfLet(let_expr) => {
let let_bind = self.define_bindings_in_pat(pat, body_succ); let let_bind = self.define_bindings_in_pat(let_expr.pat, body_succ);
self.propagate_through_expr(e, let_bind) self.propagate_through_expr(let_expr.init, let_bind)
} }
}); });
let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ); let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);

View file

@ -82,13 +82,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Guard::If(e) => { hir::Guard::If(e) => {
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {}); self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
} }
hir::Guard::IfLet(pat, e) => { hir::Guard::IfLet(l) => {
let scrutinee_ty = self.demand_scrutinee_type( self.check_expr_let(l);
e,
pat.contains_explicit_ref_binding(),
false,
);
self.check_pat_top(&pat, scrutinee_ty, None, true);
} }
}; };
} }

View file

@ -1064,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { pub(super) fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> {
// for let statements, this is done in check_stmt // for let statements, this is done in check_stmt
let init = let_expr.init; let init = let_expr.init;
self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");

View file

@ -298,9 +298,8 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
Guard::If(ref e) => { Guard::If(ref e) => {
self.visit_expr(e); self.visit_expr(e);
} }
Guard::IfLet(ref pat, ref e) => { Guard::IfLet(ref l) => {
self.visit_pat(pat); self.visit_let_expr(l);
self.visit_expr(e);
} }
} }

View file

@ -344,9 +344,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
// B -> C and E -> F are added implicitly due to the traversal order. // B -> C and E -> F are added implicitly due to the traversal order.
match guard { match guard {
Some(Guard::If(expr)) => self.visit_expr(expr), Some(Guard::If(expr)) => self.visit_expr(expr),
Some(Guard::IfLet(pat, expr)) => { Some(Guard::IfLet(let_expr)) => {
self.visit_pat(pat); self.visit_let_expr(let_expr);
self.visit_expr(expr);
} }
None => (), None => (),
} }

View file

@ -625,8 +625,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
if let Some(hir::Guard::If(e)) = arm.guard { if let Some(hir::Guard::If(e)) = arm.guard {
self.consume_expr(e) self.consume_expr(e)
} else if let Some(hir::Guard::IfLet(_, ref e)) = arm.guard { } else if let Some(hir::Guard::IfLet(ref l)) = arm.guard {
self.consume_expr(e) self.consume_expr(l.init)
} }
self.consume_expr(arm.body); self.consume_expr(arm.body);

View file

@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/typeck.rs:9:22 --> $DIR/typeck.rs:9:22
| |
LL | Ok(x) if let Err(_) = x => {}, LL | Ok(x) if let Err(_) = x => {},
| ^^^^^^ expected enum `Option`, found enum `Result` | ^^^^^^ - this expression has type `Option<bool>`
| |
| expected enum `Option`, found enum `Result`
| |
= note: expected enum `Option<bool>` = note: expected enum `Option<bool>`
found enum `Result<_, _>` found enum `Result<_, _>`
@ -11,7 +13,9 @@ error[E0308]: mismatched types
--> $DIR/typeck.rs:11:22 --> $DIR/typeck.rs:11:22
| |
LL | Ok(x) if let 0 = x => {}, LL | Ok(x) if let 0 = x => {},
| ^ expected enum `Option`, found integer | ^ - this expression has type `Option<bool>`
| |
| expected enum `Option`, found integer
| |
= note: expected enum `Option<bool>` = note: expected enum `Option<bool>`
found type `{integer}` found type `{integer}`