]> git.proxmox.com Git - rustc.git/blob - src/librustc_hir/def.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_hir / def.rs
1 use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2 use crate::hir;
3
4 use rustc_ast as ast;
5 use rustc_ast::NodeId;
6 use rustc_macros::HashStable_Generic;
7 use rustc_span::hygiene::MacroKind;
8
9 use std::fmt::Debug;
10
11 /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
12 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
13 #[derive(HashStable_Generic)]
14 pub enum CtorOf {
15 /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
16 Struct,
17 /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
18 Variant,
19 }
20
21 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
22 #[derive(HashStable_Generic)]
23 pub enum CtorKind {
24 /// Constructor function automatically created by a tuple struct/variant.
25 Fn,
26 /// Constructor constant automatically created by a unit struct/variant.
27 Const,
28 /// Unusable name in value namespace created by a struct variant.
29 Fictive,
30 }
31
32 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
33 #[derive(HashStable_Generic)]
34 pub enum NonMacroAttrKind {
35 /// Single-segment attribute defined by the language (`#[inline]`)
36 Builtin,
37 /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
38 Tool,
39 /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
40 DeriveHelper,
41 /// Single-segment custom attribute registered with `#[register_attr]`.
42 Registered,
43 }
44
45 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
46 #[derive(HashStable_Generic)]
47 pub enum DefKind {
48 // Type namespace
49 Mod,
50 /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists.
51 Struct,
52 Union,
53 Enum,
54 /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
55 Variant,
56 Trait,
57 /// `type Foo = Bar;`
58 TyAlias,
59 ForeignTy,
60 TraitAlias,
61 AssocTy,
62 TyParam,
63
64 // Value namespace
65 Fn,
66 Const,
67 ConstParam,
68 Static,
69 /// Refers to the struct or enum variant's constructor.
70 Ctor(CtorOf, CtorKind),
71 AssocFn,
72 AssocConst,
73
74 // Macro namespace
75 Macro(MacroKind),
76
77 // Not namespaced (or they are, but we don't treat them so)
78 ExternCrate,
79 Use,
80 ForeignMod,
81 AnonConst,
82 OpaqueTy,
83 Field,
84 LifetimeParam,
85 GlobalAsm,
86 Impl,
87 Closure,
88 Generator,
89 }
90
91 impl DefKind {
92 pub fn descr(self, def_id: DefId) -> &'static str {
93 match self {
94 DefKind::Fn => "function",
95 DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
96 "crate"
97 }
98 DefKind::Mod => "module",
99 DefKind::Static => "static",
100 DefKind::Enum => "enum",
101 DefKind::Variant => "variant",
102 DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
103 DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
104 DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
105 DefKind::Struct => "struct",
106 DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
107 DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
108 DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
109 panic!("impossible struct constructor")
110 }
111 DefKind::OpaqueTy => "opaque type",
112 DefKind::TyAlias => "type alias",
113 DefKind::TraitAlias => "trait alias",
114 DefKind::AssocTy => "associated type",
115 DefKind::Union => "union",
116 DefKind::Trait => "trait",
117 DefKind::ForeignTy => "foreign type",
118 DefKind::AssocFn => "associated function",
119 DefKind::Const => "constant",
120 DefKind::AssocConst => "associated constant",
121 DefKind::TyParam => "type parameter",
122 DefKind::ConstParam => "const parameter",
123 DefKind::Macro(macro_kind) => macro_kind.descr(),
124 DefKind::LifetimeParam => "lifetime parameter",
125 DefKind::Use => "import",
126 DefKind::ForeignMod => "foreign module",
127 DefKind::AnonConst => "constant expression",
128 DefKind::Field => "field",
129 DefKind::Impl => "implementation",
130 DefKind::Closure => "closure",
131 DefKind::Generator => "generator",
132 DefKind::ExternCrate => "extern crate",
133 DefKind::GlobalAsm => "global assembly block",
134 }
135 }
136
137 /// Gets an English article for the definition.
138 pub fn article(&self) -> &'static str {
139 match *self {
140 DefKind::AssocTy
141 | DefKind::AssocConst
142 | DefKind::AssocFn
143 | DefKind::Enum
144 | DefKind::OpaqueTy
145 | DefKind::Impl
146 | DefKind::Use
147 | DefKind::ExternCrate => "an",
148 DefKind::Macro(macro_kind) => macro_kind.article(),
149 _ => "a",
150 }
151 }
152
153 pub fn ns(&self) -> Option<Namespace> {
154 match self {
155 DefKind::Mod
156 | DefKind::Struct
157 | DefKind::Union
158 | DefKind::Enum
159 | DefKind::Variant
160 | DefKind::Trait
161 | DefKind::OpaqueTy
162 | DefKind::TyAlias
163 | DefKind::ForeignTy
164 | DefKind::TraitAlias
165 | DefKind::AssocTy
166 | DefKind::TyParam => Some(Namespace::TypeNS),
167
168 DefKind::Fn
169 | DefKind::Const
170 | DefKind::ConstParam
171 | DefKind::Static
172 | DefKind::Ctor(..)
173 | DefKind::AssocFn
174 | DefKind::AssocConst => Some(Namespace::ValueNS),
175
176 DefKind::Macro(..) => Some(Namespace::MacroNS),
177
178 // Not namespaced.
179 DefKind::AnonConst
180 | DefKind::Field
181 | DefKind::LifetimeParam
182 | DefKind::ExternCrate
183 | DefKind::Closure
184 | DefKind::Generator
185 | DefKind::Use
186 | DefKind::ForeignMod
187 | DefKind::GlobalAsm
188 | DefKind::Impl => None,
189 }
190 }
191 }
192
193 /// The resolution of a path or export.
194 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
195 #[derive(HashStable_Generic)]
196 pub enum Res<Id = hir::HirId> {
197 Def(DefKind, DefId),
198
199 // Type namespace
200 PrimTy(hir::PrimTy),
201 SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
202 ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
203
204 // Value namespace
205 SelfCtor(DefId /* impl */), // `DefId` refers to the impl
206 Local(Id),
207
208 // Macro namespace
209 NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
210
211 // All namespaces
212 Err,
213 }
214
215 /// The result of resolving a path before lowering to HIR,
216 /// with "module" segments resolved and associated item
217 /// segments deferred to type checking.
218 /// `base_res` is the resolution of the resolved part of the
219 /// path, `unresolved_segments` is the number of unresolved
220 /// segments.
221 ///
222 /// ```text
223 /// module::Type::AssocX::AssocY::MethodOrAssocType
224 /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
225 /// base_res unresolved_segments = 3
226 ///
227 /// <T as Trait>::AssocX::AssocY::MethodOrAssocType
228 /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
229 /// base_res unresolved_segments = 2
230 /// ```
231 #[derive(Copy, Clone, Debug)]
232 pub struct PartialRes {
233 base_res: Res<NodeId>,
234 unresolved_segments: usize,
235 }
236
237 impl PartialRes {
238 #[inline]
239 pub fn new(base_res: Res<NodeId>) -> Self {
240 PartialRes { base_res, unresolved_segments: 0 }
241 }
242
243 #[inline]
244 pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
245 if base_res == Res::Err {
246 unresolved_segments = 0
247 }
248 PartialRes { base_res, unresolved_segments }
249 }
250
251 #[inline]
252 pub fn base_res(&self) -> Res<NodeId> {
253 self.base_res
254 }
255
256 #[inline]
257 pub fn unresolved_segments(&self) -> usize {
258 self.unresolved_segments
259 }
260 }
261
262 /// Different kinds of symbols don't influence each other.
263 ///
264 /// Therefore, they have a separate universe (namespace).
265 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
266 pub enum Namespace {
267 TypeNS,
268 ValueNS,
269 MacroNS,
270 }
271
272 impl Namespace {
273 pub fn descr(self) -> &'static str {
274 match self {
275 Self::TypeNS => "type",
276 Self::ValueNS => "value",
277 Self::MacroNS => "macro",
278 }
279 }
280 }
281
282 /// Just a helper ‒ separate structure for each namespace.
283 #[derive(Copy, Clone, Default, Debug)]
284 pub struct PerNS<T> {
285 pub value_ns: T,
286 pub type_ns: T,
287 pub macro_ns: T,
288 }
289
290 impl<T> PerNS<T> {
291 pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
292 PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
293 }
294 }
295
296 impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
297 type Output = T;
298
299 fn index(&self, ns: Namespace) -> &T {
300 match ns {
301 Namespace::ValueNS => &self.value_ns,
302 Namespace::TypeNS => &self.type_ns,
303 Namespace::MacroNS => &self.macro_ns,
304 }
305 }
306 }
307
308 impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
309 fn index_mut(&mut self, ns: Namespace) -> &mut T {
310 match ns {
311 Namespace::ValueNS => &mut self.value_ns,
312 Namespace::TypeNS => &mut self.type_ns,
313 Namespace::MacroNS => &mut self.macro_ns,
314 }
315 }
316 }
317
318 impl<T> PerNS<Option<T>> {
319 /// Returns `true` if all the items in this collection are `None`.
320 pub fn is_empty(&self) -> bool {
321 self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
322 }
323
324 /// Returns an iterator over the items which are `Some`.
325 pub fn present_items(self) -> impl Iterator<Item = T> {
326 use std::iter::once;
327
328 once(self.type_ns).chain(once(self.value_ns)).chain(once(self.macro_ns)).filter_map(|it| it)
329 }
330 }
331
332 impl CtorKind {
333 pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
334 match *vdata {
335 ast::VariantData::Tuple(..) => CtorKind::Fn,
336 ast::VariantData::Unit(..) => CtorKind::Const,
337 ast::VariantData::Struct(..) => CtorKind::Fictive,
338 }
339 }
340
341 pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
342 match *vdata {
343 hir::VariantData::Tuple(..) => CtorKind::Fn,
344 hir::VariantData::Unit(..) => CtorKind::Const,
345 hir::VariantData::Struct(..) => CtorKind::Fictive,
346 }
347 }
348 }
349
350 impl NonMacroAttrKind {
351 pub fn descr(self) -> &'static str {
352 match self {
353 NonMacroAttrKind::Builtin => "built-in attribute",
354 NonMacroAttrKind::Tool => "tool attribute",
355 NonMacroAttrKind::DeriveHelper => "derive helper attribute",
356 NonMacroAttrKind::Registered => "explicitly registered attribute",
357 }
358 }
359
360 pub fn article(self) -> &'static str {
361 match self {
362 NonMacroAttrKind::Registered => "an",
363 _ => "a",
364 }
365 }
366
367 /// Users of some attributes cannot mark them as used, so they are considered always used.
368 pub fn is_used(self) -> bool {
369 match self {
370 NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
371 NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
372 }
373 }
374 }
375
376 impl<Id> Res<Id> {
377 /// Return the `DefId` of this `Def` if it has an ID, else panic.
378 pub fn def_id(&self) -> DefId
379 where
380 Id: Debug,
381 {
382 self.opt_def_id()
383 .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self))
384 }
385
386 /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
387 pub fn opt_def_id(&self) -> Option<DefId> {
388 match *self {
389 Res::Def(_, id) => Some(id),
390
391 Res::Local(..)
392 | Res::PrimTy(..)
393 | Res::SelfTy(..)
394 | Res::SelfCtor(..)
395 | Res::ToolMod
396 | Res::NonMacroAttr(..)
397 | Res::Err => None,
398 }
399 }
400
401 /// Return the `DefId` of this `Res` if it represents a module.
402 pub fn mod_def_id(&self) -> Option<DefId> {
403 match *self {
404 Res::Def(DefKind::Mod, id) => Some(id),
405 _ => None,
406 }
407 }
408
409 /// A human readable name for the res kind ("function", "module", etc.).
410 pub fn descr(&self) -> &'static str {
411 match *self {
412 Res::Def(kind, def_id) => kind.descr(def_id),
413 Res::SelfCtor(..) => "self constructor",
414 Res::PrimTy(..) => "builtin type",
415 Res::Local(..) => "local variable",
416 Res::SelfTy(..) => "self type",
417 Res::ToolMod => "tool module",
418 Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
419 Res::Err => "unresolved item",
420 }
421 }
422
423 /// Gets an English article for the `Res`.
424 pub fn article(&self) -> &'static str {
425 match *self {
426 Res::Def(kind, _) => kind.article(),
427 Res::NonMacroAttr(kind) => kind.article(),
428 Res::Err => "an",
429 _ => "a",
430 }
431 }
432
433 pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
434 match self {
435 Res::Def(kind, id) => Res::Def(kind, id),
436 Res::SelfCtor(id) => Res::SelfCtor(id),
437 Res::PrimTy(id) => Res::PrimTy(id),
438 Res::Local(id) => Res::Local(map(id)),
439 Res::SelfTy(a, b) => Res::SelfTy(a, b),
440 Res::ToolMod => Res::ToolMod,
441 Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
442 Res::Err => Res::Err,
443 }
444 }
445
446 pub fn macro_kind(self) -> Option<MacroKind> {
447 match self {
448 Res::Def(DefKind::Macro(kind), _) => Some(kind),
449 Res::NonMacroAttr(..) => Some(MacroKind::Attr),
450 _ => None,
451 }
452 }
453
454 pub fn matches_ns(&self, ns: Namespace) -> bool {
455 match self {
456 Res::Def(kind, ..) => kind.ns() == Some(ns),
457 Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS,
458 Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS,
459 Res::NonMacroAttr(..) => ns == Namespace::MacroNS,
460 Res::Err => true,
461 }
462 }
463 }