about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/input_output.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs27
-rw-r--r--src/test/ui/impl-trait/closure-calling-parent-fn.rs14
3 files changed, 37 insertions, 5 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index acde4587d77..942f19965bf 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -70,6 +70,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         if let Err(terr) = self.eq_opaque_type_and_type(
             mir_output_ty,
             normalized_output_ty,
+            self.mir_def_id,
             Locations::All(output_span),
             ConstraintCategory::BoringNoLocation,
         ) {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 4c2ef58a3a7..ef4cc3452b1 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -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(
         &mut self,
         sub: Ty<'tcx>,
@@ -910,7 +914,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     ) -> Fallible<()> {
         if let Err(terr) = self.sub_types(sub, sup, locations, category) {
             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 {
                 return Err(terr);
             }
@@ -958,13 +966,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         revealed_ty: Ty<'tcx>,
         anon_ty: Ty<'tcx>,
+        anon_owner_def_id: DefId,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
+        debug!(
+            "eq_opaque_type_and_type( \
+             revealed_ty={:?}, \
+             anon_ty={:?})",
+            revealed_ty, anon_ty
+        );
         let infcx = self.infcx;
         let tcx = infcx.tcx;
         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(
             locations,
             category,
@@ -975,7 +990,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     let dummy_body_id = ObligationCause::dummy().body_id;
                     let (output_ty, opaque_type_map) =
                         obligations.add(infcx.instantiate_opaque_types(
-                            parent_def_id,
+                            anon_owner_def_id,
                             dummy_body_id,
                             param_env,
                             &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 = renumber::renumber_regions(infcx, &opaque_defn_ty);
                         debug!(
-                            "eq_opaque_type_and_type: concrete_ty={:?} opaque_defn_ty={:?}",
-                            opaque_decl.concrete_ty, opaque_defn_ty
+                            "eq_opaque_type_and_type: 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
                             .at(&ObligationCause::dummy(), param_env)
diff --git a/src/test/ui/impl-trait/closure-calling-parent-fn.rs b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
new file mode 100644
index 00000000000..cb5f78bd6fc
--- /dev/null
+++ b/src/test/ui/impl-trait/closure-calling-parent-fn.rs
@@ -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() { }