Inside eager ty aliases on unresolved assoc tys suggest fully qualifying instead of restricting their self ty
This commit is contained in:
parent
898448ca58
commit
3c8b108512
@ -20,8 +20,13 @@ hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identi
|
|||||||
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
|
} associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`
|
||||||
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
|
hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found
|
||||||
hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind}
|
hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind}
|
||||||
|
hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg =
|
||||||
|
consider fully qualifying{$identically_named ->
|
||||||
|
[true] {""}
|
||||||
|
*[false] {" "}and renaming
|
||||||
|
} the associated {$assoc_kind}
|
||||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
|
hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`
|
||||||
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = and also change the associated {$assoc_kind} name
|
hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name
|
||||||
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
|
hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name
|
||||||
|
|
||||||
hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
|
hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
|
||||||
|
@ -126,6 +126,22 @@ pub enum AssocItemNotFoundSugg<'a> {
|
|||||||
assoc_kind: &'static str,
|
assoc_kind: &'static str,
|
||||||
suggested_name: Symbol,
|
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(
|
#[suggestion(
|
||||||
hir_analysis_assoc_item_not_found_other_sugg,
|
hir_analysis_assoc_item_not_found_other_sugg,
|
||||||
code = "{suggested_name}",
|
code = "{suggested_name}",
|
||||||
|
@ -219,7 +219,7 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
|
|||||||
suggested_name,
|
suggested_name,
|
||||||
identically_named: suggested_name == assoc_name.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
|
// 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).
|
// 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...
|
// FIXME: However, for trait aliases, this incorrectly returns the enclosing module...
|
||||||
@ -251,27 +251,44 @@ pub(super) fn complain_about_assoc_item_not_found<I>(
|
|||||||
return self.dcx().emit_err(err);
|
return self.dcx().emit_err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut err = self.dcx().create_err(err);
|
let identically_named = suggested_name == assoc_name.name;
|
||||||
if suggest_constraining_type_param(
|
|
||||||
tcx,
|
if let DefKind::TyAlias = tcx.def_kind(item_def_id)
|
||||||
generics,
|
&& !tcx.type_alias_is_lazy(item_def_id)
|
||||||
&mut err,
|
|
||||||
&qself_str,
|
|
||||||
&trait_name,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
) && suggested_name != assoc_name.name
|
|
||||||
{
|
{
|
||||||
// We suggested constraining a type parameter, but the associated item on it
|
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath {
|
||||||
// was also not an exact match, so we also suggest changing it.
|
lo: ty_param_span.shrink_to_lo(),
|
||||||
err.span_suggestion_verbose(
|
mi: ty_param_span.shrink_to_hi(),
|
||||||
assoc_name.span,
|
hi: (!identically_named).then_some(assoc_name.span),
|
||||||
fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
|
// FIXME(fmease): Use a full trait ref here (with placeholders).
|
||||||
|
trait_: &trait_name,
|
||||||
|
identically_named,
|
||||||
suggested_name,
|
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);
|
return self.dcx().emit_err(err);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ fn lowerer(&self) -> &dyn HirTyLowerer<'tcx>
|
|||||||
/// For diagnostic purposes only.
|
/// For diagnostic purposes only.
|
||||||
enum AssocItemQSelf {
|
enum AssocItemQSelf {
|
||||||
Trait(DefId),
|
Trait(DefId),
|
||||||
TyParam(LocalDefId),
|
TyParam(LocalDefId, Span),
|
||||||
SelfTyAlias,
|
SelfTyAlias,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ impl AssocItemQSelf {
|
|||||||
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
|
fn to_string(&self, tcx: TyCtxt<'_>) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Trait(def_id) => tcx.def_path_str(def_id),
|
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(),
|
Self::SelfTyAlias => kw::SelfUpper.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -820,6 +820,7 @@ fn lower_path_segment(
|
|||||||
fn probe_single_ty_param_bound_for_assoc_ty(
|
fn probe_single_ty_param_bound_for_assoc_ty(
|
||||||
&self,
|
&self,
|
||||||
ty_param_def_id: LocalDefId,
|
ty_param_def_id: LocalDefId,
|
||||||
|
ty_param_span: Span,
|
||||||
assoc_name: Ident,
|
assoc_name: Ident,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
|
||||||
@ -836,7 +837,7 @@ fn probe_single_ty_param_bound_for_assoc_ty(
|
|||||||
.filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref)));
|
.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)
|
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,
|
ty::AssocKind::Type,
|
||||||
assoc_name,
|
assoc_name,
|
||||||
span,
|
span,
|
||||||
@ -1080,6 +1081,7 @@ pub fn lower_assoc_path(
|
|||||||
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
|
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
|
||||||
) => self.probe_single_ty_param_bound_for_assoc_ty(
|
) => self.probe_single_ty_param_bound_for_assoc_ty(
|
||||||
param_did.expect_local(),
|
param_did.expect_local(),
|
||||||
|
qself.span,
|
||||||
assoc_ident,
|
assoc_ident,
|
||||||
span,
|
span,
|
||||||
)?,
|
)?,
|
||||||
|
@ -19,7 +19,7 @@ help: consider further restricting type parameter `T`
|
|||||||
|
|
|
|
||||||
LL | T::Baa: std::fmt::Debug, T: Foo
|
LL | T::Baa: std::fmt::Debug, T: Foo
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
help: and also change the associated type name
|
help: ...and changing the associated type name
|
||||||
|
|
|
|
||||||
LL | T::Bar: std::fmt::Debug,
|
LL | T::Bar: std::fmt::Debug,
|
||||||
| ~~~
|
| ~~~
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
error[E0220]: associated type `Assoc` not found for `T`
|
||||||
|
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:11:22
|
||||||
|
|
|
||||||
|
LL | type AssocOf<T> = T::Assoc;
|
||||||
|
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
|
||||||
|
|
|
||||||
|
help: consider fully qualifying the associated type
|
||||||
|
|
|
||||||
|
LL | type AssocOf<T> = <T as Trait>::Assoc;
|
||||||
|
| + +++++++++
|
||||||
|
|
||||||
|
error[E0220]: associated type `Assok` not found for `T`
|
||||||
|
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:15:22
|
||||||
|
|
|
||||||
|
LL | type AssokOf<T> = T::Assok;
|
||||||
|
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
|
||||||
|
|
|
||||||
|
help: consider fully qualifying and renaming the associated type
|
||||||
|
|
|
||||||
|
LL | type AssokOf<T> = <T as Trait>::Assoc;
|
||||||
|
| + +++++++++ ~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0220`.
|
@ -0,0 +1,29 @@
|
|||||||
|
error[E0220]: associated type `Assoc` not found for `T`
|
||||||
|
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:11:22
|
||||||
|
|
|
||||||
|
LL | type AssocOf<T> = T::Assoc;
|
||||||
|
| ^^^^^ there is an associated type `Assoc` in the trait `Trait`
|
||||||
|
|
|
||||||
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | type AssocOf<T: Trait> = T::Assoc;
|
||||||
|
| +++++++
|
||||||
|
|
||||||
|
error[E0220]: associated type `Assok` not found for `T`
|
||||||
|
--> $DIR/unresolved-assoc-ty-suggest-trait.rs:15:22
|
||||||
|
|
|
||||||
|
LL | type AssokOf<T> = T::Assok;
|
||||||
|
| ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait`
|
||||||
|
|
|
||||||
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | type AssokOf<T: Trait> = T::Assok;
|
||||||
|
| +++++++
|
||||||
|
help: ...and changing the associated type name
|
||||||
|
|
|
||||||
|
LL | type AssokOf<T> = T::Assoc;
|
||||||
|
| ~~~~~
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0220`.
|
20
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
Normal file
20
tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Ensure that we don't suggest *type alias bounds* for **eager** type aliases.
|
||||||
|
// issue: rust-lang/rust#125789
|
||||||
|
|
||||||
|
//@ revisions: eager lazy
|
||||||
|
#![cfg_attr(lazy, feature(lazy_type_alias), allow(incomplete_features))]
|
||||||
|
|
||||||
|
// FIXME(fmease): Suggest a full trait ref (with placeholders) instead of just a trait name.
|
||||||
|
|
||||||
|
trait Trait<T> { type Assoc; }
|
||||||
|
|
||||||
|
type AssocOf<T> = T::Assoc; //~ ERROR associated type `Assoc` not found for `T`
|
||||||
|
//[eager]~^ HELP consider fully qualifying the associated type
|
||||||
|
//[lazy]~| HELP consider restricting type parameter `T`
|
||||||
|
|
||||||
|
type AssokOf<T> = T::Assok; //~ ERROR associated type `Assok` not found for `T`
|
||||||
|
//[eager]~^ HELP consider fully qualifying and renaming the associated type
|
||||||
|
//[lazy]~| HELP consider restricting type parameter `T`
|
||||||
|
//[lazy]~| HELP and changing the associated type name
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user