|  | //! 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 crate::def::DefKind; | 
|  | use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir}; | 
|  |  | 
|  | #[derive(Copy, Clone, PartialEq, Debug)] | 
|  | pub enum GenericParamKind { | 
|  | Type, | 
|  | Lifetime, | 
|  | Const, | 
|  | } | 
|  |  | 
|  | #[derive(Copy, Clone, PartialEq, Debug)] | 
|  | pub enum MethodKind { | 
|  | Trait { body: bool }, | 
|  | Inherent, | 
|  | } | 
|  |  | 
|  | #[derive(Copy, Clone, PartialEq, Debug)] | 
|  | pub enum Target { | 
|  | ExternCrate, | 
|  | Use, | 
|  | Static, | 
|  | Const, | 
|  | Fn, | 
|  | Closure, | 
|  | Mod, | 
|  | ForeignMod, | 
|  | GlobalAsm, | 
|  | TyAlias, | 
|  | Enum, | 
|  | Variant, | 
|  | Struct, | 
|  | Field, | 
|  | Union, | 
|  | Trait, | 
|  | TraitAlias, | 
|  | Impl, | 
|  | Expression, | 
|  | Statement, | 
|  | Arm, | 
|  | AssocConst, | 
|  | Method(MethodKind), | 
|  | AssocTy, | 
|  | ForeignFn, | 
|  | ForeignStatic, | 
|  | ForeignTy, | 
|  | GenericParam(GenericParamKind), | 
|  | MacroDef, | 
|  | Param, | 
|  | PatField, | 
|  | ExprField, | 
|  | WherePredicate, | 
|  | } | 
|  |  | 
|  | 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::WherePredicate => 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 { .. } => Target::Impl, | 
|  | } | 
|  | } | 
|  |  | 
|  | // 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 { .. } => Target::Impl, | 
|  | _ => panic!("impossible case reached"), | 
|  | } | 
|  | } | 
|  |  | 
|  | 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 { .. } => Target::GenericParam(GenericParamKind::Type), | 
|  | hir::GenericParamKind::Lifetime { .. } => { | 
|  | Target::GenericParam(GenericParamKind::Lifetime) | 
|  | } | 
|  | hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub fn name(self) -> &'static str { | 
|  | match self { | 
|  | Target::ExternCrate => "extern crate", | 
|  | Target::Use => "use", | 
|  | Target::Static => "static item", | 
|  | Target::Const => "constant item", | 
|  | 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", | 
|  | }, | 
|  | 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", | 
|  | } | 
|  | } | 
|  | } |