diff options
| author | bors <bors@rust-lang.org> | 2022-09-03 15:33:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-03 15:33:21 +0000 |
| commit | 8ddb8b7e8ed9fd99f580503b5ee94e8452d57f5e (patch) | |
| tree | a1022512826d9f9c93e9ae736579742b2f606f2d | |
| parent | afa374e58e0bce33b666ee83baa24f16cb486a75 (diff) | |
| parent | 020f6895e51c54be77cb2568cd27e93e04c27851 (diff) | |
Auto merge of #13183 - Veykril:break-break, r=Veykril
Fix nested break expressions, expecting unknown types
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 43 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/simple.rs | 14 |
2 files changed, 35 insertions, 22 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index f3f4ee65bb2..2d04a864a2c 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -382,36 +382,35 @@ impl<'a> InferenceContext<'a> { TyKind::Never.intern(Interner) } Expr::Break { expr, label } => { - let mut coerce = match find_breakable(&mut self.breakables, label.as_ref()) { - Some(ctxt) => { - // avoiding the borrowck - mem::replace( - &mut ctxt.coerce, - CoerceMany::new(self.result.standard_types.unknown.clone()), - ) - } - None => CoerceMany::new(self.result.standard_types.unknown.clone()), - }; - let val_ty = if let Some(expr) = *expr { self.infer_expr(expr, &Expectation::none()) } else { TyBuilder::unit() }; - // FIXME: create a synthetic `()` during lowering so we have something to refer to here? - coerce.coerce(self, *expr, &val_ty); + match find_breakable(&mut self.breakables, label.as_ref()) { + Some(ctxt) => { + // avoiding the borrowck + let mut coerce = mem::replace( + &mut ctxt.coerce, + CoerceMany::new(self.result.standard_types.unknown.clone()), + ); - if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { - ctxt.coerce = coerce; - ctxt.may_break = true; - } else { - self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { - expr: tgt_expr, - is_break: true, - }); - }; + // FIXME: create a synthetic `()` during lowering so we have something to refer to here? + coerce.coerce(self, *expr, &val_ty); + let ctxt = find_breakable(&mut self.breakables, label.as_ref()) + .expect("breakable stack changed during coercion"); + ctxt.coerce = coerce; + ctxt.may_break = true; + } + None => { + self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { + expr: tgt_expr, + is_break: true, + }); + } + } TyKind::Never.intern(Interner) } Expr::Return { expr } => { diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 707e9e84506..4ea103e5d9e 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -3069,3 +3069,17 @@ fn main() { "#, ); } + +#[test] +fn nested_break() { + check_no_mismatches( + r#" +fn func() { + let int = loop { + break 0; + break (break 0); + }; +} + "#, + ); +} |
