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