Skip to content

Commit

Permalink
Fix enforcement of generics for associated items
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 15, 2023
1 parent 04fafd6 commit bc1ca6b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 19 deletions.
22 changes: 22 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2845,6 +2845,28 @@ impl Item {
pub fn span_with_attributes(&self) -> Span {
self.attrs.iter().fold(self.span, |acc, attr| acc.to(attr.span))
}

pub fn opt_generics(&self) -> Option<&Generics> {
match &self.kind {
ItemKind::ExternCrate(_)
| ItemKind::Use(_)
| ItemKind::Mod(_, _)
| ItemKind::ForeignMod(_)
| ItemKind::GlobalAsm(_)
| ItemKind::MacCall(_)
| ItemKind::MacroDef(_) => None,
ItemKind::Static(_) => None,
ItemKind::Const(i) => Some(&i.generics),
ItemKind::Fn(i) => Some(&i.generics),
ItemKind::TyAlias(i) => Some(&i.generics),
ItemKind::TraitAlias(generics, _)
| ItemKind::Enum(_, generics)
| ItemKind::Struct(_, generics)
| ItemKind::Union(_, generics) => Some(&generics),
ItemKind::Trait(i) => Some(&i.generics),
ItemKind::Impl(i) => Some(&i.generics),
}
}
}

/// `extern` qualifier on a function item or function type.
Expand Down
36 changes: 36 additions & 0 deletions compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,42 @@ impl Display for Target {
}

impl Target {
pub fn is_associated_item(self) -> bool {
match self {
Target::AssocConst | Target::AssocTy | Target::Method(_) => true,
Target::ExternCrate
| Target::Use
| Target::Static
| Target::Const
| Target::Fn
| Target::Closure
| Target::Mod
| Target::ForeignMod
| Target::GlobalAsm
| Target::TyAlias
| Target::OpaqueTy
| Target::Enum
| Target::Variant
| Target::Struct
| Target::Field
| Target::Union
| Target::Trait
| Target::TraitAlias
| Target::Impl
| Target::Expression
| Target::Statement
| Target::Arm
| Target::ForeignFn
| Target::ForeignStatic
| Target::ForeignTy
| Target::GenericParam(_)
| Target::MacroDef
| Target::Param
| Target::PatField
| Target::ExprField => false,
}
}

pub fn from_item(item: &Item<'_>) -> Target {
match item.kind {
ItemKind::ExternCrate(..) => Target::ExternCrate,
Expand Down
46 changes: 27 additions & 19 deletions compiler/rustc_passes/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,15 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
// Some other types like Box and various functions like drop_in_place
// have minimum requirements.

let actual_num = generics.params.len();
// FIXME: This still doesn't count, e.g., elided lifetimes and APITs.
let mut actual_num = generics.params.len();
if target.is_associated_item() {
actual_num += self
.parent_item
.unwrap()
.opt_generics()
.map_or(0, |generics| generics.params.len());
}

let mut at_least = false;
let required = match lang_item.required_generics() {
Expand Down Expand Up @@ -258,23 +266,23 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {

impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
fn visit_item(&mut self, i: &'ast ast::Item) {
let (target, generics) = match &i.kind {
ast::ItemKind::ExternCrate(_) => (Target::ExternCrate, None),
ast::ItemKind::Use(_) => (Target::Use, None),
ast::ItemKind::Static(_) => (Target::Static, None),
ast::ItemKind::Const(ct) => (Target::Const, Some(&ct.generics)),
ast::ItemKind::Fn(fun) => (Target::Fn, Some(&fun.generics)),
ast::ItemKind::Mod(_, _) => (Target::Mod, None),
ast::ItemKind::ForeignMod(_) => (Target::ForeignFn, None),
ast::ItemKind::GlobalAsm(_) => (Target::GlobalAsm, None),
ast::ItemKind::TyAlias(alias) => (Target::TyAlias, Some(&alias.generics)),
ast::ItemKind::Enum(_, generics) => (Target::Enum, Some(generics)),
ast::ItemKind::Struct(_, generics) => (Target::Struct, Some(generics)),
ast::ItemKind::Union(_, generics) => (Target::Union, Some(generics)),
ast::ItemKind::Trait(tr) => (Target::Trait, Some(&tr.generics)),
ast::ItemKind::TraitAlias(generics, _) => (Target::TraitAlias, Some(generics)),
ast::ItemKind::Impl(_) => (Target::Impl, None),
ast::ItemKind::MacroDef(_) => (Target::MacroDef, None),
let target = match &i.kind {
ast::ItemKind::ExternCrate(_) => Target::ExternCrate,
ast::ItemKind::Use(_) => Target::Use,
ast::ItemKind::Static(_) => Target::Static,
ast::ItemKind::Const(_) => Target::Const,
ast::ItemKind::Fn(_) => Target::Fn,
ast::ItemKind::Mod(_, _) => Target::Mod,
ast::ItemKind::ForeignMod(_) => Target::ForeignFn,
ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm,
ast::ItemKind::TyAlias(_) => Target::TyAlias,
ast::ItemKind::Enum(_, _) => Target::Enum,
ast::ItemKind::Struct(_, _) => Target::Struct,
ast::ItemKind::Union(_, _) => Target::Union,
ast::ItemKind::Trait(_) => Target::Trait,
ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias,
ast::ItemKind::Impl(_) => Target::Impl,
ast::ItemKind::MacroDef(_) => Target::MacroDef,
ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"),
};

Expand All @@ -283,7 +291,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
self.resolver.node_id_to_def_id[&i.id],
&i.attrs,
i.span,
generics,
i.opt_generics(),
);

let parent_item = self.parent_item.replace(i);
Expand Down

0 comments on commit bc1ca6b

Please sign in to comment.