]>
Commit | Line | Data |
---|---|---|
e1599b0c XL |
1 | use self::Namespace::*; |
2 | ||
416331ca | 3 | use crate::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; |
e1599b0c XL |
4 | use crate::hir; |
5 | use crate::ty; | |
48663c56 | 6 | use crate::util::nodemap::DefIdMap; |
e1599b0c | 7 | |
1a4d82fc | 8 | use syntax::ast; |
48663c56 | 9 | use syntax::ast::NodeId; |
e74abb32 | 10 | use syntax_pos::hygiene::MacroKind; |
cc61c64b | 11 | use syntax_pos::Span; |
532ac7d7 | 12 | use rustc_macros::HashStable; |
1a4d82fc | 13 | |
e1599b0c | 14 | use std::fmt::Debug; |
94b46f34 | 15 | |
48663c56 | 16 | /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct. |
532ac7d7 XL |
17 | #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
18 | pub enum CtorOf { | |
48663c56 | 19 | /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct. |
532ac7d7 | 20 | Struct, |
48663c56 | 21 | /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant. |
532ac7d7 XL |
22 | Variant, |
23 | } | |
24 | ||
25 | #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] | |
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 | ||
532ac7d7 | 35 | #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
b7449926 XL |
36 | pub enum NonMacroAttrKind { |
37 | /// Single-segment attribute defined by the language (`#[inline]`) | |
38 | Builtin, | |
39 | /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`). | |
40 | Tool, | |
41 | /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`). | |
42 | DeriveHelper, | |
60c5eb7d XL |
43 | /// Single-segment custom attribute registered with `#[register_attr]`. |
44 | Registered, | |
b7449926 XL |
45 | } |
46 | ||
532ac7d7 | 47 | #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] |
48663c56 | 48 | pub enum DefKind { |
c30ab7b3 | 49 | // Type namespace |
48663c56 XL |
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, | |
416331ca XL |
58 | /// `type Foo = impl Bar;` |
59 | OpaqueTy, | |
8faf50e0 | 60 | /// `type Foo = Bar;` |
48663c56 XL |
61 | TyAlias, |
62 | ForeignTy, | |
63 | TraitAlias, | |
dc9dc135 | 64 | AssocTy, |
416331ca XL |
65 | /// `type Foo = impl Bar;` |
66 | AssocOpaqueTy, | |
48663c56 XL |
67 | TyParam, |
68 | ||
69 | // Value namespace | |
70 | Fn, | |
71 | Const, | |
72 | ConstParam, | |
73 | Static, | |
74 | /// Refers to the struct or enum variant's constructor. | |
75 | Ctor(CtorOf, CtorKind), | |
76 | Method, | |
dc9dc135 | 77 | AssocConst, |
48663c56 XL |
78 | |
79 | // Macro namespace | |
80 | Macro(MacroKind), | |
81 | } | |
82 | ||
83 | impl DefKind { | |
416331ca | 84 | pub fn descr(self, def_id: DefId) -> &'static str { |
48663c56 XL |
85 | match self { |
86 | DefKind::Fn => "function", | |
416331ca XL |
87 | DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => |
88 | "crate", | |
48663c56 XL |
89 | DefKind::Mod => "module", |
90 | DefKind::Static => "static", | |
91 | DefKind::Enum => "enum", | |
92 | DefKind::Variant => "variant", | |
93 | DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant", | |
94 | DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant", | |
95 | DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant", | |
96 | DefKind::Struct => "struct", | |
97 | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", | |
98 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", | |
99 | DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => | |
100 | bug!("impossible struct constructor"), | |
416331ca | 101 | DefKind::OpaqueTy => "opaque type", |
48663c56 XL |
102 | DefKind::TyAlias => "type alias", |
103 | DefKind::TraitAlias => "trait alias", | |
dc9dc135 | 104 | DefKind::AssocTy => "associated type", |
416331ca | 105 | DefKind::AssocOpaqueTy => "associated opaque type", |
48663c56 XL |
106 | DefKind::Union => "union", |
107 | DefKind::Trait => "trait", | |
108 | DefKind::ForeignTy => "foreign type", | |
109 | DefKind::Method => "method", | |
110 | DefKind::Const => "constant", | |
dc9dc135 | 111 | DefKind::AssocConst => "associated constant", |
48663c56 XL |
112 | DefKind::TyParam => "type parameter", |
113 | DefKind::ConstParam => "const parameter", | |
114 | DefKind::Macro(macro_kind) => macro_kind.descr(), | |
115 | } | |
116 | } | |
117 | ||
e1599b0c | 118 | /// Gets an English article for the definition. |
48663c56 XL |
119 | pub fn article(&self) -> &'static str { |
120 | match *self { | |
dc9dc135 XL |
121 | DefKind::AssocTy |
122 | | DefKind::AssocConst | |
416331ca | 123 | | DefKind::AssocOpaqueTy |
48663c56 | 124 | | DefKind::Enum |
416331ca | 125 | | DefKind::OpaqueTy => "an", |
48663c56 XL |
126 | DefKind::Macro(macro_kind) => macro_kind.article(), |
127 | _ => "a", | |
128 | } | |
129 | } | |
60c5eb7d XL |
130 | |
131 | pub fn matches_ns(&self, ns: Namespace) -> bool { | |
132 | match self { | |
133 | DefKind::Mod | |
134 | | DefKind::Struct | |
135 | | DefKind::Union | |
136 | | DefKind::Enum | |
137 | | DefKind::Variant | |
138 | | DefKind::Trait | |
139 | | DefKind::OpaqueTy | |
140 | | DefKind::TyAlias | |
141 | | DefKind::ForeignTy | |
142 | | DefKind::TraitAlias | |
143 | | DefKind::AssocTy | |
144 | | DefKind::AssocOpaqueTy | |
145 | | DefKind::TyParam => ns == Namespace::TypeNS, | |
146 | ||
147 | DefKind::Fn | |
148 | | DefKind::Const | |
149 | | DefKind::ConstParam | |
150 | | DefKind::Static | |
151 | | DefKind::Ctor(..) | |
152 | | DefKind::Method | |
153 | | DefKind::AssocConst => ns == Namespace::ValueNS, | |
154 | ||
155 | DefKind::Macro(..) => ns == Namespace::MacroNS, | |
156 | } | |
157 | } | |
48663c56 XL |
158 | } |
159 | ||
160 | #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] | |
161 | pub enum Res<Id = hir::HirId> { | |
162 | Def(DefKind, DefId), | |
163 | ||
164 | // Type namespace | |
e1599b0c | 165 | |
7453a54e | 166 | PrimTy(hir::PrimTy), |
c30ab7b3 | 167 | SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */), |
0731742a | 168 | ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]` |
1a4d82fc | 169 | |
c30ab7b3 | 170 | // Value namespace |
e1599b0c | 171 | |
0731742a | 172 | SelfCtor(DefId /* impl */), // `DefId` refers to the impl |
48663c56 | 173 | Local(Id), |
c30ab7b3 | 174 | |
476ff2be | 175 | // Macro namespace |
e1599b0c | 176 | |
0731742a | 177 | NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]` |
cc61c64b | 178 | |
48663c56 | 179 | // All namespaces |
e1599b0c | 180 | |
7453a54e | 181 | Err, |
c34b1796 AL |
182 | } |
183 | ||
48663c56 XL |
184 | /// The result of resolving a path before lowering to HIR, |
185 | /// with "module" segments resolved and associated item | |
186 | /// segments deferred to type checking. | |
187 | /// `base_res` is the resolution of the resolved part of the | |
8bb4bdeb XL |
188 | /// path, `unresolved_segments` is the number of unresolved |
189 | /// segments. | |
c34b1796 | 190 | /// |
ff7c6d11 XL |
191 | /// ```text |
192 | /// module::Type::AssocX::AssocY::MethodOrAssocType | |
193 | /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
48663c56 | 194 | /// base_res unresolved_segments = 3 |
ff7c6d11 XL |
195 | /// |
196 | /// <T as Trait>::AssocX::AssocY::MethodOrAssocType | |
197 | /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ | |
48663c56 | 198 | /// base_res unresolved_segments = 2 |
ff7c6d11 | 199 | /// ``` |
c34b1796 | 200 | #[derive(Copy, Clone, Debug)] |
48663c56 XL |
201 | pub struct PartialRes { |
202 | base_res: Res<NodeId>, | |
8bb4bdeb | 203 | unresolved_segments: usize, |
c34b1796 AL |
204 | } |
205 | ||
48663c56 XL |
206 | impl PartialRes { |
207 | #[inline] | |
208 | pub fn new(base_res: Res<NodeId>) -> Self { | |
209 | PartialRes { base_res, unresolved_segments: 0 } | |
8bb4bdeb XL |
210 | } |
211 | ||
48663c56 XL |
212 | #[inline] |
213 | pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self { | |
214 | if base_res == Res::Err { unresolved_segments = 0 } | |
215 | PartialRes { base_res, unresolved_segments } | |
8bb4bdeb XL |
216 | } |
217 | ||
218 | #[inline] | |
48663c56 XL |
219 | pub fn base_res(&self) -> Res<NodeId> { |
220 | self.base_res | |
8bb4bdeb XL |
221 | } |
222 | ||
223 | #[inline] | |
224 | pub fn unresolved_segments(&self) -> usize { | |
225 | self.unresolved_segments | |
3157f602 | 226 | } |
1a4d82fc JJ |
227 | } |
228 | ||
94b46f34 XL |
229 | /// Different kinds of symbols don't influence each other. |
230 | /// | |
231 | /// Therefore, they have a separate universe (namespace). | |
232 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | |
233 | pub enum Namespace { | |
234 | TypeNS, | |
235 | ValueNS, | |
236 | MacroNS, | |
237 | } | |
238 | ||
8faf50e0 XL |
239 | impl Namespace { |
240 | pub fn descr(self) -> &'static str { | |
241 | match self { | |
242 | TypeNS => "type", | |
243 | ValueNS => "value", | |
244 | MacroNS => "macro", | |
245 | } | |
246 | } | |
247 | } | |
248 | ||
94b46f34 XL |
249 | /// Just a helper ‒ separate structure for each namespace. |
250 | #[derive(Copy, Clone, Default, Debug)] | |
251 | pub struct PerNS<T> { | |
252 | pub value_ns: T, | |
253 | pub type_ns: T, | |
254 | pub macro_ns: T, | |
255 | } | |
256 | ||
257 | impl<T> PerNS<T> { | |
258 | pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> { | |
259 | PerNS { | |
260 | value_ns: f(self.value_ns), | |
261 | type_ns: f(self.type_ns), | |
262 | macro_ns: f(self.macro_ns), | |
263 | } | |
264 | } | |
265 | } | |
266 | ||
267 | impl<T> ::std::ops::Index<Namespace> for PerNS<T> { | |
268 | type Output = T; | |
0731742a | 269 | |
94b46f34 XL |
270 | fn index(&self, ns: Namespace) -> &T { |
271 | match ns { | |
272 | ValueNS => &self.value_ns, | |
273 | TypeNS => &self.type_ns, | |
274 | MacroNS => &self.macro_ns, | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
279 | impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> { | |
280 | fn index_mut(&mut self, ns: Namespace) -> &mut T { | |
281 | match ns { | |
282 | ValueNS => &mut self.value_ns, | |
283 | TypeNS => &mut self.type_ns, | |
284 | MacroNS => &mut self.macro_ns, | |
285 | } | |
286 | } | |
287 | } | |
288 | ||
289 | impl<T> PerNS<Option<T>> { | |
9fa01778 | 290 | /// Returns `true` if all the items in this collection are `None`. |
94b46f34 XL |
291 | pub fn is_empty(&self) -> bool { |
292 | self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none() | |
293 | } | |
294 | ||
295 | /// Returns an iterator over the items which are `Some`. | |
296 | pub fn present_items(self) -> impl Iterator<Item=T> { | |
297 | use std::iter::once; | |
298 | ||
299 | once(self.type_ns) | |
300 | .chain(once(self.value_ns)) | |
301 | .chain(once(self.macro_ns)) | |
302 | .filter_map(|it| it) | |
303 | } | |
304 | } | |
305 | ||
041b39d2 XL |
306 | /// This is the replacement export map. It maps a module to all of the exports |
307 | /// within. | |
48663c56 | 308 | pub type ExportMap<Id> = DefIdMap<Vec<Export<Id>>>; |
94b46f34 | 309 | |
532ac7d7 | 310 | #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] |
48663c56 | 311 | pub struct Export<Id> { |
041b39d2 XL |
312 | /// The name of the target. |
313 | pub ident: ast::Ident, | |
48663c56 XL |
314 | /// The resolution of the target. |
315 | pub res: Res<Id>, | |
316 | /// The span of the target. | |
041b39d2 | 317 | pub span: Span, |
ff7c6d11 XL |
318 | /// The visibility of the export. |
319 | /// We include non-`pub` exports for hygienic macros that get used from extern crates. | |
320 | pub vis: ty::Visibility, | |
c30ab7b3 SL |
321 | } |
322 | ||
48663c56 XL |
323 | impl<Id> Export<Id> { |
324 | pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> { | |
325 | Export { | |
326 | ident: self.ident, | |
327 | res: self.res.map_id(map), | |
328 | span: self.span, | |
329 | vis: self.vis, | |
330 | } | |
331 | } | |
332 | } | |
333 | ||
c30ab7b3 SL |
334 | impl CtorKind { |
335 | pub fn from_ast(vdata: &ast::VariantData) -> CtorKind { | |
336 | match *vdata { | |
337 | ast::VariantData::Tuple(..) => CtorKind::Fn, | |
338 | ast::VariantData::Unit(..) => CtorKind::Const, | |
339 | ast::VariantData::Struct(..) => CtorKind::Fictive, | |
340 | } | |
341 | } | |
0731742a | 342 | |
c30ab7b3 SL |
343 | pub fn from_hir(vdata: &hir::VariantData) -> CtorKind { |
344 | match *vdata { | |
345 | hir::VariantData::Tuple(..) => CtorKind::Fn, | |
346 | hir::VariantData::Unit(..) => CtorKind::Const, | |
347 | hir::VariantData::Struct(..) => CtorKind::Fictive, | |
348 | } | |
349 | } | |
1a4d82fc JJ |
350 | } |
351 | ||
b7449926 | 352 | impl NonMacroAttrKind { |
69743fb6 | 353 | pub fn descr(self) -> &'static str { |
b7449926 XL |
354 | match self { |
355 | NonMacroAttrKind::Builtin => "built-in attribute", | |
356 | NonMacroAttrKind::Tool => "tool attribute", | |
357 | NonMacroAttrKind::DeriveHelper => "derive helper attribute", | |
60c5eb7d XL |
358 | NonMacroAttrKind::Registered => "explicitly registered attribute", |
359 | } | |
360 | } | |
361 | ||
362 | pub fn article(self) -> &'static str { | |
363 | match self { | |
364 | NonMacroAttrKind::Registered => "an", | |
365 | _ => "a", | |
366 | } | |
367 | } | |
368 | ||
369 | /// Users of some attributes cannot mark them as used, so they are considered always used. | |
370 | pub fn is_used(self) -> bool { | |
371 | match self { | |
372 | NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true, | |
373 | NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false, | |
b7449926 XL |
374 | } |
375 | } | |
376 | } | |
377 | ||
48663c56 | 378 | impl<Id> Res<Id> { |
e1599b0c | 379 | /// Return the `DefId` of this `Def` if it has an ID, else panic. |
48663c56 XL |
380 | pub fn def_id(&self) -> DefId |
381 | where | |
382 | Id: Debug, | |
383 | { | |
13cf67c4 | 384 | self.opt_def_id().unwrap_or_else(|| { |
48663c56 | 385 | bug!("attempted .def_id() on invalid res: {:?}", self) |
13cf67c4 XL |
386 | }) |
387 | } | |
388 | ||
e1599b0c | 389 | /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`. |
13cf67c4 | 390 | pub fn opt_def_id(&self) -> Option<DefId> { |
1a4d82fc | 391 | match *self { |
48663c56 XL |
392 | Res::Def(_, id) => Some(id), |
393 | ||
394 | Res::Local(..) | | |
48663c56 XL |
395 | Res::PrimTy(..) | |
396 | Res::SelfTy(..) | | |
397 | Res::SelfCtor(..) | | |
398 | Res::ToolMod | | |
399 | Res::NonMacroAttr(..) | | |
400 | Res::Err => { | |
13cf67c4 | 401 | None |
b039eaaf | 402 | } |
1a4d82fc JJ |
403 | } |
404 | } | |
405 | ||
48663c56 | 406 | /// Return the `DefId` of this `Res` if it represents a module. |
9fa01778 XL |
407 | pub fn mod_def_id(&self) -> Option<DefId> { |
408 | match *self { | |
48663c56 | 409 | Res::Def(DefKind::Mod, id) => Some(id), |
9fa01778 XL |
410 | _ => None, |
411 | } | |
412 | } | |
413 | ||
48663c56 XL |
414 | /// A human readable name for the res kind ("function", "module", etc.). |
415 | pub fn descr(&self) -> &'static str { | |
54a0048b | 416 | match *self { |
416331ca | 417 | Res::Def(kind, def_id) => kind.descr(def_id), |
48663c56 XL |
418 | Res::SelfCtor(..) => "self constructor", |
419 | Res::PrimTy(..) => "builtin type", | |
420 | Res::Local(..) => "local variable", | |
48663c56 XL |
421 | Res::SelfTy(..) => "self type", |
422 | Res::ToolMod => "tool module", | |
423 | Res::NonMacroAttr(attr_kind) => attr_kind.descr(), | |
424 | Res::Err => "unresolved item", | |
54a0048b SL |
425 | } |
426 | } | |
13cf67c4 | 427 | |
e1599b0c | 428 | /// Gets an English article for the `Res`. |
13cf67c4 XL |
429 | pub fn article(&self) -> &'static str { |
430 | match *self { | |
48663c56 | 431 | Res::Def(kind, _) => kind.article(), |
60c5eb7d | 432 | Res::NonMacroAttr(kind) => kind.article(), |
48663c56 | 433 | Res::Err => "an", |
13cf67c4 XL |
434 | _ => "a", |
435 | } | |
436 | } | |
48663c56 XL |
437 | |
438 | pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> { | |
439 | match self { | |
440 | Res::Def(kind, id) => Res::Def(kind, id), | |
441 | Res::SelfCtor(id) => Res::SelfCtor(id), | |
442 | Res::PrimTy(id) => Res::PrimTy(id), | |
443 | Res::Local(id) => Res::Local(map(id)), | |
48663c56 XL |
444 | Res::SelfTy(a, b) => Res::SelfTy(a, b), |
445 | Res::ToolMod => Res::ToolMod, | |
446 | Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind), | |
447 | Res::Err => Res::Err, | |
448 | } | |
449 | } | |
416331ca XL |
450 | |
451 | pub fn macro_kind(self) -> Option<MacroKind> { | |
452 | match self { | |
453 | Res::Def(DefKind::Macro(kind), _) => Some(kind), | |
454 | Res::NonMacroAttr(..) => Some(MacroKind::Attr), | |
455 | _ => None, | |
456 | } | |
457 | } | |
60c5eb7d XL |
458 | |
459 | pub fn matches_ns(&self, ns: Namespace) -> bool { | |
460 | match self { | |
461 | Res::Def(kind, ..) => kind.matches_ns(ns), | |
462 | Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => ns == Namespace::TypeNS, | |
463 | Res::SelfCtor(..) | Res::Local(..) => ns == Namespace::ValueNS, | |
464 | Res::NonMacroAttr(..) => ns == Namespace::MacroNS, | |
465 | Res::Err => true, | |
466 | } | |
467 | } | |
1a4d82fc | 468 | } |