Skip to content

Commit

Permalink
remove diverging type variables from fn check
Browse files Browse the repository at this point in the history
The comment seems incorrect. Testing revealed that the examples in
question still work (as well as some variants) even without the
special casing here.
  • Loading branch information
nikomatsakis authored and Mark-Simulacrum committed Sep 17, 2021
1 parent 2ee8914 commit ebb8ff9
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 25 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_infer/src/infer/type_variable.rs
Expand Up @@ -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,
}

Expand Down
32 changes: 8 additions & 24 deletions compiler/rustc_typeck/src/check/check.rs
Expand Up @@ -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);

Expand Down

0 comments on commit ebb8ff9

Please sign in to comment.