about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-01-11 17:31:07 +0000
committerbors <bors@rust-lang.org>2022-01-11 17:31:07 +0000
commit1409c015b44a4d4d38bef2250b2a37c17b8b7463 (patch)
tree1735254891cc0646c11f1d7d73b48952bb203b89
parent2e2c86eba21a08cf505cd67073736d03ff3887ad (diff)
parent15f7e818ec83cd8b6a726e625b24e1507d8687ee (diff)
downloadrust-1409c015b44a4d4d38bef2250b2a37c17b8b7463.tar.gz
rust-1409c015b44a4d4d38bef2250b2a37c17b8b7463.zip
Auto merge of #90948 - oli-obk:🧹, r=nikomatsakis
Actually instantiate the opaque type when checking bounds

Before this change, `instantiate_opaque_types` was a no-op, because it only works relative to the defined opaque type inference anchor. If it is a no-op, the for loop will not actually have anything to iterate over, and thus nothing is checked at all.
-rw-r--r--compiler/rustc_typeck/src/check/check.rs44
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr26
2 files changed, 49 insertions, 21 deletions
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index dcf42e1aefe..4b52513014d 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -626,6 +626,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
 ///
 /// Without this check the above code is incorrectly accepted: we would ICE if
 /// some tried, for example, to clone an `Option<X<&mut ()>>`.
+#[instrument(level = "debug", skip(tcx))]
 fn check_opaque_meets_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
@@ -633,17 +634,14 @@ fn check_opaque_meets_bounds<'tcx>(
     span: Span,
     origin: &hir::OpaqueTyOrigin,
 ) {
-    match origin {
-        // Checked when type checking the function containing them.
-        hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return,
-        // Can have different predicates to their defining use
-        hir::OpaqueTyOrigin::TyAlias => {}
-    }
-
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let param_env = tcx.param_env(def_id);
+    let defining_use_anchor = match *origin {
+        hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
+        hir::OpaqueTyOrigin::TyAlias => def_id,
+    };
+    let param_env = tcx.param_env(defining_use_anchor);
 
-    tcx.infer_ctxt().enter(move |infcx| {
+    tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).enter(move |infcx| {
         let inh = Inherited::new(infcx, def_id);
         let infcx = &inh.infcx;
         let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
@@ -656,16 +654,15 @@ fn check_opaque_meets_bounds<'tcx>(
 
         let opaque_type_map = infcx.inner.borrow().opaque_types.clone();
         for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map {
-            match infcx
-                .at(&misc_cause, param_env)
-                .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, substs))
-            {
+            let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
+            trace!(?hidden_type);
+            match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) {
                 Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
                 Err(ty_err) => tcx.sess.delay_span_bug(
-                    opaque_defn.definition_span,
+                    span,
                     &format!(
-                        "could not unify `{}` with revealed type:\n{}",
-                        opaque_defn.concrete_ty, ty_err,
+                        "could not check bounds on revealed type `{}`:\n{}",
+                        hidden_type, ty_err,
                     ),
                 ),
             }
@@ -678,10 +675,17 @@ fn check_opaque_meets_bounds<'tcx>(
             infcx.report_fulfillment_errors(&errors, None, false);
         }
 
-        // Finally, resolve all regions. This catches wily misuses of
-        // lifetime parameters.
-        let fcx = FnCtxt::new(&inh, param_env, hir_id);
-        fcx.regionck_item(hir_id, span, FxHashSet::default());
+        match origin {
+            // Checked when type checking the function containing them.
+            hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return,
+            // Can have different predicates to their defining use
+            hir::OpaqueTyOrigin::TyAlias => {
+                // Finally, resolve all regions. This catches wily misuses of
+                // lifetime parameters.
+                let fcx = FnCtxt::new(&inh, param_env, hir_id);
+                fcx.regionck_item(hir_id, span, FxHashSet::default());
+            }
+        }
     });
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
index 8c9cb742fac..a4ccae4eb7e 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr
@@ -10,5 +10,29 @@ error: higher-ranked subtype error
 LL |         |x| x
    |         ^^^^^
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r X,)>`
+              found type `Fn<(&'static X,)>`
+note: this closure does not fulfill the lifetime requirements
+  --> $DIR/issue-57611-trait-alias.rs:21:9
+   |
+LL |         |x| x
+   |         ^^^^^
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue-57611-trait-alias.rs:17:16
+   |
+LL |     type Bar = impl Baz<Self, Self>;
+   |                ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'static X) -> &'static X` must implement `FnOnce<(&'0 X,)>`, for any lifetime `'0`...
+   = note: ...but it actually implements `FnOnce<(&'static X,)>`
+
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.