-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Improve spans for specialization error #98782
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
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 |
---|---|---|
|
@@ -279,11 +279,16 @@ fn check_predicates<'tcx>( | |
span: Span, | ||
) { | ||
let tcx = infcx.tcx; | ||
let impl1_predicates: Vec<_> = traits::elaborate_predicates( | ||
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); | ||
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( | ||
tcx, | ||
tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), | ||
std::iter::zip( | ||
instantiated.predicates, | ||
// Don't drop predicates (unsound!) because `spans` is too short | ||
instantiated.spans.into_iter().chain(std::iter::repeat(span)), | ||
), | ||
) | ||
.map(|obligation| obligation.predicate) | ||
.map(|obligation| (obligation.predicate, obligation.cause.span)) | ||
.collect(); | ||
|
||
let mut impl2_predicates = if impl2_node.is_from_trait() { | ||
|
@@ -321,7 +326,7 @@ fn check_predicates<'tcx>( | |
// which is sound because we forbid impls like the following | ||
// | ||
// impl<D: Debug> AlwaysApplicable for D { } | ||
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { | ||
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| { | ||
matches!( | ||
trait_predicate_kind(tcx, predicate), | ||
Some(TraitSpecializationKind::AlwaysApplicable) | ||
|
@@ -345,11 +350,11 @@ fn check_predicates<'tcx>( | |
} | ||
} | ||
impl2_predicates.extend( | ||
traits::elaborate_predicates(tcx, always_applicable_traits) | ||
traits::elaborate_predicates_with_span(tcx, always_applicable_traits) | ||
.map(|obligation| obligation.predicate), | ||
); | ||
|
||
for predicate in impl1_predicates { | ||
for (predicate, span) in impl1_predicates { | ||
if !impl2_predicates.contains(&predicate) { | ||
check_specialization_on(tcx, predicate, span) | ||
} | ||
|
@@ -384,9 +389,17 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc | |
.emit(); | ||
} | ||
} | ||
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { | ||
tcx.sess | ||
.struct_span_err( | ||
span, | ||
&format!("cannot specialize on associated type `{projection_ty} == {term}`",), | ||
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. hm, i guess i could rebind 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. yea, not really worth it for the diagnostic. You could emit another note if the binders actually bind anything stating that specialization on lifetimes is not... ideal. But unless we have some good specialization docs for that that we could link to, not really worth it. |
||
) | ||
.emit(); | ||
} | ||
_ => { | ||
tcx.sess | ||
.struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) | ||
.struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate)) | ||
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. the other predicates have a display impl, why not use it |
||
.emit(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[54ea]::Id::This) }, Ty((I,))), [])` | ||
--> $DIR/repeated_projection_type.rs:19:1 | ||
error: cannot specialize on associated type `<V as Id>::This == (I,)` | ||
--> $DIR/repeated_projection_type.rs:19:15 | ||
| | ||
LL | impl<I, V: Id<This = (I,)>> X for V { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| ^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
error: cannot specialize on trait `HasMethod` | ||
--> $DIR/spec-marker-supertraits.rs:22:1 | ||
--> $DIR/spec-marker-supertraits.rs:22:9 | ||
| | ||
LL | impl<T: Marker> Spec for T { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| ^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
error: cannot specialize on trait `Default` | ||
--> $DIR/specialization_super_trait.rs:13:1 | ||
--> $DIR/specialization_super_trait.rs:13:9 | ||
| | ||
LL | impl<T: Default> SpecMarker for T { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| ^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
error: cannot specialize on trait `SpecMarker` | ||
--> $DIR/specialize_on_trait.rs:15:1 | ||
--> $DIR/specialize_on_trait.rs:15:9 | ||
| | ||
LL | impl<T: SpecMarker> X for T { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| ^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
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 can't leave a comment on line (new) 385 (old 380), but we should probably just print the whole trait ref instead of just the def path...?