Skip to content

Commit b725272

Browse files
committed
port if-then-else to use CoerceMany
1 parent 56847af commit b725272

File tree

1 file changed

+34
-37
lines changed
  • src/librustc_typeck/check

1 file changed

+34
-37
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type parameter).
7777
*/
7878

7979
pub use self::Expectation::*;
80+
use self::coercion::CoerceMany;
8081
pub use self::compare_method::{compare_impl_method, compare_const_impl};
8182
use self::TupleArgumentsFlag::*;
8283

@@ -299,12 +300,23 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
299300
}
300301
}
301302

303+
/// It sometimes happens that we want to turn an expectation into
304+
/// a **hard constraint** (i.e., something that must be satisfied
305+
/// for the program to type-check). `only_has_type` will return
306+
/// such a constraint, if it exists.
302307
fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
303308
match self.resolve(fcx) {
304309
ExpectHasType(ty) => Some(ty),
305310
_ => None
306311
}
307312
}
313+
314+
/// Like `only_has_type`, but instead of returning `None` if no
315+
/// hard constraint exists, creates a fresh type variable.
316+
fn only_has_type_or_fresh_var(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'tcx> {
317+
self.only_has_type(fcx)
318+
.unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span)))
319+
}
308320
}
309321

310322
#[derive(Copy, Clone)]
@@ -2743,54 +2755,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
27432755
let then_diverges = self.diverges.get();
27442756
self.diverges.set(Diverges::Maybe);
27452757

2746-
let unit = self.tcx.mk_nil();
2747-
let (cause, expected_ty, found_ty, result);
2758+
// We've already taken the expected type's preferences
2759+
// into account when typing the `then` branch. To figure
2760+
// out the initial shot at a LUB, we thus only consider
2761+
// `expected` if it represents a *hard* constraint
2762+
// (`only_has_type`); otherwise, we just go with a
2763+
// fresh type variable.
2764+
let coerce_to_ty = expected.only_has_type_or_fresh_var(self, sp);
2765+
let mut coerce = CoerceMany::new(coerce_to_ty);
2766+
2767+
let if_cause = self.cause(sp, ObligationCauseCode::IfExpression);
2768+
coerce.coerce(self, &if_cause, then_expr, then_ty);
2769+
27482770
if let Some(else_expr) = opt_else_expr {
27492771
let else_ty = self.check_expr_with_expectation(else_expr, expected);
27502772
let else_diverges = self.diverges.get();
2751-
cause = self.cause(sp, ObligationCauseCode::IfExpression);
2752-
2753-
// Only try to coerce-unify if we have a then expression
2754-
// to assign coercions to, otherwise it's () or diverging.
2755-
expected_ty = then_ty;
2756-
found_ty = else_ty;
2757-
2758-
let coerce_to = expected.only_has_type(self).unwrap_or(then_ty);
2759-
result = {
2760-
self.try_coerce(then_expr, then_ty, coerce_to)
2761-
.and_then(|t| {
2762-
self.try_find_coercion_lub(&cause, || Some(then_expr), t, else_expr, else_ty)
2763-
})
2764-
};
2773+
2774+
coerce.coerce(self, &if_cause, else_expr, else_ty);
27652775

27662776
// We won't diverge unless both branches do (or the condition does).
27672777
self.diverges.set(cond_diverges | then_diverges & else_diverges);
27682778
} else {
2779+
let else_cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse);
2780+
coerce.coerce_forced_unit(self, &else_cause);
2781+
27692782
// If the condition is false we can't diverge.
27702783
self.diverges.set(cond_diverges);
2771-
2772-
cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse);
2773-
expected_ty = unit;
2774-
found_ty = then_ty;
2775-
result = self.eq_types(true, &cause, unit, then_ty)
2776-
.map(|ok| {
2777-
self.register_infer_ok_obligations(ok);
2778-
unit
2779-
});
27802784
}
27812785

2782-
match result {
2783-
Ok(ty) => {
2784-
if cond_ty.references_error() {
2785-
self.tcx.types.err
2786-
} else {
2787-
ty
2788-
}
2789-
}
2790-
Err(e) => {
2791-
self.report_mismatched_types(&cause, expected_ty, found_ty, e).emit();
2792-
self.tcx.types.err
2793-
}
2786+
let result_ty = coerce.complete(self);
2787+
if cond_ty.references_error() {
2788+
self.tcx.types.err
2789+
} else {
2790+
result_ty
27942791
}
27952792
}
27962793

0 commit comments

Comments
 (0)