]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_span/src/hygiene.rs
Auto merge of #88650 - sapessi:issue-77175-fix, r=estebank
[rust.git] / compiler / rustc_span / src / hygiene.rs
1 //! Machinery for hygienic macros.
2 //!
3 //! Inspired by Matthew Flatt et al., “Macros That Work Together: Compile-Time Bindings, Partial
4 //! Expansion, and Definition Contexts,” *Journal of Functional Programming* 22, no. 2
5 //! (March 1, 2012): 181–216, <https://doi.org/10.1017/S0956796812000093>.
6
7 // Hygiene data is stored in a global variable and accessed via TLS, which
8 // means that accesses are somewhat expensive. (`HygieneData::with`
9 // encapsulates a single access.) Therefore, on hot code paths it is worth
10 // ensuring that multiple HygieneData accesses are combined into a single
11 // `HygieneData::with`.
12 //
13 // This explains why `HygieneData`, `SyntaxContext` and `ExpnId` have interfaces
14 // with a certain amount of redundancy in them. For example,
15 // `SyntaxContext::outer_expn_data` combines `SyntaxContext::outer` and
16 // `ExpnId::expn_data` so that two `HygieneData` accesses can be performed within
17 // a single `HygieneData::with` call.
18 //
19 // It also explains why many functions appear in `HygieneData` and again in
20 // `SyntaxContext` or `ExpnId`. For example, `HygieneData::outer` and
21 // `SyntaxContext::outer` do the same thing, but the former is for use within a
22 // `HygieneData::with` call while the latter is for use outside such a call.
23 // When modifying this file it is important to understand this distinction,
24 // because getting it wrong can lead to nested `HygieneData::with` calls that
25 // trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
26
27 use crate::edition::Edition;
28 use crate::symbol::{kw, sym, Symbol};
29 use crate::with_session_globals;
30 use crate::{HashStableContext, Span, DUMMY_SP};
31
32 use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
33 use rustc_data_structures::fingerprint::Fingerprint;
34 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
35 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
36 use rustc_data_structures::sync::{Lock, Lrc};
37 use rustc_data_structures::unhash::UnhashMap;
38 use rustc_index::vec::IndexVec;
39 use rustc_macros::HashStable_Generic;
40 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
41 use std::fmt;
42 use std::hash::Hash;
43 use tracing::*;
44
45 /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
46 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
47 pub struct SyntaxContext(u32);
48
49 #[derive(Debug, Encodable, Decodable, Clone)]
50 pub struct SyntaxContextData {
51     outer_expn: ExpnId,
52     outer_transparency: Transparency,
53     parent: SyntaxContext,
54     /// This context, but with all transparent and semi-transparent expansions filtered away.
55     opaque: SyntaxContext,
56     /// This context, but with all transparent expansions filtered away.
57     opaque_and_semitransparent: SyntaxContext,
58     /// Name of the crate to which `$crate` with this context would resolve.
59     dollar_crate_name: Symbol,
60 }
61
62 rustc_index::newtype_index! {
63     /// A unique ID associated with a macro invocation and expansion.
64     pub struct ExpnIndex {
65         ENCODABLE = custom
66     }
67 }
68
69 /// A unique ID associated with a macro invocation and expansion.
70 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
71 pub struct ExpnId {
72     pub krate: CrateNum,
73     pub local_id: ExpnIndex,
74 }
75
76 impl fmt::Debug for ExpnId {
77     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78         // Generate crate_::{{expn_}}.
79         write!(f, "{:?}::{{{{expn{}}}}}", self.krate, self.local_id.private)
80     }
81 }
82
83 rustc_index::newtype_index! {
84     /// A unique ID associated with a macro invocation and expansion.
85     pub struct LocalExpnId {
86         ENCODABLE = custom
87         DEBUG_FORMAT = "expn{}"
88     }
89 }
90
91 /// A unique hash value associated to an expansion.
92 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
93 pub struct ExpnHash(Fingerprint);
94
95 impl ExpnHash {
96     /// Returns the [StableCrateId] identifying the crate this [ExpnHash]
97     /// originates from.
98     #[inline]
99     pub fn stable_crate_id(self) -> StableCrateId {
100         StableCrateId(self.0.as_value().0)
101     }
102
103     /// Returns the crate-local part of the [ExpnHash].
104     ///
105     /// Used for tests.
106     #[inline]
107     pub fn local_hash(self) -> u64 {
108         self.0.as_value().1
109     }
110
111     #[inline]
112     pub fn is_root(self) -> bool {
113         self.0 == Fingerprint::ZERO
114     }
115
116     /// Builds a new [ExpnHash] with the given [StableCrateId] and
117     /// `local_hash`, where `local_hash` must be unique within its crate.
118     fn new(stable_crate_id: StableCrateId, local_hash: u64) -> ExpnHash {
119         ExpnHash(Fingerprint::new(stable_crate_id.0, local_hash))
120     }
121 }
122
123 /// A property of a macro expansion that determines how identifiers
124 /// produced by that expansion are resolved.
125 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)]
126 #[derive(HashStable_Generic)]
127 pub enum Transparency {
128     /// Identifier produced by a transparent expansion is always resolved at call-site.
129     /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
130     Transparent,
131     /// Identifier produced by a semi-transparent expansion may be resolved
132     /// either at call-site or at definition-site.
133     /// If it's a local variable, label or `$crate` then it's resolved at def-site.
134     /// Otherwise it's resolved at call-site.
135     /// `macro_rules` macros behave like this, built-in macros currently behave like this too,
136     /// but that's an implementation detail.
137     SemiTransparent,
138     /// Identifier produced by an opaque expansion is always resolved at definition-site.
139     /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
140     Opaque,
141 }
142
143 impl LocalExpnId {
144     /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
145     pub const ROOT: LocalExpnId = LocalExpnId::from_u32(0);
146
147     pub fn from_raw(idx: ExpnIndex) -> LocalExpnId {
148         LocalExpnId::from_u32(idx.as_u32())
149     }
150
151     pub fn as_raw(self) -> ExpnIndex {
152         ExpnIndex::from_u32(self.as_u32())
153     }
154
155     pub fn fresh_empty() -> LocalExpnId {
156         HygieneData::with(|data| {
157             let expn_id = data.local_expn_data.push(None);
158             let _eid = data.local_expn_hashes.push(ExpnHash(Fingerprint::ZERO));
159             debug_assert_eq!(expn_id, _eid);
160             expn_id
161         })
162     }
163
164     pub fn fresh(mut expn_data: ExpnData, ctx: impl HashStableContext) -> LocalExpnId {
165         debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
166         let expn_hash = update_disambiguator(&mut expn_data, ctx);
167         HygieneData::with(|data| {
168             let expn_id = data.local_expn_data.push(Some(expn_data));
169             let _eid = data.local_expn_hashes.push(expn_hash);
170             debug_assert_eq!(expn_id, _eid);
171             let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, expn_id.to_expn_id());
172             debug_assert!(_old_id.is_none());
173             expn_id
174         })
175     }
176
177     #[inline]
178     pub fn expn_hash(self) -> ExpnHash {
179         HygieneData::with(|data| data.local_expn_hash(self))
180     }
181
182     #[inline]
183     pub fn expn_data(self) -> ExpnData {
184         HygieneData::with(|data| data.local_expn_data(self).clone())
185     }
186
187     #[inline]
188     pub fn to_expn_id(self) -> ExpnId {
189         ExpnId { krate: LOCAL_CRATE, local_id: self.as_raw() }
190     }
191
192     #[inline]
193     pub fn set_expn_data(self, mut expn_data: ExpnData, ctx: impl HashStableContext) {
194         debug_assert_eq!(expn_data.parent.krate, LOCAL_CRATE);
195         let expn_hash = update_disambiguator(&mut expn_data, ctx);
196         HygieneData::with(|data| {
197             let old_expn_data = &mut data.local_expn_data[self];
198             assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
199             *old_expn_data = Some(expn_data);
200             debug_assert_eq!(data.local_expn_hashes[self].0, Fingerprint::ZERO);
201             data.local_expn_hashes[self] = expn_hash;
202             let _old_id = data.expn_hash_to_expn_id.insert(expn_hash, self.to_expn_id());
203             debug_assert!(_old_id.is_none());
204         });
205     }
206
207     #[inline]
208     pub fn is_descendant_of(self, ancestor: LocalExpnId) -> bool {
209         self.to_expn_id().is_descendant_of(ancestor.to_expn_id())
210     }
211
212     /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
213     /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
214     #[inline]
215     pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
216         self.to_expn_id().outer_expn_is_descendant_of(ctxt)
217     }
218
219     /// Returns span for the macro which originally caused this expansion to happen.
220     ///
221     /// Stops backtracing at include! boundary.
222     #[inline]
223     pub fn expansion_cause(self) -> Option<Span> {
224         self.to_expn_id().expansion_cause()
225     }
226
227     #[inline]
228     #[track_caller]
229     pub fn parent(self) -> LocalExpnId {
230         self.expn_data().parent.as_local().unwrap()
231     }
232 }
233
234 impl ExpnId {
235     /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST.
236     /// Invariant: we do not create any ExpnId with local_id == 0 and krate != 0.
237     pub const fn root() -> ExpnId {
238         ExpnId { krate: LOCAL_CRATE, local_id: ExpnIndex::from_u32(0) }
239     }
240
241     #[inline]
242     pub fn expn_hash(self) -> ExpnHash {
243         HygieneData::with(|data| data.expn_hash(self))
244     }
245
246     #[inline]
247     pub fn from_hash(hash: ExpnHash) -> Option<ExpnId> {
248         HygieneData::with(|data| data.expn_hash_to_expn_id.get(&hash).copied())
249     }
250
251     #[inline]
252     pub fn as_local(self) -> Option<LocalExpnId> {
253         if self.krate == LOCAL_CRATE { Some(LocalExpnId::from_raw(self.local_id)) } else { None }
254     }
255
256     #[inline]
257     #[track_caller]
258     pub fn expect_local(self) -> LocalExpnId {
259         self.as_local().unwrap()
260     }
261
262     #[inline]
263     pub fn expn_data(self) -> ExpnData {
264         HygieneData::with(|data| data.expn_data(self).clone())
265     }
266
267     pub fn is_descendant_of(self, ancestor: ExpnId) -> bool {
268         HygieneData::with(|data| data.is_descendant_of(self, ancestor))
269     }
270
271     /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
272     /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
273     pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
274         HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt)))
275     }
276
277     /// Returns span for the macro which originally caused this expansion to happen.
278     ///
279     /// Stops backtracing at include! boundary.
280     pub fn expansion_cause(mut self) -> Option<Span> {
281         let mut last_macro = None;
282         loop {
283             let expn_data = self.expn_data();
284             // Stop going up the backtrace once include! is encountered
285             if expn_data.is_root()
286                 || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
287             {
288                 break;
289             }
290             self = expn_data.call_site.ctxt().outer_expn();
291             last_macro = Some(expn_data.call_site);
292         }
293         last_macro
294     }
295 }
296
297 #[derive(Debug)]
298 pub struct HygieneData {
299     /// Each expansion should have an associated expansion data, but sometimes there's a delay
300     /// between creation of an expansion ID and obtaining its data (e.g. macros are collected
301     /// first and then resolved later), so we use an `Option` here.
302     local_expn_data: IndexVec<LocalExpnId, Option<ExpnData>>,
303     local_expn_hashes: IndexVec<LocalExpnId, ExpnHash>,
304     /// Data and hash information from external crates.  We may eventually want to remove these
305     /// maps, and fetch the information directly from the other crate's metadata like DefIds do.
306     foreign_expn_data: FxHashMap<ExpnId, ExpnData>,
307     foreign_expn_hashes: FxHashMap<ExpnId, ExpnHash>,
308     expn_hash_to_expn_id: UnhashMap<ExpnHash, ExpnId>,
309     syntax_context_data: Vec<SyntaxContextData>,
310     syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>,
311     /// Maps the `local_hash` of an `ExpnData` to the next disambiguator value.
312     /// This is used by `update_disambiguator` to keep track of which `ExpnData`s
313     /// would have collisions without a disambiguator.
314     /// The keys of this map are always computed with `ExpnData.disambiguator`
315     /// set to 0.
316     expn_data_disambiguators: FxHashMap<u64, u32>,
317 }
318
319 impl HygieneData {
320     crate fn new(edition: Edition) -> Self {
321         let root_data = ExpnData::default(
322             ExpnKind::Root,
323             DUMMY_SP,
324             edition,
325             Some(CRATE_DEF_ID.to_def_id()),
326             None,
327         );
328
329         HygieneData {
330             local_expn_data: IndexVec::from_elem_n(Some(root_data), 1),
331             local_expn_hashes: IndexVec::from_elem_n(ExpnHash(Fingerprint::ZERO), 1),
332             foreign_expn_data: FxHashMap::default(),
333             foreign_expn_hashes: FxHashMap::default(),
334             expn_hash_to_expn_id: std::iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
335                 .collect(),
336             syntax_context_data: vec![SyntaxContextData {
337                 outer_expn: ExpnId::root(),
338                 outer_transparency: Transparency::Opaque,
339                 parent: SyntaxContext(0),
340                 opaque: SyntaxContext(0),
341                 opaque_and_semitransparent: SyntaxContext(0),
342                 dollar_crate_name: kw::DollarCrate,
343             }],
344             syntax_context_map: FxHashMap::default(),
345             expn_data_disambiguators: FxHashMap::default(),
346         }
347     }
348
349     pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
350         with_session_globals(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
351     }
352
353     #[inline]
354     fn local_expn_hash(&self, expn_id: LocalExpnId) -> ExpnHash {
355         self.local_expn_hashes[expn_id]
356     }
357
358     #[inline]
359     fn expn_hash(&self, expn_id: ExpnId) -> ExpnHash {
360         match expn_id.as_local() {
361             Some(expn_id) => self.local_expn_hashes[expn_id],
362             None => self.foreign_expn_hashes[&expn_id],
363         }
364     }
365
366     fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
367         self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
368     }
369
370     fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
371         if let Some(expn_id) = expn_id.as_local() {
372             self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
373         } else {
374             &self.foreign_expn_data[&expn_id]
375         }
376     }
377
378     fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
379         while expn_id != ancestor {
380             if expn_id == ExpnId::root() {
381                 return false;
382             }
383             expn_id = self.expn_data(expn_id).parent;
384         }
385         true
386     }
387
388     fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
389         self.syntax_context_data[ctxt.0 as usize].opaque
390     }
391
392     fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
393         self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent
394     }
395
396     fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
397         self.syntax_context_data[ctxt.0 as usize].outer_expn
398     }
399
400     fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
401         let data = &self.syntax_context_data[ctxt.0 as usize];
402         (data.outer_expn, data.outer_transparency)
403     }
404
405     fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
406         self.syntax_context_data[ctxt.0 as usize].parent
407     }
408
409     fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) {
410         let outer_mark = self.outer_mark(*ctxt);
411         *ctxt = self.parent_ctxt(*ctxt);
412         outer_mark
413     }
414
415     fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
416         let mut marks = Vec::new();
417         while ctxt != SyntaxContext::root() {
418             debug!("marks: getting parent of {:?}", ctxt);
419             marks.push(self.outer_mark(ctxt));
420             ctxt = self.parent_ctxt(ctxt);
421         }
422         marks.reverse();
423         marks
424     }
425
426     fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
427         debug!("walk_chain({:?}, {:?})", span, to);
428         debug!("walk_chain: span ctxt = {:?}", span.ctxt());
429         while span.from_expansion() && span.ctxt() != to {
430             let outer_expn = self.outer_expn(span.ctxt());
431             debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
432             let expn_data = self.expn_data(outer_expn);
433             debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
434             span = expn_data.call_site;
435         }
436         span
437     }
438
439     fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
440         let mut scope = None;
441         while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
442             scope = Some(self.remove_mark(ctxt).0);
443         }
444         scope
445     }
446
447     fn apply_mark(
448         &mut self,
449         ctxt: SyntaxContext,
450         expn_id: ExpnId,
451         transparency: Transparency,
452     ) -> SyntaxContext {
453         assert_ne!(expn_id, ExpnId::root());
454         if transparency == Transparency::Opaque {
455             return self.apply_mark_internal(ctxt, expn_id, transparency);
456         }
457
458         let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt();
459         let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
460             self.normalize_to_macros_2_0(call_site_ctxt)
461         } else {
462             self.normalize_to_macro_rules(call_site_ctxt)
463         };
464
465         if call_site_ctxt == SyntaxContext::root() {
466             return self.apply_mark_internal(ctxt, expn_id, transparency);
467         }
468
469         // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a
470         // macros 2.0 expansion, i.e., a macros 1.0 invocation is in a macros 2.0 definition.
471         //
472         // In this case, the tokens from the macros 1.0 definition inherit the hygiene
473         // at their invocation. That is, we pretend that the macros 1.0 definition
474         // was defined at its invocation (i.e., inside the macros 2.0 definition)
475         // so that the macros 2.0 definition remains hygienic.
476         //
477         // See the example at `test/ui/hygiene/legacy_interaction.rs`.
478         for (expn_id, transparency) in self.marks(ctxt) {
479             call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency);
480         }
481         self.apply_mark_internal(call_site_ctxt, expn_id, transparency)
482     }
483
484     fn apply_mark_internal(
485         &mut self,
486         ctxt: SyntaxContext,
487         expn_id: ExpnId,
488         transparency: Transparency,
489     ) -> SyntaxContext {
490         let syntax_context_data = &mut self.syntax_context_data;
491         let mut opaque = syntax_context_data[ctxt.0 as usize].opaque;
492         let mut opaque_and_semitransparent =
493             syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent;
494
495         if transparency >= Transparency::Opaque {
496             let parent = opaque;
497             opaque = *self
498                 .syntax_context_map
499                 .entry((parent, expn_id, transparency))
500                 .or_insert_with(|| {
501                     let new_opaque = SyntaxContext(syntax_context_data.len() as u32);
502                     syntax_context_data.push(SyntaxContextData {
503                         outer_expn: expn_id,
504                         outer_transparency: transparency,
505                         parent,
506                         opaque: new_opaque,
507                         opaque_and_semitransparent: new_opaque,
508                         dollar_crate_name: kw::DollarCrate,
509                     });
510                     new_opaque
511                 });
512         }
513
514         if transparency >= Transparency::SemiTransparent {
515             let parent = opaque_and_semitransparent;
516             opaque_and_semitransparent = *self
517                 .syntax_context_map
518                 .entry((parent, expn_id, transparency))
519                 .or_insert_with(|| {
520                     let new_opaque_and_semitransparent =
521                         SyntaxContext(syntax_context_data.len() as u32);
522                     syntax_context_data.push(SyntaxContextData {
523                         outer_expn: expn_id,
524                         outer_transparency: transparency,
525                         parent,
526                         opaque,
527                         opaque_and_semitransparent: new_opaque_and_semitransparent,
528                         dollar_crate_name: kw::DollarCrate,
529                     });
530                     new_opaque_and_semitransparent
531                 });
532         }
533
534         let parent = ctxt;
535         *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| {
536             let new_opaque_and_semitransparent_and_transparent =
537                 SyntaxContext(syntax_context_data.len() as u32);
538             syntax_context_data.push(SyntaxContextData {
539                 outer_expn: expn_id,
540                 outer_transparency: transparency,
541                 parent,
542                 opaque,
543                 opaque_and_semitransparent,
544                 dollar_crate_name: kw::DollarCrate,
545             });
546             new_opaque_and_semitransparent_and_transparent
547         })
548     }
549 }
550
551 pub fn clear_syntax_context_map() {
552     HygieneData::with(|data| data.syntax_context_map = FxHashMap::default());
553 }
554
555 pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
556     HygieneData::with(|data| data.walk_chain(span, to))
557 }
558
559 pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
560     // The new contexts that need updating are at the end of the list and have `$crate` as a name.
561     let (len, to_update) = HygieneData::with(|data| {
562         (
563             data.syntax_context_data.len(),
564             data.syntax_context_data
565                 .iter()
566                 .rev()
567                 .take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate)
568                 .count(),
569         )
570     });
571     // The callback must be called from outside of the `HygieneData` lock,
572     // since it will try to acquire it too.
573     let range_to_update = len - to_update..len;
574     let names: Vec<_> =
575         range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
576     HygieneData::with(|data| {
577         range_to_update.zip(names).for_each(|(idx, name)| {
578             data.syntax_context_data[idx].dollar_crate_name = name;
579         })
580     })
581 }
582
583 pub fn debug_hygiene_data(verbose: bool) -> String {
584     HygieneData::with(|data| {
585         if verbose {
586             format!("{:#?}", data)
587         } else {
588             let mut s = String::from("");
589             s.push_str("Expansions:");
590             let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| {
591                 s.push_str(&format!(
592                     "\n{:?}: parent: {:?}, call_site_ctxt: {:?}, def_site_ctxt: {:?}, kind: {:?}",
593                     id,
594                     expn_data.parent,
595                     expn_data.call_site.ctxt(),
596                     expn_data.def_site.ctxt(),
597                     expn_data.kind,
598                 ))
599             };
600             data.local_expn_data.iter_enumerated().for_each(|(id, expn_data)| {
601                 let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID");
602                 debug_expn_data((&id.to_expn_id(), expn_data))
603             });
604             data.foreign_expn_data.iter().for_each(debug_expn_data);
605             s.push_str("\n\nSyntaxContexts:");
606             data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| {
607                 s.push_str(&format!(
608                     "\n#{}: parent: {:?}, outer_mark: ({:?}, {:?})",
609                     id, ctxt.parent, ctxt.outer_expn, ctxt.outer_transparency,
610                 ));
611             });
612             s
613         }
614     })
615 }
616
617 impl SyntaxContext {
618     #[inline]
619     pub const fn root() -> Self {
620         SyntaxContext(0)
621     }
622
623     #[inline]
624     crate fn as_u32(self) -> u32 {
625         self.0
626     }
627
628     #[inline]
629     crate fn from_u32(raw: u32) -> SyntaxContext {
630         SyntaxContext(raw)
631     }
632
633     /// Extend a syntax context with a given expansion and transparency.
634     crate fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
635         HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
636     }
637
638     /// Pulls a single mark off of the syntax context. This effectively moves the
639     /// context up one macro definition level. That is, if we have a nested macro
640     /// definition as follows:
641     ///
642     /// ```rust
643     /// macro_rules! f {
644     ///    macro_rules! g {
645     ///        ...
646     ///    }
647     /// }
648     /// ```
649     ///
650     /// and we have a SyntaxContext that is referring to something declared by an invocation
651     /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
652     /// invocation of f that created g1.
653     /// Returns the mark that was removed.
654     pub fn remove_mark(&mut self) -> ExpnId {
655         HygieneData::with(|data| data.remove_mark(self).0)
656     }
657
658     pub fn marks(self) -> Vec<(ExpnId, Transparency)> {
659         HygieneData::with(|data| data.marks(self))
660     }
661
662     /// Adjust this context for resolution in a scope created by the given expansion.
663     /// For example, consider the following three resolutions of `f`:
664     ///
665     /// ```rust
666     /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty.
667     /// m!(f);
668     /// macro m($f:ident) {
669     ///     mod bar {
670     ///         pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
671     ///         pub fn $f() {} // `$f`'s `SyntaxContext` is empty.
672     ///     }
673     ///     foo::f(); // `f`'s `SyntaxContext` has a single `ExpnId` from `m`
674     ///     //^ Since `mod foo` is outside this expansion, `adjust` removes the mark from `f`,
675     ///     //| and it resolves to `::foo::f`.
676     ///     bar::f(); // `f`'s `SyntaxContext` has a single `ExpnId` from `m`
677     ///     //^ Since `mod bar` not outside this expansion, `adjust` does not change `f`,
678     ///     //| and it resolves to `::bar::f`.
679     ///     bar::$f(); // `f`'s `SyntaxContext` is empty.
680     ///     //^ Since `mod bar` is not outside this expansion, `adjust` does not change `$f`,
681     ///     //| and it resolves to `::bar::$f`.
682     /// }
683     /// ```
684     /// This returns the expansion whose definition scope we use to privacy check the resolution,
685     /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
686     pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
687         HygieneData::with(|data| data.adjust(self, expn_id))
688     }
689
690     /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
691     pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
692         HygieneData::with(|data| {
693             *self = data.normalize_to_macros_2_0(*self);
694             data.adjust(self, expn_id)
695         })
696     }
697
698     /// Adjust this context for resolution in a scope created by the given expansion
699     /// via a glob import with the given `SyntaxContext`.
700     /// For example:
701     ///
702     /// ```rust
703     /// m!(f);
704     /// macro m($i:ident) {
705     ///     mod foo {
706     ///         pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
707     ///         pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
708     ///     }
709     ///     n(f);
710     ///     macro n($j:ident) {
711     ///         use foo::*;
712     ///         f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
713     ///         //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::f`.
714     ///         $i(); // `$i`'s `SyntaxContext` has a mark from `n`
715     ///         //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::$i`.
716     ///         $j(); // `$j`'s `SyntaxContext` has a mark from `m`
717     ///         //^ This cannot be glob-adjusted, so this is a resolution error.
718     ///     }
719     /// }
720     /// ```
721     /// This returns `None` if the context cannot be glob-adjusted.
722     /// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
723     pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
724         HygieneData::with(|data| {
725             let mut scope = None;
726             let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
727             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
728                 scope = Some(data.remove_mark(&mut glob_ctxt).0);
729                 if data.remove_mark(self).0 != scope.unwrap() {
730                     return None;
731                 }
732             }
733             if data.adjust(self, expn_id).is_some() {
734                 return None;
735             }
736             Some(scope)
737         })
738     }
739
740     /// Undo `glob_adjust` if possible:
741     ///
742     /// ```rust
743     /// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) {
744     ///     assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
745     /// }
746     /// ```
747     pub fn reverse_glob_adjust(
748         &mut self,
749         expn_id: ExpnId,
750         glob_span: Span,
751     ) -> Option<Option<ExpnId>> {
752         HygieneData::with(|data| {
753             if data.adjust(self, expn_id).is_some() {
754                 return None;
755             }
756
757             let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt());
758             let mut marks = Vec::new();
759             while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) {
760                 marks.push(data.remove_mark(&mut glob_ctxt));
761             }
762
763             let scope = marks.last().map(|mark| mark.0);
764             while let Some((expn_id, transparency)) = marks.pop() {
765                 *self = data.apply_mark(*self, expn_id, transparency);
766             }
767             Some(scope)
768         })
769     }
770
771     pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool {
772         HygieneData::with(|data| {
773             let mut self_normalized = data.normalize_to_macros_2_0(self);
774             data.adjust(&mut self_normalized, expn_id);
775             self_normalized == data.normalize_to_macros_2_0(other)
776         })
777     }
778
779     #[inline]
780     pub fn normalize_to_macros_2_0(self) -> SyntaxContext {
781         HygieneData::with(|data| data.normalize_to_macros_2_0(self))
782     }
783
784     #[inline]
785     pub fn normalize_to_macro_rules(self) -> SyntaxContext {
786         HygieneData::with(|data| data.normalize_to_macro_rules(self))
787     }
788
789     #[inline]
790     pub fn outer_expn(self) -> ExpnId {
791         HygieneData::with(|data| data.outer_expn(self))
792     }
793
794     /// `ctxt.outer_expn_data()` is equivalent to but faster than
795     /// `ctxt.outer_expn().expn_data()`.
796     #[inline]
797     pub fn outer_expn_data(self) -> ExpnData {
798         HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
799     }
800
801     #[inline]
802     pub fn outer_mark(self) -> (ExpnId, Transparency) {
803         HygieneData::with(|data| data.outer_mark(self))
804     }
805
806     pub fn dollar_crate_name(self) -> Symbol {
807         HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
808     }
809
810     pub fn edition(self) -> Edition {
811         HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
812     }
813 }
814
815 impl fmt::Debug for SyntaxContext {
816     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817         write!(f, "#{}", self.0)
818     }
819 }
820
821 impl Span {
822     /// Creates a fresh expansion with given properties.
823     /// Expansions are normally created by macros, but in some cases expansions are created for
824     /// other compiler-generated code to set per-span properties like allowed unstable features.
825     /// The returned span belongs to the created expansion and has the new properties,
826     /// but its location is inherited from the current span.
827     pub fn fresh_expansion(self, expn_data: ExpnData, ctx: impl HashStableContext) -> Span {
828         self.fresh_expansion_with_transparency(expn_data, Transparency::Transparent, ctx)
829     }
830
831     pub fn fresh_expansion_with_transparency(
832         self,
833         expn_data: ExpnData,
834         transparency: Transparency,
835         ctx: impl HashStableContext,
836     ) -> Span {
837         let expn_id = LocalExpnId::fresh(expn_data, ctx).to_expn_id();
838         HygieneData::with(|data| {
839             self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
840         })
841     }
842
843     /// Reuses the span but adds information like the kind of the desugaring and features that are
844     /// allowed inside this span.
845     pub fn mark_with_reason(
846         self,
847         allow_internal_unstable: Option<Lrc<[Symbol]>>,
848         reason: DesugaringKind,
849         edition: Edition,
850         ctx: impl HashStableContext,
851     ) -> Span {
852         let expn_data = ExpnData {
853             allow_internal_unstable,
854             ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None, None)
855         };
856         self.fresh_expansion(expn_data, ctx)
857     }
858 }
859
860 /// A subset of properties from both macro definition and macro call available through global data.
861 /// Avoid using this if you have access to the original definition or call structures.
862 #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
863 pub struct ExpnData {
864     // --- The part unique to each expansion.
865     /// The kind of this expansion - macro or compiler desugaring.
866     pub kind: ExpnKind,
867     /// The expansion that produced this expansion.
868     pub parent: ExpnId,
869     /// The location of the actual macro invocation or syntax sugar , e.g.
870     /// `let x = foo!();` or `if let Some(y) = x {}`
871     ///
872     /// This may recursively refer to other macro invocations, e.g., if
873     /// `foo!()` invoked `bar!()` internally, and there was an
874     /// expression inside `bar!`; the call_site of the expression in
875     /// the expansion would point to the `bar!` invocation; that
876     /// call_site span would have its own ExpnData, with the call_site
877     /// pointing to the `foo!` invocation.
878     pub call_site: Span,
879     /// Used to force two `ExpnData`s to have different `Fingerprint`s.
880     /// Due to macro expansion, it's possible to end up with two `ExpnId`s
881     /// that have identical `ExpnData`s. This violates the contract of `HashStable`
882     /// - the two `ExpnId`s are not equal, but their `Fingerprint`s are equal
883     /// (since the numerical `ExpnId` value is not considered by the `HashStable`
884     /// implementation).
885     ///
886     /// The `disambiguator` field is set by `update_disambiguator` when two distinct
887     /// `ExpnId`s would end up with the same `Fingerprint`. Since `ExpnData` includes
888     /// a `krate` field, this value only needs to be unique within a single crate.
889     disambiguator: u32,
890
891     // --- The part specific to the macro/desugaring definition.
892     // --- It may be reasonable to share this part between expansions with the same definition,
893     // --- but such sharing is known to bring some minor inconveniences without also bringing
894     // --- noticeable perf improvements (PR #62898).
895     /// The span of the macro definition (possibly dummy).
896     /// This span serves only informational purpose and is not used for resolution.
897     pub def_site: Span,
898     /// List of `#[unstable]`/feature-gated features that the macro is allowed to use
899     /// internally without forcing the whole crate to opt-in
900     /// to them.
901     pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
902     /// Whether the macro is allowed to use `unsafe` internally
903     /// even if the user crate has `#![forbid(unsafe_code)]`.
904     pub allow_internal_unsafe: bool,
905     /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
906     /// for a given macro.
907     pub local_inner_macros: bool,
908     /// Edition of the crate in which the macro is defined.
909     pub edition: Edition,
910     /// The `DefId` of the macro being invoked,
911     /// if this `ExpnData` corresponds to a macro invocation
912     pub macro_def_id: Option<DefId>,
913     /// The normal module (`mod`) in which the expanded macro was defined.
914     pub parent_module: Option<DefId>,
915 }
916
917 impl !PartialEq for ExpnData {}
918 impl !Hash for ExpnData {}
919
920 impl ExpnData {
921     pub fn new(
922         kind: ExpnKind,
923         parent: ExpnId,
924         call_site: Span,
925         def_site: Span,
926         allow_internal_unstable: Option<Lrc<[Symbol]>>,
927         allow_internal_unsafe: bool,
928         local_inner_macros: bool,
929         edition: Edition,
930         macro_def_id: Option<DefId>,
931         parent_module: Option<DefId>,
932     ) -> ExpnData {
933         ExpnData {
934             kind,
935             parent,
936             call_site,
937             def_site,
938             allow_internal_unstable,
939             allow_internal_unsafe,
940             local_inner_macros,
941             edition,
942             macro_def_id,
943             parent_module,
944             disambiguator: 0,
945         }
946     }
947
948     /// Constructs expansion data with default properties.
949     pub fn default(
950         kind: ExpnKind,
951         call_site: Span,
952         edition: Edition,
953         macro_def_id: Option<DefId>,
954         parent_module: Option<DefId>,
955     ) -> ExpnData {
956         ExpnData {
957             kind,
958             parent: ExpnId::root(),
959             call_site,
960             def_site: DUMMY_SP,
961             allow_internal_unstable: None,
962             allow_internal_unsafe: false,
963             local_inner_macros: false,
964             edition,
965             macro_def_id,
966             parent_module,
967             disambiguator: 0,
968         }
969     }
970
971     pub fn allow_unstable(
972         kind: ExpnKind,
973         call_site: Span,
974         edition: Edition,
975         allow_internal_unstable: Lrc<[Symbol]>,
976         macro_def_id: Option<DefId>,
977         parent_module: Option<DefId>,
978     ) -> ExpnData {
979         ExpnData {
980             allow_internal_unstable: Some(allow_internal_unstable),
981             ..ExpnData::default(kind, call_site, edition, macro_def_id, parent_module)
982         }
983     }
984
985     #[inline]
986     pub fn is_root(&self) -> bool {
987         matches!(self.kind, ExpnKind::Root)
988     }
989
990     #[inline]
991     fn hash_expn(&self, ctx: &mut impl HashStableContext) -> u64 {
992         let mut hasher = StableHasher::new();
993         self.hash_stable(ctx, &mut hasher);
994         hasher.finish()
995     }
996 }
997
998 /// Expansion kind.
999 #[derive(Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
1000 pub enum ExpnKind {
1001     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
1002     Root,
1003     /// Expansion produced by a macro.
1004     Macro(MacroKind, Symbol),
1005     /// Transform done by the compiler on the AST.
1006     AstPass(AstPass),
1007     /// Desugaring done by the compiler during HIR lowering.
1008     Desugaring(DesugaringKind),
1009     /// MIR inlining
1010     Inlined,
1011 }
1012
1013 impl ExpnKind {
1014     pub fn descr(&self) -> String {
1015         match *self {
1016             ExpnKind::Root => kw::PathRoot.to_string(),
1017             ExpnKind::Macro(macro_kind, name) => match macro_kind {
1018                 MacroKind::Bang => format!("{}!", name),
1019                 MacroKind::Attr => format!("#[{}]", name),
1020                 MacroKind::Derive => format!("#[derive({})]", name),
1021             },
1022             ExpnKind::AstPass(kind) => kind.descr().to_string(),
1023             ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()),
1024             ExpnKind::Inlined => "inlined source".to_string(),
1025         }
1026     }
1027 }
1028
1029 /// The kind of macro invocation or definition.
1030 #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
1031 #[derive(HashStable_Generic)]
1032 pub enum MacroKind {
1033     /// A bang macro `foo!()`.
1034     Bang,
1035     /// An attribute macro `#[foo]`.
1036     Attr,
1037     /// A derive macro `#[derive(Foo)]`
1038     Derive,
1039 }
1040
1041 impl MacroKind {
1042     pub fn descr(self) -> &'static str {
1043         match self {
1044             MacroKind::Bang => "macro",
1045             MacroKind::Attr => "attribute macro",
1046             MacroKind::Derive => "derive macro",
1047         }
1048     }
1049
1050     pub fn descr_expected(self) -> &'static str {
1051         match self {
1052             MacroKind::Attr => "attribute",
1053             _ => self.descr(),
1054         }
1055     }
1056
1057     pub fn article(self) -> &'static str {
1058         match self {
1059             MacroKind::Attr => "an",
1060             _ => "a",
1061         }
1062     }
1063 }
1064
1065 /// The kind of AST transform.
1066 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
1067 pub enum AstPass {
1068     StdImports,
1069     TestHarness,
1070     ProcMacroHarness,
1071 }
1072
1073 impl AstPass {
1074     pub fn descr(self) -> &'static str {
1075         match self {
1076             AstPass::StdImports => "standard library imports",
1077             AstPass::TestHarness => "test harness",
1078             AstPass::ProcMacroHarness => "proc macro harness",
1079         }
1080     }
1081 }
1082
1083 /// The kind of compiler desugaring.
1084 #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
1085 pub enum DesugaringKind {
1086     /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
1087     /// However, we do not want to blame `c` for unreachability but rather say that `i`
1088     /// is unreachable. This desugaring kind allows us to avoid blaming `c`.
1089     /// This also applies to `while` loops.
1090     CondTemporary,
1091     QuestionMark,
1092     TryBlock,
1093     /// Desugaring of an `impl Trait` in return type position
1094     /// to an `type Foo = impl Trait;` and replacing the
1095     /// `impl Trait` with `Foo`.
1096     OpaqueTy,
1097     Async,
1098     Await,
1099     ForLoop(ForLoopLoc),
1100     LetElse,
1101 }
1102
1103 /// A location in the desugaring of a `for` loop
1104 #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
1105 pub enum ForLoopLoc {
1106     Head,
1107     IntoIter,
1108 }
1109
1110 impl DesugaringKind {
1111     /// The description wording should combine well with "desugaring of {}".
1112     pub fn descr(self) -> &'static str {
1113         match self {
1114             DesugaringKind::CondTemporary => "`if` or `while` condition",
1115             DesugaringKind::Async => "`async` block or function",
1116             DesugaringKind::Await => "`await` expression",
1117             DesugaringKind::QuestionMark => "operator `?`",
1118             DesugaringKind::TryBlock => "`try` block",
1119             DesugaringKind::OpaqueTy => "`impl Trait`",
1120             DesugaringKind::ForLoop(_) => "`for` loop",
1121             DesugaringKind::LetElse => "`let...else`",
1122         }
1123     }
1124 }
1125
1126 #[derive(Default)]
1127 pub struct HygieneEncodeContext {
1128     /// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata.
1129     /// This is `None` after we finish encoding `SyntaxContexts`, to ensure
1130     /// that we don't accidentally try to encode any more `SyntaxContexts`
1131     serialized_ctxts: Lock<FxHashSet<SyntaxContext>>,
1132     /// The `SyntaxContexts` that we have serialized (e.g. as a result of encoding `Spans`)
1133     /// in the most recent 'round' of serializnig. Serializing `SyntaxContextData`
1134     /// may cause us to serialize more `SyntaxContext`s, so serialize in a loop
1135     /// until we reach a fixed point.
1136     latest_ctxts: Lock<FxHashSet<SyntaxContext>>,
1137
1138     serialized_expns: Lock<FxHashSet<ExpnId>>,
1139
1140     latest_expns: Lock<FxHashSet<ExpnId>>,
1141 }
1142
1143 impl HygieneEncodeContext {
1144     /// Record the fact that we need to serialize the corresponding `ExpnData`.
1145     pub fn schedule_expn_data_for_encoding(&self, expn: ExpnId) {
1146         if !self.serialized_expns.lock().contains(&expn) {
1147             self.latest_expns.lock().insert(expn);
1148         }
1149     }
1150
1151     pub fn encode<T, R>(
1152         &self,
1153         encoder: &mut T,
1154         mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
1155         mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash) -> Result<(), R>,
1156     ) -> Result<(), R> {
1157         // When we serialize a `SyntaxContextData`, we may end up serializing
1158         // a `SyntaxContext` that we haven't seen before
1159         while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() {
1160             debug!(
1161                 "encode_hygiene: Serializing a round of {:?} SyntaxContextDatas: {:?}",
1162                 self.latest_ctxts.lock().len(),
1163                 self.latest_ctxts
1164             );
1165
1166             // Consume the current round of SyntaxContexts.
1167             // Drop the lock() temporary early
1168             let latest_ctxts = { std::mem::take(&mut *self.latest_ctxts.lock()) };
1169
1170             // It's fine to iterate over a HashMap, because the serialization
1171             // of the table that we insert data into doesn't depend on insertion
1172             // order
1173             for_all_ctxts_in(latest_ctxts.into_iter(), |index, ctxt, data| {
1174                 if self.serialized_ctxts.lock().insert(ctxt) {
1175                     encode_ctxt(encoder, index, data)?;
1176                 }
1177                 Ok(())
1178             })?;
1179
1180             let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
1181
1182             for_all_expns_in(latest_expns.into_iter(), |expn, data, hash| {
1183                 if self.serialized_expns.lock().insert(expn) {
1184                     encode_expn(encoder, expn, data, hash)?;
1185                 }
1186                 Ok(())
1187             })?;
1188         }
1189         debug!("encode_hygiene: Done serializing SyntaxContextData");
1190         Ok(())
1191     }
1192 }
1193
1194 #[derive(Default)]
1195 /// Additional information used to assist in decoding hygiene data
1196 pub struct HygieneDecodeContext {
1197     // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current
1198     // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
1199     // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
1200     // so that multiple occurrences of the same serialized id are decoded to the same
1201     // `SyntaxContext`
1202     remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
1203 }
1204
1205 /// Register an expansion which has been decoded from the on-disk-cache for the local crate.
1206 pub fn register_local_expn_id(data: ExpnData, hash: ExpnHash) -> ExpnId {
1207     HygieneData::with(|hygiene_data| {
1208         let expn_id = hygiene_data.local_expn_data.next_index();
1209         hygiene_data.local_expn_data.push(Some(data));
1210         let _eid = hygiene_data.local_expn_hashes.push(hash);
1211         debug_assert_eq!(expn_id, _eid);
1212
1213         let expn_id = expn_id.to_expn_id();
1214
1215         let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
1216         debug_assert!(_old_id.is_none());
1217         expn_id
1218     })
1219 }
1220
1221 /// Register an expansion which has been decoded from the metadata of a foreign crate.
1222 pub fn register_expn_id(
1223     krate: CrateNum,
1224     local_id: ExpnIndex,
1225     data: ExpnData,
1226     hash: ExpnHash,
1227 ) -> ExpnId {
1228     let expn_id = ExpnId { krate, local_id };
1229     HygieneData::with(|hygiene_data| {
1230         let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
1231         debug_assert!(_old_data.is_none());
1232         let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash);
1233         debug_assert!(_old_hash.is_none());
1234         let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
1235         debug_assert!(_old_id.is_none());
1236     });
1237     expn_id
1238 }
1239
1240 /// Decode an expansion from the metadata of a foreign crate.
1241 pub fn decode_expn_id(
1242     krate: CrateNum,
1243     index: u32,
1244     decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash),
1245 ) -> ExpnId {
1246     if index == 0 {
1247         debug!("decode_expn_id: deserialized root");
1248         return ExpnId::root();
1249     }
1250
1251     let index = ExpnIndex::from_u32(index);
1252
1253     // This function is used to decode metadata, so it cannot decode information about LOCAL_CRATE.
1254     debug_assert_ne!(krate, LOCAL_CRATE);
1255     let expn_id = ExpnId { krate, local_id: index };
1256
1257     // Fast path if the expansion has already been decoded.
1258     if HygieneData::with(|hygiene_data| hygiene_data.foreign_expn_data.contains_key(&expn_id)) {
1259         return expn_id;
1260     }
1261
1262     // Don't decode the data inside `HygieneData::with`, since we need to recursively decode
1263     // other ExpnIds
1264     let (expn_data, hash) = decode_data(expn_id);
1265
1266     register_expn_id(krate, index, expn_data, hash)
1267 }
1268
1269 // Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
1270 // to track which `SyntaxContext`s we have already decoded.
1271 // The provided closure will be invoked to deserialize a `SyntaxContextData`
1272 // if we haven't already seen the id of the `SyntaxContext` we are deserializing.
1273 pub fn decode_syntax_context<
1274     D: Decoder,
1275     F: FnOnce(&mut D, u32) -> Result<SyntaxContextData, D::Error>,
1276 >(
1277     d: &mut D,
1278     context: &HygieneDecodeContext,
1279     decode_data: F,
1280 ) -> Result<SyntaxContext, D::Error> {
1281     let raw_id: u32 = Decodable::decode(d)?;
1282     if raw_id == 0 {
1283         debug!("decode_syntax_context: deserialized root");
1284         // The root is special
1285         return Ok(SyntaxContext::root());
1286     }
1287
1288     let outer_ctxts = &context.remapped_ctxts;
1289
1290     // Ensure that the lock() temporary is dropped early
1291     {
1292         if let Some(ctxt) = outer_ctxts.lock().get(raw_id as usize).copied().flatten() {
1293             return Ok(ctxt);
1294         }
1295     }
1296
1297     // Allocate and store SyntaxContext id *before* calling the decoder function,
1298     // as the SyntaxContextData may reference itself.
1299     let new_ctxt = HygieneData::with(|hygiene_data| {
1300         let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
1301         // Push a dummy SyntaxContextData to ensure that nobody else can get the
1302         // same ID as us. This will be overwritten after call `decode_Data`
1303         hygiene_data.syntax_context_data.push(SyntaxContextData {
1304             outer_expn: ExpnId::root(),
1305             outer_transparency: Transparency::Transparent,
1306             parent: SyntaxContext::root(),
1307             opaque: SyntaxContext::root(),
1308             opaque_and_semitransparent: SyntaxContext::root(),
1309             dollar_crate_name: kw::Empty,
1310         });
1311         let mut ctxts = outer_ctxts.lock();
1312         let new_len = raw_id as usize + 1;
1313         if ctxts.len() < new_len {
1314             ctxts.resize(new_len, None);
1315         }
1316         ctxts[raw_id as usize] = Some(new_ctxt);
1317         drop(ctxts);
1318         new_ctxt
1319     });
1320
1321     // Don't try to decode data while holding the lock, since we need to
1322     // be able to recursively decode a SyntaxContext
1323     let mut ctxt_data = decode_data(d, raw_id)?;
1324     // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`
1325     // We don't care what the encoding crate set this to - we want to resolve it
1326     // from the perspective of the current compilation session
1327     ctxt_data.dollar_crate_name = kw::DollarCrate;
1328
1329     // Overwrite the dummy data with our decoded SyntaxContextData
1330     HygieneData::with(|hygiene_data| {
1331         let dummy = std::mem::replace(
1332             &mut hygiene_data.syntax_context_data[new_ctxt.as_u32() as usize],
1333             ctxt_data,
1334         );
1335         // Make sure nothing weird happening while `decode_data` was running
1336         assert_eq!(dummy.dollar_crate_name, kw::Empty);
1337     });
1338
1339     Ok(new_ctxt)
1340 }
1341
1342 fn for_all_ctxts_in<E, F: FnMut(u32, SyntaxContext, &SyntaxContextData) -> Result<(), E>>(
1343     ctxts: impl Iterator<Item = SyntaxContext>,
1344     mut f: F,
1345 ) -> Result<(), E> {
1346     let all_data: Vec<_> = HygieneData::with(|data| {
1347         ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
1348     });
1349     for (ctxt, data) in all_data.into_iter() {
1350         f(ctxt.0, ctxt, &data)?;
1351     }
1352     Ok(())
1353 }
1354
1355 fn for_all_expns_in<E>(
1356     expns: impl Iterator<Item = ExpnId>,
1357     mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
1358 ) -> Result<(), E> {
1359     let all_data: Vec<_> = HygieneData::with(|data| {
1360         expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
1361     });
1362     for (expn, data, hash) in all_data.into_iter() {
1363         f(expn, &data, hash)?;
1364     }
1365     Ok(())
1366 }
1367
1368 impl<E: Encoder> Encodable<E> for LocalExpnId {
1369     fn encode(&self, e: &mut E) -> Result<(), E::Error> {
1370         self.to_expn_id().encode(e)
1371     }
1372 }
1373
1374 impl<E: Encoder> Encodable<E> for ExpnId {
1375     default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
1376         panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
1377     }
1378 }
1379
1380 impl<D: Decoder> Decodable<D> for LocalExpnId {
1381     fn decode(d: &mut D) -> Result<Self, D::Error> {
1382         ExpnId::decode(d).map(ExpnId::expect_local)
1383     }
1384 }
1385
1386 impl<D: Decoder> Decodable<D> for ExpnId {
1387     default fn decode(_: &mut D) -> Result<Self, D::Error> {
1388         panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
1389     }
1390 }
1391
1392 pub fn raw_encode_syntax_context<E: Encoder>(
1393     ctxt: SyntaxContext,
1394     context: &HygieneEncodeContext,
1395     e: &mut E,
1396 ) -> Result<(), E::Error> {
1397     if !context.serialized_ctxts.lock().contains(&ctxt) {
1398         context.latest_ctxts.lock().insert(ctxt);
1399     }
1400     ctxt.0.encode(e)
1401 }
1402
1403 impl<E: Encoder> Encodable<E> for SyntaxContext {
1404     default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
1405         panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
1406     }
1407 }
1408
1409 impl<D: Decoder> Decodable<D> for SyntaxContext {
1410     default fn decode(_: &mut D) -> Result<Self, D::Error> {
1411         panic!("cannot decode `SyntaxContext` with `{}`", std::any::type_name::<D>());
1412     }
1413 }
1414
1415 /// Updates the `disambiguator` field of the corresponding `ExpnData`
1416 /// such that the `Fingerprint` of the `ExpnData` does not collide with
1417 /// any other `ExpnIds`.
1418 ///
1419 /// This method is called only when an `ExpnData` is first associated
1420 /// with an `ExpnId` (when the `ExpnId` is initially constructed, or via
1421 /// `set_expn_data`). It is *not* called for foreign `ExpnId`s deserialized
1422 /// from another crate's metadata - since `ExpnHash` includes the stable crate id,
1423 /// collisions are only possible between `ExpnId`s within the same crate.
1424 fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash {
1425     // This disambiguator should not have been set yet.
1426     assert_eq!(
1427         expn_data.disambiguator, 0,
1428         "Already set disambiguator for ExpnData: {:?}",
1429         expn_data
1430     );
1431     let mut expn_hash = expn_data.hash_expn(&mut ctx);
1432
1433     let disambiguator = HygieneData::with(|data| {
1434         // If this is the first ExpnData with a given hash, then keep our
1435         // disambiguator at 0 (the default u32 value)
1436         let disambig = data.expn_data_disambiguators.entry(expn_hash).or_default();
1437         let disambiguator = *disambig;
1438         *disambig += 1;
1439         disambiguator
1440     });
1441
1442     if disambiguator != 0 {
1443         debug!("Set disambiguator for expn_data={:?} expn_hash={:?}", expn_data, expn_hash);
1444
1445         expn_data.disambiguator = disambiguator;
1446         expn_hash = expn_data.hash_expn(&mut ctx);
1447
1448         // Verify that the new disambiguator makes the hash unique
1449         #[cfg(debug_assertions)]
1450         HygieneData::with(|data| {
1451             assert_eq!(
1452                 data.expn_data_disambiguators.get(&expn_hash),
1453                 None,
1454                 "Hash collision after disambiguator update!",
1455             );
1456         });
1457     }
1458
1459     ExpnHash::new(ctx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), expn_hash)
1460 }
1461
1462 impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
1463     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
1464         const TAG_EXPANSION: u8 = 0;
1465         const TAG_NO_EXPANSION: u8 = 1;
1466
1467         if *self == SyntaxContext::root() {
1468             TAG_NO_EXPANSION.hash_stable(ctx, hasher);
1469         } else {
1470             TAG_EXPANSION.hash_stable(ctx, hasher);
1471             let (expn_id, transparency) = self.outer_mark();
1472             expn_id.hash_stable(ctx, hasher);
1473             transparency.hash_stable(ctx, hasher);
1474         }
1475     }
1476 }
1477
1478 impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
1479     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
1480         let hash = if *self == ExpnId::root() {
1481             // Avoid fetching TLS storage for a trivial often-used value.
1482             Fingerprint::ZERO
1483         } else {
1484             self.expn_hash().0
1485         };
1486
1487         hash.hash_stable(ctx, hasher);
1488     }
1489 }