1 //! This module implements some validity checks for attributes. 2 //! In particular it verifies that `#[inline]` and `#[repr]` attributes are 3 //! attached to items that actually support them and if there are 4 //! conflicts between multiple such attributes attached to the same 5 //! item. 6 7 use crate::hir; 8 use crate::{Item, ItemKind, TraitItem, TraitItemKind}; 9 10 use crate::def::DefKind; 11 use std::fmt::{self, Display}; 12 13 #[derive(Copy, Clone, PartialEq, Debug)] 14 pub enum GenericParamKind { 15 Type, 16 Lifetime, 17 Const, 18 } 19 20 #[derive(Copy, Clone, PartialEq, Debug)] 21 pub enum MethodKind { 22 Trait { body: bool }, 23 Inherent, 24 } 25 26 #[derive(Copy, Clone, PartialEq, Debug)] 27 pub enum Target { 28 ExternCrate, 29 Use, 30 Static, 31 Const, 32 Fn, 33 Closure, 34 Mod, 35 ForeignMod, 36 GlobalAsm, 37 TyAlias, 38 OpaqueTy, 39 ImplTraitPlaceholder, 40 Enum, 41 Variant, 42 Struct, 43 Field, 44 Union, 45 Trait, 46 TraitAlias, 47 Impl, 48 Expression, 49 Statement, 50 Arm, 51 AssocConst, 52 Method(MethodKind), 53 AssocTy, 54 ForeignFn, 55 ForeignStatic, 56 ForeignTy, 57 GenericParam(GenericParamKind), 58 MacroDef, 59 Param, 60 PatField, 61 ExprField, 62 } 63 64 impl Display for Target { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 66 write!(f, "{}", Self::name(*self)) 67 } 68 } 69 70 impl Target { from_item(item: &Item<'_>) -> Target71 pub fn from_item(item: &Item<'_>) -> Target { 72 match item.kind { 73 ItemKind::ExternCrate(..) => Target::ExternCrate, 74 ItemKind::Use(..) => Target::Use, 75 ItemKind::Static(..) => Target::Static, 76 ItemKind::Const(..) => Target::Const, 77 ItemKind::Fn(..) => Target::Fn, 78 ItemKind::Macro(..) => Target::MacroDef, 79 ItemKind::Mod(..) => Target::Mod, 80 ItemKind::ForeignMod { .. } => Target::ForeignMod, 81 ItemKind::GlobalAsm(..) => Target::GlobalAsm, 82 ItemKind::TyAlias(..) => Target::TyAlias, 83 ItemKind::OpaqueTy(ref opaque) => { 84 if opaque.in_trait { 85 Target::ImplTraitPlaceholder 86 } else { 87 Target::OpaqueTy 88 } 89 } 90 ItemKind::Enum(..) => Target::Enum, 91 ItemKind::Struct(..) => Target::Struct, 92 ItemKind::Union(..) => Target::Union, 93 ItemKind::Trait(..) => Target::Trait, 94 ItemKind::TraitAlias(..) => Target::TraitAlias, 95 ItemKind::Impl { .. } => Target::Impl, 96 } 97 } 98 99 // FIXME: For now, should only be used with def_kinds from ItemIds from_def_kind(def_kind: DefKind) -> Target100 pub fn from_def_kind(def_kind: DefKind) -> Target { 101 match def_kind { 102 DefKind::ExternCrate => Target::ExternCrate, 103 DefKind::Use => Target::Use, 104 DefKind::Static(..) => Target::Static, 105 DefKind::Const => Target::Const, 106 DefKind::Fn => Target::Fn, 107 DefKind::Macro(..) => Target::MacroDef, 108 DefKind::Mod => Target::Mod, 109 DefKind::ForeignMod => Target::ForeignMod, 110 DefKind::GlobalAsm => Target::GlobalAsm, 111 DefKind::TyAlias => Target::TyAlias, 112 DefKind::OpaqueTy => Target::OpaqueTy, 113 DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder, 114 DefKind::Enum => Target::Enum, 115 DefKind::Struct => Target::Struct, 116 DefKind::Union => Target::Union, 117 DefKind::Trait => Target::Trait, 118 DefKind::TraitAlias => Target::TraitAlias, 119 DefKind::Impl { .. } => Target::Impl, 120 _ => panic!("impossible case reached"), 121 } 122 } 123 from_trait_item(trait_item: &TraitItem<'_>) -> Target124 pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target { 125 match trait_item.kind { 126 TraitItemKind::Const(..) => Target::AssocConst, 127 TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { 128 Target::Method(MethodKind::Trait { body: false }) 129 } 130 TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { 131 Target::Method(MethodKind::Trait { body: true }) 132 } 133 TraitItemKind::Type(..) => Target::AssocTy, 134 } 135 } 136 from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target137 pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target { 138 match foreign_item.kind { 139 hir::ForeignItemKind::Fn(..) => Target::ForeignFn, 140 hir::ForeignItemKind::Static(..) => Target::ForeignStatic, 141 hir::ForeignItemKind::Type => Target::ForeignTy, 142 } 143 } 144 from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target145 pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target { 146 match generic_param.kind { 147 hir::GenericParamKind::Type { .. } => Target::GenericParam(GenericParamKind::Type), 148 hir::GenericParamKind::Lifetime { .. } => { 149 Target::GenericParam(GenericParamKind::Lifetime) 150 } 151 hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const), 152 } 153 } 154 name(self) -> &'static str155 pub fn name(self) -> &'static str { 156 match self { 157 Target::ExternCrate => "extern crate", 158 Target::Use => "use", 159 Target::Static => "static item", 160 Target::Const => "constant item", 161 Target::Fn => "function", 162 Target::Closure => "closure", 163 Target::Mod => "module", 164 Target::ForeignMod => "foreign module", 165 Target::GlobalAsm => "global asm", 166 Target::TyAlias => "type alias", 167 Target::OpaqueTy => "opaque type", 168 Target::ImplTraitPlaceholder => "opaque type in trait", 169 Target::Enum => "enum", 170 Target::Variant => "enum variant", 171 Target::Struct => "struct", 172 Target::Field => "struct field", 173 Target::Union => "union", 174 Target::Trait => "trait", 175 Target::TraitAlias => "trait alias", 176 Target::Impl => "implementation block", 177 Target::Expression => "expression", 178 Target::Statement => "statement", 179 Target::Arm => "match arm", 180 Target::AssocConst => "associated const", 181 Target::Method(kind) => match kind { 182 MethodKind::Inherent => "inherent method", 183 MethodKind::Trait { body: false } => "required trait method", 184 MethodKind::Trait { body: true } => "provided trait method", 185 }, 186 Target::AssocTy => "associated type", 187 Target::ForeignFn => "foreign function", 188 Target::ForeignStatic => "foreign static item", 189 Target::ForeignTy => "foreign type", 190 Target::GenericParam(kind) => match kind { 191 GenericParamKind::Type => "type parameter", 192 GenericParamKind::Lifetime => "lifetime parameter", 193 GenericParamKind::Const => "const parameter", 194 }, 195 Target::MacroDef => "macro def", 196 Target::Param => "function param", 197 Target::PatField => "pattern field", 198 Target::ExprField => "struct field", 199 } 200 } 201 } 202