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