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