Skip to content

Commit 8c0a364

Browse files
committed
Use more detailed spans in dyn compat errors within bodies
1 parent 95a2212 commit 8c0a364

File tree

60 files changed

+217
-654
lines changed

Some content is hidden

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

60 files changed

+217
-654
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
3131
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
3232
use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind};
3333
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
34-
use rustc_infer::traits::ObligationCause;
34+
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
3535
use rustc_middle::hir::nested_filter;
3636
use rustc_middle::query::Providers;
3737
use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug};
4040
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
4141
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
4242
use rustc_trait_selection::infer::InferCtxtExt;
43-
use rustc_trait_selection::traits::ObligationCtxt;
43+
use rustc_trait_selection::traits::{ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations};
4444
use tracing::{debug, instrument};
4545

4646
use crate::errors;
@@ -625,6 +625,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
625625

626626
(input_tys, output_ty)
627627
}
628+
629+
fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
630+
hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
631+
}
628632
}
629633

630634
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::{
1111
};
1212
use rustc_span::{ErrorGuaranteed, Span};
1313
use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
14-
use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations};
14+
use rustc_trait_selection::traits;
1515
use smallvec::{SmallVec, smallvec};
1616
use tracing::{debug, instrument};
1717

@@ -97,8 +97,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
9797
// to avoid ICEs.
9898
for (clause, span) in user_written_bounds {
9999
if let Some(trait_pred) = clause.as_trait_clause() {
100-
let violations =
101-
hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id());
100+
let violations = self.dyn_compatibility_violations(trait_pred.def_id());
102101
if !violations.is_empty() {
103102
let reported = report_dyn_incompatibility(
104103
tcx,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
3333
use rustc_hir::def_id::{DefId, LocalDefId};
3434
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
3535
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
36-
use rustc_infer::traits::ObligationCause;
36+
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
3737
use rustc_middle::middle::stability::AllowUnstable;
3838
use rustc_middle::mir::interpret::LitToConstInput;
3939
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
@@ -200,6 +200,10 @@ pub trait HirTyLowerer<'tcx> {
200200
{
201201
self
202202
}
203+
204+
/// Performs minimalistic dyn compat checks outside of bodies, but full within bodies.
205+
/// Outside of bodies we could end up in cycles, so we delay most checks to later phases.
206+
fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation>;
203207
}
204208

205209
/// The "qualified self" of an associated item path.

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1414
use rustc_hir::{self as hir, HirId, ItemLocalMap};
1515
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
1616
use rustc_infer::infer;
17-
use rustc_infer::traits::Obligation;
17+
use rustc_infer::traits::{DynCompatibilityViolation, Obligation};
1818
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1919
use rustc_session::Session;
2020
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
@@ -388,6 +388,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
388388
};
389389
(input_tys, output_ty)
390390
}
391+
392+
fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
393+
self.tcx.dyn_compatibility_violations(trait_def_id).to_vec()
394+
}
391395
}
392396

393397
/// The `ty` representation of a user-provided type. Depending on the use-site

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

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
88
= note: `#[warn(incomplete_features)]` on by default
99

1010
error[E0038]: the trait `AsyncTrait` is not dyn compatible
11-
--> $DIR/mut-is-pointer-like.rs:35:16
11+
--> $DIR/mut-is-pointer-like.rs:35:29
1212
|
1313
LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f;
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
14+
| ^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
1515
|
1616
note: for a trait to be dyn compatible it needs to allow building a vtable
1717
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -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: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
88
= note: `#[warn(incomplete_features)]` on by default
99

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

28-
error[E0038]: the trait `AsyncTrait` is not dyn compatible
29-
--> $DIR/works.rs:27:16
30-
|
31-
LL | let x: &dyn AsyncTrait = &"hello, world!";
32-
| ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
33-
|
34-
note: for a trait to be dyn compatible it needs to allow building a vtable
35-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
36-
--> $DIR/works.rs:14:14
37-
|
38-
LL | trait AsyncTrait {
39-
| ---------- this trait is not dyn compatible...
40-
LL | async fn async_dispatch(&self);
41-
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
42-
= help: consider moving `async_dispatch` to another trait
43-
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
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/wrong-size.stderr

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ LL | #![feature(async_fn_in_dyn_trait)]
88
= note: `#[warn(incomplete_features)]` on by default
99

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

28-
error[E0038]: the trait `AsyncTrait` is not dyn compatible
29-
--> $DIR/wrong-size.rs:21:12
30-
|
31-
LL | let x: &dyn AsyncTrait = &"hello, world!";
32-
| ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible
33-
|
34-
note: for a trait to be dyn compatible it needs to allow building a vtable
35-
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
36-
--> $DIR/wrong-size.rs:9:14
37-
|
38-
LL | trait AsyncTrait {
39-
| ---------- this trait is not dyn compatible...
40-
LL | async fn async_dispatch(&self);
41-
| ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
42-
= help: consider moving `async_dispatch` to another trait
43-
= help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
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/in-trait/dyn-compatibility.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `Foo` is not dyn compatible
2-
--> $DIR/dyn-compatibility.rs:9:12
2+
--> $DIR/dyn-compatibility.rs:9:17
33
|
44
LL | let x: &dyn Foo = todo!();
5-
| ^^^^^^^^ `Foo` is not dyn compatible
5+
| ^^^ `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>

tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ fn main() {
44
let _: &Copy + 'static; //~ ERROR expected a path
55
//~^ ERROR is not dyn compatible
66
let _: &'static Copy + 'static; //~ ERROR expected a path
7+
//~^ ERROR is not dyn compatible
78
}

tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,26 @@ LL | let _: &'static (Copy + 'static);
2121
| + +
2222

2323
error[E0038]: the trait `Copy` is not dyn compatible
24-
--> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12
24+
--> $DIR/trait-object-reference-without-parens-suggestion.rs:4:13
2525
|
2626
LL | let _: &Copy + 'static;
27-
| ^^^^^ `Copy` is not dyn compatible
27+
| ^^^^ `Copy` is not dyn compatible
28+
|
29+
= note: the trait is not dyn compatible because it requires `Self: Sized`
30+
= note: for a trait to be dyn compatible it needs to allow building a vtable
31+
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
32+
33+
error[E0038]: the trait `Copy` is not dyn compatible
34+
--> $DIR/trait-object-reference-without-parens-suggestion.rs:6:21
35+
|
36+
LL | let _: &'static Copy + 'static;
37+
| ^^^^ `Copy` is not dyn compatible
2838
|
2939
= note: the trait is not dyn compatible because it requires `Self: Sized`
3040
= note: for a trait to be dyn compatible it needs to allow building a vtable
3141
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
3242

33-
error: aborting due to 3 previous errors
43+
error: aborting due to 4 previous errors
3444

3545
Some errors have detailed explanations: E0038, E0178.
3646
For more information about an 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: 6 additions & 24 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...
@@ -16,14 +16,14 @@ LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
1616
= help: consider moving `transmute` to another trait
1717

1818
error[E0038]: the trait `Foo` is not dyn compatible
19-
--> $DIR/almost-supertrait-associated-type.rs:7:27
19+
--> $DIR/almost-supertrait-associated-type.rs:7:32
2020
|
2121
LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
22-
| ^^^^^^^^^^^^^^ `Foo` is not dyn compatible
22+
| ^^^^^^^^^ `Foo` is not dyn compatible
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/generics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
2222
//~^ ERROR E0038
2323
t as &dyn Bar
2424
//~^ ERROR E0038
25-
//~| ERROR E0038
2625
}
2726

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

tests/ui/dyn-compatibility/generics.stderr

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ LL | fn bar<T>(&self, t: T);
4848
= note: required for the cast from `&T` to `&dyn Bar`
4949

5050
error[E0038]: the trait `Bar` is not dyn compatible
51-
--> $DIR/generics.rs:23:10
51+
--> $DIR/generics.rs:23:15
5252
|
5353
LL | t as &dyn Bar
54-
| ^^^^^^^^ `Bar` is not dyn compatible
54+
| ^^^ `Bar` is not dyn compatible
5555
|
5656
note: for a trait to be dyn compatible it needs to allow building a vtable
5757
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@@ -63,23 +63,6 @@ LL | fn bar<T>(&self, t: T);
6363
| ^^^ ...because method `bar` has generic type parameters
6464
= help: consider moving `bar` to another trait
6565

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
66+
error: aborting due to 4 previous errors
8467

8568
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
}

0 commit comments

Comments
 (0)