]> git.lizzy.rs Git - rust.git/blob - src/librustc_hir/def.rs
Auto merge of #71321 - matthewjasper:alloc-min-spec, r=sfackler
[rust.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::ast;
5 use rustc_ast::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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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, RustcEncodable, RustcDecodable, 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 = impl Bar;`
58     OpaqueTy,
59     /// `type Foo = Bar;`
60     TyAlias,
61     ForeignTy,
62     TraitAlias,
63     AssocTy,
64     /// `type Foo = impl Bar;`
65     AssocOpaqueTy,
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     Field,
87     LifetimeParam,
88     GlobalAsm,
89     Impl,
90     Closure,
91     Generator,
92 }
93
94 impl DefKind {
95     pub fn descr(self, def_id: DefId) -> &'static str {
96         match self {
97             DefKind::Fn => "function",
98             DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
99                 "crate"
100             }
101             DefKind::Mod => "module",
102             DefKind::Static => "static",
103             DefKind::Enum => "enum",
104             DefKind::Variant => "variant",
105             DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
106             DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
107             DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
108             DefKind::Struct => "struct",
109             DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
110             DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
111             DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
112                 panic!("impossible struct constructor")
113             }
114             DefKind::OpaqueTy => "opaque type",
115             DefKind::TyAlias => "type alias",
116             DefKind::TraitAlias => "trait alias",
117             DefKind::AssocTy => "associated type",
118             DefKind::AssocOpaqueTy => "associated opaque 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::AssocOpaqueTy
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 matches_ns(&self, ns: Namespace) -> bool {
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::AssocOpaqueTy
172             | DefKind::TyParam => ns == Namespace::TypeNS,
173
174             DefKind::Fn
175             | DefKind::Const
176             | DefKind::ConstParam
177             | DefKind::Static
178             | DefKind::Ctor(..)
179             | DefKind::AssocFn
180             | DefKind::AssocConst => ns == Namespace::ValueNS,
181
182             DefKind::Macro(..) => ns == Namespace::MacroNS,
183
184             // Not namespaced.
185             DefKind::AnonConst
186             | DefKind::Field
187             | DefKind::LifetimeParam
188             | DefKind::ExternCrate
189             | DefKind::Closure
190             | DefKind::Generator
191             | DefKind::Use
192             | DefKind::ForeignMod
193             | DefKind::GlobalAsm
194             | DefKind::Impl => false,
195         }
196     }
197 }
198
199 /// The resolution of a path or export.
200 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
201 #[derive(HashStable_Generic)]
202 pub enum Res<Id = hir::HirId> {
203     Def(DefKind, DefId),
204
205     // Type namespace
206     PrimTy(hir::PrimTy),
207     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
208     ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
209
210     // Value namespace
211     SelfCtor(DefId /* impl */), // `DefId` refers to the impl
212     Local(Id),
213
214     // Macro namespace
215     NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
216
217     // All namespaces
218     Err,
219 }
220
221 /// The result of resolving a path before lowering to HIR,
222 /// with "module" segments resolved and associated item
223 /// segments deferred to type checking.
224 /// `base_res` is the resolution of the resolved part of the
225 /// path, `unresolved_segments` is the number of unresolved
226 /// segments.
227 ///
228 /// ```text
229 /// module::Type::AssocX::AssocY::MethodOrAssocType
230 /// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
231 /// base_res      unresolved_segments = 3
232 ///
233 /// <T as Trait>::AssocX::AssocY::MethodOrAssocType
234 ///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
235 ///       base_res        unresolved_segments = 2
236 /// ```
237 #[derive(Copy, Clone, Debug)]
238 pub struct PartialRes {
239     base_res: Res<NodeId>,
240     unresolved_segments: usize,
241 }
242
243 impl PartialRes {
244     #[inline]
245     pub fn new(base_res: Res<NodeId>) -> Self {
246         PartialRes { base_res, unresolved_segments: 0 }
247     }
248
249     #[inline]
250     pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
251         if base_res == Res::Err {
252             unresolved_segments = 0
253         }
254         PartialRes { base_res, unresolved_segments }
255     }
256
257     #[inline]
258     pub fn base_res(&self) -> Res<NodeId> {
259         self.base_res
260     }
261
262     #[inline]
263     pub fn unresolved_segments(&self) -> usize {
264         self.unresolved_segments
265     }
266 }
267
268 /// Different kinds of symbols don't influence each other.
269 ///
270 /// Therefore, they have a separate universe (namespace).
271 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
272 pub enum Namespace {
273     TypeNS,
274     ValueNS,
275     MacroNS,
276 }
277
278 impl Namespace {
279     pub fn descr(self) -> &'static str {
280         match self {
281             Self::TypeNS => "type",
282             Self::ValueNS => "value",
283             Self::MacroNS => "macro",
284         }
285     }
286 }
287
288 /// Just a helper ‒ separate structure for each namespace.
289 #[derive(Copy, Clone, Default, Debug)]
290 pub struct PerNS<T> {
291     pub value_ns: T,
292     pub type_ns: T,
293     pub macro_ns: T,
294 }
295
296 impl<T> PerNS<T> {
297     pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
298         PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
299     }
300 }
301
302 impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
303     type Output = T;
304
305     fn index(&self, ns: Namespace) -> &T {
306         match ns {
307             Namespace::ValueNS => &self.value_ns,
308             Namespace::TypeNS => &self.type_ns,
309             Namespace::MacroNS => &self.macro_ns,
310         }
311     }
312 }
313
314 impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
315     fn index_mut(&mut self, ns: Namespace) -> &mut T {
316         match ns {
317             Namespace::ValueNS => &mut self.value_ns,
318             Namespace::TypeNS => &mut self.type_ns,
319             Namespace::MacroNS => &mut self.macro_ns,
320         }
321     }
322 }
323
324 impl<T> PerNS<Option<T>> {
325     /// Returns `true` if all the items in this collection are `None`.
326     pub fn is_empty(&self) -> bool {
327         self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
328     }
329
330     /// Returns an iterator over the items which are `Some`.
331     pub fn present_items(self) -> impl Iterator<Item = T> {
332         use std::iter::once;
333
334         once(self.type_ns).chain(once(self.value_ns)).chain(once(self.macro_ns)).filter_map(|it| it)
335     }
336 }
337
338 impl CtorKind {
339     pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
340         match *vdata {
341             ast::VariantData::Tuple(..) => CtorKind::Fn,
342             ast::VariantData::Unit(..) => CtorKind::Const,
343             ast::VariantData::Struct(..) => CtorKind::Fictive,
344         }
345     }
346
347     pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
348         match *vdata {
349             hir::VariantData::Tuple(..) => CtorKind::Fn,
350             hir::VariantData::Unit(..) => CtorKind::Const,
351             hir::VariantData::Struct(..) => CtorKind::Fictive,
352         }
353     }
354 }
355
356 impl NonMacroAttrKind {
357     pub fn descr(self) -> &'static str {
358         match self {
359             NonMacroAttrKind::Builtin => "built-in attribute",
360             NonMacroAttrKind::Tool => "tool attribute",
361             NonMacroAttrKind::DeriveHelper => "derive helper attribute",
362             NonMacroAttrKind::Registered => "explicitly registered attribute",
363         }
364     }
365
366     pub fn article(self) -> &'static str {
367         match self {
368             NonMacroAttrKind::Registered => "an",
369             _ => "a",
370         }
371     }
372
373     /// Users of some attributes cannot mark them as used, so they are considered always used.
374     pub fn is_used(self) -> bool {
375         match self {
376             NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
377             NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
378         }
379     }
380 }
381
382 impl<Id> Res<Id> {
383     /// Return the `DefId` of this `Def` if it has an ID, else panic.
384     pub fn def_id(&self) -> DefId
385     where
386         Id: Debug,
387     {
388         self.opt_def_id()
389             .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self))
390     }
391
392     /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
393     pub fn opt_def_id(&self) -> Option<DefId> {
394         match *self {
395             Res::Def(_, id) => Some(id),
396
397             Res::Local(..)
398             | Res::PrimTy(..)
399             | Res::SelfTy(..)
400             | Res::SelfCtor(..)
401             | Res::ToolMod
402             | Res::NonMacroAttr(..)
403             | Res::Err => None,
404         }
405     }
406
407     /// Return the `DefId` of this `Res` if it represents a module.
408     pub fn mod_def_id(&self) -> Option<DefId> {
409         match *self {
410             Res::Def(DefKind::Mod, id) => Some(id),
411             _ => None,
412         }
413     }
414
415     /// A human readable name for the res kind ("function", "module", etc.).
416     pub fn descr(&self) -> &'static str {
417         match *self {
418             Res::Def(kind, def_id) => kind.descr(def_id),
419             Res::SelfCtor(..) => "self constructor",
420             Res::PrimTy(..) => "builtin type",
421             Res::Local(..) => "local variable",
422             Res::SelfTy(..) => "self type",
423             Res::ToolMod => "tool module",
424             Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
425             Res::Err => "unresolved item",
426         }
427     }
428
429     /// Gets an English article for the `Res`.
430     pub fn article(&self) -> &'static str {
431         match *self {
432             Res::Def(kind, _) => kind.article(),
433             Res::NonMacroAttr(kind) => kind.article(),
434             Res::Err => "an",
435             _ => "a",
436         }
437     }
438
439     pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
440         match self {
441             Res::Def(kind, id) => Res::Def(kind, id),
442             Res::SelfCtor(id) => Res::SelfCtor(id),
443             Res::PrimTy(id) => Res::PrimTy(id),
444             Res::Local(id) => Res::Local(map(id)),
445             Res::SelfTy(a, b) => Res::SelfTy(a, b),
446             Res::ToolMod => Res::ToolMod,
447             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
448             Res::Err => Res::Err,
449         }
450     }
451
452     pub fn macro_kind(self) -> Option<MacroKind> {
453         match self {
454             Res::Def(DefKind::Macro(kind), _) => Some(kind),
455             Res::NonMacroAttr(..) => Some(MacroKind::Attr),
456             _ => None,
457         }
458     }
459
460     pub fn matches_ns(&self, ns: Namespace) -> bool {
461         match self {
462             Res::Def(kind, ..) => kind.matches_ns(ns),
463             Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS,
464             Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS,
465             Res::NonMacroAttr(..) => ns == Namespace::MacroNS,
466             Res::Err => true,
467         }
468     }
469 }