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    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 { .. } => Target::Impl,
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 { .. } => Target::Impl,
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 { .. } => Target::GenericParam(GenericParamKind::Type),
173            hir::GenericParamKind::Lifetime { .. } => {
174                Target::GenericParam(GenericParamKind::Lifetime)
175            }
176            hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
177        }
178    }
179
180    pub fn name(self) -> &'static str {
181        match self {
182            Target::ExternCrate => "extern crate",
183            Target::Use => "use",
184            Target::Static => "static item",
185            Target::Const => "constant item",
186            Target::Fn => "function",
187            Target::Closure => "closure",
188            Target::Mod => "module",
189            Target::ForeignMod => "foreign module",
190            Target::GlobalAsm => "global asm",
191            Target::TyAlias => "type alias",
192            Target::Enum => "enum",
193            Target::Variant => "enum variant",
194            Target::Struct => "struct",
195            Target::Field => "struct field",
196            Target::Union => "union",
197            Target::Trait => "trait",
198            Target::TraitAlias => "trait alias",
199            Target::Impl => "implementation block",
200            Target::Expression => "expression",
201            Target::Statement => "statement",
202            Target::Arm => "match arm",
203            Target::AssocConst => "associated const",
204            Target::Method(kind) => match kind {
205                MethodKind::Inherent => "inherent method",
206                MethodKind::Trait { body: false } => "required trait method",
207                MethodKind::Trait { body: true } => "provided trait method",
208            },
209            Target::AssocTy => "associated type",
210            Target::ForeignFn => "foreign function",
211            Target::ForeignStatic => "foreign static item",
212            Target::ForeignTy => "foreign type",
213            Target::GenericParam(kind) => match kind {
214                GenericParamKind::Type => "type parameter",
215                GenericParamKind::Lifetime => "lifetime parameter",
216                GenericParamKind::Const => "const parameter",
217            },
218            Target::MacroDef => "macro def",
219            Target::Param => "function param",
220            Target::PatField => "pattern field",
221            Target::ExprField => "struct field",
222            Target::WherePredicate => "where predicate",
223        }
224    }
225}