Skip to content

Commit eb50e75

Browse files
committed
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
2 parents 9653f79 + bcfdfe4 commit eb50e75

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

src/librustc_mir/borrow_check/nll/type_check/input_output.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
7070
if let Err(terr) = self.eq_opaque_type_and_type(
7171
mir_output_ty,
7272
normalized_output_ty,
73+
self.mir_def_id,
7374
Locations::All(output_span),
7475
ConstraintCategory::BoringNoLocation,
7576
) {

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
901901
)
902902
}
903903

904+
/// Try to relate `sub <: sup`; if this fails, instantiate opaque
905+
/// variables in `sub` with their inferred definitions and try
906+
/// again. This is used for opaque types in places (e.g., `let x:
907+
/// impl Foo = ..`).
904908
fn sub_types_or_anon(
905909
&mut self,
906910
sub: Ty<'tcx>,
@@ -910,7 +914,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
910914
) -> Fallible<()> {
911915
if let Err(terr) = self.sub_types(sub, sup, locations, category) {
912916
if let TyKind::Opaque(..) = sup.sty {
913-
return self.eq_opaque_type_and_type(sub, sup, locations, category);
917+
// When you have `let x: impl Foo = ...` in a closure,
918+
// the resulting inferend values are stored with the
919+
// def-id of the base function.
920+
let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id);
921+
return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
914922
} else {
915923
return Err(terr);
916924
}
@@ -958,13 +966,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
958966
&mut self,
959967
revealed_ty: Ty<'tcx>,
960968
anon_ty: Ty<'tcx>,
969+
anon_owner_def_id: DefId,
961970
locations: Locations,
962971
category: ConstraintCategory,
963972
) -> Fallible<()> {
973+
debug!(
974+
"eq_opaque_type_and_type( \
975+
revealed_ty={:?}, \
976+
anon_ty={:?})",
977+
revealed_ty, anon_ty
978+
);
964979
let infcx = self.infcx;
965980
let tcx = infcx.tcx;
966981
let param_env = self.param_env;
967-
let parent_def_id = infcx.tcx.closure_base_def_id(self.mir_def_id);
982+
debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
968983
let opaque_type_map = self.fully_perform_op(
969984
locations,
970985
category,
@@ -975,7 +990,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
975990
let dummy_body_id = ObligationCause::dummy().body_id;
976991
let (output_ty, opaque_type_map) =
977992
obligations.add(infcx.instantiate_opaque_types(
978-
parent_def_id,
993+
anon_owner_def_id,
979994
dummy_body_id,
980995
param_env,
981996
&anon_ty,
@@ -996,8 +1011,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
9961011
let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs);
9971012
let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty);
9981013
debug!(
999-
"eq_opaque_type_and_type: concrete_ty={:?} opaque_defn_ty={:?}",
1000-
opaque_decl.concrete_ty, opaque_defn_ty
1014+
"eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
1015+
opaque_decl.concrete_ty,
1016+
infcx.resolve_type_vars_if_possible(&opaque_decl.concrete_ty),
1017+
opaque_defn_ty
10011018
);
10021019
obligations.add(infcx
10031020
.at(&ObligationCause::dummy(), param_env)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(nll)]
2+
3+
// Regression test for #54593: the MIR type checker was going wrong
4+
// when a closure returns the `impl Copy` from its parent fn. It was
5+
// (incorrectly) replacing the `impl Copy` in its return type with the
6+
// hidden type (`()`) but that type resulted from a recursive call to
7+
// `foo` and hence is treated opaquely within the closure body. This
8+
// resulted in a failed subtype relationship.
9+
//
10+
// run-pass
11+
12+
fn foo() -> impl Copy { || foo(); }
13+
fn bar() -> impl Copy { || bar(); }
14+
fn main() { }

0 commit comments

Comments
 (0)