Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/expr.rs')
-rw-r--r--crates/hir-ty/src/infer/expr.rs49
1 files changed, 34 insertions, 15 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 09d8320252..f3f4ee65bb 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -23,7 +23,7 @@ use syntax::ast::RangeOp;
use crate::{
autoderef::{self, Autoderef},
consteval,
- infer::coerce::CoerceMany,
+ infer::{coerce::CoerceMany, find_continuable, BreakableKind},
lower::{
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
},
@@ -120,15 +120,19 @@ impl<'a> InferenceContext<'a> {
let ty = match label {
Some(_) => {
let break_ty = self.table.new_type_var();
- let (breaks, ty) =
- self.with_breakable_ctx(break_ty.clone(), *label, |this| {
+ let (breaks, ty) = self.with_breakable_ctx(
+ BreakableKind::Block,
+ break_ty.clone(),
+ *label,
+ |this| {
this.infer_block(
tgt_expr,
statements,
*tail,
&Expectation::has_type(break_ty),
)
- });
+ },
+ );
breaks.unwrap_or(ty)
}
None => self.infer_block(tgt_expr, statements, *tail, expected),
@@ -136,9 +140,17 @@ impl<'a> InferenceContext<'a> {
self.resolver = old_resolver;
ty
}
- Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
+ Expr::Unsafe { body } => self.infer_expr(*body, expected),
+ Expr::Const { body } => {
+ self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
+ this.infer_expr(*body, expected)
+ })
+ .1
+ }
Expr::TryBlock { body } => {
- let _inner = self.infer_expr(*body, expected);
+ self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
+ let _inner = this.infer_expr(*body, expected);
+ });
// FIXME should be std::result::Result<{inner}, _>
self.err_ty()
}
@@ -147,7 +159,10 @@ impl<'a> InferenceContext<'a> {
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
- let inner_ty = self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
+ let (_, inner_ty) =
+ self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
+ this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty))
+ });
self.diverges = prev_diverges;
self.return_ty = prev_ret_ty;
@@ -161,9 +176,10 @@ impl<'a> InferenceContext<'a> {
}
&Expr::Loop { body, label } => {
let ty = self.table.new_type_var();
- let (breaks, ()) = self.with_breakable_ctx(ty, label, |this| {
- this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
- });
+ let (breaks, ()) =
+ self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
+ this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
+ });
match breaks {
Some(breaks) => {
@@ -174,7 +190,7 @@ impl<'a> InferenceContext<'a> {
}
}
&Expr::While { condition, body, label } => {
- self.with_breakable_ctx(self.err_ty(), label, |this| {
+ self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
this.infer_expr(
condition,
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
@@ -192,7 +208,7 @@ impl<'a> InferenceContext<'a> {
self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
self.infer_pat(pat, &pat_ty, BindingMode::default());
- self.with_breakable_ctx(self.err_ty(), label, |this| {
+ self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
});
@@ -251,7 +267,9 @@ impl<'a> InferenceContext<'a> {
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
- self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
+ self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
+ this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
+ });
self.diverges = prev_diverges;
self.return_ty = prev_ret_ty;
@@ -355,7 +373,7 @@ impl<'a> InferenceContext<'a> {
self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or_else(|| self.err_ty())
}
Expr::Continue { label } => {
- if let None = find_breakable(&mut self.breakables, label.as_ref()) {
+ if let None = find_continuable(&mut self.breakables, label.as_ref()) {
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
expr: tgt_expr,
is_break: false,
@@ -1466,13 +1484,14 @@ impl<'a> InferenceContext<'a> {
fn with_breakable_ctx<T>(
&mut self,
+ kind: BreakableKind,
ty: Ty,
label: Option<LabelId>,
cb: impl FnOnce(&mut Self) -> T,
) -> (Option<Ty>, T) {
self.breakables.push({
let label = label.map(|label| self.body[label].name.clone());
- BreakableContext { may_break: false, coerce: CoerceMany::new(ty), label }
+ BreakableContext { kind, may_break: false, coerce: CoerceMany::new(ty), label }
});
let res = cb(self);
let ctx = self.breakables.pop().expect("breakable stack broken");