rustc_hir/
target.rs

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
7use std::fmt::{self, Display};
8
9use crate::def::DefKind;
10use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir};
11
12#[derive(Copy, Clone, PartialEq, Debug)]
13pub enum GenericParamKind {
14    Type,
15    Lifetime,
16    Const,
17}
18
19#[derive(Copy, Clone, PartialEq, Debug)]
20pub enum MethodKind {
21    Trait { body: bool },
22    Inherent,
23}
24
25#[derive(Copy, Clone, PartialEq, Debug)]
26pub enum Target {
27    ExternCrate,
28    Use,
29    Static,
30    Const,
31    Fn,
32    Closure,
33    Mod,
34    ForeignMod,
35    GlobalAsm,
36    TyAlias,
37    Enum,
38    Variant,
39    Struct,
40    Field,
41    Union,
42    Trait,
43    TraitAlias,
44    Impl { of_trait: bool },
45    Expression,
46    Statement,
47    Arm,
48    AssocConst,
49    Method(MethodKind),
50    AssocTy,
51    ForeignFn,
52    ForeignStatic,
53    ForeignTy,
54    GenericParam { kind: GenericParamKind, has_default: bool },
55    MacroDef,
56    Param,
57    PatField,
58    ExprField,
59    WherePredicate,
60}
61
62impl Display for Target {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(f, "{}", Self::name(*self))
65    }
66}
67
68impl Target {
69    pub fn is_associated_item(self) -> bool {
70        match self {
71            Target::AssocConst | Target::AssocTy | Target::Method(_) => true,
72            Target::ExternCrate
73            | Target::Use
74            | Target::Static
75            | Target::Const
76            | Target::Fn
77            | Target::Closure
78            | Target::Mod
79            | Target::ForeignMod
80            | Target::GlobalAsm
81            | Target::TyAlias
82            | Target::Enum
83            | Target::Variant
84            | Target::Struct
85            | Target::Field
86            | Target::Union
87            | Target::Trait
88            | Target::TraitAlias
89            | Target::Impl { .. }
90            | Target::Expression
91            | Target::Statement
92            | Target::Arm
93            | Target::ForeignFn
94            | Target::ForeignStatic
95            | Target::ForeignTy
96            | Target::GenericParam { .. }
97            | Target::MacroDef
98            | Target::Param
99            | Target::PatField
100            | Target::ExprField
101            | Target::WherePredicate => false,
102        }
103    }
104
105    pub fn from_item(item: &Item<'_>) -> Target {
106        match item.kind {
107            ItemKind::ExternCrate(..) => Target::ExternCrate,
108            ItemKind::Use(..) => Target::Use,
109            ItemKind::Static { .. } => Target::Static,
110            ItemKind::Const(..) => Target::Const,
111            ItemKind::Fn { .. } => Target::Fn,
112            ItemKind::Macro(..) => Target::MacroDef,
113            ItemKind::Mod(..) => Target::Mod,
114            ItemKind::ForeignMod { .. } => Target::ForeignMod,
115            ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
116            ItemKind::TyAlias(..) => Target::TyAlias,
117            ItemKind::Enum(..) => Target::Enum,
118            ItemKind::Struct(..) => Target::Struct,
119            ItemKind::Union(..) => Target::Union,
120            ItemKind::Trait(..) => Target::Trait,
121            ItemKind::TraitAlias(..) => Target::TraitAlias,
122            ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
123        }
124    }
125
126    // FIXME: For now, should only be used with def_kinds from ItemIds
127    pub fn from_def_kind(def_kind: DefKind) -> Target {
128        match def_kind {
129            DefKind::ExternCrate => Target::ExternCrate,
130            DefKind::Use => Target::Use,
131            DefKind::Static { .. } => Target::Static,
132            DefKind::Const => Target::Const,
133            DefKind::Fn => Target::Fn,
134            DefKind::Macro(..) => Target::MacroDef,
135            DefKind::Mod => Target::Mod,
136            DefKind::ForeignMod => Target::ForeignMod,
137            DefKind::GlobalAsm => Target::GlobalAsm,
138            DefKind::TyAlias => Target::TyAlias,
139            DefKind::Enum => Target::Enum,
140            DefKind::Struct => Target::Struct,
141            DefKind::Union => Target::Union,
142            DefKind::Trait => Target::Trait,
143            DefKind::TraitAlias => Target::TraitAlias,
144            DefKind::Impl { of_trait } => Target::Impl { of_trait },
145            _ => panic!("impossible case reached"),
146        }
147    }
148
149    pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
150        match trait_item.kind {
151            TraitItemKind::Const(..) => Target::AssocConst,
152            TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
153                Target::Method(MethodKind::Trait { body: false })
154            }
155            TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
156                Target::Method(MethodKind::Trait { body: true })
157            }
158            TraitItemKind::Type(..) => Target::AssocTy,
159        }
160    }
161
162    pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
163        match foreign_item.kind {
164            hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
165            hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
166            hir::ForeignItemKind::Type => Target::ForeignTy,
167        }
168    }
169
170    pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
171        match generic_param.kind {
172            hir::GenericParamKind::Type { default, .. } => Target::GenericParam {
173                kind: GenericParamKind::Type,
174                has_default: default.is_some(),
175            },
176            hir::GenericParamKind::Lifetime { .. } => {
177                Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }
178            }
179            hir::GenericParamKind::Const { default, .. } => Target::GenericParam {
180                kind: GenericParamKind::Const,
181                has_default: default.is_some(),
182            },
183        }
184    }
185
186    pub fn name(self) -> &'static str {
187        match self {
188            Target::ExternCrate => "extern crate",
189            Target::Use => "use",
190            Target::Static => "static item",
191            Target::Const => "constant item",
192            Target::Fn => "function",
193            Target::Closure => "closure",
194            Target::Mod => "module",
195            Target::ForeignMod => "foreign module",
196            Target::GlobalAsm => "global asm",
197            Target::TyAlias => "type alias",
198            Target::Enum => "enum",
199            Target::Variant => "enum variant",
200            Target::Struct => "struct",
201            Target::Field => "struct field",
202            Target::Union => "union",
203            Target::Trait => "trait",
204            Target::TraitAlias => "trait alias",
205            Target::Impl { of_trait: false } => "inherent implementation block",
206            Target::Impl { of_trait: true } => "trait implementation block",
207            Target::Expression => "expression",
208            Target::Statement => "statement",
209            Target::Arm => "match arm",
210            Target::AssocConst => "associated const",
211            Target::Method(kind) => match kind {
212                MethodKind::Inherent => "inherent method",
213                MethodKind::Trait { body: false } => "required trait method",
214                MethodKind::Trait { body: true } => "provided trait method",
215            },
216            Target::AssocTy => "associated type",
217            Target::ForeignFn => "foreign function",
218            Target::ForeignStatic => "foreign static item",
219            Target::ForeignTy => "foreign type",
220            Target::GenericParam { kind, has_default: _ } => match kind {
221                GenericParamKind::Type => "type parameter",
222                GenericParamKind::Lifetime => "lifetime parameter",
223                GenericParamKind::Const => "const parameter",
224            },
225            Target::MacroDef => "macro def",
226            Target::Param => "function param",
227            Target::PatField => "pattern field",
228            Target::ExprField => "struct field",
229            Target::WherePredicate => "where predicate",
230        }
231    }
232}