diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index a87112dcc1230..355b2be1c4349 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -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; @@ -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)]) + } _ => &[], } } diff --git a/tests/ui/associated-consts/associated-const-in-trait.rs b/tests/ui/associated-consts/associated-const-in-trait.rs index 4e8143d5795db..3c43480ef86e8 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.rs +++ b/tests/ui/associated-consts/associated-const-in-trait.rs @@ -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] } diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr index 88360cd2dd5c2..2995b0cd3612f 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.stderr +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -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 + --> $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 @@ -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`. diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs index daf29a0005dec..494127f0ffe97 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs @@ -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 diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr index 90285d512ef03..2fff379264926 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr @@ -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 --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 @@ -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