Skip to content

Commit 244e060

Browse files
committed
Auto merge of #155337 - aerooneqq:delayed-lowering-in-sandbox, r=<try>
Execute delayed lowering in a sandbox
2 parents e8e4541 + a36a0dc commit 244e060

52 files changed

Lines changed: 3574 additions & 84 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_data_structures/src/sharded.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,16 @@ impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
199199
}
200200
}
201201
}
202+
203+
#[inline]
204+
pub fn remove(&self, key: &K) {
205+
let hash = make_hash(key);
206+
let mut shard = self.lock_shard_by_hash(hash);
207+
208+
if let Entry::Occupied(e) = table_entry(&mut shard, hash, key) {
209+
e.remove();
210+
}
211+
}
202212
}
203213

204214
impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {

compiler/rustc_data_structures/src/vec_cache.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,24 @@ impl SlotIndex {
206206

207207
index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release);
208208
}
209+
210+
#[inline]
211+
unsafe fn remove<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) {
212+
let bucket = &buckets[self.bucket_idx];
213+
let ptr = self.bucket_ptr(bucket);
214+
215+
debug_assert!(self.index_in_bucket < self.bucket_idx.capacity());
216+
217+
// SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
218+
// must be inbounds.
219+
let slot = unsafe { ptr.add(self.index_in_bucket) };
220+
221+
// SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for
222+
// AtomicU32 access.
223+
let index_and_lock = unsafe { &(*slot).index_and_lock };
224+
225+
index_and_lock.store(0, Ordering::Release);
226+
}
209227
}
210228

211229
/// In-memory cache for queries whose keys are densely-numbered IDs
@@ -339,6 +357,39 @@ where
339357
pub fn len(&self) -> usize {
340358
self.len.load(Ordering::Acquire)
341359
}
360+
361+
pub fn remove(&self, key: &K) {
362+
let key = u32::try_from(key.index()).unwrap();
363+
let slot_idx = SlotIndex::from_index(key);
364+
365+
unsafe { slot_idx.remove(&self.buckets) };
366+
}
367+
368+
pub fn invalidate(&self, selector: impl Fn(K) -> bool) {
369+
let mut to_remove = vec![];
370+
let mut remaining = vec![];
371+
372+
self.for_each(&mut |key, _, _| {
373+
if selector(*key) {
374+
to_remove.push(*key);
375+
} else {
376+
remaining.push(*key);
377+
}
378+
});
379+
380+
for key in to_remove {
381+
self.remove(&key);
382+
}
383+
384+
for (index, key) in remaining.iter().enumerate() {
385+
let slot = SlotIndex::from_index(u32::try_from(index).unwrap());
386+
let key = u32::try_from(key.index()).unwrap();
387+
388+
unsafe { slot.put_unique(&self.present, (), key) };
389+
}
390+
391+
self.len.store(remaining.len(), Ordering::Release);
392+
}
342393
}
343394

344395
/// Index into an array of buckets.

compiler/rustc_hir/src/definitions.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use std::fmt::{self, Write};
88
use std::hash::Hash;
99

10+
use rustc_data_structures::indexmap::IndexSet;
1011
use rustc_data_structures::stable_hasher::StableHasher;
1112
use rustc_data_structures::unord::UnordMap;
1213
use rustc_hashes::Hash64;
@@ -30,6 +31,7 @@ pub struct DefPathTable {
3031
// We do only store the local hash, as all the definitions are from the current crate.
3132
def_path_hashes: IndexVec<DefIndex, Hash64>,
3233
def_path_hash_to_index: DefPathHashMap,
34+
allow_overwrite: IndexSet<DefIndex>,
3335
}
3436

3537
impl DefPathTable {
@@ -39,38 +41,45 @@ impl DefPathTable {
3941
index_to_key: Default::default(),
4042
def_path_hashes: Default::default(),
4143
def_path_hash_to_index: Default::default(),
44+
allow_overwrite: Default::default(),
4245
}
4346
}
4447

45-
fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
48+
fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash, in_sandbox: bool) -> DefIndex {
4649
// Assert that all DefPathHashes correctly contain the local crate's StableCrateId.
4750
debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
4851
let local_hash = def_path_hash.local_hash();
49-
50-
let index = self.index_to_key.push(key);
51-
debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
52-
53-
self.def_path_hashes.push(local_hash);
54-
debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
52+
let index = self.index_to_key.next_index();
5553

5654
// Check for hash collisions of DefPathHashes. These should be
5755
// exceedingly rare.
5856
if let Some(existing) = self.def_path_hash_to_index.insert(&local_hash, &index) {
59-
let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
60-
let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
61-
62-
// Continuing with colliding DefPathHashes can lead to correctness
63-
// issues. We must abort compilation.
64-
//
65-
// The likelihood of such a collision is very small, so actually
66-
// running into one could be indicative of a poor hash function
67-
// being used.
68-
//
69-
// See the documentation for DefPathHash for more information.
70-
panic!(
71-
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
57+
if !in_sandbox && self.allow_overwrite.swap_remove(&existing) {
58+
self.def_path_hash_to_index.insert(&local_hash, &existing);
59+
return existing;
60+
} else {
61+
let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
62+
let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
63+
64+
// Continuing with colliding DefPathHashes can lead to correctness
65+
// issues. We must abort compilation.
66+
//
67+
// The likelihood of such a collision is very small, so actually
68+
// running into one could be indicative of a poor hash function
69+
// being used.
70+
//
71+
// See the documentation for DefPathHash for more information.
72+
panic!(
73+
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
7274
Compilation cannot continue."
73-
);
75+
);
76+
}
77+
} else {
78+
self.index_to_key.push(key);
79+
debug!("DefPathTable::insert() - {key:?} <-> {index:?}");
80+
81+
self.def_path_hashes.push(local_hash);
82+
debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
7483
}
7584

7685
index
@@ -374,7 +383,7 @@ impl Definitions {
374383

375384
// Create the root definition.
376385
let mut table = DefPathTable::new(stable_crate_id);
377-
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
386+
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash, false) };
378387
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
379388

