]> git.lizzy.rs Git - rust.git/blob - src/librustc_hir/def.rs
pin docs: add some forward references
[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 = 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, RustcEncodable, RustcDecodable, 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 }