Skip to content

Commit b6badee

Browse files
committed
Fix span when suggesting to add an associated type bound
1 parent b919797 commit b6badee

File tree

1 file changed

+45
-20
lines changed

1 file changed

+45
-20
lines changed

compiler/rustc_middle/src/ty/error.rs

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ impl<T> Trait<T> for X {
628628
assoc_substs,
629629
ty,
630630
msg,
631+
false,
631632
) {
632633
return true;
633634
}
@@ -646,6 +647,7 @@ impl<T> Trait<T> for X {
646647
assoc_substs,
647648
ty,
648649
msg,
650+
false,
649651
);
650652
}
651653
}
@@ -771,13 +773,24 @@ fn foo(&self) -> Self::T { String::new() }
771773
) -> bool {
772774
let assoc = self.associated_item(proj_ty.item_def_id);
773775
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
774-
self.constrain_associated_type_structured_suggestion(
776+
let opaque_local_def_id = def_id.expect_local();
777+
let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id);
778+
let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind {
779+
hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
780+
_ => bug!("The HirId comes from a `ty::Opaque`"),
781+
};
782+
783+
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
784+
785+
self.constrain_generic_bound_associated_type_structured_suggestion(
775786
db,
776-
self.def_span(def_id),
777-
&assoc,
778-
proj_ty.trait_ref_and_own_substs(self).1,
787+
&trait_ref,
788+
opaque_hir_ty.bounds,
789+
assoc,
790+
assoc_substs,
779791
ty,
780-
&msg,
792+
msg,
793+
true,
781794
)
782795
} else {
783796
false
@@ -899,6 +912,11 @@ fn foo(&self) -> Self::T { String::new() }
899912

900913
/// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
901914
/// requirement, provide a structured suggestion to constrain it to a given type `ty`.
915+
///
916+
/// `is_bound_surely_present` indicates whether we know the bound we're looking for is
917+
/// inside `bounds`. If that's the case then we can consider `bounds` containing only one
918+
/// trait bound as the one we're looking for. This can help in cases where the associated
919+
/// type is defined on a supertrait of the one present in the bounds.
902920
fn constrain_generic_bound_associated_type_structured_suggestion(
903921
self,
904922
db: &mut DiagnosticBuilder<'_>,
@@ -908,23 +926,30 @@ fn foo(&self) -> Self::T { String::new() }
908926
assoc_substs: &[ty::GenericArg<'tcx>],
909927
ty: Ty<'tcx>,
910928
msg: &str,
929+
is_bound_surely_present: bool,
911930
) -> bool {
912931
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
913-
bounds.iter().any(|bound| match bound {
914-
hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => {
915-
// Relate the type param against `T` in `<A as T>::Foo`.
916-
ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)
917-
&& self.constrain_associated_type_structured_suggestion(
918-
db,
919-
ptr.span,
920-
assoc,
921-
assoc_substs,
922-
ty,
923-
msg,
924-
)
925-
}
926-
_ => false,
927-
})
932+
933+
let trait_bounds = bounds.iter().filter_map(|bound| match bound {
934+
hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
935+
_ => None,
936+
});
937+
938+
let matching_trait_bounds = trait_bounds
939+
.clone()
940+
.filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
941+
.collect::<Vec<_>>();
942+
943+
let span = match &matching_trait_bounds[..] {
944+
&[ptr] => ptr.span,
945+
&[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
946+
&[ptr] => ptr.span,
947+
_ => return false,
948+
},
949+
_ => return false,
950+
};
951+
952+
self.constrain_associated_type_structured_suggestion(db, span, assoc, assoc_substs, ty, msg)
928953
}
929954

930955
/// Given a span corresponding to a bound, provide a structured suggestion to set an

0 commit comments

Comments
 (0)