Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/expr_store.rs2
-rw-r--r--crates/hir-def/src/expr_store/lower.rs19
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs2
-rw-r--r--crates/hir-def/src/expr_store/scope.rs2
-rw-r--r--crates/hir-def/src/hir.rs12
-rw-r--r--crates/hir-ty/src/infer/expr.rs113
-rw-r--r--crates/hir-ty/src/infer/mutability.rs2
-rw-r--r--crates/hir-ty/src/mir/lower.rs2
-rw-r--r--crates/hir-ty/src/tests/macros.rs6
-rw-r--r--crates/hir-ty/src/tests/never_type.rs38
-rw-r--r--crates/hir-ty/src/tests/patterns.rs2
-rw-r--r--crates/hir-ty/src/tests/regression.rs36
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs2
-rw-r--r--crates/hir-ty/src/tests/simple.rs56
-rw-r--r--crates/hir-ty/src/tests/traits.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs3
16 files changed, 181 insertions, 126 deletions
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index fa33a00a80..8768413ce5 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -720,7 +720,7 @@ impl ExpressionStore {
}
visitor.on_expr_opt(*tail);
}
- Expr::Loop { body, label: _ } => visitor.on_expr(*body),
+ Expr::Loop { body, label: _, source: _ } => visitor.on_expr(*body),
Expr::Call { callee, args } => {
visitor.on_expr(*callee);
visitor.on_exprs(args);
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 21b5b19986..242a0b0b4f 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -49,9 +49,9 @@ use crate::{
},
hir::{
Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
- CoroutineKind, CoroutineSource, Expr, ExprId, Item, Label, LabelId, Literal, MatchArm,
- Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread, Statement,
- generics::GenericParams,
+ CoroutineKind, CoroutineSource, Expr, ExprId, Item, Label, LabelId, Literal, LoopSource,
+ MatchArm, Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, RecordSpread,
+ Statement, generics::GenericParams,
},
item_scope::BuiltinShadowMode,
item_tree::FieldsShape,
@@ -1351,7 +1351,7 @@ impl<'db> ExprCollector<'db> {
(self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
});
let body = self.collect_labelled_block_opt(label, e.loop_body());
- self.alloc_expr(Expr::Loop { body, label: label.map(|it| it.1) }, syntax_ptr)
+ self.alloc_expr(Expr::Loop { body, label: label.map(|it| it.1), source: LoopSource::Loop }, syntax_ptr)
}
ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e),
ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
@@ -2133,7 +2133,10 @@ impl<'db> ExprCollector<'db> {
Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
syntax_ptr,
);
- self.alloc_expr(Expr::Loop { body: if_expr, label: label.map(|it| it.1) }, syntax_ptr)
+ self.alloc_expr(
+ Expr::Loop { body: if_expr, label: label.map(|it| it.1), source: LoopSource::While },
+ syntax_ptr,
+ )
}
/// Desugar `ast::ForExpr` from: `[opt_ident]: for <pat> in <head> <body>` into:
@@ -2215,7 +2218,11 @@ impl<'db> ExprCollector<'db> {
syntax_ptr,
);
let loop_outer = self.alloc_expr_desugared_with_ptr(
- Expr::Loop { body: loop_inner, label: label.map(|it| it.1) },
+ Expr::Loop {
+ body: loop_inner,
+ label: label.map(|it| it.1),
+ source: LoopSource::ForLoop,
+ },
syntax_ptr,
);
let iter_binding =
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 35e3fc44c3..293adfc9bd 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -567,7 +567,7 @@ impl Printer<'_> {
w!(self, " = ");
self.print_expr_in(prec, *expr);
}
- Expr::Loop { body, label } => {
+ Expr::Loop { body, label, source: _ } => {
if let Some(lbl) = label {
w!(self, "{}: ", self.store[*lbl].name.display(self.db, self.edition));
}
diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs
index ddb8285137..7a2c8dc3ff 100644
--- a/crates/hir-def/src/expr_store/scope.rs
+++ b/crates/hir-def/src/expr_store/scope.rs
@@ -350,7 +350,7 @@ fn compute_expr_scopes(
Expr::Unsafe { id, statements, tail } => {
handle_block(*id, statements, *tail, None, scopes, scope, const_scope);
}
- Expr::Loop { body: body_expr, label } => {
+ Expr::Loop { body: body_expr, label, source: _ } => {
let mut scope = scopes.new_labeled_scope(*scope, make_label(*label));
compute_expr_scopes(scopes, *body_expr, &mut scope, const_scope);
}
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index 4c8d835ad7..2f7724c72e 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -224,6 +224,7 @@ pub enum Expr {
Loop {
body: ExprId,
label: Option<LabelId>,
+ source: LoopSource,
},
Call {
callee: ExprId,
@@ -389,6 +390,17 @@ impl Expr {
}
}
+/// The loop type that yielded an `Expr::Loop`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum LoopSource {
+ /// A `loop { .. }` loop.
+ Loop,
+ /// A `while _ { .. }` loop.
+ While,
+ /// A `for _ in _ { .. }` loop.
+ ForLoop,
+}
+
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OffsetOf {
pub container: TypeRefId,
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index c7562567ef..75e6440334 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -8,7 +8,8 @@ use hir_def::{
expr_store::path::{GenericArgs as HirGenericArgs, Path},
hir::{
Array, AsmOperand, AsmOptions, BinaryOp, BindingAnnotation, Expr, ExprId, ExprOrPatId,
- InlineAsmKind, LabelId, Pat, PatId, RecordLitField, RecordSpread, Statement, UnaryOp,
+ InlineAsmKind, LabelId, LoopSource, Pat, PatId, RecordLitField, RecordSpread, Statement,
+ UnaryOp,
},
resolver::ValueNs,
signatures::VariantFields,
@@ -401,24 +402,29 @@ impl<'db> InferenceContext<'_, 'db> {
})
.1
}
- &Expr::Loop { body, label } => {
- let ty = expected.coercion_target_type(&mut self.table, tgt_expr.into());
+ &Expr::Loop { body, label, source } => {
+ let coerce = match source {
+ // you can only use break with a value from a normal `loop { }`
+ LoopSource::Loop => {
+ Some(expected.coercion_target_type(&mut self.table, body.into()))
+ }
+ LoopSource::While | LoopSource::ForLoop => None,
+ };
let (breaks, ()) =
- self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| {
- this.infer_expr(
+ self.with_breakable_ctx(BreakableKind::Loop, coerce, label, |this| {
+ this.infer_expr_suptype_coerce_never(
body,
&Expectation::HasType(this.types.types.unit),
ExprIsRead::Yes,
);
});
- match breaks {
- Some(breaks) => {
- self.diverges = Diverges::Maybe;
- breaks
- }
- None => self.types.types.never,
+ if breaks.may_break {
+ self.diverges = Diverges::Maybe;
+ } else {
+ self.diverges = Diverges::Always;
}
+ breaks.coerce.map(|c| c.complete(self)).unwrap_or(self.types.types.unit)
}
Expr::Closure { body, args, ret_type, arg_types, closure_kind, capture_by: _ } => self
.infer_closure(
@@ -1499,10 +1505,11 @@ impl<'db> InferenceContext<'_, 'db> {
label: Option<LabelId>,
expected: &Expectation<'db>,
) -> Ty<'db> {
+ let prev_diverges = self.diverges;
let coerce_ty = expected.coercion_target_type(&mut self.table, expr.into());
let g = self.resolver.update_to_inner_scope(self.db, self.store_owner, expr);
- let (break_ty, ty) =
+ let (ctxt, tail_expr_ty) =
self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty), label, |this| {
for stmt in statements {
match stmt {
@@ -1570,42 +1577,54 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
- // FIXME: This should make use of the breakable CoerceMany
- if let Some(expr) = tail {
- this.infer_expr_coerce(expr, expected, ExprIsRead::Yes)
- } else {
- // Citing rustc: if there is no explicit tail expression,
- // that is typically equivalent to a tail expression
- // of `()` -- except if the block diverges. In that
- // case, there is no value supplied from the tail
- // expression (assuming there are no other breaks,
- // this implies that the type of the block will be
- // `!`).
- if this.diverges.is_always() {
- // we don't even make an attempt at coercion
- this.table.new_maybe_never_var(expr.into())
- } else if let Some(t) = expected.only_has_type(&mut this.table) {
- if this
- .coerce(
- expr,
- this.types.types.unit,
- t,
- AllowTwoPhase::No,
- ExprIsRead::Yes,
- )
- .is_err()
- {
- this.emit_type_mismatch(expr.into(), t, this.types.types.unit);
- }
- t
- } else {
- this.types.types.unit
- }
- }
+ // check the tail expression **without** holding the
+ // `enclosing_breakables` lock below.
+ tail.map(|expr| (expr, this.infer_expr_inner(expr, expected, ExprIsRead::Yes)))
});
+
+ let mut coerce = ctxt.coerce.unwrap();
+ if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
+ let cause = ObligationCause::new(tail_expr);
+ coerce.coerce_inner(
+ self,
+ &cause,
+ tail_expr,
+ tail_expr_ty,
+ false,
+ false,
+ ExprIsRead::Yes,
+ );
+ } else {
+ // Subtle: if there is no explicit tail expression,
+ // that is typically equivalent to a tail expression
+ // of `()` -- except if the block diverges. In that
+ // case, there is no value supplied from the tail
+ // expression (assuming there are no other breaks,
+ // this implies that the type of the block will be
+ // `!`).
+ //
+ // #41425 -- label the implicit `()` as being the
+ // "found type" here, rather than the "expected type".
+ if !self.diverges.is_always() {
+ coerce.coerce_forced_unit(
+ self,
+ expr,
+ &ObligationCause::new(expr),
+ false,
+ ExprIsRead::Yes,
+ );
+ }
+ }
+
+ if ctxt.may_break {
+ // If we can break from the block, then the block's exit is always reachable
+ // (... as long as the entry is reachable) - regardless of the tail of the block.
+ self.diverges = prev_diverges;
+ }
+
self.resolver.reset_to_guard(g);
- break_ty.unwrap_or(ty)
+ coerce.complete(self)
}
fn lookup_field(
@@ -2178,13 +2197,13 @@ impl<'db> InferenceContext<'_, 'db> {
ty: Option<Ty<'db>>,
label: Option<LabelId>,
cb: impl FnOnce(&mut Self) -> T,
- ) -> (Option<Ty<'db>>, T) {
+ ) -> (BreakableContext<'db>, T) {
self.breakables.push({
BreakableContext { kind, may_break: false, coerce: ty.map(CoerceMany::new), label }
});
let res = cb(self);
let ctx = self.breakables.pop().expect("breakable stack broken");
- (if ctx.may_break { ctx.coerce.map(|ctx| ctx.complete(self)) } else { None }, res)
+ (ctx, res)
}
}
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index c3b532638f..483f54a227 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -160,7 +160,7 @@ impl<'db> InferenceContext<'_, 'db> {
| Expr::Range { rhs: Some(expr), lhs: None, range_type: _ }
| Expr::Await { expr }
| Expr::Box { expr }
- | Expr::Loop { body: expr, label: _ }
+ | Expr::Loop { body: expr, label: _, source: _ }
| Expr::Cast { expr, type_ref: _ } => {
self.infer_mut_expr(*expr, Mutability::Not);
}
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 68612c2ce2..394cac8065 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -669,7 +669,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
self.lower_block_to_place(statements, current, *tail, place, expr_id.into())
}
}
- Expr::Loop { body, label } => {
+ Expr::Loop { body, label, source: _ } => {
self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
let scope = this.push_drop_scope();
if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? {
diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index f81028c174..c0da6cfd30 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -194,7 +194,7 @@ fn expr_macro_def_expanded_in_various_places() {
!0..6 '1isize': isize
!0..6 '1isize': isize
!0..6 '1isize': isize
- 39..442 '{ ...!(); }': {unknown}
+ 39..442 '{ ...!(); }': !
73..94 'spam!(...am!())': {unknown}
100..119 'for _ ...!() {}': !
100..119 'for _ ...!() {}': {unknown}
@@ -288,7 +288,7 @@ fn expr_macro_rules_expanded_in_various_places() {
!0..6 '1isize': isize
!0..6 '1isize': isize
!0..6 '1isize': isize
- 53..456 '{ ...!(); }': {unknown}
+ 53..456 '{ ...!(); }': !
87..108 'spam!(...am!())': {unknown}
114..133 'for _ ...!() {}': !
114..133 'for _ ...!() {}': {unknown}
@@ -1493,7 +1493,7 @@ fn main() {
!0..136 'builti...tack))': ()
!0..449 'builti...urn),)': !
10..1236 '{ ... } }': ()
- 16..1234 'unsafe... }': ()
+ 16..1234 'unsafe... }': !
37..40 'foo': i32
43..44 '1': i32
58..63 'mut o': i32
diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs
index 19a6a6b486..fd21286d50 100644
--- a/crates/hir-ty/src/tests/never_type.rs
+++ b/crates/hir-ty/src/tests/never_type.rs
@@ -262,42 +262,42 @@ fn diverging_expression_1() {
let x: u32 = { let y: u32 = { loop {}; }; };
}
",
- expect![[r"
- 11..39 '{ ...urn; }': ()
+ expect![[r#"
+ 11..39 '{ ...urn; }': !
21..22 'x': u32
30..36 'return': !
- 51..84 '{ ...; }; }': ()
+ 51..84 '{ ...; }; }': !
61..62 'x': u32
- 70..81 '{ return; }': u32
+ 70..81 '{ return; }': !
72..78 'return': !
- 96..125 '{ ... {}; }': ()
+ 96..125 '{ ... {}; }': !
106..107 'x': u32
115..122 'loop {}': !
120..122 '{}': ()
- 137..170 '{ ...} }; }': ()
+ 137..170 '{ ...} }; }': !
147..148 'x': u32
156..167 '{ loop {} }': u32
158..165 'loop {}': !
163..165 '{}': ()
- 182..246 '{ ...} }; }': ()
+ 182..246 '{ ...} }; }': !
192..193 'x': u32
201..243 '{ if t...}; } }': u32
203..241 'if tru... {}; }': u32
206..210 'true': bool
- 211..223 '{ loop {}; }': u32
+ 211..223 '{ loop {}; }': !
213..220 'loop {}': !
218..220 '{}': ()
- 229..241 '{ loop {}; }': u32
+ 229..241 '{ loop {}; }': !
231..238 'loop {}': !
236..238 '{}': ()
- 258..310 '{ ...; }; }': ()
+ 258..310 '{ ...; }; }': !
268..269 'x': u32
- 277..307 '{ let ...; }; }': u32
+ 277..307 '{ let ...; }; }': !
283..284 'y': u32
- 292..304 '{ loop {}; }': u32
+ 292..304 '{ loop {}; }': !
294..301 'loop {}': !
299..301 '{}': ()
- "]],
+ "#]],
);
}
@@ -312,7 +312,7 @@ fn diverging_expression_2() {
}
"#,
expect![[r#"
- 11..84 '{ ..." }; }': ()
+ 11..84 '{ ..." }; }': !
54..55 'x': u32
63..81 '{ loop...foo" }': u32
65..72 'loop {}': !
@@ -355,7 +355,7 @@ fn diverging_expression_3_break() {
54..55 'x': u32
63..82 '{ loop...k; } }': u32
65..80 'loop { break; }': u32
- 70..80 '{ break; }': ()
+ 70..80 '{ break; }': !
72..77 'break': !
72..77: expected u32, got ()
97..343 '{ ...; }; }': ()
@@ -374,7 +374,7 @@ fn diverging_expression_3_break() {
160..161 'b': {unknown}
160..161 'b': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
160..161 'b': <{unknown} as IntoIterator>::IntoIter
- 162..172 '{ break; }': ()
+ 162..172 '{ break; }': !
164..169 'break': !
226..227 'x': u32
235..253 '{ for ... {}; }': u32
@@ -407,7 +407,7 @@ fn diverging_expression_3_break() {
324..325 'b': {unknown}
324..325 'b': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
324..325 'b': <{unknown} as IntoIterator>::IntoIter
- 326..337 '{ return; }': ()
+ 326..337 '{ return; }': !
328..334 'return': !
149..175: expected u32, got ()
235..253: expected u32, got ()
@@ -419,7 +419,7 @@ fn diverging_expression_3_break() {
409..430 'while ...eak; }': ()
409..430 'while ...eak; }': ()
415..419 'true': bool
- 420..430 '{ break; }': ()
+ 420..430 '{ break; }': !
422..427 'break': !
537..538 'x': u32
546..564 '{ whil... {}; }': u32
@@ -434,7 +434,7 @@ fn diverging_expression_3_break() {
626..648 'while ...urn; }': ()
626..648 'while ...urn; }': ()
632..636 'true': bool
- 637..648 '{ return; }': ()
+ 637..648 '{ return; }': !
639..645 'return': !
407..433: expected u32, got ()
546..564: expected u32, got ()
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index c48112ee81..a6e864916f 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -606,7 +606,7 @@ fn enum_variant_through_self_in_pattern() {
}
"#,
expect![[r#"
- 75..217 '{ ... }': ()
+ 75..217 '{ ... }': !
85..210 'match ... }': ()
92..99 'loop {}': !
97..99 '{}': ()
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index c1c714f8d4..22404087bf 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -279,29 +279,29 @@ fn infer_std_crash_5() {
32..320 'for co... }': ()
32..320 'for co... }': ()
32..320 'for co... }': ()
- 36..43 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 36..43 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
47..60 'doesnt_matter': {unknown}
47..60 'doesnt_matter': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
47..60 'doesnt_matter': <{unknown} as IntoIterator>::IntoIter
61..320 '{ ... }': ()
- 75..79 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 82..166 'if doe... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 75..79 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 82..166 'if doe... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
85..98 'doesnt_matter': bool
99..128 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
113..118 'first': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 134..166 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 148..156 '&content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 149..156 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 181..188 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 191..313 'if ICE... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 134..166 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 148..156 '&content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 149..156 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 181..188 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 191..313 'if ICE... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
194..231 'ICE_RE..._VALUE': {unknown}
194..247 'ICE_RE...&name)': bool
- 241..246 '&name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 242..246 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 248..276 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 262..266 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 282..313 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
- 296..303 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 241..246 '&name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 242..246 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 248..276 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 262..266 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 282..313 '{ ... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
+ 296..303 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
"#]],
);
}
@@ -416,7 +416,7 @@ fn issue_2669() {
120..215 '{ ... }': ()
130..133 'end': fn end<{unknown}>()
130..135 'end()': ()
- 164..209 '{ ... }': ()
+ 164..209 '{ ... }': !
182..184 '_x': !
191..198 'loop {}': !
196..198 '{}': ()
@@ -631,7 +631,7 @@ fn issue_4053_diesel_where_clauses() {
65..69 'self': Self
267..271 'self': Self
466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
- 488..522 '{ ... }': {unknown}
+ 488..522 '{ ... }': ()
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
498..508 'self.order': O
498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
@@ -1059,7 +1059,7 @@ fn cfg_tail() {
216..227 '{ "third" }': ()
218..225 '"third"': &'static str
293..357 '{ ...] 15 }': ()
- 299..311 '{ "fourth" }': &'static str
+ 299..311 '{ "fourth" }': &'? str
301..309 '"fourth"': &'static str
"#]],
)
@@ -2238,7 +2238,7 @@ type Bar = impl Foo;
async fn f<A, B, C>() -> Bar {}
"#,
expect![[r#"
- 64..66 '{}': impl Foo + ?Sized
+ 64..66 '{}': ()
"#]],
);
}
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index 33a12fcd1e..c77b20f4b5 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -357,7 +357,7 @@ where
"#,
expect![[r#"
182..183 't': T
- 230..280 '{ ... {}; }': ()
+ 230..280 '{ ... {}; }': !
240..241 't': <T as DimMax<U>>::Output
270..277 'loop {}': !
275..277 '{}': ()
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index c0b8d93b47..b54ed08031 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -135,7 +135,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
16..17 'b': isize
26..27 'c': !
32..33 'd': &'? str
- 41..120 '{ ...f32; }': ()
+ 41..120 '{ ...f32; }': !
47..48 'a': u32
54..55 'b': isize
61..62 'c': !
@@ -1018,14 +1018,14 @@ fn foo() {
28..32 'true': bool
33..50 '{ ... }': i32
43..44 '1': i32
- 56..79 '{ ... }': i32
+ 56..79 '{ ... }': !
66..72 'return': !
89..92 '_x2': i32
95..148 'if tru... }': i32
98..102 'true': bool
103..120 '{ ... }': i32
113..114 '2': i32
- 126..148 '{ ... }': !
+ 126..148 '{ ... }': i32
136..142 'return': !
158..161 '_x3': i32
164..246 'match ... }': i32
@@ -1034,7 +1034,7 @@ fn foo() {
185..189 'true': bool
193..194 '3': i32
204..205 '_': bool
- 209..240 '{ ... }': i32
+ 209..240 '{ ... }': !
223..229 'return': !
256..259 '_x4': i32
262..319 'match ... }': i32
@@ -1939,7 +1939,7 @@ fn closure_return() {
16..58 '{ ...; }; }': u32
26..27 'x': impl Fn() -> usize
30..55 '|| -> ...n 1; }': impl Fn() -> usize
- 42..55 '{ return 1; }': usize
+ 42..55 '{ return 1; }': !
44..52 'return 1': !
51..52 '1': usize
"#]],
@@ -1958,7 +1958,7 @@ fn closure_return_unit() {
16..47 '{ ...; }; }': u32
26..27 'x': impl Fn()
30..44 '|| { return; }': impl Fn()
- 33..44 '{ return; }': ()
+ 33..44 '{ return; }': !
35..41 'return': !
"#]],
);
@@ -2434,10 +2434,10 @@ fn infer_loop_break_with_val() {
59..168 '{ ... }; }': ()
69..70 'x': Option<bool>
73..165 'loop {... }': Option<bool>
- 78..165 '{ ... }': ()
+ 78..165 '{ ... }': !
88..132 'if fal... }': ()
91..96 'false': bool
- 97..132 '{ ... }': ()
+ 97..132 '{ ... }': !
111..121 'break None': !
117..121 'None': Option<bool>
142..158 'break ...(true)': !
@@ -2470,7 +2470,7 @@ fn infer_loop_break_without_val() {
78..133 '{ ... }': ()
88..127 'if fal... }': ()
91..96 'false': bool
- 97..127 '{ ... }': ()
+ 97..127 '{ ... }': !
111..116 'break': !
"#]],
);
@@ -2500,24 +2500,24 @@ fn infer_labelled_break_with_val() {
19..21 '_x': impl Fn() -> bool
24..332 '|| 'ou... }': impl Fn() -> bool
27..332 ''outer... }': bool
- 40..332 '{ ... }': ()
+ 40..332 '{ ... }': !
54..59 'inner': i8
62..300 ''inner... }': i8
- 75..300 '{ ... }': ()
+ 75..300 '{ ... }': !
93..94 'i': bool
97..113 'Defaul...efault': {unknown}
97..115 'Defaul...ault()': bool
129..269 'if (br... }': ()
133..147 'break 'outer i': !
146..147 'i': bool
- 149..208 '{ ... }': ()
+ 149..208 '{ ... }': !
167..193 'loop {...5i8; }': !
- 172..193 '{ brea...5i8; }': ()
+ 172..193 '{ brea...5i8; }': !
174..190 'break ...er 5i8': !
187..190 '5i8': i8
214..269 'if tru... }': ()
217..221 'true': bool
- 222..269 '{ ... }': ()
+ 222..269 '{ ... }': !
240..254 'break 'inner 6': !
253..254 '6': i8
282..289 'break 7': !
@@ -2566,12 +2566,12 @@ fn foo() {
140..270 'if (br... }': ()
144..158 'break 'outer i': !
157..158 'i': bool
- 160..209 '{ ... }': ()
+ 160..209 '{ ... }': !
178..194 'break ...er 5i8': !
191..194 '5i8': i8
215..270 'if tru... }': ()
218..222 'true': bool
- 223..270 '{ ... }': ()
+ 223..270 '{ ... }': !
241..255 'break 'inner 6': !
254..255 '6': i8
283..313 'break ... { 0 }': !
@@ -2666,7 +2666,7 @@ fn generic_default_in_struct_literal() {
}
"#,
expect![[r#"
- 99..319 '{ ...32); }': ()
+ 99..319 '{ ...32); }': !
109..110 'x': Thing<!>
113..133 'Thing ...p {} }': Thing<!>
124..131 'loop {}': !
@@ -3254,9 +3254,9 @@ fn main() {
expect![[r#"
104..108 'self': &'? Box<T>
188..192 'self': &'a Box<Foo<T>>
- 218..220 '{}': &'a T
+ 218..220 '{}': &'? T
242..246 'self': &'a Box<Foo<T>>
- 275..277 '{}': &'a Foo<T>
+ 275..277 '{}': &'? Foo<T>
297..301 'self': Box<Foo<T>>
322..324 '{}': Foo<T>
338..559 '{ ...r(); }': ()
@@ -4305,3 +4305,21 @@ enum Enum {
"#]],
);
}
+
+#[test]
+fn labelled_block_break() {
+ check_types(
+ r#"
+//- minicore: option
+fn foo() {
+ 'a: {
+ if false {
+ break 'a Some(1);
+ }
+ None
+ // ^^^^ Option<i32>
+ };
+}
+ "#,
+ );
+}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 4eab1d6314..85c93abcf9 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1490,7 +1490,7 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) {
expect![[r#"
29..33 'self': &'? Self
54..58 'self': &'? Self
- 206..208 '{}': Box<dyn Trait<u64> + 'static>
+ 206..208 '{}': Box<dyn Trait<u64> + '?>
218..219 'x': Box<dyn Trait<u64> + 'static>
242..243 'y': &'? (dyn Trait<u64> + 'static)
262..379 '{ ...2(); }': ()
@@ -1571,7 +1571,7 @@ fn test(x: Trait, y: &Trait) -> u64 {
}"#,
expect![[r#"
26..30 'self': &'? Self
- 60..62 '{}': dyn Trait + 'static
+ 60..62 '{}': dyn Trait + '?
72..73 'x': dyn Trait + 'static
82..83 'y': &'? (dyn Trait + 'static)
100..175 '{ ...o(); }': u64
@@ -1712,7 +1712,7 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
}"#,
expect![[r#"
81..82 't': T
- 109..111 '{}': <T as Trait>::Type
+ 109..111 '{}': ()
143..144 't': T
154..156 '{}': U
186..187 't': T
@@ -5018,7 +5018,7 @@ where
"#,
expect![[r#"
84..86 'de': D
- 135..138 '{ }': <D as Deserializer<'de>>::Error
+ 135..138 '{ }': ()
"#]],
);
}
@@ -5083,7 +5083,7 @@ fn main() {
let _ = iter.into_iter();
}"#,
expect![[r#"
- 10..313 '{ ...r(); }': ()
+ 10..313 '{ ...r(); }': !
223..227 'iter': Box<dyn Iterator<Item = &'? [u8]> + 'static>
273..280 'loop {}': !
278..280 '{}': ()
diff --git a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
index b7265c47b6..43eb4ab8e0 100644
--- a/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
+++ b/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
@@ -126,14 +126,13 @@ fn foo() {
#[test]
fn value_break_in_for_loop() {
- // FIXME: the error is correct, but the message is terrible
check_diagnostics(
r#"
//- minicore: iterator
fn test() {
for _ in [()] {
break 3;
- // ^ error: expected (), found i32
+ // ^^^^^^^ error: can't break with a value in this position
}
}
"#,