Skip to content

Commit c623c58

Browse files
committed
Auto merge of #155337 - aerooneqq:delayed-lowering-in-sandbox, r=<try>
Execute delayed lowering in a sandbox
2 parents 53509ca + b6ed349 commit c623c58

52 files changed

Lines changed: 3545 additions & 90 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
@@ -207,6 +207,16 @@ impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
207207
}
208208
}
209209
}
210+
211+
#[inline]
212+
pub fn remove(&self, key: &K) {
213+
let hash = make_hash(key);
214+
let mut shard = self.lock_shard_by_hash(hash);
215+
216+
if let Entry::Occupied(e) = table_entry(&mut shard, hash, key) {
217+
e.remove();
218+
}
219+
}
210220
}
211221

212222
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: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::fmt::{self, Write};
88
use std::hash::Hash;
99

1010
use rustc_data_structures::fx::FxHashMap;
11+
use rustc_data_structures::indexmap::IndexSet;
1112
use rustc_data_structures::stable_hash::StableHasher;
1213
use rustc_hashes::Hash64;
1314
use rustc_index::IndexVec;
@@ -52,6 +53,7 @@ pub struct Definitions {
5253
// We do only store the local hash, as all the definitions are from the current crate.
5354
def_path_hashes: IndexVec<LocalDefId, Hash64>,
5455
def_path_hash_to_index: DefPathHashMap,
56+
allow_overwrite: IndexSet<LocalDefId>,
5557
}
5658

5759
/// A unique identifier that we can use to lookup a definition
@@ -298,46 +300,60 @@ impl Definitions {
298300
def_path_hashes: Default::default(),
299301
def_id_to_key: Default::default(),
300302
def_path_hash_to_index: Default::default(),
303+
allow_overwrite: Default::default(),
301304
};
302305

303306
// Create the root definition.
304-
let root = defs.allocate(key, def_path_hash);
307+
let root = defs.allocate(key, def_path_hash, false);
305308
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
306309

307310
defs
308311
}
309312

310-
fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> LocalDefId {
313+
fn allocate(
314+
&mut self,
315+
key: DefKey,
316+
def_path_hash: DefPathHash,
317+
in_sandbox: bool,
318+
) -> LocalDefId {
311319
// Assert that all DefPathHashes correctly contain the local crate's StableCrateId.
312320
debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id());
313321
let local_hash = def_path_hash.local_hash();
314-
315-
let def_id = self.def_id_to_key.push(key);
316-
debug!("def_id_to_key.push() - {key:?} <-> {:?}", def_id.local_def_index);
317-
318-
self.def_path_hashes.push(local_hash);
319-
debug_assert!(self.def_path_hashes.len() == self.def_id_to_key.len());
322+
let def_id = self.def_id_to_key.next_index();
320323

321324
// Check for hash collisions of DefPathHashes. These should be
322325
// exceedingly rare.
323326
if let Some(existing) =
324327
self.def_path_hash_to_index.insert(&local_hash, &def_id.local_def_index)
325328
{
326-
let def_path1 = self.def_path(LocalDefId { local_def_index: existing });
327-
let def_path2 = self.def_path(def_id);
328-
329-
// Continuing with colliding DefPathHashes can lead to correctness
330-
// issues. We must abort compilation.
331-
//
332-
// The likelihood of such a collision is very small, so actually
333-
// running into one could be indicative of a poor hash function
334-
// being used.
335-
//
336-
// See the documentation for DefPathHash for more information.
337-
panic!(
338-
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
329+
let existing = LocalDefId { local_def_index: existing };
330+
331+
if !in_sandbox && self.allow_overwrite.swap_remove(&existing) {
332+
self.def_path_hash_to_index.insert(&local_hash, &existing.local_def_index);
333+
return existing;
334+
} else {
335+
let def_path1 = self.def_path(existing);
336+
let def_path2 = self.def_path(def_id);
337+
338+
// Continuing with colliding DefPathHashes can lead to correctness
339+
// issues. We must abort compilation.
340+
//
341+
// The likelihood of such a collision is very small, so actually
342+
// running into one could be indicative of a poor hash function
343+
// being used.
344+
//
345+
// See the documentation for DefPathHash for more information.
346+
panic!(
347+
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
339348
Compilation cannot continue."
340-
);
349+
);
350+
}
351+
} else {
352+
self.def_id_to_key.push(key);
353+
debug!("def_id_to_key.push() - {key:?} <-> {:?}", def_id.local_def_index);
354+
355+
self.def_path_hashes.push(local_hash);
356+
debug_assert!(self.def_path_hashes.len() == self.def_id_to_key.len());
341357
}
342358

343359
def_id
@@ -361,6 +377,7 @@ impl Definitions {
361377
parent: LocalDefId,
362378
data: DefPathData,
363379
disambiguator: &mut PerParentDisambiguatorState,
380+
in_sandbox: bool,
364381
) -> LocalDefId {
365382
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
366383
// reference to `Definitions` and we're already holding a mutable reference.
@@ -396,8 +413,12 @@ impl Definitions {
396413

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

399-
// Create the definition.
400-
self.allocate(key, def_path_hash)
416+
let def_id = self.allocate(key, def_path_hash, in_sandbox);
417+
if in_sandbox {
418+
assert_eq!(self.allow_overwrite.insert(def_id), true);
419+
}
420+
421+
def_id
401422
}
402423

403424
#[inline(always)]

compiler/rustc_hir/src/intravisit.rs

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

224+
#[inline]
225+
fn visit_if_delayed(&self, _: LocalDefId) -> bool {
226+
true
227+
}
228+
224229
/// If `type NestedFilter` is set to visit nested items, this method
225230
/// must also be overridden to provide a map to retrieve nested items.
226231
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
@@ -239,18 +244,23 @@ pub trait Visitor<'v>: Sized {
239244
/// this method is if you want a nested pattern but cannot supply a
240245
/// `TyCtxt`; see `maybe_tcx` for advice.
241246
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
242-
if Self::NestedFilter::INTER {
247+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
243248
let item = self.maybe_tcx().hir_item(id);
244249
try_visit!(self.visit_item(item));
245250
}
246251
Self::Result::output()
247252
}
248253

254+
// Now delayed owners are only delegations, which are either item, trait item or impl item.
255+
fn should_visit_maybe_delayed_inter(&mut self, id: LocalDefId) -> bool {
256+
Self::NestedFilter::INTER && self.visit_if_delayed(id)
257+
}
258+
249259
/// Like `visit_nested_item()`, but for trait items. See
250260
/// `visit_nested_item()` for advice on when to override this
251261
/// method.
252262
fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
253-
if Self::NestedFilter::INTER {
263+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
254264
let item = self.maybe_tcx().hir_trait_item(id);
255265
try_visit!(self.visit_trait_item(item));
256266
}
@@ -261,7 +271,7 @@ pub trait Visitor<'v>: Sized {
261271
/// `visit_nested_item()` for advice on when to override this
262272
/// method.
263273
fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
264-
if Self::NestedFilter::INTER {
274+
if self.should_visit_maybe_delayed_inter(id.owner_id.def_id) {
265275
let item = self.maybe_tcx().hir_impl_item(id);
266276
try_visit!(self.visit_impl_item(item));
267277
}

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)