From 8aaa286a26e7e862311a29fa359aea8c0d8537c4 Mon Sep 17 00:00:00 2001 From: Ada Bohm Date: Wed, 8 Apr 2026 17:12:50 +0200 Subject: [PATCH] Error on projection of dyn noncompat type in old trait solver --- .../src/traits/project.rs | 6 +++++ ...ch-dyn-incompatible-that-does-not-deref.rs | 2 +- ...yn-incompatible-that-does-not-deref.stderr | 19 ++++----------- .../ui/traits/ice-with-dyn-pointee-errors.rs | 3 ++- .../traits/ice-with-dyn-pointee-errors.stderr | 23 ++++++++++++++++--- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 72d3ba9629f4d..5ecd80b7fc4cb 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -813,6 +813,12 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( } _ => return, }; + + // Projecting `dyn Trait` is only valid when `Trait` is dyn-compatible. + if data.principal_def_id().is_some_and(|def_id| !tcx.is_dyn_compatible(def_id)) { + return; + } + let env_predicates = data .projection_bounds() .filter(|bound| bound.item_def_id() == obligation.predicate.def_id) diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs index af35d1e0359db..40c1e07a70073 100644 --- a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs +++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs @@ -12,7 +12,7 @@ trait Foo: Deref { fn test(x: &dyn Foo) { //~^ ERROR the trait `Foo` is not dyn compatible x.method(); - //~^ ERROR the trait `Foo` is not dyn compatible + //~^ ERROR no method named `method` found for reference `&dyn Foo` } fn main() {} diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr index 237bbc5671515..bb071ad87195f 100644 --- a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr +++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr @@ -25,25 +25,16 @@ LL | fn method(self: &W) {} = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0038]: the trait `Foo` is not dyn compatible - --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:14:5 +error[E0599]: no method named `method` found for reference `&dyn Foo` in the current scope + --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:14:7 | LL | fn method(self: &W) {} - | -- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self` + | -- the method might not be found because of this arbitrary self type ... LL | x.method(); - | ^^^^^^^^^^ `Foo` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21 - | -LL | trait Foo: Deref { - | --- this trait is not dyn compatible... -LL | fn method(self: &W) {} - | ^^ ...because method `method`'s `self` parameter cannot be dispatched on + | ^^^^^^ method not found in `&dyn Foo` error: aborting due to 3 previous errors -Some errors have detailed explanations: E0038, E0307. +Some errors have detailed explanations: E0038, E0307, E0599. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.rs b/tests/ui/traits/ice-with-dyn-pointee-errors.rs index bb89f103e3f95..4c2b775f25c9a 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.rs +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.rs @@ -8,7 +8,8 @@ fn unknown_sized_object_ptr_in(_: &(impl Pointee + ?Sized)) {} fn raw_pointer_in(x: &dyn Pointee) { //~^ ERROR the trait `Pointee` is not dyn compatible unknown_sized_object_ptr_in(x) - //~^ ERROR the trait `Pointee` is not dyn compatible + //~^ ERROR type mismatch resolving ` as Pointee>::Metadata == ()` + //~| ERROR the trait `Pointee` is not dyn compatible } fn main() { diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr index 9ff0445cda09b..b6eee86bdef2e 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr @@ -10,6 +10,22 @@ note: for a trait to be dyn compatible it needs to allow building a vtable | = note: the trait is not dyn compatible because it opted out of dyn-compatibility +error[E0271]: type mismatch resolving ` as Pointee>::Metadata == ()` + --> $DIR/ice-with-dyn-pointee-errors.rs:10:33 + | +LL | unknown_sized_object_ptr_in(x) + | --------------------------- ^ expected `()`, found `DynMetadata>` + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found struct `DynMetadata>` +note: required by a bound in `unknown_sized_object_ptr_in` + --> $DIR/ice-with-dyn-pointee-errors.rs:6:50 + | +LL | fn unknown_sized_object_ptr_in(_: &(impl Pointee + ?Sized)) {} + | ^^^^^^^^^^^^^ required by this bound in `unknown_sized_object_ptr_in` + error[E0038]: the trait `Pointee` is not dyn compatible --> $DIR/ice-with-dyn-pointee-errors.rs:10:5 | @@ -23,7 +39,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable = note: the trait is not dyn compatible because it opted out of dyn-compatibility error[E0038]: the trait `Pointee` is not dyn compatible - --> $DIR/ice-with-dyn-pointee-errors.rs:15:20 + --> $DIR/ice-with-dyn-pointee-errors.rs:16:20 | LL | raw_pointer_in(&42) | ^^^ `Pointee` is not dyn compatible @@ -34,6 +50,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable | = note: the trait is not dyn compatible because it opted out of dyn-compatibility -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0038, E0271. +For more information about an error, try `rustc --explain E0038`.