- Added a few more variants which are needed for various attributes - Previously a trait method with default block had the same target representation as a method in a `impl trait for` block, this has been changed (See `MethodKind`) - Added `plural_name` for more precision on the form of the name
365 lines
14 KiB
Rust
365 lines
14 KiB
Rust
//! This module implements some validity checks for attributes.
|
|
//! In particular it verifies that `#[inline]` and `#[repr]` attributes are
|
|
//! attached to items that actually support them and if there are
|
|
//! conflicts between multiple such attributes attached to the same
|
|
//! item.
|
|
|
|
use std::fmt::{self, Display};
|
|
|
|
use rustc_ast::visit::AssocCtxt;
|
|
use rustc_ast::{AssocItemKind, ForeignItemKind, ast};
|
|
use rustc_macros::HashStable_Generic;
|
|
|
|
use crate::def::DefKind;
|
|
use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir};
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
|
|
pub enum GenericParamKind {
|
|
Type,
|
|
Lifetime,
|
|
Const,
|
|
}
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
|
|
pub enum MethodKind {
|
|
/// Method in a `trait Trait` block
|
|
Trait {
|
|
/// Whether a default is provided for this method
|
|
body: bool,
|
|
},
|
|
/// Method in a `impl Trait for Type` block
|
|
TraitImpl,
|
|
/// Method in a `impl Type` block
|
|
Inherent,
|
|
}
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
|
|
pub enum Target {
|
|
ExternCrate,
|
|
Use,
|
|
Static,
|
|
Const,
|
|
Fn,
|
|
Closure,
|
|
Mod,
|
|
ForeignMod,
|
|
GlobalAsm,
|
|
TyAlias,
|
|
Enum,
|
|
Variant,
|
|
Struct,
|
|
Field,
|
|
Union,
|
|
Trait,
|
|
TraitAlias,
|
|
Impl { of_trait: bool },
|
|
Expression,
|
|
Statement,
|
|
Arm,
|
|
AssocConst,
|
|
Method(MethodKind),
|
|
AssocTy,
|
|
ForeignFn,
|
|
ForeignStatic,
|
|
ForeignTy,
|
|
GenericParam { kind: GenericParamKind, has_default: bool },
|
|
MacroDef,
|
|
Param,
|
|
PatField,
|
|
ExprField,
|
|
WherePredicate,
|
|
MacroCall,
|
|
Crate,
|
|
Delegation { mac: bool },
|
|
}
|
|
|
|
impl Display for Target {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{}", Self::name(*self))
|
|
}
|
|
}
|
|
|
|
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::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
|
|
| Target::MacroCall
|
|
| Target::Crate
|
|
| Target::WherePredicate
|
|
| Target::Delegation { .. } => false,
|
|
}
|
|
}
|
|
|
|
pub fn from_item(item: &Item<'_>) -> Target {
|
|
match item.kind {
|
|
ItemKind::ExternCrate(..) => Target::ExternCrate,
|
|
ItemKind::Use(..) => Target::Use,
|
|
ItemKind::Static { .. } => Target::Static,
|
|
ItemKind::Const(..) => Target::Const,
|
|
ItemKind::Fn { .. } => Target::Fn,
|
|
ItemKind::Macro(..) => Target::MacroDef,
|
|
ItemKind::Mod(..) => Target::Mod,
|
|
ItemKind::ForeignMod { .. } => Target::ForeignMod,
|
|
ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
|
|
ItemKind::TyAlias(..) => Target::TyAlias,
|
|
ItemKind::Enum(..) => Target::Enum,
|
|
ItemKind::Struct(..) => Target::Struct,
|
|
ItemKind::Union(..) => Target::Union,
|
|
ItemKind::Trait(..) => Target::Trait,
|
|
ItemKind::TraitAlias(..) => Target::TraitAlias,
|
|
ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
|
|
}
|
|
}
|
|
|
|
// FIXME: For now, should only be used with def_kinds from ItemIds
|
|
pub fn from_def_kind(def_kind: DefKind) -> Target {
|
|
match def_kind {
|
|
DefKind::ExternCrate => Target::ExternCrate,
|
|
DefKind::Use => Target::Use,
|
|
DefKind::Static { .. } => Target::Static,
|
|
DefKind::Const => Target::Const,
|
|
DefKind::Fn => Target::Fn,
|
|
DefKind::Macro(..) => Target::MacroDef,
|
|
DefKind::Mod => Target::Mod,
|
|
DefKind::ForeignMod => Target::ForeignMod,
|
|
DefKind::GlobalAsm => Target::GlobalAsm,
|
|
DefKind::TyAlias => Target::TyAlias,
|
|
DefKind::Enum => Target::Enum,
|
|
DefKind::Struct => Target::Struct,
|
|
DefKind::Union => Target::Union,
|
|
DefKind::Trait => Target::Trait,
|
|
DefKind::TraitAlias => Target::TraitAlias,
|
|
DefKind::Impl { of_trait } => Target::Impl { of_trait },
|
|
_ => panic!("impossible case reached"),
|
|
}
|
|
}
|
|
|
|
pub fn from_ast_item(item: &ast::Item) -> Target {
|
|
match item.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::ForeignMod,
|
|
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(ref i) => Target::Impl { of_trait: i.of_trait.is_some() },
|
|
ast::ItemKind::MacCall(..) => Target::MacroCall,
|
|
ast::ItemKind::MacroDef(..) => Target::MacroDef,
|
|
ast::ItemKind::Delegation(..) => Target::Delegation { mac: false },
|
|
ast::ItemKind::DelegationMac(..) => Target::Delegation { mac: true },
|
|
}
|
|
}
|
|
|
|
pub fn from_foreign_item_kind(kind: &ast::ForeignItemKind) -> Target {
|
|
match kind {
|
|
ForeignItemKind::Static(_) => Target::ForeignStatic,
|
|
ForeignItemKind::Fn(_) => Target::ForeignFn,
|
|
ForeignItemKind::TyAlias(_) => Target::ForeignTy,
|
|
ForeignItemKind::MacCall(_) => Target::MacroCall,
|
|
}
|
|
}
|
|
|
|
pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
|
|
match trait_item.kind {
|
|
TraitItemKind::Const(..) => Target::AssocConst,
|
|
TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
|
|
Target::Method(MethodKind::Trait { body: false })
|
|
}
|
|
TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
|
|
Target::Method(MethodKind::Trait { body: true })
|
|
}
|
|
TraitItemKind::Type(..) => Target::AssocTy,
|
|
}
|
|
}
|
|
|
|
pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
|
|
match foreign_item.kind {
|
|
hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
|
|
hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
|
|
hir::ForeignItemKind::Type => Target::ForeignTy,
|
|
}
|
|
}
|
|
|
|
pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
|
|
match generic_param.kind {
|
|
hir::GenericParamKind::Type { default, .. } => Target::GenericParam {
|
|
kind: GenericParamKind::Type,
|
|
has_default: default.is_some(),
|
|
},
|
|
hir::GenericParamKind::Lifetime { .. } => {
|
|
Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }
|
|
}
|
|
hir::GenericParamKind::Const { default, .. } => Target::GenericParam {
|
|
kind: GenericParamKind::Const,
|
|
has_default: default.is_some(),
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target {
|
|
match kind {
|
|
AssocItemKind::Const(_) => Target::AssocConst,
|
|
AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt {
|
|
AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() },
|
|
AssocCtxt::Impl { of_trait } => {
|
|
if of_trait {
|
|
MethodKind::TraitImpl
|
|
} else {
|
|
MethodKind::Inherent
|
|
}
|
|
}
|
|
}),
|
|
AssocItemKind::Type(_) => Target::AssocTy,
|
|
AssocItemKind::Delegation(_) => Target::Delegation { mac: false },
|
|
AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true },
|
|
AssocItemKind::MacCall(_) => Target::MacroCall,
|
|
}
|
|
}
|
|
|
|
pub fn from_expr(expr: &ast::Expr) -> Self {
|
|
match &expr.kind {
|
|
ast::ExprKind::Closure(..) | ast::ExprKind::Gen(..) => Self::Closure,
|
|
ast::ExprKind::Paren(e) => Self::from_expr(&e),
|
|
_ => Self::Expression,
|
|
}
|
|
}
|
|
|
|
pub fn name(self) -> &'static str {
|
|
match self {
|
|
Target::ExternCrate => "extern crate",
|
|
Target::Use => "use",
|
|
Target::Static => "static",
|
|
Target::Const => "constant",
|
|
Target::Fn => "function",
|
|
Target::Closure => "closure",
|
|
Target::Mod => "module",
|
|
Target::ForeignMod => "foreign module",
|
|
Target::GlobalAsm => "global asm",
|
|
Target::TyAlias => "type alias",
|
|
Target::Enum => "enum",
|
|
Target::Variant => "enum variant",
|
|
Target::Struct => "struct",
|
|
Target::Field => "struct field",
|
|
Target::Union => "union",
|
|
Target::Trait => "trait",
|
|
Target::TraitAlias => "trait alias",
|
|
Target::Impl { .. } => "implementation block",
|
|
Target::Expression => "expression",
|
|
Target::Statement => "statement",
|
|
Target::Arm => "match arm",
|
|
Target::AssocConst => "associated const",
|
|
Target::Method(kind) => match kind {
|
|
MethodKind::Inherent => "inherent method",
|
|
MethodKind::Trait { body: false } => "required trait method",
|
|
MethodKind::Trait { body: true } => "provided trait method",
|
|
MethodKind::TraitImpl => "trait method in an impl block",
|
|
},
|
|
Target::AssocTy => "associated type",
|
|
Target::ForeignFn => "foreign function",
|
|
Target::ForeignStatic => "foreign static item",
|
|
Target::ForeignTy => "foreign type",
|
|
Target::GenericParam { kind, .. } => match kind {
|
|
GenericParamKind::Type => "type parameter",
|
|
GenericParamKind::Lifetime => "lifetime parameter",
|
|
GenericParamKind::Const => "const parameter",
|
|
},
|
|
Target::MacroDef => "macro def",
|
|
Target::Param => "function param",
|
|
Target::PatField => "pattern field",
|
|
Target::ExprField => "struct field",
|
|
Target::WherePredicate => "where predicate",
|
|
Target::MacroCall => "macro call",
|
|
Target::Crate => "crate",
|
|
Target::Delegation { .. } => "delegation",
|
|
}
|
|
}
|
|
|
|
pub fn plural_name(self) -> &'static str {
|
|
match self {
|
|
Target::ExternCrate => "extern crates",
|
|
Target::Use => "use statements",
|
|
Target::Static => "statics",
|
|
Target::Const => "constants",
|
|
Target::Fn => "functions",
|
|
Target::Closure => "closures",
|
|
Target::Mod => "modules",
|
|
Target::ForeignMod => "foreign modules",
|
|
Target::GlobalAsm => "global asms",
|
|
Target::TyAlias => "type aliases",
|
|
Target::Enum => "enums",
|
|
Target::Variant => "enum variants",
|
|
Target::Struct => "structs",
|
|
Target::Field => "struct fields",
|
|
Target::Union => "unions",
|
|
Target::Trait => "traits",
|
|
Target::TraitAlias => "trait aliases",
|
|
Target::Impl { of_trait: false } => "inherent impl blocks",
|
|
Target::Impl { of_trait: true } => "trait impl blocks",
|
|
Target::Expression => "expressions",
|
|
Target::Statement => "statements",
|
|
Target::Arm => "match arms",
|
|
Target::AssocConst => "associated consts",
|
|
Target::Method(kind) => match kind {
|
|
MethodKind::Inherent => "inherent methods",
|
|
MethodKind::Trait { body: false } => "required trait methods",
|
|
MethodKind::Trait { body: true } => "provided trait methods",
|
|
MethodKind::TraitImpl => "trait methods in impl blocks",
|
|
},
|
|
Target::AssocTy => "associated types",
|
|
Target::ForeignFn => "foreign functions",
|
|
Target::ForeignStatic => "foreign statics",
|
|
Target::ForeignTy => "foreign types",
|
|
Target::GenericParam { kind, has_default: _ } => match kind {
|
|
GenericParamKind::Type => "type parameters",
|
|
GenericParamKind::Lifetime => "lifetime parameters",
|
|
GenericParamKind::Const => "const parameters",
|
|
},
|
|
Target::MacroDef => "macro defs",
|
|
Target::Param => "function params",
|
|
Target::PatField => "pattern fields",
|
|
Target::ExprField => "struct fields",
|
|
Target::WherePredicate => "where predicates",
|
|
Target::MacroCall => "macro calls",
|
|
Target::Crate => "crates",
|
|
Target::Delegation { .. } => "delegations",
|
|
}
|
|
}
|
|
}
|