Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_data_structures/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub use self::mode::{
FromDyn, check_dyn_thread_safe, is_dyn_thread_safe, set_dyn_thread_safe_mode,
};
pub use self::parallel::{
broadcast, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn,
broadcast, par_filter_map, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn,
try_par_for_each_in,
};
pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
Expand Down Expand Up @@ -189,6 +189,7 @@ impl<T> RwLock<T> {
}

#[inline(always)]
#[track_caller]
pub fn read(&self) -> ReadGuard<'_, T> {
if ERROR_CHECKING {
self.0.try_read().expect("lock was already held")
Expand All @@ -203,6 +204,7 @@ impl<T> RwLock<T> {
}

#[inline(always)]
#[track_caller]

@petrochenkov petrochenkov Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These track callers can cause unintended regressions in other places in the compiler, it's better to benchmark this change separately.

View changes since the review

pub fn write(&self) -> WriteGuard<'_, T> {
if ERROR_CHECKING {
self.0.try_write().expect("lock was already held")
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_data_structures/src/sync/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,33 @@ pub fn par_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterato
})
}

pub fn par_filter_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterator<R>>(

@LorrensP-2158466 LorrensP-2158466 Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost a mirror of filter_map just with flatten for the nested Option.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the Nones in the map to avoid introducing this?
write_import_resolutions (or whatever place consumes the resulting table) can then skip them.

@petrochenkov petrochenkov Jul 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But ideally we'd do everything in place with par_slice, of course.

t: T,
map: impl Fn(I) -> Option<R> + DynSync + DynSend,
) -> C {
parallel_guard(|guard| {
if let Some(proof) = mode::check_dyn_thread_safe() {
let map = proof.derive(map);

let mut items: Vec<(Option<I>, Option<Option<R>>)> =
t.into_iter().map(|i| (Some(i), None)).collect();

par_slice(
&mut items,
guard,
|i| {
i.1 = Some(map(i.0.take().unwrap()));
},
proof,
);

items.into_iter().filter_map(|(_, r)| r.flatten()).collect()
} else {
t.into_iter().filter_map(|i| guard.run(|| map(i)).flatten()).collect()
}
})
}

pub fn broadcast<R: DynSend>(op: impl Fn(usize) -> R + DynSync) -> Vec<R> {
if let Some(proof) = mode::check_dyn_thread_safe() {
let op = proof.derive(op);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,8 @@ fn resolver_for_lowering_raw<'tcx>(
&'tcx Steal<ast::Crate>,
&'tcx ty::ResolverGlobalCtxt,
) {
let arenas = Resolver::arenas();
let arenas = Resolver::new_arenas();
let extern_arenas = Resolver::new_arenas();

@petrochenkov petrochenkov Jul 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected having new locked fields inside the existing ResolverArenas, because we don't need to lock the whole ResolverArenas to do something with one field.
But perhaps this is indeed more convenient for a start.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this was just to make it work.

let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
let mut resolver = Resolver::new(
Expand All @@ -800,6 +801,7 @@ fn resolver_for_lowering_raw<'tcx>(
krate.spans.inner_span,
krate.spans.inject_use_span,
&arenas,
&extern_arenas,
);
let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);

Expand Down
Loading
Loading