Implement typechecking if-let guards
This commit is contained in:
parent
77d80b22f1
commit
f9cc626028
2 changed files with 24 additions and 12 deletions
|
@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// FIXME(60707): Consider removing hack with principled solution.
|
// FIXME(60707): Consider removing hack with principled solution.
|
||||||
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
|
self.check_expr_has_type_or_error(scrut, self.tcx.types.bool, |_| {})
|
||||||
} else {
|
} else {
|
||||||
self.demand_scrutinee_type(arms, scrut)
|
self.demand_scrutinee_type(scrut, arms_contain_ref_bindings(arms), arms.is_empty())
|
||||||
};
|
};
|
||||||
|
|
||||||
// If there are no arms, that is a diverging match; a special case.
|
// If there are no arms, that is a diverging match; a special case.
|
||||||
|
@ -98,7 +98,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.diverges.set(Diverges::Maybe);
|
self.diverges.set(Diverges::Maybe);
|
||||||
match g {
|
match g {
|
||||||
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) => {
|
||||||
|
let scrutinee_ty = self.demand_scrutinee_type(
|
||||||
|
e,
|
||||||
|
pat.contains_explicit_ref_binding(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
self.check_pat_top(&pat, scrutinee_ty, None, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -450,8 +458,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
fn demand_scrutinee_type(
|
fn demand_scrutinee_type(
|
||||||
&self,
|
&self,
|
||||||
arms: &'tcx [hir::Arm<'tcx>],
|
|
||||||
scrut: &'tcx hir::Expr<'tcx>,
|
scrut: &'tcx hir::Expr<'tcx>,
|
||||||
|
contains_ref_bindings: Option<hir::Mutability>,
|
||||||
|
no_arms: bool,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
// Not entirely obvious: if matches may create ref bindings, we want to
|
// Not entirely obvious: if matches may create ref bindings, we want to
|
||||||
// use the *precise* type of the scrutinee, *not* some supertype, as
|
// use the *precise* type of the scrutinee, *not* some supertype, as
|
||||||
|
@ -505,17 +514,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// (once introduced) is populated by the time we get here.
|
// (once introduced) is populated by the time we get here.
|
||||||
//
|
//
|
||||||
// See #44848.
|
// See #44848.
|
||||||
let contains_ref_bindings = arms
|
|
||||||
.iter()
|
|
||||||
.filter_map(|a| a.pat.contains_explicit_ref_binding())
|
|
||||||
.max_by_key(|m| match *m {
|
|
||||||
hir::Mutability::Mut => 1,
|
|
||||||
hir::Mutability::Not => 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(m) = contains_ref_bindings {
|
if let Some(m) = contains_ref_bindings {
|
||||||
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
|
self.check_expr_with_needs(scrut, Needs::maybe_mut_place(m))
|
||||||
} else if arms.is_empty() {
|
} else if no_arms {
|
||||||
self.check_expr(scrut)
|
self.check_expr(scrut)
|
||||||
} else {
|
} else {
|
||||||
// ...but otherwise we want to use any supertype of the
|
// ...but otherwise we want to use any supertype of the
|
||||||
|
@ -546,3 +547,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option<hir::Mutability> {
|
||||||
|
arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m {
|
||||||
|
hir::Mutability::Mut => 1,
|
||||||
|
hir::Mutability::Not => 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -246,6 +246,10 @@ 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) => {
|
||||||
|
self.visit_pat(pat);
|
||||||
|
self.visit_expr(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scope_var_ids =
|
let mut scope_var_ids =
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue