Skip to content

Commit 2ffefb5

Browse files
committed
Reduce number of error messages
1 parent 28f1c43 commit 2ffefb5

8 files changed

Lines changed: 95 additions & 31 deletions

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use super::{
2626
SelectionError, specialization_graph, translate_args, util,
2727
};
2828
use crate::diagnostics::InherentProjectionNormalizationOverflow;
29+
use crate::error_reporting::traits::report_dyn_incompatibility;
2930
use crate::infer::{BoundRegionConversionTime, InferOk};
3031
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
3132
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -712,6 +713,35 @@ fn project<'cx, 'tcx>(
712713
)));
713714
}
714715

716+
// `<dyn Trait>::Name` is only valid when `Trait` is dyn-compatible.
717+
// If it isn't, create an error at the projection site and return a tainted error term.
718+
let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty());
719+
if let ty::Dynamic(data, ..) = self_ty.kind() {
720+
if let Some(def_id) = data.principal_def_id() {
721+
let tcx = selcx.tcx();
722+
if !tcx.is_dyn_compatible(def_id) {
723+
let span = obligation.cause.span;
724+
let guar = if !span.is_dummy() {
725+
let violations = tcx.dyn_compatibility_violations(def_id);
726+
report_dyn_incompatibility(tcx, span, None, def_id, &violations).emit()
727+
} else {
728+
tcx.dcx().span_delayed_bug(
729+
span,
730+
format!(
731+
"projection from non-dyn-compatible trait `{}`",
732+
tcx.def_path_str(def_id)
733+
),
734+
)
735+
};
736+
return Ok(Projected::Progress(Progress::error_for_term(
737+
tcx,
738+
obligation.predicate,
739+
guar,
740+
)));
741+
}
742+
}
743+
}
744+
715745
let mut candidates = ProjectionCandidateSet::None;
716746

717747
// Make sure that the following procedures are kept in order. ParamEnv
@@ -857,11 +887,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
857887
_ => return,
858888
};
859889

860-
// Projecting `dyn Trait` is only valid when `Trait` is dyn-compatible.
861-
if data.principal_def_id().is_some_and(|def_id| !tcx.is_dyn_compatible(def_id)) {
862-
return;
863-
}
864-
865890
let env_predicates = data
866891
.projection_bounds()
867892
.filter(|bound| bound.item_def_id() == obligation.predicate.expect_projection_def_id())

tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ trait Foo: Deref<Target = W> {
1212
fn test(x: &dyn Foo) {
1313
//~^ ERROR the trait `Foo` is not dyn compatible
1414
x.method();
15-
//~^ ERROR no method named `method` found for reference `&dyn Foo`
1615
}
1716

1817
fn main() {}

tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,7 @@ LL | fn method(self: &W) {}
2525
= note: type of `self` must be `Self` or a type that dereferences to it
2626
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
2727

28-
error[E0599]: no method named `method` found for reference `&dyn Foo` in the current scope
29-
--> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:14:7
30-
|
31-
LL | fn method(self: &W) {}
32-
| -- the method might not be found because of this arbitrary self type
33-
...
34-
LL | x.method();
35-
| ^^^^^^ method not found in `&dyn Foo`
36-
37-
error: aborting due to 3 previous errors
28+
error: aborting due to 2 previous errors
3829

39-
Some errors have detailed explanations: E0038, E0307, E0599.
30+
Some errors have detailed explanations: E0038, E0307.
4031
For more information about an error, try `rustc --explain E0038`.

tests/ui/traits/ice-with-dyn-pointee-errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn unknown_sized_object_ptr_in(_: &(impl Pointee<Metadata = ()> + ?Sized)) {}
88
fn raw_pointer_in(x: &dyn Pointee<Metadata = ()>) {
99
//~^ ERROR the trait `Pointee` is not dyn compatible
1010
unknown_sized_object_ptr_in(x)
11-
//~^ ERROR type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::Metadata == ()`
11+
//~^ ERROR the trait `Pointee` is not dyn compatible
1212
//~| ERROR the trait `Pointee` is not dyn compatible
1313
}
1414

tests/ui/traits/ice-with-dyn-pointee-errors.stderr

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,17 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
1010
|
1111
= note: the trait is not dyn compatible because it opted out of dyn-compatibility
1212

13-
error[E0271]: type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::Metadata == ()`
14-
--> $DIR/ice-with-dyn-pointee-errors.rs:10:33
13+
error[E0038]: the trait `Pointee` is not dyn compatible
14+
--> $DIR/ice-with-dyn-pointee-errors.rs:10:5
1515
|
1616
LL | unknown_sized_object_ptr_in(x)
17-
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ()>>`
18-
| |
19-
| required by a bound introduced by this call
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Pointee` is not dyn compatible
2018
|
21-
= note: expected unit type `()`
22-
found struct `DynMetadata<dyn Pointee<Metadata = ()>>`
23-
note: required by a bound in `unknown_sized_object_ptr_in`
24-
--> $DIR/ice-with-dyn-pointee-errors.rs:6:50
19+
note: for a trait to be dyn compatible it needs to allow building a vtable
20+
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
21+
--> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
2522
|
26-
LL | fn unknown_sized_object_ptr_in(_: &(impl Pointee<Metadata = ()> + ?Sized)) {}
27-
| ^^^^^^^^^^^^^ required by this bound in `unknown_sized_object_ptr_in`
23+
= note: the trait is not dyn compatible because it opted out of dyn-compatibility
2824

2925
error[E0038]: the trait `Pointee` is not dyn compatible
3026
--> $DIR/ice-with-dyn-pointee-errors.rs:10:5
@@ -52,5 +48,4 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
5248

5349
error: aborting due to 4 previous errors
5450

55-
Some errors have detailed explanations: E0038, E0271.
56-
For more information about an error, try `rustc --explain E0038`.
51+
For more information about this error, try `rustc --explain E0038`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Check that we are not producing long error messages
2+
3+
trait Trait {
4+
type Output;
5+
fn process<T>(&mut self, input: T) -> T;
6+
}
7+
8+
struct MyImpl;
9+
10+
impl Trait for MyImpl {
11+
type Output = &'static str;
12+
fn process<T>(&mut self, input: T) -> T { input }
13+
}
14+
15+
fn make() -> impl Trait<Output = <dyn Trait<Output = &'static str> as Trait>::Output> {
16+
//~^ ERROR the trait `Trait` is not dyn compatible
17+
MyImpl
18+
}
19+
20+
fn main() {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0038]: the trait `Trait` is not dyn compatible
2+
--> $DIR/dyn-proj-non-dyn-compat.rs:15:14
3+
|
4+
LL | fn make() -> impl Trait<Output = <dyn Trait<Output = &'static str> as Trait>::Output> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` 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/dyn-proj-non-dyn-compat.rs:5:8
10+
|
11+
LL | trait Trait {
12+
| ----- this trait is not dyn compatible...
13+
LL | type Output;
14+
LL | fn process<T>(&mut self, input: T) -> T;
15+
| ^^^^^^^ ...because method `process` has generic type parameters
16+
= help: consider moving `process` to another trait
17+
= help: only type `MyImpl` implements `Trait`; consider using it directly instead.
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0038`.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ check-pass
2+
// Protection against a naive fix for #152607
3+
4+
//@ revisions: current next
5+
6+
//@ ignore-compare-mode-next-solver (explicit revisions)
7+
//@[next] compile-flags: -Znext-solver
8+
9+
trait Trait<T: Sized> {}
10+
11+
fn foo(_: &dyn Trait<[u32]>) {}
12+
13+
fn main() {}

0 commit comments

Comments
 (0)