Skip to content

Commit 92b07de

Browse files
authored
Rollup merge of rust-lang#141439 - compiler-errors:dyn-compatible-coerce, r=oli-obk
Deduplicate dyn compatibility violations due to coercion Don't unnecessarily emit dyn compatibility violations due to coercion to a non-dyn-compatible target type. For us to even have that target type, we would have had to write `dyn Trait` somewhere in source, and that would have led to us *already* emitting a dyn compatibility violation when checking that user written type is WF. r? oli-obk
2 parents 9f93c48 + a59c86a commit 92b07de

File tree

62 files changed

+73
-767
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+73
-767
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use rustc_infer::infer::relate::RelateResult;
4747
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
4848
use rustc_infer::traits::{
4949
IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
50-
PredicateObligations,
50+
PredicateObligations, SelectionError,
5151
};
5252
use rustc_middle::span_bug;
5353
use rustc_middle::ty::adjustment::{
@@ -677,7 +677,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
677677
return Err(TypeError::Mismatch);
678678
}
679679

680-
// Dyn-compatibility violations or miscellaneous.
680+
Err(SelectionError::TraitDynIncompatible(_)) => {
681+
// Dyn compatibility errors in coercion will *always* be due to the
682+
// fact that the RHS of the coercion is a non-dyn compatible `dyn Trait`
683+
// writen in source somewhere (otherwise we will never have lowered
684+
// the dyn trait from HIR to middle).
685+
//
686+
// There's no reason to emit yet another dyn compatibility error,
687+
// especially since the span will differ slightly and thus not be
688+
// deduplicated at all!
689+
self.fcx.set_tainted_by_errors(
690+
self.fcx
691+
.dcx()
692+
.span_delayed_bug(self.cause.span, "dyn compatibility during coercion"),
693+
);
694+
}
681695
Err(err) => {
682696
let guar = self.err_ctxt().report_selection_error(
683697
obligation.clone(),

tests/ui/async-await/dyn/mut-is-pointer-like.stderr

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,6 @@ LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
2424
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
2525
= help: consider moving `async_dispatch` to another trait
2626

27-
error[E0038]: the trait `AsyncTrait` is not dyn compatible
28-
--> $DIR/mut-is-pointer-like.rs:35:56
29-
|
30-
LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
31-
| ^ `AsyncTrait` is not dyn compatible
32-
|
33-
note: for a trait to be dyn compatible it needs to allow building a vtable
34-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
35-
--> $DIR/mut-is-pointer-like.rs:16:14
36-
|
37-
LL | trait AsyncTrait {
38-
| ---------- this trait is not dyn compatible...
39-
...
40-
LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output;
41-
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
42-
= help: consider moving `async_dispatch` to another trait
43-
= 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 = ()>>`
44-
45-
error: aborting due to 2 previous errors; 1 warning emitted
27+
error: aborting due to 1 previous error; 1 warning emitted
4628

4729
For more information about this error, try `rustc --explain E0038`.

tests/ui/async-await/dyn/works.stderr

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)]
77
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error[E0038]: the trait `AsyncTrait` is not dyn compatible
11-
--> $DIR/works.rs:27:34
12-
|
13-
LL | let x: &dyn AsyncTrait = &"hello, world!";
14-
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
15-
|
16-
note: for a trait to be dyn compatible it needs to allow building a vtable
17-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
18-
--> $DIR/works.rs:14:14
19-
|
20-
LL | trait AsyncTrait {
21-
| ---------- this trait is not dyn compatible...
22-
LL | async fn async_dispatch(&self);
23-
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
24-
= help: consider moving `async_dispatch` to another trait
25-
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
26-
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
27-
2810
error[E0038]: the trait `AsyncTrait` is not dyn compatible
2911
--> $DIR/works.rs:27:16
3012
|
@@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self);
4224
= help: consider moving `async_dispatch` to another trait
4325
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
4426

45-
error: aborting due to 2 previous errors; 1 warning emitted
27+
error: aborting due to 1 previous error; 1 warning emitted
4628

4729
For more information about this error, try `rustc --explain E0038`.

tests/ui/async-await/dyn/wrong-size.stderr

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,6 @@ LL | #![feature(async_fn_in_dyn_trait)]
77
= note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error[E0038]: the trait `AsyncTrait` is not dyn compatible
11-
--> $DIR/wrong-size.rs:21:30
12-
|
13-
LL | let x: &dyn AsyncTrait = &"hello, world!";
14-
| ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
15-
|
16-
note: for a trait to be dyn compatible it needs to allow building a vtable
17-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
18-
--> $DIR/wrong-size.rs:9:14
19-
|
20-
LL | trait AsyncTrait {
21-
| ---------- this trait is not dyn compatible...
22-
LL | async fn async_dispatch(&self);
23-
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
24-
= help: consider moving `async_dispatch` to another trait
25-
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
26-
= note: required for the cast from `&&'static str` to `&dyn AsyncTrait`
27-
2810
error[E0038]: the trait `AsyncTrait` is not dyn compatible
2911
--> $DIR/wrong-size.rs:21:12
3012
|
@@ -42,6 +24,6 @@ LL | async fn async_dispatch(&self);
4224
= help: consider moving `async_dispatch` to another trait
4325
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
4426

45-
error: aborting due to 2 previous errors; 1 warning emitted
27+
error: aborting due to 1 previous error; 1 warning emitted
4628

4729
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::marker::PhantomData;
66
fn transmute<T, U>(t: T) -> U {
77
(&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
88
//~^ ERROR the trait `Foo` is not dyn compatible
9-
//~| ERROR the trait `Foo` is not dyn compatible
109
}
1110

1211
struct ActuallySuper;
Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
error[E0038]: the trait `Foo` is not dyn compatible
2-
--> $DIR/almost-supertrait-associated-type.rs:21:20
2+
--> $DIR/almost-supertrait-associated-type.rs:20:20
33
|
44
LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {
55
| ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
66
|
77
note: for a trait to be dyn compatible it needs to allow building a vtable
88
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
9-
--> $DIR/almost-supertrait-associated-type.rs:33:34
9+
--> $DIR/almost-supertrait-associated-type.rs:32:34
1010
|
1111
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
1212
| --- this trait is not dyn compatible...
@@ -23,7 +23,7 @@ LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
2323
|
2424
note: for a trait to be dyn compatible it needs to allow building a vtable
2525
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
26-
--> $DIR/almost-supertrait-associated-type.rs:33:34
26+
--> $DIR/almost-supertrait-associated-type.rs:32:34
2727
|
2828
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
2929
| --- this trait is not dyn compatible...
@@ -32,24 +32,6 @@ LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
3333
= help: consider moving `transmute` to another trait
3434

35-
error[E0038]: the trait `Foo` is not dyn compatible
36-
--> $DIR/almost-supertrait-associated-type.rs:7:6
37-
|
38-
LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
39-
| ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
40-
|
41-
note: for a trait to be dyn compatible it needs to allow building a vtable
42-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
43-
--> $DIR/almost-supertrait-associated-type.rs:33:34
44-
|
45-
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
46-
| --- this trait is not dyn compatible...
47-
...
48-
LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type
50-
= help: consider moving `transmute` to another trait
51-
= note: required for the cast from `&PhantomData<T>` to `&dyn Foo<T, U>`
52-
53-
error: aborting due to 3 previous errors
35+
error: aborting due to 2 previous errors
5436

5537
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/associated-consts.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ trait Bar {
88
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
99
//~^ ERROR E0038
1010
t
11-
//~^ ERROR E0038
1211
}
1312

1413
fn main() {

tests/ui/dyn-compatibility/associated-consts.stderr

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,6 @@ LL | const X: usize;
1414
| ^ ...because it contains this associated `const`
1515
= help: consider moving `X` to another trait
1616

17-
error[E0038]: the trait `Bar` is not dyn compatible
18-
--> $DIR/associated-consts.rs:10:5
19-
|
20-
LL | t
21-
| ^ `Bar` is not dyn compatible
22-
|
23-
note: for a trait to be dyn compatible it needs to allow building a vtable
24-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
25-
--> $DIR/associated-consts.rs:5:11
26-
|
27-
LL | trait Bar {
28-
| --- this trait is not dyn compatible...
29-
LL | const X: usize;
30-
| ^ ...because it contains this associated `const`
31-
= help: consider moving `X` to another trait
32-
= note: required for the cast from `&T` to `&dyn Bar`
33-
34-
error: aborting due to 2 previous errors
17+
error: aborting due to 1 previous error
3518

3619
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/generics.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ trait Quux {
1515
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
1616
//~^ ERROR E0038
1717
t
18-
//~^ ERROR E0038
1918
}
2019

2120
fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
2221
//~^ ERROR E0038
2322
t as &dyn Bar
2423
//~^ ERROR E0038
25-
//~| ERROR E0038
2624
}
2725

2826
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {

tests/ui/dyn-compatibility/generics.stderr

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | fn bar<T>(&self, t: T);
1515
= help: consider moving `bar` to another trait
1616

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

3333
error[E0038]: the trait `Bar` is not dyn compatible
34-
--> $DIR/generics.rs:17:5
35-
|
36-
LL | t
37-
| ^ `Bar` is not dyn compatible
38-
|
39-
note: for a trait to be dyn compatible it needs to allow building a vtable
40-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
41-
--> $DIR/generics.rs:7:8
42-
|
43-
LL | trait Bar {
44-
| --- this trait is not dyn compatible...
45-
LL | fn bar<T>(&self, t: T);
46-
| ^^^ ...because method `bar` has generic type parameters
47-
= help: consider moving `bar` to another trait
48-
= note: required for the cast from `&T` to `&dyn Bar`
49-
50-
error[E0038]: the trait `Bar` is not dyn compatible
51-
--> $DIR/generics.rs:23:10
34+
--> $DIR/generics.rs:22:10
5235
|
5336
LL | t as &dyn Bar
5437
| ^^^^^^^^ `Bar` is not dyn compatible
@@ -63,23 +46,6 @@ LL | fn bar<T>(&self, t: T);
6346
| ^^^ ...because method `bar` has generic type parameters
6447
= help: consider moving `bar` to another trait
6548

66-
error[E0038]: the trait `Bar` is not dyn compatible
67-
--> $DIR/generics.rs:23:5
68-
|
69-
LL | t as &dyn Bar
70-
| ^ `Bar` is not dyn compatible
71-
|
72-
note: for a trait to be dyn compatible it needs to allow building a vtable
73-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
74-
--> $DIR/generics.rs:7:8
75-
|
76-
LL | trait Bar {
77-
| --- this trait is not dyn compatible...
78-
LL | fn bar<T>(&self, t: T);
79-
| ^^^ ...because method `bar` has generic type parameters
80-
= help: consider moving `bar` to another trait
81-
= note: required for the cast from `&T` to `&dyn Bar`
82-
83-
error: aborting due to 5 previous errors
49+
error: aborting due to 3 previous errors
8450

8551
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ fn main() {
1818
let mut thing = Thing;
1919
let test: &mut dyn Bar = &mut thing;
2020
//~^ ERROR E0038
21-
//~| ERROR E0038
2221
}
Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,3 @@
1-
error[E0038]: the trait `Bar` is not dyn compatible
2-
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30
3-
|
4-
LL | let test: &mut dyn Bar = &mut thing;
5-
| ^^^^^^^^^^ `Bar` is not dyn compatible
6-
|
7-
note: for a trait to be dyn compatible it needs to allow building a vtable
8-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
9-
--> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8
10-
|
11-
LL | fn foo<T>(&self, val: T);
12-
| ^^^ ...because method `foo` has generic type parameters
13-
...
14-
LL | trait Bar: Foo { }
15-
| --- this trait is not dyn compatible...
16-
= help: consider moving `foo` to another trait
17-
= help: only type `Thing` implements `Bar`; consider using it directly instead.
18-
= note: required for the cast from `&mut Thing` to `&mut dyn Bar`
19-
201
error[E0038]: the trait `Bar` is not dyn compatible
212
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15
223
|
@@ -35,6 +16,6 @@ LL | trait Bar: Foo { }
3516
= help: consider moving `foo` to another trait
3617
= help: only type `Thing` implements `Bar`; consider using it directly instead.
3718

38-
error: aborting due to 2 previous errors
19+
error: aborting due to 1 previous error
3920

4021
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/mentions-Self.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ trait Quux {
1818
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
1919
//~^ ERROR E0038
2020
t
21-
//~^ ERROR E0038
2221
}
2322

2423
fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
2524
//~^ ERROR E0038
2625
t
27-
//~^ ERROR E0038
2826
}
2927

3028
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {

tests/ui/dyn-compatibility/mentions-Self.stderr

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | fn bar(&self, x: &Self);
1515
= help: consider moving `bar` to another trait
1616

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

33-
error[E0038]: the trait `Bar` is not dyn compatible
34-
--> $DIR/mentions-Self.rs:20:5
35-
|
36-
LL | t
37-
| ^ `Bar` is not dyn compatible
38-
|
39-
note: for a trait to be dyn compatible it needs to allow building a vtable
40-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
41-
--> $DIR/mentions-Self.rs:7:22
42-
|
43-
LL | trait Bar {
44-
| --- this trait is not dyn compatible...
45-
LL | fn bar(&self, x: &Self);
46-
| ^^^^^ ...because method `bar` references the `Self` type in this parameter
47-
= help: consider moving `bar` to another trait
48-
= note: required for the cast from `&T` to `&dyn Bar`
49-
50-
error[E0038]: the trait `Baz` is not dyn compatible
51-
--> $DIR/mentions-Self.rs:26:5
52-
|
53-
LL | t
54-
| ^ `Baz` is not dyn compatible
55-
|
56-
note: for a trait to be dyn compatible it needs to allow building a vtable
57-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
58-
--> $DIR/mentions-Self.rs:11:22
59-
|
60-
LL | trait Baz {
61-
| --- this trait is not dyn compatible...
62-
LL | fn baz(&self) -> Self;
63-
| ^^^^ ...because method `baz` references the `Self` type in its return type
64-
= help: consider moving `baz` to another trait
65-
= note: required for the cast from `&T` to `&dyn Baz`
66-
67-
error: aborting due to 4 previous errors
33+
error: aborting due to 2 previous errors
6834

6935
For more information about this error, try `rustc --explain E0038`.

tests/ui/dyn-compatibility/no-static.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,4 @@ impl Foo for Bar {}
1717
fn main() {
1818
let b: Box<dyn Foo> = Box::new(Bar);
1919
//~^ ERROR E0038
20-
//~| ERROR E0038
2120
}

0 commit comments

Comments
 (0)