]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir-ty/src/infer.rs
Auto merge of #13223 - lowr:fix/hir-proj-normalization, r=flodiebold
[rust.git] / crates / hir-ty / src / infer.rs
index 5df48e5fdcbaf40502d0aa11f3b9bd666132b771..e37763e8ea7f03075b5c19349d4c7d5ff1baf69d 100644 (file)
@@ -182,7 +182,7 @@ fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> {
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub enum InferenceDiagnostic {
     NoSuchField { expr: ExprId },
-    BreakOutsideOfLoop { expr: ExprId },
+    BreakOutsideOfLoop { expr: ExprId, is_break: bool },
     MismatchedArgCount { call_expr: ExprId, expected: usize, found: usize },
 }
 
@@ -418,18 +418,45 @@ pub(crate) struct InferenceContext<'a> {
 
 #[derive(Clone, Debug)]
 struct BreakableContext {
+    /// Whether this context contains at least one break expression.
     may_break: bool,
+    /// The coercion target of the context.
     coerce: CoerceMany,
+    /// The optional label of the context.
     label: Option<name::Name>,
+    kind: BreakableKind,
+}
+
+#[derive(Clone, Debug)]
+enum BreakableKind {
+    Block,
+    Loop,
+    /// A border is something like an async block, closure etc. Anything that prevents
+    /// breaking/continuing through
+    Border,
 }
 
 fn find_breakable<'c>(
     ctxs: &'c mut [BreakableContext],
     label: Option<&name::Name>,
+) -> Option<&'c mut BreakableContext> {
+    let mut ctxs = ctxs
+        .iter_mut()
+        .rev()
+        .take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));
+    match label {
+        Some(_) => ctxs.find(|ctx| ctx.label.as_ref() == label),
+        None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),
+    }
+}
+
+fn find_continuable<'c>(
+    ctxs: &'c mut [BreakableContext],
+    label: Option<&name::Name>,
 ) -> Option<&'c mut BreakableContext> {
     match label {
-        Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label),
-        None => ctxs.last_mut(),
+        Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
+        None => find_breakable(ctxs, label),
     }
 }
 
@@ -646,10 +673,6 @@ fn insert_type_vars(&mut self, ty: Ty) -> Ty {
         )
     }
 
-    fn resolve_obligations_as_possible(&mut self) {
-        self.table.resolve_obligations_as_possible();
-    }
-
     fn push_obligation(&mut self, o: DomainGoal) {
         self.table.register_obligation(o.cast(Interner));
     }
@@ -669,7 +692,6 @@ fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
     }
 
     fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
-        self.resolve_obligations_as_possible();
         self.table.resolve_ty_shallow(ty)
     }