diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5755ae8a8bc47..9d543563c0f96 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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. diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 0d65ddb5642af..8948a03e4a6f8 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -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, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 536d5b46fcbe6..6d14a14096d0b 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -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() { @@ -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"), }; @@ -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);