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