Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6e1effe

Browse files
hygiene: Ensure uniqueness of SyntaxContextDatas
1 parent 360a87d commit 6e1effe

File tree

1 file changed

+34
-26
lines changed

1 file changed

+34
-26
lines changed

‎compiler/rustc_span/src/hygiene.rs‎

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ impl SyntaxContextData {
9393
fn is_decode_placeholder(&self) -> bool {
9494
self.dollar_crate_name == kw::Empty
9595
}
96+
97+
fn key(&self) -> SyntaxContextKey {
98+
(self.parent, self.outer_expn, self.outer_transparency)
99+
}
96100
}
97101

98102
rustc_index::newtype_index! {
@@ -395,7 +399,7 @@ impl HygieneData {
395399
expn_hash_to_expn_id: iter::once((ExpnHash(Fingerprint::ZERO), ExpnId::root()))
396400
.collect(),
397401
syntax_context_data: vec![root_ctxt_data],
398-
syntax_context_map: FxHashMap::default(),
402+
syntax_context_map: iter::once((root_ctxt_data.key(),SyntaxContext(0))).collect(),
399403
expn_data_disambiguators: UnhashMap::default(),
400404
}
401405
}
@@ -1454,34 +1458,38 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
14541458
// Don't try to decode data while holding the lock, since we need to
14551459
// be able to recursively decode a SyntaxContext
14561460
let ctxt_data = decode_data(d, raw_id);
1461+
let ctxt_key = ctxt_data.key();
14571462

14581463
let ctxt = HygieneData::with(|hygiene_data| {
1459-
let old = if let Some(old) = hygiene_data.syntax_context_data.get(raw_id as usize)
1460-
&& old.outer_expn == ctxt_data.outer_expn
1461-
&& old.outer_transparency == ctxt_data.outer_transparency
1462-
&& old.parent == ctxt_data.parent
1463-
{
1464-
Some(old.clone())
1465-
} else {
1466-
None
1467-
};
1468-
// Overwrite its placeholder data with our decoded data.
1469-
let ctxt_data_ref = &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize];
1470-
let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data);
1471-
// Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1472-
// We don't care what the encoding crate set this to - we want to resolve it
1473-
// from the perspective of the current compilation session
1474-
ctxt_data_ref.dollar_crate_name = kw::DollarCrate;
1475-
if let Some(old) = old {
1476-
*ctxt_data_ref = old;
1477-
}
1478-
// Make sure nothing weird happened while `decode_data` was running.
1479-
if !prev_ctxt_data.is_decode_placeholder() {
1480-
// Another thread may have already inserted the decoded data,
1481-
// but the decoded data should match.
1482-
assert_eq!(prev_ctxt_data, *ctxt_data_ref);
1464+
match hygiene_data.syntax_context_map.get(&ctxt_key) {
1465+
// Ensure that syntax contexts are unique.
1466+
// If syntax contexts with the given key already exists, reuse it instead of
1467+
// using `pending_ctxt`.
1468+
// `pending_ctxt` will leave an unused hole in the vector of syntax contexts.
1469+
// Hopefully its value isn't stored anywhere during decoding and its dummy data
1470+
// is never accessed later. The `is_decode_placeholder` asserts on all
1471+
// accesses to syntax context data attempt to ensure it.
1472+
Some(&ctxt) => ctxt,
1473+
// This is a completely new context.
1474+
// Overwrite its placeholder data with our decoded data.
1475+
None => {
1476+
let ctxt_data_ref =
1477+
&mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize];
1478+
let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data);
1479+
// Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`.
1480+
// We don't care what the encoding crate set this to - we want to resolve it
1481+
// from the perspective of the current compilation session.
1482+
ctxt_data_ref.dollar_crate_name = kw::DollarCrate;
1483+
// Make sure nothing weird happened while `decode_data` was running.
1484+
if !prev_ctxt_data.is_decode_placeholder() {
1485+
// Another thread may have already inserted the decoded data,
1486+
// but the decoded data should match.
1487+
assert_eq!(prev_ctxt_data, *ctxt_data_ref);
1488+
}
1489+
hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt);
1490+
pending_ctxt
1491+
}
14831492
}
1484-
pending_ctxt
14851493
});
14861494

14871495
// Mark the context as completed

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /