]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_hir/src/def.rs
New upstream version 1.49.0~beta.4+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 /// We do however allow `Self` in repeat expression even if it is generic to not break code
210 /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint.
211 ///
212 /// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable.
213 SelfTy(Option<DefId> /* trait */, Option<(DefId, bool)> /* impl */),
214 ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
215
216 // Value namespace
217 SelfCtor(DefId /* impl */), // `DefId` refers to the impl
218 Local(Id),
219
220 // Macro namespace
221 NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
222
223 // All namespaces
224 Err,
225 }
226
227 /// The result of resolving a path before lowering to HIR,
228 /// with "module" segments resolved and associated item
229 /// segments deferred to type checking.
230 /// `base_res` is the resolution of the resolved part of the
231 /// path, `unresolved_segments` is the number of unresolved
232 /// segments.
233 ///
234 /// ```text
235 /// module::Type::AssocX::AssocY::MethodOrAssocType
236 /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 /// base_res unresolved_segments = 3
238 ///
239 /// <T as Trait>::AssocX::AssocY::MethodOrAssocType
240 /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
241 /// base_res unresolved_segments = 2
242 /// ```
243 #[derive(Copy, Clone, Debug)]
244 pub struct PartialRes {
245 base_res: Res<NodeId>,
246 unresolved_segments: usize,
247 }
248
249 impl PartialRes {
250 #[inline]
251 pub fn new(base_res: Res<NodeId>) -> Self {
252 PartialRes { base_res, unresolved_segments: 0 }
253 }
254
255 #[inline]
256 pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
257 if base_res == Res::Err {
258 unresolved_segments = 0
259 }
260 PartialRes { base_res, unresolved_segments }
261 }
262
263 #[inline]
264 pub fn base_res(&self) -> Res<NodeId> {
265 self.base_res
266 }
267
268 #[inline]
269 pub fn unresolved_segments(&self) -> usize {
270 self.unresolved_segments
271 }
272 }
273
274 /// Different kinds of symbols don't influence each other.
275 ///
276 /// Therefore, they have a separate universe (namespace).
277 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
278 pub enum Namespace {
279 TypeNS,
280 ValueNS,
281 MacroNS,
282 }
283
284 impl Namespace {
285 pub fn descr(self) -> &'static str {
286 match self {
287 Self::TypeNS => "type",
288 Self::ValueNS => "value",
289 Self::MacroNS => "macro",
290 }
291 }
292 }
293
294 /// Just a helper ‒ separate structure for each namespace.
295 #[derive(Copy, Clone, Default, Debug)]
296 pub struct PerNS<T> {
297 pub value_ns: T,
298 pub type_ns: T,
299 pub macro_ns: T,
300 }
301
302 impl<T> PerNS<T> {
303 pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
304 PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
305 }
306
307 pub fn into_iter(self) -> IntoIter<T, 3> {
308 IntoIter::new([self.value_ns, self.type_ns, self.macro_ns])
309 }
310
311 pub fn iter(&self) -> IntoIter<&T, 3> {
312 IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns])
313 }
314 }
315
316 impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
317 type Output = T;
318
319 fn index(&self, ns: Namespace) -> &T {
320 match ns {
321 Namespace::ValueNS => &self.value_ns,
322 Namespace::TypeNS => &self.type_ns,
323 Namespace::MacroNS => &self.macro_ns,
324 }
325 }
326 }
327
328 impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
329 fn index_mut(&mut self, ns: Namespace) -> &mut T {
330 match ns {
331 Namespace::ValueNS => &mut self.value_ns,
332 Namespace::TypeNS => &mut self.type_ns,
333 Namespace::MacroNS => &mut self.macro_ns,
334 }
335 }
336 }
337
338 impl<T> PerNS<Option<T>> {
339 /// Returns `true` if all the items in this collection are `None`.
340 pub fn is_empty(&self) -> bool {
341 self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
342 }
343
344 /// Returns an iterator over the items which are `Some`.
345 pub fn present_items(self) -> impl Iterator<Item = T> {
346 IntoIter::new([self.type_ns, self.value_ns, 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
488 /// Returns whether such a resolved path can occur in a tuple struct/variant pattern
489 pub fn expected_in_tuple_struct_pat(&self) -> bool {
490 matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..))
491 }
492 }