Skip to content

Commit 6eaa669

Browse files
committed
loop return value inference: coerce_merge branches
1 parent 0fe8769 commit 6eaa669

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

crates/ra_hir_ty/src/infer/expr.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,17 @@ impl<'a> InferenceContext<'a> {
9393
Ty::Unknown
9494
}
9595
Expr::Loop { body } => {
96-
self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
96+
self.breakables.push(BreakableContext {
97+
may_break: false,
98+
break_ty: self.table.new_type_var(),
99+
});
97100
self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
98101

99102
let ctxt = self.breakables.pop().expect("breakable stack broken");
100103
if ctxt.may_break {
101104
self.diverges = Diverges::Maybe;
102105
}
103-
// FIXME handle break with value
106+
104107
if ctxt.may_break {
105108
ctxt.break_ty
106109
} else {
@@ -229,26 +232,31 @@ impl<'a> InferenceContext<'a> {
229232
}
230233
Expr::Continue => Ty::simple(TypeCtor::Never),
231234
Expr::Break { expr } => {
232-
let mut has_val_ty = None;
235+
let val_ty = if let Some(expr) = expr {
236+
self.infer_expr(*expr, &Expectation::none())
237+
} else {
238+
Ty::unit()
239+
};
233240

234-
if let Some(expr) = expr {
235-
has_val_ty = Some(self.infer_expr(*expr, &Expectation::none()));
236-
}
241+
let mut has_brkctx = false;
237242

238-
if let Some(ctxt) = self.breakables.last_mut() {
239-
ctxt.may_break = true;
240-
if let Some(val_ty) = has_val_ty {
241-
if ctxt.break_ty == Ty::Unknown {
242-
ctxt.break_ty = val_ty;
243-
} else if ctxt.break_ty != val_ty {
244-
// TODO: Unify partially matching type information (Option<{unknown}> + Option<i32> => Option<i32>)
245-
}
246-
}
243+
if self.breakables.last().is_some() {
244+
has_brkctx = true;
247245
} else {
248246
self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
249247
expr: tgt_expr,
250248
});
251249
}
250+
251+
if has_brkctx {
252+
let last_ty = self.breakables.last().expect("This is a bug").break_ty.clone();
253+
let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
254+
255+
let ctxt = self.breakables.last_mut().expect("This is a bug");
256+
ctxt.may_break = true;
257+
ctxt.break_ty = merged_type;
258+
}
259+
252260
Ty::simple(TypeCtor::Never)
253261
}
254262
Expr::Return { expr } => {

0 commit comments

Comments
 (0)