380389
Definitions { table }
@@ -390,6 +399,7 @@ impl Definitions {
390399
parent: LocalDefId,
391400
data: DefPathData,
392401
disambiguator: &mut DisambiguatorState,
402+
in_sandbox: bool,
393403
) -> LocalDefId {
394404
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
395405
// reference to `Definitions` and we're already holding a mutable reference.
@@ -418,8 +428,14 @@ impl Definitions {
418428

419429
debug!("create_def: after disambiguation, key = {:?}", key);
420430

431+
let local_def_index = self.table.allocate(key, def_path_hash, in_sandbox);
432+
433+
if in_sandbox {
434+
assert_eq!(self.table.allow_overwrite.insert(local_def_index), true);
435+
}
436+
421437
// Create the definition.
422-
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
438+
LocalDefId { local_def_index }
423439
}
424440

425441
#[inline(always)]

compiler/rustc_hir/src/intravisit.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ pub trait Visitor<'v>: Sized {
226226
/// or `ControlFlow<T>`.
227227
type Result: VisitorResult = ();
228228

229+
#[inline]
230+
fn visit_if_delayed(&self, _: LocalDefId) -> bool {
231+
true
232+
}
233+
229234
/// If `type NestedFilter` is set to visit nested items, this method
230235
/// must also be overridden to provide a map to retrieve nested items.
231236
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
@@ -244,18 +249,23 @@ pub trait Visitor<'v>: Sized {
244249
/// this method is if you want a nested pattern but cannot supply a
245250
/// `TyCtxt`; see `maybe_tcx` for advice.
246251
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
247-
if Self::NestedFilter::INTER {
252+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
248253
let item = self.maybe_tcx().hir_item(id);
249254
try_visit!(self.visit_item(item));
250255
}
251256
Self::Result::output()
252257
}
253258

259+
// Now delayed owners are only delegations, which are either item, trait item or impl item.
260+
fn should_visit_maybe_delayed_inter(&mut self, id: LocalDefId) -> bool {
261+
Self::NestedFilter::INTER && self.visit_if_delayed(id)
262+
}
263+
254264
/// Like `visit_nested_item()`, but for trait items. See
255265
/// `visit_nested_item()` for advice on when to override this
256266
/// method.
257267
fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
258-
if Self::NestedFilter::INTER {
268+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
259269
let item = self.maybe_tcx().hir_trait_item(id);
260270
try_visit!(self.visit_trait_item(item));
261271
}
@@ -266,7 +276,7 @@ pub trait Visitor<'v>: Sized {
266276
/// `visit_nested_item()` for advice on when to override this
267277
/// method.
268278
fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
269-
if Self::NestedFilter::INTER {
279+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
270280
let item = self.maybe_tcx().hir_impl_item(id);
271281
try_visit!(self.visit_impl_item(item));
272282
}

compiler/rustc_macros/src/query.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct QueryModifiers {
138138
// tidy-alphabetical-start
139139
arena_cache: Option<Ident>,
140140
cache_on_disk: Option<Ident>,
141+
callfront: Option<Ident>,
141142
depth_limit: Option<Ident>,
142143
desc: Desc,
143144
eval_always: Option<Ident>,
@@ -153,6 +154,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
153154
// tidy-alphabetical-start
154155
let mut arena_cache = None;
155156
let mut cache_on_disk = None;
157+
let mut callfront = None;
156158
let mut depth_limit = None;
157159
let mut desc = None;
158160
let mut eval_always = None;
@@ -179,6 +181,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
179181
try_insert!(arena_cache = modifier);
180182
} else if modifier == "cache_on_disk" {
181183
try_insert!(cache_on_disk = modifier);
184+
} else if modifier == "callfront" {
185+
try_insert!(callfront = modifier);
182186
} else if modifier == "depth_limit" {
183187
try_insert!(depth_limit = modifier);
184188
} else if modifier == "desc" {
@@ -211,6 +215,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
211215
// tidy-alphabetical-start
212216
arena_cache,
213217
cache_on_disk,
218+
callfront,
214219
depth_limit,
215220
desc,
216221
eval_always,
@@ -247,6 +252,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
247252
// tidy-alphabetical-start
248253
arena_cache,
249254
cache_on_disk,
255+
callfront,
250256
depth_limit,
251257
desc,
252258
eval_always,
@@ -261,6 +267,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
261267
// tidy-alphabetical-start
262268
let arena_cache = arena_cache.is_some();
263269
let cache_on_disk = cache_on_disk.is_some();
270+
let callfront = callfront.is_some();
264271
let depth_limit = depth_limit.is_some();
265272
let desc = {
266273
// Put a description closure in the `desc` modifier.
@@ -284,7 +291,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
284291
// tidy-alphabetical-end
285292

286293
// Giving an input span to the modifier names in the modifier list seems
287-
// to give slightly more helpful errors when one of the callback macros
294+
// to give slightly more helpful errors when one of the callfront macros
288295
// fails to parse the modifier list.
289296
let query_name_span = query.name.span();
290297
quote_spanned! {
@@ -293,6 +300,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
293300
// tidy-alphabetical-start
294301
arena_cache: #arena_cache,
295302
cache_on_disk: #cache_on_disk,
303+
callfront: #callfront,
296304
depth_limit: #depth_limit,
297305
desc: #desc,
298306
eval_always: #eval_always,

0 commit comments

Comments
 (0)