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