Skip to content

Commit

Permalink
Deduplicate oject safety errors on impl dyn Trait { .. }
Browse files Browse the repository at this point in the history
`impl dyn Trait {}` has an implicit `dyn Trait: 'static` bound. We add it in
`inferred_outlives_of` for more context in errors. With this we point at
`impl dyn Trait` and not to it's associated functions, deduplicating errors
to a single one per `impl dyn Trait` instead of one for it plus one for each
associated function.
  • Loading branch information
estebank committed Feb 16, 2024
1 parent 0f806a9 commit 1e03e2b
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 6 deletions.
19 changes: 19 additions & 0 deletions compiler/rustc_hir_analysis/src/outlives/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
Expand Down Expand Up @@ -46,6 +47,24 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
&[]
}
}
DefKind::Impl { of_trait: false }
if let hir::ItemKind::Impl(item) = tcx.hir().expect_item(item_def_id).kind
&& let hir::Impl { self_ty, .. } = &item
&& let hir::TyKind::TraitObject(
_,
hir::Lifetime { res: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
_,
) = self_ty.kind =>
{
// `impl dyn Trait {}` has an implicit `dyn Trait: 'static` bound. We add it here for
// more context in errors. With this we point at `impl dyn Trait` and not to it's
// associated functions, deduplicating errors to a single one per `impl dyn Trait` instead
// of one for it plus one for each associated function.
let ty = tcx.type_of(item_def_id).instantiate_identity();
let clause_kind =
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, tcx.lifetimes.re_static));
&*tcx.arena.alloc_from_iter([(clause_kind.to_predicate(tcx), self_ty.span)])
}
_ => &[],
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/ui/associated-consts/associated-const-in-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ trait Trait {

impl dyn Trait {
//~^ ERROR the trait `Trait` cannot be made into an object [E0038]
//~| ERROR the trait `Trait` cannot be made into an object [E0038]
const fn n() -> usize { Self::N }
//~^ ERROR the trait `Trait` cannot be made into an object [E0038]
}
Expand Down
20 changes: 18 additions & 2 deletions tests/ui/associated-consts/associated-const-in-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,23 @@ LL | const N: usize;
= help: consider moving `N` to another trait

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/associated-const-in-trait.rs:9:29
--> $DIR/associated-const-in-trait.rs:7:6
|
LL | impl dyn Trait {
| ^^^^^^^^^ `Trait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/associated-const-in-trait.rs:4:11
|
LL | trait Trait {
| ----- this trait cannot be made into an object...
LL | const N: usize;
| ^ ...because it contains this associated `const`
= help: consider moving `N` to another trait
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/associated-const-in-trait.rs:10:29
|
LL | const fn n() -> usize { Self::N }
| ^^^^ `Trait` cannot be made into an object
Expand All @@ -28,6 +44,6 @@ LL | const N: usize;
| ^ ...because it contains this associated `const`
= help: consider moving `N` to another trait

error: aborting due to 2 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 @@ -15,8 +15,8 @@ impl MyTrait for Outer {

impl dyn MyTrait {
//~^ ERROR the trait `MyTrait` cannot be made into an object
//~| ERROR the trait `MyTrait` cannot be made into an object
fn other(&self) -> impl Marker {
//~^ ERROR the trait `MyTrait` cannot be made into an object
MyTrait::foo(&self)
//~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied
//~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ LL | fn foo(&self) -> impl Marker;
= help: only type `Outer` implements the trait, consider using it directly instead

error[E0038]: the trait `MyTrait` cannot be made into an object
--> $DIR/cycle-effective-visibilities-during-object-safety.rs:18:15
--> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6
|
LL | fn other(&self) -> impl Marker {
| ^^^^ `MyTrait` cannot be made into an object
LL | impl dyn MyTrait {
| ^^^^^^^^^^^ `MyTrait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22
Expand All @@ -63,6 +63,7 @@ LL | fn foo(&self) -> impl Marker;
| ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type
= help: consider moving `foo` to another trait
= help: only type `Outer` implements the trait, consider using it directly instead
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 5 previous errors

Expand Down

0 comments on commit 1e03e2b

Please sign in to comment.