adjust obligation spans for super projections
This commit is contained in:
parent
6fa58be8f4
commit
189e7843e8
@ -1294,8 +1294,9 @@ fn check_impl<'tcx>(
|
|||||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||||
// other `Foo` impls are incoherent.
|
// other `Foo` impls are incoherent.
|
||||||
tcx.ensure().coherent_trait(trait_ref.def_id)?;
|
tcx.ensure().coherent_trait(trait_ref.def_id)?;
|
||||||
|
let trait_span = ast_trait_ref.path.span;
|
||||||
let trait_ref = wfcx.normalize(
|
let trait_ref = wfcx.normalize(
|
||||||
ast_trait_ref.path.span,
|
trait_span,
|
||||||
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
|
||||||
trait_ref,
|
trait_ref,
|
||||||
);
|
);
|
||||||
@ -1306,12 +1307,21 @@ fn check_impl<'tcx>(
|
|||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
wfcx.body_def_id,
|
wfcx.body_def_id,
|
||||||
trait_pred,
|
trait_pred,
|
||||||
ast_trait_ref.path.span,
|
trait_span,
|
||||||
item,
|
item,
|
||||||
);
|
);
|
||||||
for obligation in &mut obligations {
|
for obligation in &mut obligations {
|
||||||
|
if obligation.cause.span != trait_span {
|
||||||
|
// We already have a better span.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred()
|
if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred()
|
||||||
&& pred.self_ty().skip_binder() == trait_ref.self_ty()
|
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
||||||
|
{
|
||||||
|
obligation.cause.span = ast_self_ty.span;
|
||||||
|
}
|
||||||
|
if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred()
|
||||||
|
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
|
||||||
{
|
{
|
||||||
obligation.cause.span = ast_self_ty.span;
|
obligation.cause.span = ast_self_ty.span;
|
||||||
}
|
}
|
||||||
|
@ -223,60 +223,84 @@ enum Elaborate {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Points the cause span of a super predicate at the relevant associated type.
|
||||||
|
///
|
||||||
|
/// Given a trait impl item:
|
||||||
|
///
|
||||||
|
/// ```ignore (incomplete)
|
||||||
|
/// impl TargetTrait for TargetType {
|
||||||
|
/// type Assoc = SomeType;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// And a super predicate of `TargetTrait` that has any of the following forms:
|
||||||
|
///
|
||||||
|
/// 1. `<OtherType as OtherTrait>::Assoc = <TargetType as TargetTrait>::Assoc`
|
||||||
|
/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc = OtherType`
|
||||||
|
/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait`
|
||||||
|
///
|
||||||
|
/// Replace the span of the cause with the span of the associated item:
|
||||||
|
///
|
||||||
|
/// ```ignore (incomplete)
|
||||||
|
/// impl TargetTrait for TargetType {
|
||||||
|
/// type Assoc = SomeType;
|
||||||
|
/// // ^^^^^^^^ this span
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Note that bounds that can be expressed as associated item bounds are **not**
|
||||||
|
/// super predicates. This means that form 2 and 3 from above are only relevant if
|
||||||
|
/// the [`GenericArgsRef`] of the projection type are not its identity arguments.
|
||||||
fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
|
||||||
item: Option<&hir::Item<'tcx>>,
|
item: Option<&hir::Item<'tcx>>,
|
||||||
cause: &mut traits::ObligationCause<'tcx>,
|
cause: &mut traits::ObligationCause<'tcx>,
|
||||||
pred: ty::Predicate<'tcx>,
|
pred: ty::Predicate<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation");
|
||||||
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
|
|
||||||
trait_ref, item, cause, pred
|
|
||||||
);
|
|
||||||
let (items, impl_def_id) = match item {
|
let (items, impl_def_id) = match item {
|
||||||
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => {
|
Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => {
|
||||||
(impl_.items, *owner_id)
|
(impl_.items, *owner_id)
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let fix_span =
|
|
||||||
|impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
|
let ty_to_impl_span = |ty: Ty<'_>| {
|
||||||
hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span,
|
if let ty::Alias(ty::Projection, projection_ty) = ty.kind()
|
||||||
_ => impl_item_ref.span,
|
&& let Some(&impl_item_id) =
|
||||||
};
|
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
|
||||||
|
&& let Some(impl_item) =
|
||||||
|
items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id)
|
||||||
|
{
|
||||||
|
Some(tcx.hir().impl_item(impl_item.id).expect_type().span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// It is fine to skip the binder as we don't care about regions here.
|
// It is fine to skip the binder as we don't care about regions here.
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
|
||||||
// The obligation comes not from the current `impl` nor the `trait` being implemented,
|
// Form 1: The obligation comes not from the current `impl` nor the `trait` being
|
||||||
// but rather from a "second order" obligation, where an associated type has a
|
// implemented, but rather from a "second order" obligation, where an associated
|
||||||
// projection coming from another associated type. See
|
// type has a projection coming from another associated type.
|
||||||
// `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
// See `tests/ui/traits/assoc-type-in-superbad.rs` for an example.
|
||||||
// `traits-assoc-type-in-supertrait-bad.rs`.
|
if let Some(term_ty) = proj.term.ty()
|
||||||
if let Some(ty::Alias(ty::Projection, projection_ty)) =
|
&& let Some(impl_item_span) = ty_to_impl_span(term_ty)
|
||||||
proj.term.ty().map(|ty| ty.kind())
|
|
||||||
&& let Some(&impl_item_id) =
|
|
||||||
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
|
|
||||||
&& let Some(impl_item_span) = items
|
|
||||||
.iter()
|
|
||||||
.find(|item| item.id.owner_id.to_def_id() == impl_item_id)
|
|
||||||
.map(fix_span)
|
|
||||||
{
|
{
|
||||||
cause.span = impl_item_span;
|
cause.span = impl_item_span;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Form 2: A projection obligation for an associated item failed to be met.
|
||||||
|
if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) {
|
||||||
|
cause.span = impl_item_span;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||||
// An associated item obligation born out of the `trait` failed to be met. An example
|
// Form 3: A trait obligation for an associated item failed to be met.
|
||||||
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
|
|
||||||
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
||||||
if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
|
if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) {
|
||||||
&& let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
|
|
||||||
&& let Some(impl_item_span) = items
|
|
||||||
.iter()
|
|
||||||
.find(|item| item.id.owner_id.to_def_id() == impl_item_id)
|
|
||||||
.map(fix_span)
|
|
||||||
{
|
|
||||||
cause.span = impl_item_span;
|
cause.span = impl_item_span;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,9 +379,7 @@ fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate
|
|||||||
traits::ObligationCauseCode::DerivedObligation,
|
traits::ObligationCauseCode::DerivedObligation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
extend_cause_with_original_assoc_item_obligation(
|
extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate);
|
||||||
tcx, trait_ref, item, &mut cause, predicate,
|
|
||||||
);
|
|
||||||
traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
|
traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ fn bug(item: &Self::Item) -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
||||||
//~^ type mismatch resolving `<T as Deref>::Target == T`
|
|
||||||
type Item = T;
|
type Item = T;
|
||||||
|
//~^ type mismatch resolving `<T as Deref>::Target == T`
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
|
error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
|
||||||
--> $DIR/hr-associated-type-projection-1.rs:13:33
|
--> $DIR/hr-associated-type-projection-1.rs:14:17
|
||||||
|
|
|
|
||||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
||||||
| - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
| - expected this type parameter
|
||||||
| |
|
LL | type Item = T;
|
||||||
| expected this type parameter
|
| ^ expected type parameter `T`, found associated type
|
||||||
|
|
|
|
||||||
= note: expected type parameter `T`
|
= note: expected type parameter `T`
|
||||||
found associated type `<T as Deref>::Target`
|
found associated type `<T as Deref>::Target`
|
||||||
|
@ -29,9 +29,9 @@ trait BoundOnGat where Self::Assoc<u8>: Sub {
|
|||||||
type Assoc<T>;
|
type Assoc<T>;
|
||||||
}
|
}
|
||||||
impl BoundOnGat for u8 {
|
impl BoundOnGat for u8 {
|
||||||
//~^ ERROR type mismatch resolving `<() as Super>::Assoc == u16`
|
|
||||||
type Assoc<T> = ();
|
type Assoc<T> = ();
|
||||||
//~^ ERROR the trait bound `(): Sub` is not satisfied
|
//~^ ERROR the trait bound `(): Sub` is not satisfied
|
||||||
|
//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trivial_bound() where (): Sub {}
|
fn trivial_bound() where (): Sub {}
|
||||||
|
@ -16,10 +16,10 @@ LL | trait BoundOnSelf: Sub {}
|
|||||||
| ^^^ required by this bound in `BoundOnSelf`
|
| ^^^ required by this bound in `BoundOnSelf`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:10:6
|
--> $DIR/super-assoc-mismatch.rs:10:22
|
||||||
|
|
|
|
||||||
LL | impl BoundOnSelf for () {}
|
LL | impl BoundOnSelf for () {}
|
||||||
| ^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
| ^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
|
|
|
|
||||||
note: expected this to be `u16`
|
note: expected this to be `u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:5:18
|
--> $DIR/super-assoc-mismatch.rs:5:18
|
||||||
@ -55,10 +55,10 @@ LL | trait BoundOnParam<T: Sub> {}
|
|||||||
| ^^^ required by this bound in `BoundOnParam`
|
| ^^^ required by this bound in `BoundOnParam`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:15:6
|
--> $DIR/super-assoc-mismatch.rs:15:27
|
||||||
|
|
|
|
||||||
LL | impl BoundOnParam<()> for () {}
|
LL | impl BoundOnParam<()> for () {}
|
||||||
| ^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
| ^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
|
|
|
|
||||||
note: expected this to be `u16`
|
note: expected this to be `u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:5:18
|
--> $DIR/super-assoc-mismatch.rs:5:18
|
||||||
@ -116,7 +116,7 @@ LL | type Assoc: Sub;
|
|||||||
| ^^^ required by this bound in `BoundOnAssoc::Assoc`
|
| ^^^ required by this bound in `BoundOnAssoc::Assoc`
|
||||||
|
|
||||||
error[E0277]: the trait bound `(): Sub` is not satisfied
|
error[E0277]: the trait bound `(): Sub` is not satisfied
|
||||||
--> $DIR/super-assoc-mismatch.rs:33:21
|
--> $DIR/super-assoc-mismatch.rs:32:21
|
||||||
|
|
|
|
||||||
LL | type Assoc<T> = ();
|
LL | type Assoc<T> = ();
|
||||||
| ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub`
|
| ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub`
|
||||||
@ -133,10 +133,10 @@ LL | trait BoundOnGat where Self::Assoc<u8>: Sub {
|
|||||||
| ^^^ required by this bound in `BoundOnGat`
|
| ^^^ required by this bound in `BoundOnGat`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:31:6
|
--> $DIR/super-assoc-mismatch.rs:32:21
|
||||||
|
|
|
|
||||||
LL | impl BoundOnGat for u8 {
|
LL | type Assoc<T> = ();
|
||||||
| ^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
| ^^ type mismatch resolving `<() as Super>::Assoc == u16`
|
||||||
|
|
|
|
||||||
note: expected this to be `u16`
|
note: expected this to be `u16`
|
||||||
--> $DIR/super-assoc-mismatch.rs:5:18
|
--> $DIR/super-assoc-mismatch.rs:5:18
|
||||||
|
Loading…
Reference in New Issue
Block a user