Skip to content

Deduplicate dyn compatibility violations due to coercion #141439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use rustc_infer::infer::relate::RelateResult;
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
use rustc_infer::traits::{
IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
PredicateObligations,
PredicateObligations, SelectionError,
};
use rustc_middle::span_bug;
use rustc_middle::ty::adjustment::{
Expand Down Expand Up @@ -677,7 +677,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
return Err(TypeError::Mismatch);
}

// Dyn-compatibility violations or miscellaneous.
Err(SelectionError::TraitDynIncompatible(_)) => {
// Dyn compatibility errors in coercion will *always* be due to the
// fact that the RHS of the coercion is a non-dyn compatible `dyn Trait`
// writen in source somewhere (otherwise we will never have lowered
// the dyn trait from HIR to middle).
//
// There's no reason to emit yet another dyn compatibility error,
// especially since the span will differ slightly and thus not be
// deduplicated at all!
self.fcx.set_tainted_by_errors(
self.fcx
.dcx()
.span_delayed_bug(self.cause.span, "dyn compatibility during coercion"),
);
}
Err(err) => {
let guar = self.err_ctxt().report_selection_error(
obligation.clone(),
Expand Down
20 changes: 1 addition & 19 deletions tests/ui/async-await/dyn/mut-is-pointer-like.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,6 @@ LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait

error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/mut-is-pointer-like.rs:35:56
|
LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
| ^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mut-is-pointer-like.rs:16:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
...
LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait<Output = ()>>`

error: aborting due to 2 previous errors; 1 warning emitted
error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0038`.
20 changes: 1 addition & 19 deletions tests/ui/async-await/dyn/works.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)]
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:27:34
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/works.rs:14:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`

error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/works.rs:27:16
|
Expand All @@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self);
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.

error: aborting due to 2 previous errors; 1 warning emitted
error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0038`.
20 changes: 1 addition & 19 deletions tests/ui/async-await/dyn/wrong-size.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)]
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/wrong-size.rs:21:30
|
LL | let x: &dyn AsyncTrait = &"hello, world!";
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/wrong-size.rs:9:14
|
LL | trait AsyncTrait {
| ---------- this trait is not dyn compatible...
LL | async fn async_dispatch(&self);
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`

error[E0038]: the trait `AsyncTrait` is not dyn compatible
--> $DIR/wrong-size.rs:21:12
|
Expand All @@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self);
= help: consider moving `async_dispatch` to another trait
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.

error: aborting due to 2 previous errors; 1 warning emitted
error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0038`.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use std::marker::PhantomData;
fn transmute<T, U>(t: T) -> U {
(&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
//~^ ERROR the trait `Foo` is not dyn compatible
//~| ERROR the trait `Foo` is not dyn compatible
}

struct ActuallySuper;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/almost-supertrait-associated-type.rs:21:20
--> $DIR/almost-supertrait-associated-type.rs:20:20
|
LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {
| ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/almost-supertrait-associated-type.rs:33:34
--> $DIR/almost-supertrait-associated-type.rs:32:34
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| --- this trait is not dyn compatible...
Expand All @@ -23,7 +23,7 @@ LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/almost-supertrait-associated-type.rs:33:34
--> $DIR/almost-supertrait-associated-type.rs:32:34
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| --- this trait is not dyn compatible...
Expand All @@ -32,24 +32,6 @@ LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
= help: consider moving `transmute` to another trait

error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/almost-supertrait-associated-type.rs:7:6
|
LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
| ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/almost-supertrait-associated-type.rs:33:34
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| --- this trait is not dyn compatible...
...
LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
= help: consider moving `transmute` to another trait
= note: required for the cast from `&PhantomData<T>` to `&dyn Foo<T, U>`

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0038`.
1 change: 0 additions & 1 deletion tests/ui/dyn-compatibility/associated-consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ trait Bar {
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
//~^ ERROR E0038
}

fn main() {
Expand Down
19 changes: 1 addition & 18 deletions tests/ui/dyn-compatibility/associated-consts.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,6 @@ LL | const X: usize;
| ^ ...because it contains this associated `const`
= help: consider moving `X` to another trait

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/associated-consts.rs:10:5
|
LL | t
| ^ `Bar` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/associated-consts.rs:5:11
|
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | const X: usize;
| ^ ...because it contains this associated `const`
= help: consider moving `X` to another trait
= note: required for the cast from `&T` to `&dyn Bar`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0038`.
2 changes: 0 additions & 2 deletions tests/ui/dyn-compatibility/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ trait Quux {
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
//~^ ERROR E0038
}

fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t as &dyn Bar
//~^ ERROR E0038
//~| ERROR E0038
}

fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
Expand Down
40 changes: 3 additions & 37 deletions tests/ui/dyn-compatibility/generics.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | fn bar<T>(&self, t: T);
= help: consider moving `bar` to another trait

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/generics.rs:21:40
--> $DIR/generics.rs:20:40
|
LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^ `Bar` is not dyn compatible
Expand All @@ -31,24 +31,7 @@ LL | fn bar<T>(&self, t: T);
= help: consider moving `bar` to another trait

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/generics.rs:17:5
|
LL | t
| ^ `Bar` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/generics.rs:7:8
|
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
= help: consider moving `bar` to another trait
= note: required for the cast from `&T` to `&dyn Bar`

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/generics.rs:23:10
--> $DIR/generics.rs:22:10
|
LL | t as &dyn Bar
| ^^^^^^^^ `Bar` is not dyn compatible
Expand All @@ -63,23 +46,6 @@ LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
= help: consider moving `bar` to another trait

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/generics.rs:23:5
|
LL | t as &dyn Bar
| ^ `Bar` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/generics.rs:7:8
|
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | fn bar<T>(&self, t: T);
| ^^^ ...because method `bar` has generic type parameters
= help: consider moving `bar` to another trait
= note: required for the cast from `&T` to `&dyn Bar`

error: aborting due to 5 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0038`.
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ fn main() {
let mut thing = Thing;
let test: &mut dyn Bar = &mut thing;
//~^ ERROR E0038
//~| ERROR E0038
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30
|
LL | let test: &mut dyn Bar = &mut thing;
| ^^^^^^^^^^ `Bar` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
|
LL | fn foo<T>(&self, val: T);
| ^^^ ...because method `foo` has generic type parameters
...
LL | trait Bar: Foo { }
| --- this trait is not dyn compatible...
= help: consider moving `foo` to another trait
= help: only type `Thing` implements `Bar`; consider using it directly instead.
= note: required for the cast from `&mut Thing` to `&mut dyn Bar`

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15
|
Expand All @@ -35,6 +16,6 @@ LL | trait Bar: Foo { }
= help: consider moving `foo` to another trait
= help: only type `Thing` implements `Bar`; consider using it directly instead.

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0038`.
2 changes: 0 additions & 2 deletions tests/ui/dyn-compatibility/mentions-Self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ trait Quux {
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
//~^ ERROR E0038
t
//~^ ERROR E0038
}

fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
//~^ ERROR E0038
t
//~^ ERROR E0038
}

fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
Expand Down
38 changes: 2 additions & 36 deletions tests/ui/dyn-compatibility/mentions-Self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ LL | fn bar(&self, x: &Self);
= help: consider moving `bar` to another trait

error[E0038]: the trait `Baz` is not dyn compatible
--> $DIR/mentions-Self.rs:24:31
--> $DIR/mentions-Self.rs:23:31
|
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
| ^^^^^^^ `Baz` is not dyn compatible
Expand All @@ -30,40 +30,6 @@ LL | fn baz(&self) -> Self;
| ^^^^ ...because method `baz` references the `Self` type in its return type
= help: consider moving `baz` to another trait

error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/mentions-Self.rs:20:5
|
LL | t
| ^ `Bar` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mentions-Self.rs:7:22
|
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | fn bar(&self, x: &Self);
| ^^^^^ ...because method `bar` references the `Self` type in this parameter
= help: consider moving `bar` to another trait
= note: required for the cast from `&T` to `&dyn Bar`

error[E0038]: the trait `Baz` is not dyn compatible
--> $DIR/mentions-Self.rs:26:5
|
LL | t
| ^ `Baz` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/mentions-Self.rs:11:22
|
LL | trait Baz {
| --- this trait is not dyn compatible...
LL | fn baz(&self) -> Self;
| ^^^^ ...because method `baz` references the `Self` type in its return type
= help: consider moving `baz` to another trait
= note: required for the cast from `&T` to `&dyn Baz`

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0038`.
1 change: 0 additions & 1 deletion tests/ui/dyn-compatibility/no-static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ impl Foo for Bar {}
fn main() {
let b: Box<dyn Foo> = Box::new(Bar);
//~^ ERROR E0038
//~| ERROR E0038
}
Loading
Loading