-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deduplicate object safety errors on impl dyn Trait { .. }
#121200
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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; | ||
|
@@ -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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, this should at least be asserting that the implicit object outlives is actually static:
Then at least if the object outlives bound computation changes down the road, this will ICE. |
||
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)]) | ||
} | ||
_ => &[], | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Totally unrelated but if |
||
= 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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer a solution that doesn't involve changing the rules for where we add implicit outlives obligations. This code is really delicate, and I'm worried this could turn out to be unsound without us really knowing why.
Is it possible to instead modify the object safety violation error reporting code to instead prefer pointing at
Self
type rather than arguments? We can get away with corner cases in diagnostics reporting code, but can't really get away with it in good-path code 😅There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, could you explain why adding this outlives obligation actually solves the problem? It's not necessarily clear why this is fixing what it does, and I'm not yet convinced its worth the changes to the
inferred_outlives_of
function for such a special case.