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 rustc_ast::visit::AssocCtxt;
10use rustc_ast::{AssocItemKind, ForeignItemKind, ast};
11use rustc_macros::HashStable_Generic;
12
13use crate::def::DefKind;
14use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir};
15
16#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
17pub enum GenericParamKind {
18    Type,
19    Lifetime,
20    Const,
21}
22
23#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
24pub enum MethodKind {
25    /// Method in a `trait Trait` block
26    Trait {
27        /// Whether a default is provided for this method
28        body: bool,
29    },
30    /// Method in a `impl Trait for Type` block
31    TraitImpl,
32    /// Method in a `impl Type` block
33    Inherent,
34}
35
36#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)]
37pub enum Target {
38    ExternCrate,
39    Use,
40    Static,
41    Const,
42    Fn,
43    Closure,
44    Mod,
45    ForeignMod,
46    GlobalAsm,
47    TyAlias,
48    Enum,
49    Variant,
50    Struct,
51    Field,
52    Union,
53    Trait,
54    TraitAlias,
55    Impl { of_trait: bool },
56    Expression,
57    Statement,
58    Arm,
59    AssocConst,
60    Method(MethodKind),
61    AssocTy,
62    ForeignFn,
63    ForeignStatic,
64    ForeignTy,
65    GenericParam { kind: GenericParamKind, has_default: bool },
66    MacroDef,
67    Param,
68    PatField,
69    ExprField,
70    WherePredicate,
71    MacroCall,
72    Crate,
73    Delegation { mac: bool },
74}
75
76impl Display for Target {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        write!(f, "{}", Self::name(*self))
79    }
80}
81
82impl Target {
83    pub fn is_associated_item(self) -> bool {
84        match self {
85            Target::AssocConst | Target::AssocTy | Target::Method(_) => true,
86            Target::ExternCrate
87            | Target::Use
88            | Target::Static
89            | Target::Const
90            | Target::Fn
91            | Target::Closure
92            | Target::Mod
93            | Target::ForeignMod
94            | Target::GlobalAsm
95            | Target::TyAlias
96            | Target::Enum
97            | Target::Variant
98            | Target::Struct
99            | Target::Field
100            | Target::Union
101            | Target::Trait
102            | Target::TraitAlias
103            | Target::Impl { .. }
104            | Target::Expression
105            | Target::Statement
106            | Target::Arm
107            | Target::ForeignFn
108            | Target::ForeignStatic
109            | Target::ForeignTy
110            | Target::GenericParam { .. }
111            | Target::MacroDef
112            | Target::Param
113            | Target::PatField
114            | Target::ExprField
115            | Target::MacroCall
116            | Target::Crate
117            | Target::WherePredicate
118            | Target::Delegation { .. } => false,
119        }
120    }
121
122    pub fn from_item(item: &Item<'_>) -> Target {
123        match item.kind {
124            ItemKind::ExternCrate(..) => Target::ExternCrate,
125            ItemKind::Use(..) => Target::Use,
126            ItemKind::Static { .. } => Target::Static,
127            ItemKind::Const(..) => Target::Const,
128            ItemKind::Fn { .. } => Target::Fn,
129            ItemKind::Macro(..) => Target::MacroDef,
130            ItemKind::Mod(..) => Target::Mod,
131            ItemKind::ForeignMod { .. } => Target::ForeignMod,
132            ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
133            ItemKind::TyAlias(..) => Target::TyAlias,
134            ItemKind::Enum(..) => Target::Enum,
135            ItemKind::Struct(..) => Target::Struct,
136            ItemKind::Union(..) => Target::Union,
137            ItemKind::Trait(..) => Target::Trait,
138            ItemKind::TraitAlias(..) => Target::TraitAlias,
139            ItemKind::Impl(imp_) => Target::Impl { of_trait: imp_.of_trait.is_some() },
140        }
141    }
142
143    // FIXME: For now, should only be used with def_kinds from ItemIds
144    pub fn from_def_kind(def_kind: DefKind) -> Target {
145        match def_kind {
146            DefKind::ExternCrate => Target::ExternCrate,
147            DefKind::Use => Target::Use,
148            DefKind::Static { .. } => Target::Static,
149            DefKind::Const => Target::Const,
150            DefKind::Fn => Target::Fn,
151            DefKind::Macro(..) => Target::MacroDef,
152            DefKind::Mod => Target::Mod,
153            DefKind::ForeignMod => Target::ForeignMod,
154            DefKind::GlobalAsm => Target::GlobalAsm,
155            DefKind::TyAlias => Target::TyAlias,
156            DefKind::Enum => Target::Enum,
157            DefKind::Struct => Target::Struct,
158            DefKind::Union => Target::Union,
159            DefKind::Trait => Target::Trait,
160            DefKind::TraitAlias => Target::TraitAlias,
161            DefKind::Impl { of_trait } => Target::Impl { of_trait },
162            _ => panic!("impossible case reached"),
163        }
164    }
165
166    pub fn from_ast_item(item: &ast::Item) -> Target {
167        match item.kind {
168            ast::ItemKind::ExternCrate(..) => Target::ExternCrate,
169            ast::ItemKind::Use(..) => Target::Use,
170            ast::ItemKind::Static { .. } => Target::Static,
171            ast::ItemKind::Const(..) => Target::Const,
172            ast::ItemKind::Fn { .. } => Target::Fn,
173            ast::ItemKind::Mod(..) => Target::Mod,
174            ast::ItemKind::ForeignMod { .. } => Target::ForeignMod,
175            ast::ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
176            ast::ItemKind::TyAlias(..) => Target::TyAlias,
177            ast::ItemKind::Enum(..) => Target::Enum,
178            ast::ItemKind::Struct(..) => Target::Struct,
179            ast::ItemKind::Union(..) => Target::Union,
180            ast::ItemKind::Trait(..) => Target::Trait,
181            ast::ItemKind::TraitAlias(..) => Target::TraitAlias,
182            ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() },
183            ast::ItemKind::MacCall(..) => Target::MacroCall,
184            ast::ItemKind::MacroDef(..) => Target::MacroDef,
185            ast::ItemKind::Delegation(..) => Target::Delegation { mac: false },
186            ast::ItemKind::DelegationMac(..) => Target::Delegation { mac: true },
187        }
188    }
189
190    pub fn from_foreign_item_kind(kind: &ast::ForeignItemKind) -> Target {
191        match kind {
192            ForeignItemKind::Static(_) => Target::ForeignStatic,
193            ForeignItemKind::Fn(_) => Target::ForeignFn,
194            ForeignItemKind::TyAlias(_) => Target::ForeignTy,
195            ForeignItemKind::MacCall(_) => Target::MacroCall,
196        }
197    }
198
199    pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
200        match trait_item.kind {
201            TraitItemKind::Const(..) => Target::AssocConst,
202            TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
203                Target::Method(MethodKind::Trait { body: false })
204            }
205            TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
206                Target::Method(MethodKind::Trait { body: true })
207            }
208            TraitItemKind::Type(..) => Target::AssocTy,
209        }
210    }
211
212    pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
213        match foreign_item.kind {
214            hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
215            hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
216            hir::ForeignItemKind::Type => Target::ForeignTy,
217        }
218    }
219
220    pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
221        match generic_param.kind {
222            hir::GenericParamKind::Type { default, .. } => Target::GenericParam {
223                kind: GenericParamKind::Type,
224                has_default: default.is_some(),
225            },
226            hir::GenericParamKind::Lifetime { .. } => {
227                Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }
228            }
229            hir::GenericParamKind::Const { default, .. } => Target::GenericParam {
230                kind: GenericParamKind::Const,
231                has_default: default.is_some(),
232            },
233        }
234    }
235
236    pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target {
237        match kind {
238            AssocItemKind::Const(_) => Target::AssocConst,
239            AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt {
240                AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() },
241                AssocCtxt::Impl { of_trait } => {
242                    if of_trait {
243                        MethodKind::TraitImpl
244                    } else {
245                        MethodKind::Inherent
246                    }
247                }
248            }),
249            AssocItemKind::Type(_) => Target::AssocTy,
250            AssocItemKind::Delegation(_) => Target::Delegation { mac: false },
251            AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true },
252            AssocItemKind::MacCall(_) => Target::MacroCall,
253        }
254    }
255
256    pub fn from_expr(expr: &ast::Expr) -> Self {
257        match &expr.kind {
258            ast::ExprKind::Closure(..) | ast::ExprKind::Gen(..) => Self::Closure,
259            ast::ExprKind::Paren(e) => Self::from_expr(&e),
260            _ => Self::Expression,
261        }
262    }
263
264    pub fn name(self) -> &'static str {
265        match self {
266            Target::ExternCrate => "extern crate",
267            Target::Use => "use",
268            Target::Static => "static",
269            Target::Const => "constant",
270            Target::Fn => "function",
271            Target::Closure => "closure",
272            Target::Mod => "module",
273            Target::ForeignMod => "foreign module",
274            Target::GlobalAsm => "global asm",
275            Target::TyAlias => "type alias",
276            Target::Enum => "enum",
277            Target::Variant => "enum variant",
278            Target::Struct => "struct",
279            Target::Field => "struct field",
280            Target::Union => "union",
281            Target::Trait => "trait",
282            Target::TraitAlias => "trait alias",
283            Target::Impl { .. } => "implementation block",
284            Target::Expression => "expression",
285            Target::Statement => "statement",
286            Target::Arm => "match arm",
287            Target::AssocConst => "associated const",
288            Target::Method(kind) => match kind {
289                MethodKind::Inherent => "inherent method",
290                MethodKind::Trait { body: false } => "required trait method",
291                MethodKind::Trait { body: true } => "provided trait method",
292                MethodKind::TraitImpl => "trait method in an impl block",
293            },
294            Target::AssocTy => "associated type",
295            Target::ForeignFn => "foreign function",
296            Target::ForeignStatic => "foreign static item",
297            Target::ForeignTy => "foreign type",
298            Target::GenericParam { kind, .. } => match kind {
299                GenericParamKind::Type => "type parameter",
300                GenericParamKind::Lifetime => "lifetime parameter",
301                GenericParamKind::Const => "const parameter",
302            },
303            Target::MacroDef => "macro def",
304            Target::Param => "function param",
305            Target::PatField => "pattern field",
306            Target::ExprField => "struct field",
307            Target::WherePredicate => "where predicate",
308            Target::MacroCall => "macro call",
309            Target::Crate => "crate",
310            Target::Delegation { .. } => "delegation",
311        }
312    }
313
314    pub fn plural_name(self) -> &'static str {
315        match self {
316            Target::ExternCrate => "extern crates",
317            Target::Use => "use statements",
318            Target::Static => "statics",
319            Target::Const => "constants",
320            Target::Fn => "functions",
321            Target::Closure => "closures",
322            Target::Mod => "modules",
323            Target::ForeignMod => "foreign modules",
324            Target::GlobalAsm => "global asms",
325            Target::TyAlias => "type aliases",
326            Target::Enum => "enums",
327            Target::Variant => "enum variants",
328            Target::Struct => "structs",
329            Target::Field => "struct fields",
330            Target::Union => "unions",
331            Target::Trait => "traits",
332            Target::TraitAlias => "trait aliases",
333            Target::Impl { of_trait: false } => "inherent impl blocks",
334            Target::Impl { of_trait: true } => "trait impl blocks",
335            Target::Expression => "expressions",
336            Target::Statement => "statements",
337            Target::Arm => "match arms",
338            Target::AssocConst => "associated consts",
339            Target::Method(kind) => match kind {
340                MethodKind::Inherent => "inherent methods",
341                MethodKind::Trait { body: false } => "required trait methods",
342                MethodKind::Trait { body: true } => "provided trait methods",
343                MethodKind::TraitImpl => "trait methods in impl blocks",
344            },
345            Target::AssocTy => "associated types",
346            Target::ForeignFn => "foreign functions",
347            Target::ForeignStatic => "foreign statics",
348            Target::ForeignTy => "foreign types",
349            Target::GenericParam { kind, has_default: _ } => match kind {
350                GenericParamKind::Type => "type parameters",
351                GenericParamKind::Lifetime => "lifetime parameters",
352                GenericParamKind::Const => "const parameters",
353            },
354            Target::MacroDef => "macro defs",
355            Target::Param => "function params",
356            Target::PatField => "pattern fields",
357            Target::ExprField => "struct fields",
358            Target::WherePredicate => "where predicates",
359            Target::MacroCall => "macro calls",
360            Target::Crate => "crates",
361            Target::Delegation { .. } => "delegations",
362        }
363    }
364}