about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-03-11 16:32:35 +0000
committerMichael Goulet <michael@errs.io>2025-03-11 16:32:56 +0000
commitc170d0f12fa9866d39190bc70c8df614083c3d5a (patch)
tree4f1d2b3dc1ae7f0284dc055279109577ef6956c1
parentebf0cf75d368c035f4c7e7246d203bd469ee4a51 (diff)
downloadrust-c170d0f12fa9866d39190bc70c8df614083c3d5a.tar.gz
rust-c170d0f12fa9866d39190bc70c8df614083c3d5a.zip
Elaborate param-env built for checking DispatchFromDyn for dyn compat
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs19
-rw-r--r--tests/ui/associated-types/issue-59324.rs1
-rw-r--r--tests/ui/associated-types/issue-59324.stderr21
-rw-r--r--tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs38
-rw-r--r--tests/ui/self/dyn-dispatch-requires-supertrait.rs38
5 files changed, 105 insertions, 12 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index d4502be6ccf..3fceada2510 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -24,7 +24,9 @@ use super::elaborate;
 use crate::infer::TyCtxtInferExt;
 pub use crate::traits::DynCompatibilityViolation;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{MethodViolationCode, Obligation, ObligationCause, util};
+use crate::traits::{
+    MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
+};
 
 /// Returns the dyn-compatibility violations that affect HIR ty lowering.
 ///
@@ -579,8 +581,8 @@ fn receiver_is_dispatchable<'tcx>(
     let unsized_receiver_ty =
         receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
 
-    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
-    // `U: ?Sized` is already implied here
+    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
+    // its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
     let param_env = {
         let param_env = tcx.param_env(method.def_id);
 
@@ -598,10 +600,13 @@ fn receiver_is_dispatchable<'tcx>(
             ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
         };
 
-        let caller_bounds =
-            param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
-
-        ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds))
+        normalize_param_env_or_error(
+            tcx,
+            ty::ParamEnv::new(tcx.mk_clauses_from_iter(
+                param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
+            )),
+            ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
+        )
     };
 
     // Receiver: DispatchFromDyn<Receiver[Self => U]>
diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs
index 7421e08c898..3abe8473052 100644
--- a/tests/ui/associated-types/issue-59324.rs
+++ b/tests/ui/associated-types/issue-59324.rs
@@ -15,6 +15,7 @@ pub trait ThriftService<Bug: NotFoo>:
 {
     fn get_service(
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
+    //~| ERROR the trait bound `Bug: Foo` is not satisfied
         &self,
     ) -> Self::AssocType;
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index dc8f9cfe895..f5e696b7ac1 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -32,6 +32,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
    |
 LL | /     fn get_service(
 LL | |
+LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
@@ -41,8 +42,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo`
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:5
+   |
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
+
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -54,7 +65,7 @@ LL | pub trait Foo: NotFoo {
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:19:10
+  --> $DIR/issue-59324.rs:20:10
    |
 LL |     ) -> Self::AssocType;
    |          ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
@@ -65,7 +76,7 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -78,7 +89,7 @@ LL | pub trait Foo: NotFoo {
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -95,6 +106,6 @@ help: function arguments must have a statically known size, borrowed types alway
 LL | fn with_factory<H>(factory: &dyn ThriftService<()>) {}
    |                             +
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs
new file mode 100644
index 00000000000..55c070eb036
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs
@@ -0,0 +1,38 @@
+//@ check-pass
+
+#![feature(derive_coerce_pointee)]
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+use std::marker::CoercePointee;
+use std::sync::Arc;
+
+trait MyTrait<T> {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct MyArc<T: ?Sized + MyTrait<u8>>(Arc<T>);
+
+impl<T: ?Sized + MyTrait<u8>> Deref for MyArc<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+// This is variant on "tests/ui/self/dyn-dispatch-requires-supertrait.rs" but with
+// a supertrait that requires normalization to match the pred in the old solver.
+trait MyOtherTrait: MyTrait<<u8 as Mirror>::Assoc> {
+    fn foo(self: MyArc<Self>);
+}
+
+fn test(_: MyArc<dyn MyOtherTrait>) {}
+
+fn main() {}
diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait.rs b/tests/ui/self/dyn-dispatch-requires-supertrait.rs
new file mode 100644
index 00000000000..f2661c406fe
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-requires-supertrait.rs
@@ -0,0 +1,38 @@
+//@ check-pass
+
+#![feature(derive_coerce_pointee)]
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+use std::marker::CoercePointee;
+use std::sync::Arc;
+
+trait MyTrait {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct MyArc<T>
+where
+    T: MyTrait + ?Sized,
+{
+    inner: Arc<T>
+}
+
+impl<T: MyTrait + ?Sized> Deref for MyArc<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.inner
+    }
+}
+
+// Proving that `MyArc<Self>` is dyn-dispatchable requires proving `MyArc<T>` implements
+// `DispatchFromDyn<MyArc<U>>`. The `DispatchFromDyn` impl that is generated from the
+// `CoercePointee` implementation requires the pointee impls `MyTrait`, but previously we
+// were only assuming the pointee impl'd `MyOtherTrait`. Elaboration comes to the rescue here.
+trait MyOtherTrait: MyTrait {
+    fn foo(self: MyArc<Self>);
+}
+
+fn test(_: MyArc<dyn MyOtherTrait>) {}
+
+fn main() {}