Skip to content

Conversation

@overlookmotel
Copy link
Member

@overlookmotel overlookmotel commented Aug 18, 2025

Same as #13041.

It's unsound for oxc_allocator::HashMap to be Send because if you can move a HashMap to another thread, you can call insert on it and it may allocate in the arena. This is unsound because another thread may be simultaneously be doing the same with another HashMap, and Bump is not thread-safe.

Remove the Send impl on HashMap.

However, we do want HashMap to be Sync. There's no reason why you shouldn't have 2 &HashMap references on different threads, as &HashMap doesn't allow mutating the HashMap in any way.

Tighten up the trait bounds so HashMap<K, V> is Sync only if K and V both are.

This is not yet completely sound. There are a couple of holes I'm aware of:

  1. allocator method which allows obtaining a &Bump from a &HashMap.
  2. clone which allocates into arena, taking only an immutable &self reference.

This PR closes those holes as much as possible without a major refactor. It's not completely sound, but it's at least now quite difficult to commit UB - it'd be unlikely to happen by accident.

So, not perfect, but at least there's now only a crack in the window, rather than the front door swinging wide open.


The reason these 2 impls were added originally was as a quick fix to make oxc_semantic::Scoping Send and Sync. That is addressed in the next PR in this stack.

Copy link
Member Author

overlookmotel commented Aug 18, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codspeed-hq
Copy link

codspeed-hq bot commented Aug 19, 2025

CodSpeed Instrumentation Performance Report

Merging #13203 will not alter performance

Comparing 08-18-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirement_for_hashmap_ (f490d27) with main (163dbea)1

Summary

✅ 34 untouched benchmarks

Footnotes

  1. No successful run was found on 08-12-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirements_for_vec_ (0815a89) during the generation of this report, so main (163dbea) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@overlookmotel overlookmotel marked this pull request as ready for review August 19, 2025 00:05
@graphite-app graphite-app bot added the 0-merge Merge with Graphite Merge Queue label Aug 19, 2025
@graphite-app
Copy link
Contributor

graphite-app bot commented Aug 19, 2025

Merge activity

…ment for `HashMap` (#13203)

Same as #13041.

It's unsound for `oxc_allocator::HashMap` to be `Send` because if you can move a `HashMap` to another thread, you can call `insert` on it and it may allocate in the arena. This is unsound because another thread may be simultaneously be doing the same with another `HashMap`, and `Bump` is not thread-safe.

Remove the `Send` impl on `HashMap`.

However, we do want `HashMap` to be `Sync`. There's no reason why you shouldn't have 2 `&HashMap` references on different threads, as `&HashMap` doesn't allow mutating the `HashMap` in any way.

Tighten up the trait bounds so `HashMap<K, V>` is `Sync` only if `K` and `V` both are.

This is not yet completely sound. There are a couple of holes I'm aware of:

1. `allocator` method which allows obtaining a `&Bump` from a `&HashMap`.
2. `clone` which allocates into arena, taking only an immutable `&self` reference.

This PR closes those holes as much as possible without a major refactor. It's not *completely* sound, but it's at least now quite difficult to commit UB - it'd be unlikely to happen by accident.

So, not perfect, but at least there's now only a crack in the window, rather than the front door swinging wide open.

---

The reason these 2 impls were added originally was as a quick fix to make `oxc_semantic::Scoping` `Send` and `Sync`. That is addressed in the next PR in this stack.
@graphite-app graphite-app bot force-pushed the 08-12-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirements_for_vec_ branch from bb6abbc to 0815a89 Compare August 19, 2025 21:37
@graphite-app graphite-app bot force-pushed the 08-18-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirement_for_hashmap_ branch from 1b86fbb to f490d27 Compare August 19, 2025 21:38
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Aug 19, 2025
Base automatically changed from 08-12-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirements_for_vec_ to main August 19, 2025 21:45
@graphite-app graphite-app bot merged commit f490d27 into main Aug 19, 2025
27 checks passed
@graphite-app graphite-app bot deleted the 08-18-fix_allocator_remove_unsound_send_impl_and_tighten_sync_requirement_for_hashmap_ branch August 19, 2025 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants