Auto merge of #54599 - nikomatsakis:issue-54593-impl-Trait, r=eddyb

use closure def-id in returns, but base def-id in locals

The refactorings to  handle `let x: impl Trait`  wound up breaking `impl Trait` in closure return types. I think there are some deeper problems with the code in question, but this a least should make @eddyb's example work.

Fixes #54593

r? @eddyb
This commit is contained in:
bors 2018-09-29 15:07:59 +00:00
commit eb50e75729
3 changed files with 37 additions and 5 deletions

View File

@ -70,6 +70,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
if let Err(terr) = self.eq_opaque_type_and_type( if let Err(terr) = self.eq_opaque_type_and_type(
mir_output_ty, mir_output_ty,
normalized_output_ty, normalized_output_ty,
self.mir_def_id,
Locations::All(output_span), Locations::All(output_span),
ConstraintCategory::BoringNoLocation, ConstraintCategory::BoringNoLocation,
) { ) {

View File

@ -901,6 +901,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
) )
} }
/// Try to relate `sub <: sup`; if this fails, instantiate opaque
/// variables in `sub` with their inferred definitions and try
/// again. This is used for opaque types in places (e.g., `let x:
/// impl Foo = ..`).
fn sub_types_or_anon( fn sub_types_or_anon(
&mut self, &mut self,
sub: Ty<'tcx>, sub: Ty<'tcx>,
@ -910,7 +914,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
) -> Fallible<()> { ) -> Fallible<()> {
if let Err(terr) = self.sub_types(sub, sup, locations, category) { if let Err(terr) = self.sub_types(sub, sup, locations, category) {
if let TyKind::Opaque(..) = sup.sty { if let TyKind::Opaque(..) = sup.sty {
return self.eq_opaque_type_and_type(sub, sup, locations, category); // When you have `let x: impl Foo = ...` in a closure,
// the resulting inferend values are stored with the
// def-id of the base function.
let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id);
return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
} else { } else {
return Err(terr); return Err(terr);
} }
@ -958,13 +966,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
&mut self, &mut self,
revealed_ty: Ty<'tcx>, revealed_ty: Ty<'tcx>,
anon_ty: Ty<'tcx>, anon_ty: Ty<'tcx>,
anon_owner_def_id: DefId,
locations: Locations, locations: Locations,
category: ConstraintCategory, category: ConstraintCategory,
) -> Fallible<()> { ) -> Fallible<()> {
debug!(
"eq_opaque_type_and_type( \
revealed_ty={:?}, \
anon_ty={:?})",
revealed_ty, anon_ty
);
let infcx = self.infcx; let infcx = self.infcx;
let tcx = infcx.tcx; let tcx = infcx.tcx;
let param_env = self.param_env; let param_env = self.param_env;
let parent_def_id = infcx.tcx.closure_base_def_id(self.mir_def_id); debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
let opaque_type_map = self.fully_perform_op( let opaque_type_map = self.fully_perform_op(
locations, locations,
category, category,
@ -975,7 +990,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
let dummy_body_id = ObligationCause::dummy().body_id; let dummy_body_id = ObligationCause::dummy().body_id;
let (output_ty, opaque_type_map) = let (output_ty, opaque_type_map) =
obligations.add(infcx.instantiate_opaque_types( obligations.add(infcx.instantiate_opaque_types(
parent_def_id, anon_owner_def_id,
dummy_body_id, dummy_body_id,
param_env, param_env,
&anon_ty, &anon_ty,
@ -996,8 +1011,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs);
let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty); let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty);
debug!( debug!(
"eq_opaque_type_and_type: concrete_ty={:?} opaque_defn_ty={:?}", "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
opaque_decl.concrete_ty, opaque_defn_ty opaque_decl.concrete_ty,
infcx.resolve_type_vars_if_possible(&opaque_decl.concrete_ty),
opaque_defn_ty
); );
obligations.add(infcx obligations.add(infcx
.at(&ObligationCause::dummy(), param_env) .at(&ObligationCause::dummy(), param_env)

View File

@ -0,0 +1,14 @@
#![feature(nll)]
// Regression test for #54593: the MIR type checker was going wrong
// when a closure returns the `impl Copy` from its parent fn. It was
// (incorrectly) replacing the `impl Copy` in its return type with the
// hidden type (`()`) but that type resulted from a recursive call to
// `foo` and hence is treated opaquely within the closure body. This
// resulted in a failed subtype relationship.
//
// run-pass
fn foo() -> impl Copy { || foo(); }
fn bar() -> impl Copy { || bar(); }
fn main() { }