remove diverging type variables from fn check

The comment seems incorrect. Testing revealed that the examples in
question still work (as well as some variants) even without the
special casing here.
This commit is contained in:
Niko Matsakis 2020-11-23 07:42:06 -05:00 committed by Mark Rousskov
parent 2ee89144e2
commit ebb8ff9edf
2 changed files with 13 additions and 25 deletions

View File

@ -129,7 +129,11 @@ pub enum TypeVariableOriginKind {
SubstitutionPlaceholder,
AutoDeref,
AdjustmentType,
DivergingFn,
/// In type check, when we are type checking a function that
/// returns `-> dyn Foo`, we substitute a type variable for the
/// return type for diagnostic purposes.
DynReturnFn,
LatticeVariable,
}

View File

@ -241,32 +241,16 @@ pub(super) fn check_fn<'a, 'tcx>(
// we saw and assigning it to the expected return type. This isn't
// really expected to fail, since the coercions would have failed
// earlier when trying to find a LUB.
//
// However, the behavior around `!` is sort of complex. In the
// event that the `actual_return_ty` comes back as `!`, that
// indicates that the fn either does not return or "returns" only
// values of type `!`. In this case, if there is an expected
// return type that is *not* `!`, that should be ok. But if the
// return type is being inferred, we want to "fallback" to `!`:
//
// let x = move || panic!();
//
// To allow for that, I am creating a type variable with diverging
// fallback. This was deemed ever so slightly better than unifying
// the return value with `!` because it allows for the caller to
// make more assumptions about the return type (e.g., they could do
//
// let y: Option<u32> = Some(x());
//
// which would then cause this return type to become `u32`, not
// `!`).
let coercion = fcx.ret_coercion.take().unwrap().into_inner();
let mut actual_return_ty = coercion.complete(&fcx);
if actual_return_ty.is_never() {
actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::DivergingFn,
span,
});
debug!("actual_return_ty = {:?}", actual_return_ty);
if let ty::Dynamic(..) = declared_ret_ty.kind() {
// We have special-cased the case where the function is declared
// `-> dyn Foo` and we don't actually relate it to the
// `fcx.ret_coercion`, so just substitute a type variable.
actual_return_ty =
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
debug!("actual_return_ty replaced with {:?}", actual_return_ty);
}
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);