Inside eager ty aliases on unresolved assoc tys suggest fully qualifying instead of restricting their self ty
This commit is contained in:
@@ -126,6 +126,22 @@ pub enum AssocItemNotFoundSugg<'a> {
|
||||
assoc_kind: &'static str,
|
||||
suggested_name: Symbol,
|
||||
},
|
||||
#[multipart_suggestion(
|
||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg,
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
SimilarInOtherTraitQPath {
|
||||
#[suggestion_part(code = "<")]
|
||||
lo: Span,
|
||||
#[suggestion_part(code = " as {trait_}>")]
|
||||
mi: Span,
|
||||
#[suggestion_part(code = "{suggested_name}")]
|
||||
hi: Option<Span>,
|
||||
trait_: &'a str,
|
||||
suggested_name: Symbol,
|
||||
identically_named: bool,
|
||||
},
|
||||
#[suggestion(
|
||||
hir_analysis_assoc_item_not_found_other_sugg,
|
||||
code = "{suggested_name}",
|
||||
|
||||
@@ -219,7 +219,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
suggested_name,
|
||||
identically_named: suggested_name == assoc_name.name,
|
||||
});
|
||||
if let AssocItemQSelf::TyParam(ty_param_def_id) = qself
|
||||
if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself
|
||||
// Not using `self.item_def_id()` here as that would yield the opaque type itself if we're
|
||||
// inside an opaque type while we're interested in the overarching type alias (TAIT).
|
||||
// FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
|
||||
@@ -251,27 +251,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
return self.dcx().emit_err(err);
|
||||
}
|
||||
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if suggest_constraining_type_param(
|
||||
tcx,
|
||||
generics,
|
||||
&mut err,
|
||||
&qself_str,
|
||||
&trait_name,
|
||||
None,
|
||||
None,
|
||||
) && suggested_name != assoc_name.name
|
||||
let identically_named = suggested_name == assoc_name.name;
|
||||
|
||||
if let DefKind::TyAlias = tcx.def_kind(item_def_id)
|
||||
&& !tcx.type_alias_is_lazy(item_def_id)
|
||||
{
|
||||
// We suggested constraining a type parameter, but the associated item on it
|
||||
// was also not an exact match, so we also suggest changing it.
|
||||
err.span_suggestion_verbose(
|
||||
assoc_name.span,
|
||||
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
|
||||
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
|
||||
lo: ty_param_span.shrink_to_lo(),
|
||||
mi: ty_param_span.shrink_to_hi(),
|
||||
hi: (!identically_named).then_some(assoc_name.span),
|
||||
// FIXME(fmease): Use a full trait ref here (with placeholders).
|
||||
trait_: &trait_name,
|
||||
identically_named,
|
||||
suggested_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if suggest_constraining_type_param(
|
||||
tcx,
|
||||
generics,
|
||||
&mut err,
|
||||
&qself_str,
|
||||
// FIXME(fmease): Use a full trait ref here (with placeholders).
|
||||
&trait_name,
|
||||
None,
|
||||
None,
|
||||
) && !identically_named
|
||||
{
|
||||
// We suggested constraining a type parameter, but the associated item on it
|
||||
// was also not an exact match, so we also suggest changing it.
|
||||
err.span_suggestion_verbose(
|
||||
assoc_name.span,
|
||||
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
|
||||
suggested_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
return err.emit();
|
||||
}
|
||||
return err.emit();
|
||||
}
|
||||
return self.dcx().emit_err(err);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ pub trait HirTyLowerer<'tcx> {
|
||||
/// For diagnostic purposes only.
|
||||
enum AssocItemQSelf {
|
||||
Trait(DefId),
|
||||
TyParam(LocalDefId),
|
||||
TyParam(LocalDefId, Span),
|
||||
SelfTyAlias,
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ impl AssocItemQSelf {
|
||||
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
|
||||
match *self {
|
||||
Self::Trait(def_id) => tcx.def_path_str(def_id),
|
||||
Self::TyParam(def_id) => tcx.hir().ty_param_name(def_id).to_string(),
|
||||
Self::TyParam(def_id, _) => tcx.hir().ty_param_name(def_id).to_string(),
|
||||
Self::SelfTyAlias => kw::SelfUpper.to_string(),
|
||||
}
|
||||
}
|
||||
@@ -820,6 +820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
fn probe_single_ty_param_bound_for_assoc_ty(
|
||||
&self,
|
||||
ty_param_def_id: LocalDefId,
|
||||
ty_param_span: Span,
|
||||
assoc_name: Ident,
|
||||
span: Span,
|
||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
||||
@@ -836,7 +837,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
|
||||
traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
|
||||
},
|
||||
AssocItemQSelf::TyParam(ty_param_def_id),
|
||||
AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
|
||||
ty::AssocKind::Type,
|
||||
assoc_name,
|
||||
span,
|
||||
@@ -1080,6 +1081,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
|
||||
) => self.probe_single_ty_param_bound_for_assoc_ty(
|
||||
param_did.expect_local(),
|
||||
qself.span,
|
||||
assoc_ident,
|
||||
span,
|
||||
)?,
|
||||
|
||||
Reference in New Issue
Block a user