Skip to content

Commit fbac805

Browse files
Rollup merge of rust-lang#141580 - oli-obk:early-dyn-catches-the-incompat, r=compiler-errors
Use more detailed spans in dyn compat errors within bodies Within bodies we can employ the full dyn compat check query instead of only doing the minimal hir ty lowerer one. This in turn gives us better spans and also silences many follow-up duplicate or bogus errors. alternative to rust-lang#141439, tho I think I could turn the delayed bug from that one into a bug now instead of having an error code path. r? `@compiler-errors` cc `@fmease`
2 parents 2c5361a + 3fff727 commit fbac805

File tree

45 files changed

+205
-206
lines changed

Some content is hidden

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

45 files changed

+205
-206
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: 2 additions & 2 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>

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

Lines changed: 2 additions & 2 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:16
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>

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

Lines changed: 2 additions & 2 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:12
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>

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.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ 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>

tests/ui/dyn-compatibility/generics.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ 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:22:10
34+
--> $DIR/generics.rs:22:15
3535
|
3636
LL | t as &dyn Bar
37-
| ^^^^^^^^ `Bar` is not dyn compatible
37+
| ^^^ `Bar` is not dyn compatible
3838
|
3939
note: for a trait to be dyn compatible it needs to allow building a vtable
4040
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0038]: the trait `Bar` is not dyn compatible
2-
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15
2+
--> $DIR/mention-correct-dyn-incompatible-trait.rs:19:24
33
|
44
LL | let test: &mut dyn Bar = &mut thing;
5-
| ^^^^^^^^^^^^ `Bar` is not dyn compatible
5+
| ^^^ `Bar` 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/dyn-compatibility/no-static.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ LL | fn foo() where Self: Sized {}
2323
| +++++++++++++++++
2424

2525
error[E0038]: the trait `Foo` is not dyn compatible
26-
--> $DIR/no-static.rs:18:12
26+
--> $DIR/no-static.rs:18:20
2727
|
2828
LL | let b: Box<dyn Foo> = Box::new(Bar);
29-
| ^^^^^^^^^^^^ `Foo` is not dyn compatible
29+
| ^^^ `Foo` is not dyn compatible
3030
|
3131
note: for a trait to be dyn compatible it needs to allow building a vtable
3232
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0038]: the trait `Trait` is not dyn compatible
2-
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25
2+
--> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:33
33
|
44
LL | fn ptr(self: Ptr<Self>);
55
| --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self`
66
...
77
LL | Ptr(Box::new(4)) as Ptr<dyn Trait>;
8-
| ^^^^^^^^^^^^^^ `Trait` is not dyn compatible
8+
| ^^^^^ `Trait` is not dyn compatible
99
|
1010
note: for a trait to be dyn compatible it needs to allow building a vtable
1111
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/generic-associated-types/issue-76535.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperS
1515
| ++++
1616

1717
error[E0038]: the trait `SuperTrait` is not dyn compatible
18-
--> $DIR/issue-76535.rs:34:14
18+
--> $DIR/issue-76535.rs:34:22
1919
|
2020
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible
2222
|
2323
note: for a trait to be dyn compatible it needs to allow building a vtable
2424
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/generic-associated-types/issue-78671.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
1515
| +++
1616

1717
error[E0038]: the trait `CollectionFamily` is not dyn compatible
18-
--> $DIR/issue-78671.rs:5:25
18+
--> $DIR/issue-78671.rs:5:30
1919
|
2020
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible
2222
|
2323
note: for a trait to be dyn compatible it needs to allow building a vtable
2424
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/generic-associated-types/issue-79422.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
1515
| ++++
1616

1717
error[E0038]: the trait `MapLike` is not dyn compatible
18-
--> $DIR/issue-79422.rs:45:12
18+
--> $DIR/issue-79422.rs:45:20
1919
|
2020
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible
2222
|
2323
note: for a trait to be dyn compatible it needs to allow building a vtable
2424
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@ fn main() {
1515
//~^ ERROR the trait `Foo` is not dyn compatible
1616

1717
needs_bar(x);
18-
//~^ ERROR mismatched types
1918
}
Lines changed: 4 additions & 21 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/span-bug-issue-121597.rs:14:12
2+
--> $DIR/span-bug-issue-121597.rs:14:17
33
|
44
LL | let x: &dyn Foo = &();
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>
@@ -13,23 +13,6 @@ LL | trait Foo: for<T> Bar<T> {}
1313
| |
1414
| this trait is not dyn compatible...
1515

16-
error[E0308]: mismatched types
17-
--> $DIR/span-bug-issue-121597.rs:17:15
18-
|
19-
LL | needs_bar(x);
20-
| --------- ^ types differ in mutability
21-
| |
22-
| arguments to this function are incorrect
23-
|
24-
= note: expected raw pointer `*mut Type2`
25-
found reference `&dyn Foo`
26-
note: function defined here
27-
--> $DIR/span-bug-issue-121597.rs:11:4
28-
|
29-
LL | fn needs_bar(_: *mut Type2) {}
30-
| ^^^^^^^^^ -------------
31-
32-
error: aborting due to 2 previous errors
16+
error: aborting due to 1 previous error
3317

34-
Some errors have detailed explanations: E0038, E0308.
35-
For more information about an error, try `rustc --explain E0038`.
18+
For more information about this error, try `rustc --explain E0038`.

tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ impl DynIncompatible for B {
2121

2222
fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not dyn compatible
2323
//~^ ERROR return type cannot be a trait object without pointer indirection
24+
//~| ERROR the trait `DynIncompatible` is not dyn compatible
25+
//~| ERROR the trait `DynIncompatible` is not dyn compatible
2426
if true {
2527
return A;
2628
}

0 commit comments

Comments
 (0)