# TODO

## General

- Consider introducing arena-friendly hash map and hash set

- alloc<T: Send> requires Send. A bare arena.alloc(value) -> &mut T demanding T: Send surprises people — single-threaded
arena usage feels like it shouldn't need it. The real reason is destructors: unlike bumpalo (which leaks by default and
never runs T::drop, so it needs no bound), multitude registers a drop entry and runs T::drop at arena drop; since the
arena is Send, that teardown can run on a migrated thread, which would be unsound for thread-affine !Send types. The
bound is now documented on `Arena::alloc`. Still open: a !Send-friendly path for thread-local-only use (give up
`Arena: Send` to drop the `T: Send` requirement), and/or relaxing the bound to the `T: Drop` case only (needs specialization).

- No owning IntoIterator for Box<[T]> (std has it). Minor, but an easy ergonomic win.

## Zero-copy `Vec`/`String``Arc<[T]>` / `Arc<str>`

### Problem

`Vec` and `String` are backed by a `LocalChunk` (non-atomic refcount —
`LocalChunk::inc_ref` is `unreachable!`). Freezing them into `Arc<[T]>` /
`Arc<str>` therefore copies the data into a `SharedChunk` and returns an `Arc`
pointing at the copy. The copy is mandatory today because:

- `Arc` holds an **atomic** refcount on a `SharedChunk`, and
- a thin `Arc<[T]>` recovers its length from a `usize` prefix word and its chunk
  header via the 64 KiB `CHUNK_BASE_MASK`.

Bytes living in a local chunk satisfy neither, so the only way to avoid the copy
is to **build the buffer in a shared chunk from the start**. Customers building
data specifically to hand out as `Arc<[T]>` / `Arc<str>` want to skip that copy.

### Implementation crux (shared by all API options)

A *shared* growable buffer needs two things a local one doesn't:

1. **Hold a refcount on its backing shared chunk during growth.** Otherwise an
   interleaved `alloc_arc` that triggers `refill_shared` rotates the chunk out;
   with nothing holding it, the chunk can be torn down and the builder dangles.
   So a shared builder carries a `ChunkRef` (a `+1`), re-acquired on each
   relocation. (Note the interaction with the pre-credited surplus /
   `local_shared_count` accounting in `arena/mod.rs`.)
2. **Reserve the `Arc` length-prefix slot** up front so freeze is a pointer
   fix-up rather than a copy.

With those in place, `into_arc` becomes **O(1)**: write the final length into the
prefix slot, then `mem::forget` the builder's `ChunkRef` to transfer its `+1` to
the new `Arc`. Once this machinery exists, the API-shape choice below is
secondary and cheap to swap.

### API options

- **A — separate `SharedVec` / `SharedString` types.** Clearest intent,
  type-safe freeze, no runtime branch. Source duplication can be contained with
  a `impl_arena_vec_common!` macro emitting both flavors from one body (mirrors
  the existing `impl_arena_string_common!`).
- **B — one type, flavor chosen at construction via a runtime flag**
  (`alloc_vec` vs `alloc_shared_vec`). Smallest API, but a branch in the
  growth/freeze paths and no compile-time signal that `into_arc` is free vs. a
  copy.
- **C — one type with a zero-cost marker type parameter (recommended).**
  `Vec<'a, T, A = Global, F = Local>` with a sealed `ChunkFlavor` trait
  abstracting reserve / refill / oversized / ref-holding. `Local` = today's
  behavior (default, so existing code is unchanged); `Shared` holds the
  `ChunkRef` + prefix slot. Expose `SharedVec` / `SharedString` as type aliases.
  - common ops (`push`, `extend`, `len`, …) in `impl<F: ChunkFlavor>` — one body;
  - `into_arc` is O(1) only on `F = Shared`, still available (O(n) copy) on `Local`;
  - `into_slice` (arena-lifetime, no copy) stays `Local`-only.
  Zero runtime branch (monomorphized), type-safe freeze, single impl. Cost:
  generic noise in signatures, mitigated by the `F = Local` default and aliases.

`String` wraps `Vec<u8>`, so flavor support added to `Vec` extends to `String`
(and `Utf16String`) for free.

### Recommendation

Option C for zero-cost + compile-time freeze guarantees; fall back to A-via-macro
if the generic parameter is too noisy. All options require the same underlying
"shared growable buffer holds a `ChunkRef` + prefix slot" work — start there.