Fix span when suggesting to add an associated type bound
This commit is contained in:
parent
b9197978a9
commit
b6badee140
1 changed files with 45 additions and 20 deletions
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue