]>
Commit | Line | Data |
---|---|---|
dfeec247 | 1 | use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; |
e1599b0c | 2 | use crate::hir; |
e1599b0c | 3 | |
3dfed10e XL |
4 | use rustc_ast as ast; |
5 | use rustc_ast::NodeId; | |
dfeec247 XL |
6 | use rustc_macros::HashStable_Generic; |
7 | use rustc_span::hygiene::MacroKind; | |
5869c6ff | 8 | use rustc_span::Symbol; |
1a4d82fc | 9 | |
1b1a35ee | 10 | use std::array::IntoIter; |
e1599b0c | 11 | use std::fmt::Debug; |
94b46f34 | 12 | |
48663c56 | 13 | /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. |
3dfed10e | 14 | #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] |
dfeec247 | 15 | #[derive(HashStable_Generic)] |
532ac7d7 | 16 | pub enum CtorOf { |
48663c56 | 17 | /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct. |
532ac7d7 | 18 | Struct, |
48663c56 | 19 | /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant. |
532ac7d7 XL |
20 | Variant, |
21 | } | |
22 | ||
cdc7bbd5 | 23 | /// What kind of constructor something is. |
3dfed10e | 24 | #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] |
dfeec247 | 25 | #[derive(HashStable_Generic)] |
c30ab7b3 | 26 | pub enum CtorKind { |
041b39d2 | 27 | /// Constructor function automatically created by a tuple struct/variant. |
c30ab7b3 | 28 | Fn, |
041b39d2 | 29 | /// Constructor constant automatically created by a unit struct/variant. |
c30ab7b3 | 30 | Const, |
041b39d2 | 31 | /// Unusable name in value namespace created by a struct variant. |
c30ab7b3 SL |
32 | Fictive, |
33 | } | |
34 | ||
cdc7bbd5 | 35 | /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. |
3dfed10e | 36 | #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] |
dfeec247 | 37 | #[derive(HashStable_Generic)] |
b7449926 XL |
38 | pub enum NonMacroAttrKind { |
39 | /// Single-segment attribute defined by the language (`#[inline]`) | |
5869c6ff | 40 | Builtin(Symbol), |
b7449926 XL |
41 | /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`). |
42 | Tool, | |
43 | /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). | |
44 | DeriveHelper, | |
fc512014 XL |
45 | /// Single-segment custom attribute registered by a derive macro |
46 | /// but used before that derive macro was expanded (deprecated). | |
47 | DeriveHelperCompat, | |
60c5eb7d XL |
48 | /// Single-segment custom attribute registered with `#[register_attr]`. |
49 | Registered, | |
b7449926 XL |
50 | } |
51 | ||
cdc7bbd5 | 52 | /// What kind of definition something is; e.g., `mod` vs `struct`. |
3dfed10e | 53 | #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] |
dfeec247 | 54 | #[derive(HashStable_Generic)] |
48663c56 | 55 | pub enum DefKind { |
c30ab7b3 | 56 | // Type namespace |
48663c56 | 57 | Mod, |
cdc7bbd5 | 58 | /// Refers to the struct itself, [`DefKind::Ctor`] refers to its constructor if it exists. |
48663c56 XL |
59 | Struct, |
60 | Union, | |
61 | Enum, | |
cdc7bbd5 | 62 | /// Refers to the variant itself, [`DefKind::Ctor`] refers to its constructor if it exists. |
48663c56 XL |
63 | Variant, |
64 | Trait, | |
cdc7bbd5 | 65 | /// Type alias: `type Foo = Bar;` |
48663c56 | 66 | TyAlias, |
cdc7bbd5 | 67 | /// Type from an `extern` block. |
48663c56 | 68 | ForeignTy, |
cdc7bbd5 | 69 | /// Trait alias: `trait IntIterator = Iterator<Item = i32>;` |
48663c56 | 70 | TraitAlias, |
cdc7bbd5 | 71 | /// Associated type: `trait MyTrait { type Assoc; }` |
dc9dc135 | 72 | AssocTy, |
cdc7bbd5 | 73 | /// Type parameter: the `T` in `struct Vec<T> { ... }` |
48663c56 XL |
74 | TyParam, |
75 | ||
76 | // Value namespace | |
77 | Fn, | |
78 | Const, | |
cdc7bbd5 | 79 | /// Constant generic parameter: `struct Foo<const N: usize> { ... }` |
48663c56 XL |
80 | ConstParam, |
81 | Static, | |
82 | /// Refers to the struct or enum variant's constructor. | |
cdc7bbd5 XL |
83 | /// |
84 | /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and | |
85 | /// [`DefKind::Variant`] is because structs and enum variants exist | |
86 | /// in the *type* namespace, whereas struct and enum variant *constructors* | |
87 | /// exist in the *value* namespace. | |
88 | /// | |
89 | /// You may wonder why enum variants exist in the type namespace as opposed | |
90 | /// to the value namespace. Check out [RFC 2593] for intuition on why that is. | |
91 | /// | |
92 | /// [RFC 2593]: https://github.com/rust-lang/rfcs/pull/2593 | |
48663c56 | 93 | Ctor(CtorOf, CtorKind), |
cdc7bbd5 | 94 | /// Associated function: `impl MyStruct { fn associated() {} }` |
ba9703b0 | 95 | AssocFn, |
cdc7bbd5 | 96 | /// Associated constant: `trait MyTrait { const ASSOC: usize; }` |
dc9dc135 | 97 | AssocConst, |
48663c56 XL |
98 | |
99 | // Macro namespace | |
100 | Macro(MacroKind), | |
f9f354fc XL |
101 | |
102 | // Not namespaced (or they are, but we don't treat them so) | |
103 | ExternCrate, | |
104 | Use, | |
cdc7bbd5 | 105 | /// An `extern` block. |
f9f354fc | 106 | ForeignMod, |
3c0e092e | 107 | /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` |
f9f354fc | 108 | AnonConst, |
3c0e092e XL |
109 | /// An inline constant, e.g. `const { 1 + 2 }` |
110 | InlineConst, | |
cdc7bbd5 | 111 | /// Opaque type, aka `impl Trait`. |
f035d41b | 112 | OpaqueTy, |
f9f354fc | 113 | Field, |
cdc7bbd5 | 114 | /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` |
f9f354fc | 115 | LifetimeParam, |
cdc7bbd5 | 116 | /// A use of [`global_asm!`]. |
f9f354fc XL |
117 | GlobalAsm, |
118 | Impl, | |
119 | Closure, | |
120 | Generator, | |
48663c56 XL |
121 | } |
122 | ||
123 | impl DefKind { | |
416331ca | 124 | pub fn descr(self, def_id: DefId) -> &'static str { |
48663c56 XL |
125 | match self { |
126 | DefKind::Fn => "function", | |
dfeec247 XL |
127 | DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => { |
128 | "crate" | |
129 | } | |
48663c56 XL |
130 | DefKind::Mod => "module", |
131 | DefKind::Static => "static", | |
132 | DefKind::Enum => "enum", | |
133 | DefKind::Variant => "variant", | |
134 | DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant", | |
135 | DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant", | |
136 | DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant", | |
137 | DefKind::Struct => "struct", | |
138 | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", | |
139 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", | |
dfeec247 XL |
140 | DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => { |
141 | panic!("impossible struct constructor") | |
142 | } | |
416331ca | 143 | DefKind::OpaqueTy => "opaque type", |
48663c56 XL |
144 | DefKind::TyAlias => "type alias", |
145 | DefKind::TraitAlias => "trait alias", | |
dc9dc135 | 146 | DefKind::AssocTy => "associated type", |
48663c56 XL |
147 | DefKind::Union => "union", |
148 | DefKind::Trait => "trait", | |
149 | DefKind::ForeignTy => "foreign type", | |
ba9703b0 | 150 | DefKind::AssocFn => "associated function", |
48663c56 | 151 | DefKind::Const => "constant", |
dc9dc135 | 152 | DefKind::AssocConst => "associated constant", |
48663c56 XL |
153 | DefKind::TyParam => "type parameter", |
154 | DefKind::ConstParam => "const parameter", | |
155 | DefKind::Macro(macro_kind) => macro_kind.descr(), | |
f9f354fc XL |
156 | DefKind::LifetimeParam => "lifetime parameter", |
157 | DefKind::Use => "import", | |
158 | DefKind::ForeignMod => "foreign module", | |
159 | DefKind::AnonConst => "constant expression", | |
3c0e092e | 160 | DefKind::InlineConst => "inline constant", |
f9f354fc XL |
161 | DefKind::Field => "field", |
162 | DefKind::Impl => "implementation", | |
163 | DefKind::Closure => "closure", | |
164 | DefKind::Generator => "generator", | |
165 | DefKind::ExternCrate => "extern crate", | |
166 | DefKind::GlobalAsm => "global assembly block", | |
48663c56 XL |
167 | } |
168 | } | |
169 | ||
e1599b0c | 170 | /// Gets an English article for the definition. |
48663c56 XL |
171 | pub fn article(&self) -> &'static str { |
172 | match *self { | |
dc9dc135 XL |
173 | DefKind::AssocTy |
174 | | DefKind::AssocConst | |
ba9703b0 | 175 | | DefKind::AssocFn |
48663c56 | 176 | | DefKind::Enum |
f9f354fc XL |
177 | | DefKind::OpaqueTy |
178 | | DefKind::Impl | |
179 | | DefKind::Use | |
3c0e092e | 180 | | DefKind::InlineConst |
f9f354fc | 181 | | DefKind::ExternCrate => "an", |
48663c56 XL |
182 | DefKind::Macro(macro_kind) => macro_kind.article(), |
183 | _ => "a", | |
184 | } | |
185 | } | |
60c5eb7d | 186 | |
3dfed10e | 187 | pub fn ns(&self) -> Option<Namespace> { |
60c5eb7d XL |
188 | match self { |
189 | DefKind::Mod | |
190 | | DefKind::Struct | |
191 | | DefKind::Union | |
192 | | DefKind::Enum | |
193 | | DefKind::Variant | |
194 | | DefKind::Trait | |
195 | | DefKind::OpaqueTy | |
196 | | DefKind::TyAlias | |
197 | | DefKind::ForeignTy | |
198 | | DefKind::TraitAlias | |
199 | | DefKind::AssocTy | |
3dfed10e | 200 | | DefKind::TyParam => Some(Namespace::TypeNS), |
60c5eb7d XL |
201 | |
202 | DefKind::Fn | |
203 | | DefKind::Const | |
204 | | DefKind::ConstParam | |
205 | | DefKind::Static | |
206 | | DefKind::Ctor(..) | |
ba9703b0 | 207 | | DefKind::AssocFn |
3dfed10e | 208 | | DefKind::AssocConst => Some(Namespace::ValueNS), |
60c5eb7d | 209 | |
3dfed10e | 210 | DefKind::Macro(..) => Some(Namespace::MacroNS), |
f9f354fc XL |
211 | |
212 | // Not namespaced. | |
213 | DefKind::AnonConst | |
3c0e092e | 214 | | DefKind::InlineConst |
f9f354fc XL |
215 | | DefKind::Field |
216 | | DefKind::LifetimeParam | |
217 | | DefKind::ExternCrate | |
218 | | DefKind::Closure | |
219 | | DefKind::Generator | |
220 | | DefKind::Use | |
221 | | DefKind::ForeignMod | |
222 | | DefKind::GlobalAsm | |
3dfed10e | 223 | | DefKind::Impl => None, |
60c5eb7d XL |
224 | } |
225 | } | |
48663c56 XL |
226 | } |
227 | ||
ba9703b0 | 228 | /// The resolution of a path or export. |
cdc7bbd5 XL |
229 | /// |
230 | /// For every path or identifier in Rust, the compiler must determine | |
231 | /// what the path refers to. This process is called name resolution, | |
232 | /// and `Res` is the primary result of name resolution. | |
233 | /// | |
234 | /// For example, everything prefixed with `/* Res */` in this example has | |
235 | /// an associated `Res`: | |
236 | /// | |
237 | /// ``` | |
238 | /// fn str_to_string(s: & /* Res */ str) -> /* Res */ String { | |
239 | /// /* Res */ String::from(/* Res */ s) | |
240 | /// } | |
241 | /// | |
242 | /// /* Res */ str_to_string("hello"); | |
243 | /// ``` | |
244 | /// | |
245 | /// The associated `Res`s will be: | |
246 | /// | |
247 | /// - `str` will resolve to [`Res::PrimTy`]; | |
248 | /// - `String` will resolve to [`Res::Def`], and the `Res` will include the [`DefId`] | |
249 | /// for `String` as defined in the standard library; | |
250 | /// - `String::from` will also resolve to [`Res::Def`], with the [`DefId`] | |
251 | /// pointing to `String::from`; | |
252 | /// - `s` will resolve to [`Res::Local`]; | |
253 | /// - the call to `str_to_string` will resolve to [`Res::Def`], with the [`DefId`] | |
254 | /// pointing to the definition of `str_to_string` in the current crate. | |
255 | // | |
3dfed10e | 256 | #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] |
dfeec247 | 257 | #[derive(HashStable_Generic)] |
48663c56 | 258 | pub enum Res<Id = hir::HirId> { |
cdc7bbd5 XL |
259 | /// Definition having a unique ID (`DefId`), corresponds to something defined in user code. |
260 | /// | |
261 | /// **Not bound to a specific namespace.** | |
48663c56 XL |
262 | Def(DefKind, DefId), |
263 | ||
264 | // Type namespace | |
cdc7bbd5 XL |
265 | /// A primitive type such as `i32` or `str`. |
266 | /// | |
267 | /// **Belongs to the type namespace.** | |
7453a54e | 268 | PrimTy(hir::PrimTy), |
cdc7bbd5 XL |
269 | /// The `Self` type, optionally with the trait it is associated with |
270 | /// and optionally with the [`DefId`] of the impl it is associated with. | |
271 | /// | |
272 | /// **Belongs to the type namespace.** | |
273 | /// | |
274 | /// For example, the `Self` in | |
1b1a35ee | 275 | /// |
cdc7bbd5 XL |
276 | /// ``` |
277 | /// trait Foo { | |
278 | /// fn foo() -> Box<Self>; | |
279 | /// } | |
280 | /// ``` | |
281 | /// | |
282 | /// would have the [`DefId`] of `Foo` associated with it. The `Self` in | |
283 | /// | |
284 | /// ``` | |
285 | /// struct Bar; | |
286 | /// | |
287 | /// impl Bar { | |
288 | /// fn new() -> Self { Bar } | |
289 | /// } | |
290 | /// ``` | |
291 | /// | |
292 | /// would have the [`DefId`] of the impl associated with it. Finally, the `Self` in | |
293 | /// | |
294 | /// ``` | |
295 | /// impl Foo for Bar { | |
296 | /// fn foo() -> Box<Self> { Box::new(Bar) } | |
297 | /// } | |
298 | /// ``` | |
299 | /// | |
300 | /// would have both the [`DefId`] of `Foo` and the [`DefId`] of the impl | |
301 | /// associated with it. | |
302 | /// | |
303 | /// *See also [`Res::SelfCtor`].* | |
304 | /// | |
305 | /// ----- | |
306 | /// | |
307 | /// HACK(min_const_generics): impl self types also have an optional requirement to **not** mention | |
1b1a35ee | 308 | /// any generic parameters to allow the following with `min_const_generics`: |
cdc7bbd5 XL |
309 | /// ``` |
310 | /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } } | |
1b1a35ee | 311 | /// ``` |
29967ef6 XL |
312 | /// We do however allow `Self` in repeat expression even if it is generic to not break code |
313 | /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint. | |
1b1a35ee | 314 | /// |
94222f64 | 315 | /// FIXME(generic_const_exprs): Remove this bodge once that feature is stable. |
cdc7bbd5 XL |
316 | SelfTy( |
317 | /// Optionally, the trait associated with this `Self` type. | |
318 | Option<DefId>, | |
319 | /// Optionally, the impl associated with this `Self` type. | |
320 | Option<(DefId, bool)>, | |
321 | ), | |
322 | /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`. | |
323 | /// | |
324 | /// **Belongs to the type namespace.** | |
325 | ToolMod, | |
1a4d82fc | 326 | |
c30ab7b3 | 327 | // Value namespace |
cdc7bbd5 XL |
328 | /// The `Self` constructor, along with the [`DefId`] |
329 | /// of the impl it is associated with. | |
330 | /// | |
331 | /// **Belongs to the value namespace.** | |
332 | /// | |
333 | /// *See also [`Res::SelfTy`].* | |
334 | SelfCtor(DefId), | |
335 | /// A local variable or function parameter. | |
336 | /// | |
337 | /// **Belongs to the value namespace.** | |
48663c56 | 338 | Local(Id), |
c30ab7b3 | 339 | |
476ff2be | 340 | // Macro namespace |
cdc7bbd5 XL |
341 | /// An attribute that is *not* implemented via macro. |
342 | /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives, | |
343 | /// as opposed to `#[test]`, which is a builtin macro. | |
344 | /// | |
345 | /// **Belongs to the macro namespace.** | |
0731742a | 346 | NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` |
cc61c64b | 347 | |
48663c56 | 348 | // All namespaces |
cdc7bbd5 XL |
349 | /// Name resolution failed. We use a dummy `Res` variant so later phases |
350 | /// of the compiler won't crash and can instead report more errors. | |
351 | /// | |
352 | /// **Not bound to a specific namespace.** | |
7453a54e | 353 | Err, |
c34b1796 AL |
354 | } |
355 | ||
48663c56 XL |
356 | /// The result of resolving a path before lowering to HIR, |
357 | /// with "module" segments resolved and associated item | |
358 | /// segments deferred to type checking. | |
359 | /// `base_res` is the resolution of the resolved part of the | |
8bb4bdeb XL |
360 | /// path, `unresolved_segments` is the number of unresolved |
361 | /// segments. | |
c34b1796 | 362 | /// |
ff7c6d11 XL |
363 | /// ```text |
364 | /// module::Type::AssocX::AssocY::MethodOrAssocType | |
365 | /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
48663c56 | 366 | /// base_res unresolved_segments = 3 |
ff7c6d11 XL |
367 | /// |
368 | /// <T as Trait>::AssocX::AssocY::MethodOrAssocType | |
369 | /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ | |
48663c56 | 370 | /// base_res unresolved_segments = 2 |
ff7c6d11 | 371 | /// ``` |
c34b1796 | 372 | #[derive(Copy, Clone, Debug)] |
48663c56 XL |
373 | pub struct PartialRes { |
374 | base_res: Res<NodeId>, | |
8bb4bdeb | 375 | unresolved_segments: usize, |
c34b1796 AL |
376 | } |
377 | ||
48663c56 XL |
378 | impl PartialRes { |
379 | #[inline] | |
380 | pub fn new(base_res: Res<NodeId>) -> Self { | |
381 | PartialRes { base_res, unresolved_segments: 0 } | |
8bb4bdeb XL |
382 | } |
383 | ||
48663c56 XL |
384 | #[inline] |
385 | pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self { | |
dfeec247 XL |
386 | if base_res == Res::Err { |
387 | unresolved_segments = 0 | |
388 | } | |
48663c56 | 389 | PartialRes { base_res, unresolved_segments } |
8bb4bdeb XL |
390 | } |
391 | ||
392 | #[inline] | |
48663c56 XL |
393 | pub fn base_res(&self) -> Res<NodeId> { |
394 | self.base_res | |
8bb4bdeb XL |
395 | } |
396 | ||
397 | #[inline] | |
398 | pub fn unresolved_segments(&self) -> usize { | |
399 | self.unresolved_segments | |
3157f602 | 400 | } |
1a4d82fc JJ |
401 | } |
402 | ||
cdc7bbd5 XL |
403 | /// Different kinds of symbols can coexist even if they share the same textual name. |
404 | /// Therefore, they each have a separate universe (known as a "namespace"). | |
94b46f34 XL |
405 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
406 | pub enum Namespace { | |
cdc7bbd5 XL |
407 | /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s |
408 | /// (and, by extension, crates). | |
409 | /// | |
410 | /// Note that the type namespace includes other items; this is not an | |
411 | /// exhaustive list. | |
94b46f34 | 412 | TypeNS, |
cdc7bbd5 | 413 | /// The value namespace includes `fn`s, `const`s, `static`s, and local variables (including function arguments). |
94b46f34 | 414 | ValueNS, |
cdc7bbd5 XL |
415 | /// The macro namespace includes `macro_rules!` macros, declarative `macro`s, |
416 | /// procedural macros, attribute macros, `derive` macros, and non-macro attributes | |
417 | /// like `#[inline]` and `#[rustfmt::skip]`. | |
94b46f34 XL |
418 | MacroNS, |
419 | } | |
420 | ||
8faf50e0 | 421 | impl Namespace { |
cdc7bbd5 | 422 | /// The English description of the namespace. |
8faf50e0 XL |
423 | pub fn descr(self) -> &'static str { |
424 | match self { | |
dfeec247 XL |
425 | Self::TypeNS => "type", |
426 | Self::ValueNS => "value", | |
427 | Self::MacroNS => "macro", | |
8faf50e0 XL |
428 | } |
429 | } | |
430 | } | |
431 | ||
94b46f34 XL |
432 | /// Just a helper ‒ separate structure for each namespace. |
433 | #[derive(Copy, Clone, Default, Debug)] | |
434 | pub struct PerNS<T> { | |
435 | pub value_ns: T, | |
436 | pub type_ns: T, | |
437 | pub macro_ns: T, | |
438 | } | |
439 | ||
440 | impl<T> PerNS<T> { | |
441 | pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> { | |
dfeec247 | 442 | PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) } |
94b46f34 | 443 | } |
1b1a35ee XL |
444 | |
445 | pub fn into_iter(self) -> IntoIter<T, 3> { | |
446 | IntoIter::new([self.value_ns, self.type_ns, self.macro_ns]) | |
447 | } | |
448 | ||
449 | pub fn iter(&self) -> IntoIter<&T, 3> { | |
450 | IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns]) | |
451 | } | |
94b46f34 XL |
452 | } |
453 | ||
454 | impl<T> ::std::ops::Index<Namespace> for PerNS<T> { | |
455 | type Output = T; | |
0731742a | 456 | |
94b46f34 XL |
457 | fn index(&self, ns: Namespace) -> &T { |
458 | match ns { | |
dfeec247 XL |
459 | Namespace::ValueNS => &self.value_ns, |
460 | Namespace::TypeNS => &self.type_ns, | |
461 | Namespace::MacroNS => &self.macro_ns, | |
94b46f34 XL |
462 | } |
463 | } | |
464 | } | |
465 | ||
466 | impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> { | |
467 | fn index_mut(&mut self, ns: Namespace) -> &mut T { | |
468 | match ns { | |
dfeec247 XL |
469 | Namespace::ValueNS => &mut self.value_ns, |
470 | Namespace::TypeNS => &mut self.type_ns, | |
471 | Namespace::MacroNS => &mut self.macro_ns, | |
94b46f34 XL |
472 | } |
473 | } | |
474 | } | |
475 | ||
476 | impl<T> PerNS<Option<T>> { | |
9fa01778 | 477 | /// Returns `true` if all the items in this collection are `None`. |
94b46f34 XL |
478 | pub fn is_empty(&self) -> bool { |
479 | self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none() | |
480 | } | |
481 | ||
482 | /// Returns an iterator over the items which are `Some`. | |
dfeec247 | 483 | pub fn present_items(self) -> impl Iterator<Item = T> { |
94222f64 | 484 | IntoIter::new([self.type_ns, self.value_ns, self.macro_ns]).flatten() |
48663c56 XL |
485 | } |
486 | } | |
487 | ||
c30ab7b3 SL |
488 | impl CtorKind { |
489 | pub fn from_ast(vdata: &ast::VariantData) -> CtorKind { | |
490 | match *vdata { | |
491 | ast::VariantData::Tuple(..) => CtorKind::Fn, | |
492 | ast::VariantData::Unit(..) => CtorKind::Const, | |
493 | ast::VariantData::Struct(..) => CtorKind::Fictive, | |
494 | } | |
495 | } | |
0731742a | 496 | |
dfeec247 | 497 | pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind { |
c30ab7b3 SL |
498 | match *vdata { |
499 | hir::VariantData::Tuple(..) => CtorKind::Fn, | |
500 | hir::VariantData::Unit(..) => CtorKind::Const, | |
501 | hir::VariantData::Struct(..) => CtorKind::Fictive, | |
502 | } | |
503 | } | |
1a4d82fc JJ |
504 | } |
505 | ||
b7449926 | 506 | impl NonMacroAttrKind { |
69743fb6 | 507 | pub fn descr(self) -> &'static str { |
b7449926 | 508 | match self { |
5869c6ff | 509 | NonMacroAttrKind::Builtin(..) => "built-in attribute", |
b7449926 | 510 | NonMacroAttrKind::Tool => "tool attribute", |
fc512014 XL |
511 | NonMacroAttrKind::DeriveHelper | NonMacroAttrKind::DeriveHelperCompat => { |
512 | "derive helper attribute" | |
513 | } | |
60c5eb7d XL |
514 | NonMacroAttrKind::Registered => "explicitly registered attribute", |
515 | } | |
516 | } | |
517 | ||
518 | pub fn article(self) -> &'static str { | |
519 | match self { | |
520 | NonMacroAttrKind::Registered => "an", | |
521 | _ => "a", | |
522 | } | |
523 | } | |
524 | ||
525 | /// Users of some attributes cannot mark them as used, so they are considered always used. | |
526 | pub fn is_used(self) -> bool { | |
527 | match self { | |
fc512014 XL |
528 | NonMacroAttrKind::Tool |
529 | | NonMacroAttrKind::DeriveHelper | |
530 | | NonMacroAttrKind::DeriveHelperCompat => true, | |
5869c6ff | 531 | NonMacroAttrKind::Builtin(..) | NonMacroAttrKind::Registered => false, |
b7449926 XL |
532 | } |
533 | } | |
534 | } | |
535 | ||
48663c56 | 536 | impl<Id> Res<Id> { |
e1599b0c | 537 | /// Return the `DefId` of this `Def` if it has an ID, else panic. |
48663c56 XL |
538 | pub fn def_id(&self) -> DefId |
539 | where | |
540 | Id: Debug, | |
541 | { | |
dfeec247 XL |
542 | self.opt_def_id() |
543 | .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self)) | |
13cf67c4 XL |
544 | } |
545 | ||
e1599b0c | 546 | /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`. |
13cf67c4 | 547 | pub fn opt_def_id(&self) -> Option<DefId> { |
1a4d82fc | 548 | match *self { |
48663c56 XL |
549 | Res::Def(_, id) => Some(id), |
550 | ||
dfeec247 XL |
551 | Res::Local(..) |
552 | | Res::PrimTy(..) | |
553 | | Res::SelfTy(..) | |
554 | | Res::SelfCtor(..) | |
555 | | Res::ToolMod | |
556 | | Res::NonMacroAttr(..) | |
557 | | Res::Err => None, | |
1a4d82fc JJ |
558 | } |
559 | } | |
560 | ||
48663c56 | 561 | /// Return the `DefId` of this `Res` if it represents a module. |
9fa01778 XL |
562 | pub fn mod_def_id(&self) -> Option<DefId> { |
563 | match *self { | |
48663c56 | 564 | Res::Def(DefKind::Mod, id) => Some(id), |
9fa01778 XL |
565 | _ => None, |
566 | } | |
567 | } | |
568 | ||
48663c56 XL |
569 | /// A human readable name for the res kind ("function", "module", etc.). |
570 | pub fn descr(&self) -> &'static str { | |
54a0048b | 571 | match *self { |
416331ca | 572 | Res::Def(kind, def_id) => kind.descr(def_id), |
48663c56 XL |
573 | Res::SelfCtor(..) => "self constructor", |
574 | Res::PrimTy(..) => "builtin type", | |
575 | Res::Local(..) => "local variable", | |
48663c56 XL |
576 | Res::SelfTy(..) => "self type", |
577 | Res::ToolMod => "tool module", | |
578 | Res::NonMacroAttr(attr_kind) => attr_kind.descr(), | |
579 | Res::Err => "unresolved item", | |
54a0048b SL |
580 | } |
581 | } | |
13cf67c4 | 582 | |
e1599b0c | 583 | /// Gets an English article for the `Res`. |
13cf67c4 XL |
584 | pub fn article(&self) -> &'static str { |
585 | match *self { | |
48663c56 | 586 | Res::Def(kind, _) => kind.article(), |
60c5eb7d | 587 | Res::NonMacroAttr(kind) => kind.article(), |
48663c56 | 588 | Res::Err => "an", |
13cf67c4 XL |
589 | _ => "a", |
590 | } | |
591 | } | |
48663c56 XL |
592 | |
593 | pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> { | |
594 | match self { | |
595 | Res::Def(kind, id) => Res::Def(kind, id), | |
596 | Res::SelfCtor(id) => Res::SelfCtor(id), | |
597 | Res::PrimTy(id) => Res::PrimTy(id), | |
598 | Res::Local(id) => Res::Local(map(id)), | |
48663c56 XL |
599 | Res::SelfTy(a, b) => Res::SelfTy(a, b), |
600 | Res::ToolMod => Res::ToolMod, | |
601 | Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind), | |
602 | Res::Err => Res::Err, | |
603 | } | |
604 | } | |
416331ca | 605 | |
c295e0f8 XL |
606 | #[track_caller] |
607 | pub fn expect_non_local<OtherId>(self) -> Res<OtherId> { | |
608 | self.map_id(|_| panic!("unexpected `Res::Local`")) | |
609 | } | |
610 | ||
416331ca XL |
611 | pub fn macro_kind(self) -> Option<MacroKind> { |
612 | match self { | |
613 | Res::Def(DefKind::Macro(kind), _) => Some(kind), | |
614 | Res::NonMacroAttr(..) => Some(MacroKind::Attr), | |
615 | _ => None, | |
616 | } | |
617 | } | |
60c5eb7d | 618 | |
1b1a35ee XL |
619 | /// Returns `None` if this is `Res::Err` |
620 | pub fn ns(&self) -> Option<Namespace> { | |
60c5eb7d | 621 | match self { |
1b1a35ee XL |
622 | Res::Def(kind, ..) => kind.ns(), |
623 | Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => Some(Namespace::TypeNS), | |
624 | Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS), | |
625 | Res::NonMacroAttr(..) => Some(Namespace::MacroNS), | |
626 | Res::Err => None, | |
60c5eb7d XL |
627 | } |
628 | } | |
1b1a35ee XL |
629 | |
630 | /// Always returns `true` if `self` is `Res::Err` | |
631 | pub fn matches_ns(&self, ns: Namespace) -> bool { | |
632 | self.ns().map_or(true, |actual_ns| actual_ns == ns) | |
633 | } | |
29967ef6 XL |
634 | |
635 | /// Returns whether such a resolved path can occur in a tuple struct/variant pattern | |
636 | pub fn expected_in_tuple_struct_pat(&self) -> bool { | |
637 | matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..)) | |
638 | } | |
1a4d82fc | 639 | } |