1
Fork 0

Fix span when suggesting to add an associated type bound

This commit is contained in:
Giacomo Stevanato 2021-07-21 14:42:20 +02:00
parent b9197978a9
commit b6badee140

View file

@ -628,6 +628,7 @@ impl<T> Trait<T> for X {
assoc_substs, assoc_substs,
ty, ty,
msg, msg,
false,
) { ) {
return true; return true;
} }
@ -646,6 +647,7 @@ impl<T> Trait<T> for X {
assoc_substs, assoc_substs,
ty, ty,
msg, msg,
false,
); );
} }
} }
@ -771,13 +773,24 @@ fn foo(&self) -> Self::T { String::new() }
) -> bool { ) -> bool {
let assoc = self.associated_item(proj_ty.item_def_id); let assoc = self.associated_item(proj_ty.item_def_id);
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
self.constrain_associated_type_structured_suggestion( let opaque_local_def_id = def_id.expect_local();
let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id);
let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind {
hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
_ => bug!("The HirId comes from a `ty::Opaque`"),
};
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
self.constrain_generic_bound_associated_type_structured_suggestion(
db, db,
self.def_span(def_id), &trait_ref,
&assoc, opaque_hir_ty.bounds,
proj_ty.trait_ref_and_own_substs(self).1, assoc,
assoc_substs,
ty, ty,
&msg, msg,
true,
) )
} else { } else {
false false
@ -899,6 +912,11 @@ fn foo(&self) -> Self::T { String::new() }
/// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref` /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
/// requirement, provide a structured suggestion to constrain it to a given type `ty`. /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
///
/// `is_bound_surely_present` indicates whether we know the bound we're looking for is
/// inside `bounds`. If that's the case then we can consider `bounds` containing only one
/// trait bound as the one we're looking for. This can help in cases where the associated
/// type is defined on a supertrait of the one present in the bounds.
fn constrain_generic_bound_associated_type_structured_suggestion( fn constrain_generic_bound_associated_type_structured_suggestion(
self, self,
db: &mut DiagnosticBuilder<'_>, db: &mut DiagnosticBuilder<'_>,
@ -908,23 +926,30 @@ fn foo(&self) -> Self::T { String::new() }
assoc_substs: &[ty::GenericArg<'tcx>], assoc_substs: &[ty::GenericArg<'tcx>],
ty: Ty<'tcx>, ty: Ty<'tcx>,
msg: &str, msg: &str,
is_bound_surely_present: bool,
) -> bool { ) -> bool {
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
bounds.iter().any(|bound| match bound {
hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => { let trait_bounds = bounds.iter().filter_map(|bound| match bound {
// Relate the type param against `T` in `<A as T>::Foo`. hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id) _ => None,
&& self.constrain_associated_type_structured_suggestion( });
db,
ptr.span, let matching_trait_bounds = trait_bounds
assoc, .clone()
assoc_substs, .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
ty, .collect::<Vec<_>>();
msg,
) let span = match &matching_trait_bounds[..] {
} &[ptr] => ptr.span,
_ => false, &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
}) &[ptr] => ptr.span,
_ => return false,
},
_ => return false,
};
self.constrain_associated_type_structured_suggestion(db, span, assoc, assoc_substs, ty, msg)
} }
/// Given a span corresponding to a bound, provide a structured suggestion to set an /// Given a span corresponding to a bound, provide a structured suggestion to set an