Introduce AssocTag::descr & refactor in the vicinity

This commit is contained in:
León Orell Valerian Liehr
2026-01-06 23:40:21 +01:00
parent 7c8210ea1f
commit baba337869
14 changed files with 81 additions and 78 deletions
@@ -1960,7 +1960,7 @@ fn compare_generic_param_kinds<'tcx>(
trait_item: ty::AssocItem,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
assert_eq!(impl_item.as_tag(), trait_item.as_tag());
assert_eq!(impl_item.tag(), trait_item.tag());
let ty_const_params_of = |def_id| {
tcx.generics_of(def_id).own_params.iter().filter(|param| {
@@ -171,7 +171,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order())
.filter_map(|item| {
if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag {
if !item.is_impl_trait_in_trait() && item.tag() == assoc_tag {
item.opt_name()
} else {
None
@@ -207,7 +207,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
.iter()
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
.filter_map(|item| {
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
(!item.is_impl_trait_in_trait() && item.tag() == assoc_tag).then(|| item.name())
})
.collect();
@@ -220,7 +220,7 @@ pub(super) fn report_unresolved_assoc_item<I>(
.filter(|trait_def_id| {
tcx.associated_items(trait_def_id)
.filter_by_name_unhygienic(suggested_name)
.any(|item| item.as_tag() == assoc_tag)
.any(|item| item.tag() == assoc_tag)
})
.collect::<Vec<_>>()[..]
{
@@ -383,9 +383,9 @@ fn report_assoc_kind_mismatch(
hir::Term::Ty(ty) => ty.span,
hir::Term::Const(ct) => ct.span,
};
(span, Some(ident.span), assoc_item.as_tag(), assoc_tag)
(span, Some(ident.span), assoc_item.tag(), assoc_tag)
} else {
(ident.span, None, assoc_tag, assoc_item.as_tag())
(ident.span, None, assoc_tag, assoc_item.tag())
};
self.dcx().emit_err(errors::AssocKindMismatch {
@@ -393,7 +393,7 @@ fn report_assoc_kind_mismatch(
expected: assoc_tag_str(expected),
got: assoc_tag_str(got),
expected_because_label,
assoc_kind: assoc_tag_str(assoc_item.as_tag()),
assoc_kind: assoc_tag_str(assoc_item.tag()),
def_span: tcx.def_span(assoc_item.def_id),
bound_on_assoc_const_label,
wrap_in_braces_sugg,
@@ -965,8 +965,8 @@ enum Descr {
names_len += 1;
descr = match descr {
None => Some(Descr::Tag(assoc_item.as_tag())),
Some(Descr::Tag(tag)) if tag != assoc_item.as_tag() => Some(Descr::Item),
None => Some(Descr::Tag(assoc_item.tag())),
Some(Descr::Tag(tag)) if tag != assoc_item.tag() => Some(Descr::Item),
_ => continue,
};
}
@@ -1030,10 +1030,8 @@ enum Descr {
let names = names.join(", ");
let descr = match descr.unwrap() {
// FIXME(fmease): Create `ty::AssocTag::descr`.
Descr::Tag(ty::AssocTag::Type) => "associated type",
Descr::Tag(ty::AssocTag::Const) => "associated constant",
_ => "associated item",
Descr::Item => "associated item",
Descr::Tag(tag) => tag.descr(),
};
let mut err = struct_span_code_err!(
self.dcx(),
@@ -1050,13 +1048,13 @@ enum Descr {
let mut names: UnordMap<_, usize> = Default::default();
for (item, _) in &missing_assoc_items {
items_count += 1;
*names.entry((item.name(), item.as_tag())).or_insert(0) += 1;
*names.entry((item.name(), item.tag())).or_insert(0) += 1;
}
let mut dupes = false;
let mut shadows = false;
for (item, trait_ref) in &missing_assoc_items {
let name = item.name();
let key = (name, item.as_tag());
let key = (name, item.tag());
if names[&key] > 1 {
dupes = true;
@@ -1768,7 +1768,7 @@ fn probe_assoc_item_unchecked(
let item = tcx
.associated_items(scope)
.filter_by_name_unhygienic(ident.name)
.find(|i| i.as_tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
.find(|i| i.tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?;
Some((*item, def_scope))
}
+41 -36
View File
@@ -126,27 +126,15 @@ pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
}
pub fn descr(&self) -> &'static str {
match self.kind {
ty::AssocKind::Const { .. } => "associated const",
ty::AssocKind::Fn { has_self: true, .. } => "method",
ty::AssocKind::Fn { has_self: false, .. } => "associated function",
ty::AssocKind::Type { .. } => "associated type",
}
self.kind.descr()
}
pub fn namespace(&self) -> Namespace {
match self.kind {
ty::AssocKind::Type { .. } => Namespace::TypeNS,
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
}
self.kind.namespace()
}
pub fn as_def_kind(&self) -> DefKind {
match self.kind {
AssocKind::Const { .. } => DefKind::AssocConst,
AssocKind::Fn { .. } => DefKind::AssocFn,
AssocKind::Type { .. } => DefKind::AssocTy,
}
self.kind.as_def_kind()
}
pub fn is_const(&self) -> bool {
@@ -165,12 +153,8 @@ pub fn is_type(&self) -> bool {
matches!(self.kind, ty::AssocKind::Type { .. })
}
pub fn as_tag(&self) -> AssocTag {
match self.kind {
AssocKind::Const { .. } => AssocTag::Const,
AssocKind::Fn { .. } => AssocTag::Fn,
AssocKind::Type { .. } => AssocTag::Type,
}
pub fn tag(&self) -> AssocTag {
self.kind.tag()
}
pub fn is_impl_trait_in_trait(&self) -> bool {
@@ -196,33 +180,43 @@ pub enum AssocKind {
impl AssocKind {
pub fn namespace(&self) -> Namespace {
match *self {
ty::AssocKind::Type { .. } => Namespace::TypeNS,
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS,
match self {
Self::Type { .. } => Namespace::TypeNS,
Self::Const { .. } | Self::Fn { .. } => Namespace::ValueNS,
}
}
pub fn tag(&self) -> AssocTag {
match self {
Self::Const { .. } => AssocTag::Const,
Self::Fn { .. } => AssocTag::Fn,
Self::Type { .. } => AssocTag::Type,
}
}
pub fn as_def_kind(&self) -> DefKind {
match self {
AssocKind::Const { .. } => DefKind::AssocConst,
AssocKind::Fn { .. } => DefKind::AssocFn,
AssocKind::Type { .. } => DefKind::AssocTy,
Self::Const { .. } => DefKind::AssocConst,
Self::Fn { .. } => DefKind::AssocFn,
Self::Type { .. } => DefKind::AssocTy,
}
}
pub fn descr(&self) -> &'static str {
match self {
Self::Fn { has_self: true, .. } => "method",
_ => self.tag().descr(),
}
}
}
impl std::fmt::Display for AssocKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AssocKind::Fn { has_self: true, .. } => write!(f, "method"),
AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"),
AssocKind::Const { .. } => write!(f, "associated const"),
AssocKind::Type { .. } => write!(f, "associated type"),
}
f.write_str(self.descr())
}
}
// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching.
/// Like [`AssocKind`], but just the tag, no fields. Used in various kinds of matching.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AssocTag {
Const,
@@ -230,6 +224,17 @@ pub enum AssocTag {
Type,
}
impl AssocTag {
pub fn descr(self) -> &'static str {
// This should match `DefKind::descr`.
match self {
Self::Const => "associated constant",
Self::Fn => "associated function",
Self::Type => "associated type",
}
}
}
/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
///
/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
@@ -277,7 +282,7 @@ pub fn filter_by_name_unhygienic_and_kind(
name: Symbol,
assoc_tag: AssocTag,
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
self.filter_by_name_unhygienic(name).filter(move |item| item.as_tag() == assoc_tag)
self.filter_by_name_unhygienic(name).filter(move |item| item.tag() == assoc_tag)
}
/// Returns the associated item with the given identifier and `AssocKind`, if one exists.
@@ -290,7 +295,7 @@ pub fn find_by_ident_and_kind(
parent_def_id: DefId,
) -> Option<&ty::AssocItem> {
self.filter_by_name_unhygienic(ident.name)
.filter(|item| item.as_tag() == assoc_tag)
.filter(|item| item.tag() == assoc_tag)
.find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
}
+1 -1
View File
@@ -561,7 +561,7 @@ pub(crate) fn build_impl(
.find_by_ident_and_kind(
tcx,
item.ident(tcx),
item.as_tag(),
item.tag(),
associated_trait.def_id,
)
.unwrap(); // corresponding associated item has to exist
+1 -1
View File
@@ -1226,7 +1226,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n
.associated_items(did)
.filter_by_name_unhygienic(method_name)
.next()
.filter(|item| item.as_tag() == AssocTag::Fn)
.filter(|item| item.tag() == AssocTag::Fn)
})
} else {
None
@@ -16,7 +16,7 @@ impl Bar for Foo<'_> {
const STATIC: &str = "";
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//~| WARN this was previously accepted by the compiler but is being phased out
//~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
//~| ERROR lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
}
fn main() {}
@@ -39,14 +39,14 @@ help: use the `'static` lifetime
LL | const STATIC: &'static str = "";
| +++++++
error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
error[E0195]: lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
--> $DIR/elided-lifetime.rs:16:17
|
LL | const STATIC: &str;
| - lifetimes in impl do not match this associated const in trait
| - lifetimes in impl do not match this associated constant in trait
...
LL | const STATIC: &str = "";
| ^ lifetimes do not match associated const in trait
| ^ lifetimes do not match associated constant in trait
error: aborting due to 3 previous errors
@@ -9,7 +9,7 @@ impl Bar<'_> for A {
const STATIC: &str = "";
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//~| WARN this was previously accepted by the compiler but is being phased out
//~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
//~| ERROR lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
}
struct B;
@@ -21,14 +21,14 @@ help: use the `'static` lifetime
LL | const STATIC: &'static str = "";
| +++++++
error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration
error[E0195]: lifetime parameters or bounds on associated constant `STATIC` do not match the trait declaration
--> $DIR/static-trait-impl.rs:9:17
|
LL | const STATIC: &'a str;
| - lifetimes in impl do not match this associated const in trait
| - lifetimes in impl do not match this associated constant in trait
...
LL | const STATIC: &str = "";
| ^ lifetimes do not match associated const in trait
| ^ lifetimes do not match associated constant in trait
error: aborting due to 2 previous errors
@@ -14,7 +14,7 @@ impl Trait for () {
//~| ERROR mismatched types
const Q = "";
//~^ ERROR missing type for `const` item
//~| ERROR lifetime parameters or bounds on associated const `Q` do not match the trait declaration
//~| ERROR lifetime parameters or bounds on associated constant `Q` do not match the trait declaration
}
fn main() {}
@@ -15,14 +15,14 @@ error: missing type for `const` item
LL | const K<T> = ();
| ^ help: provide a type for the associated constant: `()`
error[E0195]: lifetime parameters or bounds on associated const `Q` do not match the trait declaration
error[E0195]: lifetime parameters or bounds on associated constant `Q` do not match the trait declaration
--> $DIR/assoc-const-missing-type.rs:15:12
|
LL | const Q<'a>: &'a str;
| ---- lifetimes in impl do not match this associated const in trait
| ---- lifetimes in impl do not match this associated constant in trait
...
LL | const Q = "";
| ^ lifetimes do not match associated const in trait
| ^ lifetimes do not match associated constant in trait
error: missing type for `const` item
--> $DIR/assoc-const-missing-type.rs:15:12
@@ -14,15 +14,15 @@ trait Trait<P> {
impl<P> Trait<P> for () {
const A<T>: () = ();
//~^ ERROR const `A` has 1 type parameter but its trait declaration has 0 type parameters
//~^ ERROR constant `A` has 1 type parameter but its trait declaration has 0 type parameters
const B<const K: u64>: u64 = 0;
//~^ ERROR const `B` has 1 const parameter but its trait declaration has 2 const parameters
//~^ ERROR constant `B` has 1 const parameter but its trait declaration has 2 const parameters
const C<'a>: &'a str = "";
//~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
//~^ ERROR constant `C` has 0 type parameters but its trait declaration has 1 type parameter
const D<const N: u16>: u16 = N;
//~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
//~^ ERROR constant `D` has an incompatible generic parameter for trait `Trait`
const E: &'static () = &();
//~^ ERROR lifetime parameters or bounds on associated const `E` do not match the trait declaration
//~^ ERROR lifetime parameters or bounds on associated constant `E` do not match the trait declaration
const F: usize = 1024
where
@@ -1,4 +1,4 @@
error[E0049]: associated const `A` has 1 type parameter but its trait declaration has 0 type parameters
error[E0049]: associated constant `A` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/compare-impl-item.rs:16:13
|
LL | const A: ();
@@ -7,7 +7,7 @@ LL | const A: ();
LL | const A<T>: () = ();
| ^ found 1 type parameter
error[E0049]: associated const `B` has 1 const parameter but its trait declaration has 2 const parameters
error[E0049]: associated constant `B` has 1 const parameter but its trait declaration has 2 const parameters
--> $DIR/compare-impl-item.rs:18:13
|
LL | const B<const K: u64, const Q: u64>: u64;
@@ -18,7 +18,7 @@ LL | const B<const K: u64, const Q: u64>: u64;
LL | const B<const K: u64>: u64 = 0;
| ^^^^^^^^^^^^ found 1 const parameter
error[E0049]: associated const `C` has 0 type parameters but its trait declaration has 1 type parameter
error[E0049]: associated constant `C` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/compare-impl-item.rs:20:13
|
LL | const C<T>: T;
@@ -27,7 +27,7 @@ LL | const C<T>: T;
LL | const C<'a>: &'a str = "";
| ^^ found 0 type parameters
error[E0053]: associated const `D` has an incompatible generic parameter for trait `Trait`
error[E0053]: associated constant `D` has an incompatible generic parameter for trait `Trait`
--> $DIR/compare-impl-item.rs:22:13
|
LL | trait Trait<P> {
@@ -42,14 +42,14 @@ LL | impl<P> Trait<P> for () {
LL | const D<const N: u16>: u16 = N;
| ^^^^^^^^^^^^ found const parameter of type `u16`
error[E0195]: lifetime parameters or bounds on associated const `E` do not match the trait declaration
error[E0195]: lifetime parameters or bounds on associated constant `E` do not match the trait declaration
--> $DIR/compare-impl-item.rs:24:12
|
LL | const E<'a>: &'a ();
| ---- lifetimes in impl do not match this associated const in trait
| ---- lifetimes in impl do not match this associated constant in trait
...
LL | const E: &'static () = &();
| ^ lifetimes do not match associated const in trait
| ^ lifetimes do not match associated constant in trait
error[E0276]: impl has stricter requirements than trait
--> $DIR/compare-impl-item.rs:29:12