Skip to content

feat(lance-linalg): runtime SIMD dispatch for pre-Haswell x86_64 from-source builds#2

Draft
tobocop2 wants to merge 132 commits into
mainfrom
fix/runtime-simd-multiversion
Draft

feat(lance-linalg): runtime SIMD dispatch for pre-Haswell x86_64 from-source builds#2
tobocop2 wants to merge 132 commits into
mainfrom
fix/runtime-simd-multiversion

Conversation

@tobocop2

@tobocop2 tobocop2 commented Apr 26, 2026

Copy link
Copy Markdown
Owner

Adds runtime SIMD dispatch to lance-linalg's hot distance kernels so a from-source build with a lower x86_64 baseline produces a working binary on pre-Haswell hardware (Sandy Bridge / Ivy Bridge / Steamroller). fast-by-default with a documented from-source override for legacy users.

Today, import lancedb SIGILLs on AVX-without-AVX2 CPUs because the wheel bakes AVX2 into every compiled function with no runtime guard. numpy and pyarrow handle the same hardware via runtime dispatch. This PR brings lance to parity for the from-source legacy build path.

Summary

  • 5-tier runtime SIMD dispatch (scalar / AVX / AVX+FMA / AVX2+FMA / AVX-512) on all 10 hot f32/f64 distance kernels in lance-linalg, using the same match *SIMD_SUPPORT + mod x86 { #[target_feature(enable=...)] pub unsafe fn ... } shape as dot_u8.rs / cosine_u8.rs / l2_u8.rs. On the haswell baseline, dispatch always lands on AVX2 — modern compile output is unchanged from today.
  • lance.simd_info() Python API mirroring pyarrow.runtime_info() for tier introspection.
  • qemu-pre-haswell CI gate that builds with RUSTFLAGS="-C target-cpu=x86-64-v2" (env-var-scoped to that one job — workspace .cargo/config.toml is unchanged) and runs lance-linalg tests under qemu Nehalem.
  • CONTRIBUTING.md documents the legacy build: RUSTFLAGS="-C target-cpu=x86-64-v2" cargo build --release.

Zero new external dependencies. Dispatch shape extends an idiom lance already uses for u8 and f16/bf16 kernels rather than introducing a new convention. Recent precedent: @justinrmiller's #6540, #6517, #6506, #6510.

Verification

  • cargo test -p lance-linalg --lib — 83/83 on aarch64 dev box.
  • 38 new proptest cases verifying scalar↔SIMD bit-for-bit equivalence per tier per kernel; gated on is_x86_feature_detected!() so each runs on hosts that can execute its tier.
  • cargo clippy --all-targets -- -D warnings clean; cargo fmt --check clean; Cargo.lock unchanged.
  • SIGILL gone on Sandy Bridge Xeon E5-2609 with the documented RUSTFLAGS override (via companion lancedb wheel — see tobocop2/lancedb#2 for the verification PASS output).
  • Modern-hardware bench delta still pending. The AVX2 path is preserved as one of the per-tier kernels and the workspace baseline still bakes AVX2 into surrounding code, so by construction the modern compile is unchanged — but I'll confirm with criterion change: lines once I find a host that can hold the full cargo bench -p lance-linalg --bench {cosine,dot,l2,norm_l2} suite (Codespace's 30-min idle timeout killed my last attempt mid-run).

Closes #1.

@tobocop2 tobocop2 changed the title Runtime SIMD dispatch: 5-tier coverage from Nehalem 2008 through Sapphire Rapids 2023, full numpy/pyarrow parity fix(lance-linalg): SIGILL on pre-Haswell x86_64 — add runtime SIMD dispatch Apr 26, 2026
@tobocop2 tobocop2 changed the title fix(lance-linalg): SIGILL on pre-Haswell x86_64 — add runtime SIMD dispatch fix(lance-linalg): lancedb unusable on pre-Haswell x86_64 (import SIGILL) — add runtime SIMD dispatch Apr 26, 2026
tobocop2 added a commit that referenced this pull request Apr 26, 2026
…ch dot_u8.rs convention

Per-function doc comments on `*_scalar`/`*_avx`/`*_avx_fma`/`*_avx2`/`*_avx512`
inner functions are now one-liners matching the existing convention in
`dot_u8.rs` (see e.g. its `pub unsafe fn dot_u8_avx2` comment). Drops the
redundant "Caller must ensure..." precondition lines — those are implicit
from `unsafe fn` + `#[target_feature]`. Module-level `//!` docs and
public-API `///` docs are left detailed per project convention.

Refs #1, #2.
@tobocop2 tobocop2 force-pushed the fix/runtime-simd-multiversion branch from a3df856 to 9193496 Compare April 28, 2026 04:59
@tobocop2 tobocop2 changed the title fix(lance-linalg): lancedb unusable on pre-Haswell x86_64 (import SIGILL) — add runtime SIMD dispatch feat(lance-linalg): runtime SIMD dispatch for pre-Haswell x86_64 from-source builds Apr 28, 2026
@tobocop2 tobocop2 force-pushed the fix/runtime-simd-multiversion branch from 58325e8 to 7db5171 Compare April 28, 2026 05:43
@github-actions github-actions Bot added enhancement New feature or request python labels Apr 28, 2026
@tobocop2 tobocop2 force-pushed the fix/runtime-simd-multiversion branch from 7db5171 to 26aa7f4 Compare April 28, 2026 05:46
@github-actions github-actions Bot added the java label Apr 28, 2026
@tobocop2 tobocop2 force-pushed the fix/runtime-simd-multiversion branch 3 times, most recently from 126a6a5 to 26a520b Compare June 10, 2026 16:56
hamersaw and others added 12 commits June 25, 2026 21:14
…p-table (lance-format#7361)

## What

The mem-wal primitives sophon's drop-table two-phase commit needs:

- **`ShardWriter::abort(&self)`** — shut down the background flush tasks
(`task_executor.shutdown_all()`) *without* flushing, discarding buffered
memtable state. Unlike `close(self)` it takes `&self` (so it's callable
through the `Arc<ShardWriter>` callers hold) and does no object-store
IO. The caller must quiesce writes first (documented). Idempotent. Acked
data is **not** lost — it's durable in the WAL log and replays on the
next claim, which is what makes the drop's prepare phase reversible.
- **`ShardStatus { Active | Sealed }` on `ShardManifest`** — a durable,
reversible lifecycle marker (proto + struct + serde). `claim_epoch`
refuses a `Sealed` manifest with a **distinguishable** error instead of
minting a new epoch, so a shard mid-drop can't be re-claimed — even by a
caller that skips its own status check — and a reader can tell an
in-doubt drop apart from an ordinary epoch fence. Set/cleared through
the existing epoch-guarded `commit_update` CAS; carried across claims
via `..base`, so only the genuinely-fresh constructions default it to
`Active`.

## Why

A WAL-enabled table's drop spans two durable resources — the owning
pod's fresh-tier state and the catalog/object-store data — so sophon's
teardown is a two-phase commit. Before the dataset directory is removed,
the owning pod must:

- `abort` the writer so its background flush task can't re-create
`_mem_wal/` under the just-deleted directory (a graceful `close()` would
flush it back), and
- durably mark the shard `Sealed` so the drop is in-doubt across a pod
crash or a Maglev rehome — which the in-memory fence flag cannot
survive. The seal is reversible (rollback clears it back to `Active`),
making the prepare phase abortable without data loss.

Both build on existing machinery (`shutdown_all`, the manifest CAS) —
thin exposure, not new infrastructure.

> **Changed since first draft:** this PR previously also added
`Session::invalidate_dataset`; it has been **dropped**. Base-table read
freshness rides the recreate's new object-store `e_tag` (the QN→PE and
lance metadata caches are `e_tag`-keyed and miss the stale entry), so
cache invalidation isn't load-bearing — only `abort` and the `Sealed`
marker remain.

## Tests

- `test_abort_discards_without_flushing_and_is_idempotent` — `abort`
leaves no new L0 generation (contrast with `close`), idempotent on a
second call.
- `test_claim_epoch_refuses_sealed_manifest` — a `Sealed` manifest is
refused with the distinguishable error and left untouched (no epoch
minted); rolling the status back to `Active` makes the shard claimable
again (reversibility).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## What

Adds `LsmPointLookupPlanner::lookup_keep_tombstone` and
`lookup_many_keep_tombstone` — point-lookup variants that carry the
`_tombstone` marker through instead of filtering deleted keys out.

## Why

The existing `lookup` / `lookup_many` collapse two distinct states —
**deleted in the fresh tier** and **never written** — into a single
`None`. That's correct for a normal reader, but a caller doing a
read-on-write merge needs to tell them apart: a fresh-deleted PK must be
treated as *absent* (so a later partial update resurrects it from
carried columns + NULLs), while a never-written PK falls back to the
base row.

These variants return the deleted row with `_tombstone = true`; absent
keys still return `None`. Implemented by refactoring `plan_lookup` to
share a `plan_lookup_coalesced` helper and skipping the post-coalesce
tombstone filter, so the hot read path is unchanged.

## Tests

- `test_lookup_keep_tombstone_returns_deleted_row_with_marker`
- `test_lookup_many_keep_tombstone_includes_tombstoned_keys`

## Context

Prerequisite for a downstream WAL partial-column-update resurrection
fix: a partial update arriving after a delete must resurrect carried
columns + NULL untouched, never stale pre-delete base data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lance-format#7495)

## What

The `lance-index` **test build** is currently broken on `main`:
`error[E0046]: not all trait items implemented, missing:
with_io_priority` at `rust/lance-index/src/scalar/fmindex.rs`.

`with_io_priority` was added to the `IndexStore` trait in lance-format#7449. The
`FailNewFileStore` test fixture was added later in lance-format#7422 (which branched
before lance-format#7449 landed), so it never implemented the new method. Each PR
was green on its own; together on `main` the test build fails — a
semantic merge conflict. It only surfaces in the `Build tests` step
because the fixture is `#[cfg(test)]`.

## Fix

Implement `with_io_priority` on `FailNewFileStore` by delegating to the
inner store and re-wrapping, mirroring how the fixture already delegates
its other read methods while keeping the injected `new_index_file`
failure.

## Verification

- `cargo check -p lance-index --tests` — compiles (was failing on
`main`).
- `cargo test -p lance-index --lib fmindex` — 24 passed.
- `cargo fmt -p lance-index -- --check` and `cargo clippy -p lance-index
--tests` — clean.
## What changed

This PR narrows OSS-1346 to codec replacement work only. It adds
Lance-owned `BitPacker4x` and internal `BitPacker8x` implementations in
`lance-bitpacking`, and switches existing FTS posting-list users from
the external `bitpacking` runtime dependency to `lance-bitpacking`.

The external `bitpacking` crate remains only as a dev-dependency for
byte-for-byte compatibility tests against the legacy 4x/8x formats.

## Why

FTS currently depends on an external bitpacking crate for 128-value
posting blocks. Keeping the implementation in `lance-bitpacking` lets
Lance own the codec while preserving existing 128-block wire
compatibility. The 8x implementation is included as an internal
algorithm building block only; this PR does not expose a new block-size
option.

## How it works

- Exposes `BitPacker` / `BitPacker4x` from `lance-bitpacking` with the
same call shape used by existing FTS code.
- Adds owned backends for 128-value 4x blocks:
  - SSE3 on `x86_64`
  - NEON on `aarch64`
  - scalar fallback when SIMD backends are unavailable
- Adds an internal 256-value `BitPacker8x` algorithm:
  - AVX2 on `x86_64`
  - NEON on little-endian `aarch64`
  - scalar fallback when AVX2 or NEON is unavailable
  - not re-exported from `lance-bitpacking`
- Does not add or change FTS `block_size` parameters, metadata, Python,
Java, or docs.

## Validation

- `cargo fmt --all`
- `cargo test -p lance-bitpacking -- --nocapture`
- `cargo check -p lance-index --tests`
- `cargo check -p lance --tests`
- `cargo clippy -p lance-bitpacking --tests -- -D warnings`
- `cargo clippy -p lance-index --tests -- -D warnings`
- `cargo clippy -p lance --tests -- -D warnings`
- `cargo clippy --all --tests --benches -- -D warnings`
- `cargo metadata --manifest-path python/Cargo.toml --locked
--format-version=1 --no-deps`
- `CARGO_TARGET_DIR=/tmp/lance-target-oss1346-aarch64 cargo check -p
lance-bitpacking --tests --target aarch64-apple-darwin`
- `CARGO_TARGET_DIR=/tmp/lance-target-oss1346-x86 cargo check -p
lance-bitpacking --tests --target x86_64-apple-darwin`
- `git diff --check`
…#7483)

## What

Adds `ShardWriter::delete_no_wait`, the delete analog of `put_no_wait`:
it inserts the tombstone into the in-memory tier (visible to reads on
this writer the instant it returns) and hands back the durability
watcher *without* awaiting it. `delete` becomes a thin wrapper that
awaits the watcher.

## Why

Lets a caller hold an external lock across only the in-memory tombstone
insert and await durability after releasing it — matching how
`put_no_wait` is already used so flushes still coalesce. A downstream
WAL serializes deletes against partial-update merges under a per-bucket
lock; with the blocking `delete` it would hold that lock across
durability, and `delete_no_wait` lets it release first.

## Tests

- `test_shard_writer_delete_no_wait_visible_before_durability`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
)

The Merge arm only dropped indices for fields removed from the schema,
so a field rewritten in place (new backing data file, same field id)
kept its index covering the fragment with stale entries. Index-served
queries then silently returned wrong results -- a filter on the
rewritten column matches the old values rather than the current data.
Prune the rewritten fragment from any index over a field whose backing
data file changed, reusing the same primitive the DataReplacement arm
already uses.
## Summary

Add `lance/arrow.py` and `tests/test_arrow.py` to the pyright include
list and fix the resulting type errors. Closes lance-format#3292.

- **arrow.py**: narrow union types via typed locals / `typing.cast`,
annotate the internal decoder return types, switch the fallback to
`pyarrow.compute as pc`, and add a single `# pyright:
ignore[reportOptionalCall]` for `tf.stack` (typed as `None` by
tensorflow's incomplete stubs).
- **lance/lance/__init__.pyi**: fix the `bfloat16_array` stub signature
from `List[str | None]` to `Sequence[float | None]` — the Rust function
takes `Vec<Option<f32>>`, and `Sequence` (covariant) lets `list[float]`
callers type-check.
- **test_arrow.py**: add `import lance.arrow` so the `lance.arrow.*`
attribute accesses resolve.


## Test plan

`tensorflow` is linux-only in `pyproject.toml`, so it was installed
locally to mirror the CI (Linux) lint environment before checking.

- `pyright` → **0 errors** (15 warnings, all pre-existing missing-stub
warnings for pyarrow/pandas/etc.)
- `ruff format --check` + `ruff check` → pass
- `pytest python/tests/test_arrow.py` → **20 passed**
This fixes low recall for IVF_SQ and IVF_HNSW_SQ indexes using Dot
distance when the scalar quantization bounds include negative values.

The previous SQ Dot path computed dot distance directly in quantized u8
code space. That drops the affine offset from scalar quantization, so
zero-centered embeddings can be ranked incorrectly. The updated path
computes Dot distance against the dequantized SQ value model while
keeping the stored-code HNSW path allocation-free and able to use the u8
dot kernel.

The change also adds regression coverage for a crafted negative-bound SQ
Dot case and end-to-end IVF_SQ / IVF_HNSW_SQ Dot recall on
negative-valued vectors.
…format#7484)

## Problem

An indexed merge-insert delete by a composite primary key whose columns
are **all** indexed silently removes nothing. `merge_insert(when_matched
= Delete, use_index = true)` reports `deleted = 0`, the matched rows
stay live in the table, and resurface in later reads.

## Root cause

`WhenMatched::Delete` is only implemented in the v2 plan
(`DeleteOnlyMergeInsertExec`), which never uses a scalar index. When
every join column is indexed, `can_use_create_plan` routes the merge to
the legacy `Merger` instead (the only engine with the indexed-scan
probe). That engine's matched-row handler only ever distinguished
`DoNothing` from "update" — it folded **both** `Delete` and `Fail` into
the update path:

- a fully-indexed `Delete` rewrote the matched rows in place → 0
deletes;
- a fully-indexed `Fail` silently updated instead of erroring.

A single indexed column hits the same path, so this was never
composite-specific — composite keys just make it the common case
(partial-column updates require an index on every PK column).

## Fix

Make the legacy `Merger` dispatch every `WhenMatched` variant
explicitly, mirroring the v2 classifier (`merge_insert_action`):

- **`Delete`** collects matched row ids as deletions and emits no
replacement batch.
- **`Fail`** aborts on any match, with the same message as the v2 path.
- A **delete-only commit branch** drains the merger and applies the
deletions (resolving row ids → addresses via the row-id index for stable
row ids) without writing fragments — this keeps the O(keys) indexed
delete instead of falling back to a full table scan.
- The partial-schema (column-rewrite) commit branch physically cannot
express row deletions, so combining `Delete` with inserts from a
partial-schema source now returns a descriptive error rather than
silently dropping the deletes.

## Tests

`cargo test -p lance --lib dataset::write::merge_insert` (152 passing),
covering:

- composite-key indexed delete (index on first / second / both / neither
— the both-indexed case is the original bug);
- single-column indexed delete;
- multi-fragment + stable-row-id variants, including an appended
fragment neither index covers (unindexed-remainder union);
- `Delete` combined with `InsertAll` (not delete-only);
- `Fail` on an indexed key (match aborts, no-match inserts cleanly).

`cargo fmt` and `cargo clippy -p lance --lib --tests -- -D warnings` are
clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-format#7223)

## Summary

`LabelListIndexPlugin::train_index` unconditionally rejected
fragment-scoped
training (`fragment_ids.is_some()`), so a LabelList index could not be
built
through the distributed / segmented path (per-fragment
`execute_uncommitted` +
`merge_existing_index_segments`) the way BTree, Inverted, Bitmap, and FM
already
are. This makes LabelList a first-class distributed scalar index.

## Changes

- `lance-index/src/scalar/label_list.rs`: `train_index` ignores
`fragment_ids` and
builds over the already fragment-scoped stream (mirrors
`FMIndexPlugin`); a partial
index over a fragment subset is correct since it covers exactly those
rows. Add
`merge_label_list_indices`, which unions the per-segment bitmap states
and the
`list_nulls` row sets. LabelList wraps a `BitmapIndex` plus a null-row
set and
distributed segments cover disjoint rows, so this is a cheap union (the
same
operation `LabelListIndex::update` performs) — no source re-scan.
Mirrors
  `merge_bitmap_indices` but also carries `list_nulls`.
- `lance/src/index/scalar/label_list.rs` (new): `merge_segments` opens
each source
segment as a `LabelListIndex` and calls `merge_label_list_indices`
(mirrors
  `scalar/bitmap.rs`).
- `lance/src/index.rs`: `merge_existing_index_segments` routes
`all_label_list`
  segments (details `LabelListIndexDetails`) to the new merge; add
  `segment_has_label_list_details`.
- `lance/src/index/scalar.rs`: declare the `label_list` module.

Covered by `test_label_list_merge_existing_index_segments`: one
LabelList segment per
fragment, merged via `merge_existing_index_segments`, answers
`array_has_any` across
both fragments with the same row count as a pre-index full scan.
Summary:
- Improve FM `contains` queries so normal reads demand-load needed
wavelet blocks and page nearby blocks instead of prewarming whole
partitions.
- Add chunked explicit FM prewarm, parallel partition loading/search,
and resumable partition builds.
- Add FM `contains` benchmark and FM index management tooling.

Optimizations applied:
- Parallel FM search across partitions/segments.
- Removed query-time full-partition prewarm; explicit prewarm still
fully warms the index.
- Chunked contiguous wavelet-row prewarm with
`LANCE_FMINDEX_PREWARM_CHUNK_BYTES` and
`LANCE_FMINDEX_PREWARM_CHUNK_CONCURRENCY`.
- Cold-read demand paging with `LANCE_FMINDEX_DEMAND_PAGE_BYTES` to
reduce object-store RPS.
- Parallelized FM metadata/partition loading.
- Added resumable FM partition creation and explicit `--index-uuid`
recovery support.
- Final benchmark layout: 1 logical FM segment,
`LANCE_FMINDEX_PARTITION_ROWS=100000`, large partition-byte cap, 1,000
partitions.

Performance:
Dataset: 100M-row
`az://datasets/mmlb/mmlb_100m_fts_en_fm_20260626.lance`.
Query workload: 4 sampled 5-term patterns from `summary_in_image`,
`contains(full_content, pattern)`, `k=100`, `_rowid` only
(`projection=[]`, `row_id=true`).

| Run | Index layout | Prewarm | Query result |
| --- | --- | --- | --- |
| Baseline | 6 segments / 10k partitions | 6,525s / 108.8m | 1t: 1.58
qps, mean 633ms, p95 768ms; 8t: 12.48 qps, mean 320ms, p95 320ms |
| Demand-load + chunked prewarm | 6 segments / 10k partitions | 2,182s /
36.4m, 3.0x faster | 1t: 5.38 qps, mean 185ms, p95 307ms; 8t: 12.12 qps,
mean 326ms, p95 330ms |
| Single segment | 1 segment / 100k-row partitions | 356s / 5.94m, 18.3x
faster than baseline | 1t: 22.38 qps, mean 44.6ms, p95 54.4ms; 8t: 84.40
qps, mean 42.8ms, p95 47.3ms |

Index size:
- Final FM index UUID `78600545-625f-40e2-8790-204f35097ec0`: 1,000
partition files, 920,064,767,792 bytes / 856.9 GiB / 0.837 TiB.
- Previous 6-segment FM layout was 920,202,650,467 bytes / 857.0 GiB, so
the final relayout is effectively size-neutral.
LuciferYang and others added 30 commits July 7, 2026 15:56
…m_vec (lance-format#7614)

## What

Follow-up to lance-format#7500 (wjones127's suggestion in
lance-format#7500 (comment)).
`BFloat16Array::from(Vec<bf16>)` still walked the input a second time,
copying two bytes per element into a freshly allocated `MutableBuffer`.
This hands the input `Vec` straight to `Buffer::from_vec`, so the
existing allocation is reused as-is — no per-element copy, no
`MutableBuffer::extend` loop.

`Buffer::from_vec` requires `T: ArrowNativeType`, which `bf16` does not
implement (arrow-rs registers the trait only for `f16`/`f32`/`f64` among
the float family; Apache Arrow has no bf16 primitive type, which is why
Lance stores it as `FixedSizeBinary(2)`). The gap is bridged with
`bytemuck::cast_vec::<bf16, u16>`, which reinterprets the allocation in
place.

## Why it is sound

- `bf16` is `#[repr(transparent)]` over `u16` in `half` 2.7, so it has
the same size (2) and alignment (2) as `u16`. `cast_vec` therefore hits
its equal-size/equal-align path and reuses the allocation without
realloc; a mismatch would panic, never reach UB.
- `half`'s `bytemuck` feature (enabled here) derives `Zeroable + Pod` on
`bf16`, satisfying `cast_vec`'s trait bounds.
- The crate-root `#[cfg(not(target_endian = "little"))] compile_error!`
added in lance-format#7511 ties the reinterpretation to little-endian hosts,
matching the `FixedSizeBinary(2)` byte order Lance writes elsewhere.
Big-endian builds fail to compile, so the output is byte-identical to
the previous per-element `to_le_bytes()` path.

## Changes

- `From<Vec<bf16>>`: replace the `MutableBuffer` copy loop with
`bytemuck::cast_vec` + `Buffer::from_vec`.
- `half`: add the `bytemuck` feature; add `bytemuck` (`default-features
= false`, `extern_crate_alloc`) as a direct workspace dependency
(already resolved transitively, now promoted).
- Refresh `python/Cargo.lock` and `java/lance-jni/Cargo.lock` (the
workspace-excluded lockfiles) to record `bytemuck_derive`.
- `as_slice`'s alignment doc/SAFETY comment previously asserted every
value buffer comes from `MutableBuffer` (≥32-byte aligned); reworded to
also cover the new `Buffer::from_vec::<u16>` path (2-byte aligned), both
of which satisfy `bf16`'s 2-byte requirement.

## Tests

`test_basics` now pins the raw little-endian bytes emitted by
`From<Vec<bf16>>` (`[0x80,0x3F, 0x00,0x40, 0x40,0x40]` for `[1.0, 2.0,
3.0]`) via `FixedSizeBinaryArray::value`, so a layout or byte-order
regression is caught directly rather than only through Debug formatting.
The prior `assert_eq!(array, array2)` compared two outputs of the same
`From` impl and could not catch a regression.

`cargo fmt`, `cargo clippy -p lance-arrow --tests --benches -- -D
warnings`, and `cargo test -p lance-arrow` (93 unit + 6 doc tests) are
green.
…ance-format#7472)

## Problem
Updating an Arrow JSON column through `fragment.update_columns` / the
update merge path fails with a type-mismatch error.

## Root cause
The HashJoiner right-side stream did not convert Arrow JSON (Utf8) to
Lance JSON (LargeBinary/JSONB) before joining.

## Fix
Wrap the right-side stream in a `JsonConvertingReader` that converts
Arrow JSON fields to Lance JSON before the join.

## Test
Python `test_fragment_update_columns_with_json_column` plus dataset
update tests.

---------

Co-authored-by: xiaojiebao <xiaojiebao@xiaomi.com>
Co-authored-by: Claude Opus 4 <noreply@anthropic.com>
## Summary
- Add "Cleanup old versions" section to the Table Maintenance guide,
explaining versioning storage costs, snapshot isolation, time travel,
the `older_than` parameter, and the `delete_unverified` flag
- Add "Automatic cleanup" section documenting `AutoCleanupConfig`,
`enable_auto_cleanup`/`disable_auto_cleanup`, and dataset config keys
- Add "Other cleanup strategies" section mentioning periodic background
cleanup

## Test plan
- [ ] Verify docs render correctly with `mkdocs serve`
- [ ] Review code examples for accuracy against current Python API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… of `Error::IO` (lance-format#6569)

Closes lance-format#2067

### Summary

The blanket `From<object_store::Error>` impl mapped **all** object-store
errors to `Error::IO`, losing the semantic meaning of "not found." This
forced downstream code into fragile multi-level downcasting and left
several `Error::NotFound` match arms unreachable for the object-store
path (e.g., in `dataset.rs`, `builder.rs`, `insert.rs`).

This PR:
- Discriminates `object_store::Error::NotFound` in the `From` impl so it
converts to `Error::NotFound`
- Simplifies two call sites that relied on downcasting (`cleanup.rs`,
`refs.rs`)
- Adds tests for the conversion and `#[track_caller]` location
propagation

### Breaking Changes

`object_store::Error::NotFound` now produces `Error::NotFound` instead
of `Error::IO`. Code matching `Error::IO` to detect object-store
not-found conditions (via downcasting) will stop catching them. Match on
`Error::NotFound` instead. This is expected during the current
`6.0.0-beta.1` pre-release cycle.

### Design Notes

- The `source` field from the object-store variant is intentionally
dropped — `Error::NotFound` carries only `uri` and `location`,
consistent with all other `Error::not_found()` call sites in the
codebase.
- Call sites matching raw `object_store::Error::NotFound` before
conversion (e.g., `exists()`, commit resolution, external manifests) are
unaffected.
…#6606)

## Summary
- Adds a **Fragment Sizing** subsection to the Performance Guide that
frames the core tradeoff between manifest-level operations (cost scales
with fragment count) and fragment-level operations (cost scales with
fragment size, drives per-fragment conflict detection).
- Gives practical guidance: 1M rows/fragment default holds up to ~1B
rows, tens of thousands of fragments is generally fine, 10 GB–100 GB is
a reasonable per-fragment upper range (1 TB hard ceiling), and
concurrent update/delete/merge_insert workloads should err toward more
fragments.

## Test plan
- [ ] `mkdocs serve` renders the new section cleanly under Performance
Guide.
- [ ] Cross-link to `../format/table/transaction.md#conflict-resolution`
(already present in the surrounding section) still resolves.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…7616)

## What

`arrow-array` was declared in both `[dependencies]` and
`[dev-dependencies]` of the `fsst` crate. A normal dependency is already
visible to tests, examples, and benches, so the `[dev-dependencies]`
entry was redundant. This drops the duplicate line.

## Tests

No behavior change — purely a dependency-manifest cleanup. `cargo test
-p fsst`, `cargo build -p fsst --example benchmark`, and `cargo clippy
-p fsst --tests --benches -- -D warnings` are green. No lockfile change,
since `arrow-array` remains a workspace dependency.
Expose segment-level prewarm through the existing pylance
`prewarm_index` API by adding an optional `index_segments` argument.
Callers can pass UUIDs from `describe_indices()[i].segments[j].uuid` to
prewarm only selected physical segments of the named logical index,
while preserving the existing full-index behavior when `index_segments`
is omitted.

The resolved physical index segments are opened and prewarmed
concurrently, including both full-index prewarm and filtered segment
prewarm. This also supports the existing FTS `with_position` option for
selected segments and adds focused coverage in the index prewarm test.

Adds Rust-level tracing for prewarm investigation: request-level
selected/available/requested segment counts, selected on-disk bytes when
known, index cache entries/bytes before and after prewarm with deltas,
per-segment start/open/finish/failure with UUID, fragment count, index
version, dataset version, index type, elapsed time, and FTS
partition-level start/posting-list/docset/finish timing. Also exposes
`ds.session().index_cache_size_bytes()` in pylance for direct
before/after measurement. Checked with `cargo fmt --all` and `cargo
check --manifest-path python/Cargo.toml`.
Fix a deadlock in train_streaming_coreset_ivf_model that occurs because
weighted_hierarchical_params stays in scope until the end of the
function, causing the progress_worker task to never exit, and
progress_worker.await to block forever. This change fixes the hang and
adds a unit test.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The runtime-dispatch codecov run flagged the f32 cosine batch kernels and
the scalar x86 gather fallback as uncovered. Both are only reached at
runtime on sub-AVX2 hosts, so on the AVX2+ CI runner they were never
exercised even though the surrounding per-vector kernels have full parity
tests.

Add direct parity tests that call cosine_batch_avx, cosine_batch_avx_fma,
and cosine_batch_avx512 across the 8/16/general dimension arms, comparing
each batch entry against the scalar cosine_fast reference and gating each
tier on the matching is_x86_feature_detected! check. Add a direct test for
gather_scalar_x86 so the non-AVX2 gather path is covered on hosts that
route through the AVX2 gather at runtime.
…ance-format#7667)

## Problem

`describe_indices` — and therefore lancedb's `list_indices` /
`wait_for_index` — returns an error on any dataset with MemWAL enabled:

```
Fragment bitmap is required for index description. This index must be retrained to support this method.
```

## Cause

The `__mem_wal` system index is an inline state record: it indexes no
columns (`fields: []`), has no index files (`files: None`), and
legitimately carries `fragment_bitmap: None`.
`IndexDescriptionImpl::try_new` treats a missing `fragment_bitmap` as
*unknown* coverage and errors — the guard exists to stop legacy data
indices from silently reporting a fabricated row count.

But for a **system** index a missing bitmap isn't "unknown," it's
"indexes zero fragments" — `rows_indexed = 0` is accurate. `__mem_wal`
is committed to the base manifest as soon as MemWAL is provisioned, so
from that point on every `list_indices` / `wait_for_index` call fails.

## Fix

Fix at the root cause rather than hiding the index:

- In `try_new`, a missing bitmap on an `is_system_index` contributes
zero indexed rows (`continue`) instead of erroring. Data indices still
error — a missing bitmap there genuinely means unknown coverage, and
retraining rebuilds it with a bitmap.
- `describe_indices` no longer filters system indices, so `__mem_wal` is
now described **consistently with `__frag_reuse`**, which lance-format#6685 already
surfaces through this path (type resolved via `infer_system_index_type`,
`rows_indexed = 0`).

The curated catalog surface is unchanged: the namespace `dir` impl and
`index_statistics` keep their own `is_system_index` filters, so end-user
"list my table's indices" views still hide system internals.

## MemWAL details

`describe_indices()[i].details` now returns the decoded MemWAL state
instead of `{}`. `details()` dispatches system indices (by name,
mirroring `try_new`'s ordering) to a new `mem_wal_details_as_json`,
which decodes the stored `index_details` `Any` into a curated JSON view
— `snapshot_ts_millis`, `num_shards`, `sharding_specs`,
`maintained_indexes`, `merged_generations`, `index_catchup`,
`writer_config_defaults`. This mirrors the existing hardcoded
`vector_details_as_json` branch.

The raw `inline_snapshots` bytes are deliberately excluded (only their
size is reported) — they are serialized shard-snapshot file bytes, not
inspectable state, and can be large; the view borrows every field so the
bytes are never materialized.

> `__frag_reuse` still returns `{}` here (same gap, no decoder yet).
Unifying details serialization into a single `type_url`-keyed registry —
instead of the current per-family branches (vector, mem_wal, …) — is a
reasonable follow-up.

## Test

`test_describe_indices_includes_mem_wal_system_index`: commits a
`__mem_wal` index alongside a real BTree index and asserts
`describe_indices` returns **both**, with the system index resolved to
type `MemWal`, `rows_indexed = 0`, its committed merged generation
round-tripping through `details`, and the raw `inline_snapshots` bytes
absent from the JSON. Before the fix this errored.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…e-format#7621)

## Summary

The ICU tokenizer's stop-word removal used an **incomplete English
stop-word list**, letting the highest-frequency English
pronouns/function words through the index. On large corpora this built
pathologically large single-term posting lists and **panicked the FTS
index build** with `posting list memory size overflowed u32`.

`StopWordFilter::all()` (the path used for `base_tokenizer: icu` /
`icu/split`) sourced its English words from the local Tantivy-style
`stopwords::ENGLISH` constant (~33 words):

```
a an and are as at be but by for if in into is it no not of on or such
that the their then there these they this to was will with
```

This omits extremely common words: **`you, my, your, we, she, what, can,
about, us, them, him, our`**. Since these are among the
highest-frequency tokens in English text, they survived stop-word
removal. With `with_position: true` on a 100M+ row dataset, a single
such term's in-memory posting list exceeded `u32::MAX` bytes (~4 GiB)
and panicked the whole build.

## Root cause

Every other language in `all_stop_words()` (Arabic, Chinese, Japanese,
Korean, …) is sourced from the `stop-words` crate via
`stop_words::get(...)`, whose lists are complete. Only English used the
local, truncated constant. The Chinese list (`stop_words::get("zh")`,
~841 words) was already complete — Chinese stop words like `了/是/的` were
correctly removed; only English leaked.

## Fix

One-line change in `all_stop_words()`: source English from
`stop_words::get("en")` (~198 words) like the other languages. This list
contains the missing pronouns/function words.

## Tests

- `test_icu_common_english_stop_words_do_not_leak` — asserts
`you/my/your/we` are removed via the ICU `all()` path, for `icu` and
`icu/split`, with `stem` both false and true (the leak is independent of
stemming — it's purely the incomplete list).
- `test_icu_common_chinese_stop_words_do_not_leak` — asserts common
Chinese function words (`我 在 有 了 是 的 和`) are removed while content words
(`英语`) survive.

All existing tokenizer tests continue to pass (20 passed, 0 failed).

## Impact

Fixes FTS index builds that panicked on large English (and mixed EN+ZH)
corpora, and reduces index size by correctly dropping the
highest-frequency English stop words.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary

- Expose MemWAL `ShardWriter.delete(keys, *, schema=None)` in the Python
wrapper and PyO3 layer.
- Reuse the existing PyArrow stream-to-`RecordBatch` conversion path for
both `put` and `delete`.
- Delegate primary-key validation and tombstone construction to Rust
core, and add a Python end-to-end regression test that verifies a delete
masks a base-table row.

## Tests

- `cargo fmt --all`
- `uv run make format`
- `uv run pytest python/tests/test_mem_wal.py -q`
- `uv run make lint` (pyright reported 0 errors and 7 missing-type-stub
warnings)
- `CARGO_BUILD_JOBS=8 cargo clippy --all --tests --benches -- -D
warnings`
…at#7685)

The TensorFlow adapter now lives in the standalone
[lance-format/lance-tensorflow](https://github.com/lance-format/lance-tensorflow)
project.

Keeping `lance.tf` inside `pylance` made the default Python development
and test environment carry TensorFlow-specific dependency and platform
concerns, even though the integration is a pure Python-side adapter.
This PR removes the in-tree adapter and TensorFlow test dependency while
keeping the TensorFlow docs page as a migration entry point to the new
package.

Image array helpers now rely on Pillow or user-provided encoder/decoder
callbacks instead of trying TensorFlow as a built-in fallback.
Nested FTS indexes can be registered on leaf fields such as `data.text`,
but the flat FTS execution paths still expected the document field to
exist as a top-level column. After appends, or when FTS is used as a
post-filter/rerank path, nested fields could be read as their parent
struct without exposing the leaf path that the FTS executor looks up.

This PR makes scanner planning expose nested FTS leaf fields as
top-level aliases for flat execution while preserving the final
user-facing projection. It also adds Rust and Python coverage for
multiple indexed string leaves under the same struct.
…-format#7143)

## What

Fixes IVF training sampling memory growth for nullable vector columns by
bounding fragment-limited prefetch to the consumer's outstanding demand
and clamping sampled output to the requested training sample size.

Closes lance-format#7126

## Changes

- Tracks the consumer's outstanding demand in a shared `still_needed`
counter so each fragment-limited
prefetch round fetches at most `still_needed.min(remaining)` rows
instead of `2 * sample_size_hint`;
consumers zero the counter when their sample is full so any further poll
of the producer terminates instead
of reading another round.
- Replaces the `HashSet<u64>` of seen offsets with a `RoaringTreemap`,
keeping the visited-offset state near
`num_rows / 8` bytes even when sparse or all-null columns force the
stream to visit most selected rows.
- Samples unseen offsets via rejection sampling against the bitmap,
switching to a dense shuffle of the
unseen set only when few offsets remain unseen (`remaining <= 4 *
target`), so the dense allocation stays
proportional to the round size.
- Clamps `sample_nullable_fsl`, `sample_nullable_fallback`, and
`accumulate_fsl_values` (new `max_rows`
parameter) so oversized batches cannot grow output past
`sample_size_hint`.

## Notes

- No public API changes.
- The fallback path also slices accepted batches to the outstanding
demand, keeping the retained batches and the final `concat_batches`
bounded by the sample size.

## Tests

- `cargo test -p lance --lib index::vector::utils::tests`
- New: `test_maybe_sample_training_data_fsl_nullable_fragment_limited`
(partial-null fills the sample, all-null terminates cleanly),
`test_sample_fragment_scan_round_caps_at_still_needed` (producer round
never over-reads the demand),
`test_accumulate_fsl_values_respects_max_rows`.
…tics (lance-format#6365)

No regression for release builds, Python layer also can reuse this
mechanism

The overall design employs a two-tiered strategy of "compile-time
switching + runtime gating":

1. **Compile-time switching:** Two versions of the `MaybeBacktrace` type
are defined through conditional compilation using `#[cfg(feature =
"backtrace")]`, when the feature is disabled error size, layout, and
runtime behavior are unchanged as before

2. **Runtime Gating:** With the `backtrace` feature enabled, actual
backtrace capture is still controlled by the runtime environment
variable `RUST_BACKTRACE=1`

3. **Java integration:** The transformation logic calls
`err.backtrace()` to obtain an optional backtrace. If exists, it is
passed to the corresponding Java exception class. Users can enable this
feature during Maven builds using `-Drust.features=backtrace`.
…ance-format#7372)

The queries `X IS NULL` and `X IS NOT NULL` are very common queries.
Because validity is scattered throughout a file it is not actually that
easy to answer this query without scanning the column. This means very
wide columns can be very slow. Very wide columns also tend to be columns
that are not good candidates for btree (too much duplicated data) or
bitmap (too much cardinality).

On the flip side, a validity bitmap is pretty small, and maintaining one
for each column is probably affordable, even for the lightweight zone
map and bloom filter indexes. It would be nice to have consistent `IS
NULL` speedup when a column is indexed, regardless of the index type.

---

Captures a `RowAddrTreeMap` of every null row address during index
training. IS NULL queries can now be answered in O(1) by returning
`SearchResult::exact(null_rows)` instead of scanning all zones, which
also eliminates the downstream recheck step.

Backward-compatible: older indexes without the `null_bitmap.lance` file
load with `null_rows = None` and fall back to the previous zone-scan
path.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…rvation (lance-format#7675)

Raises the per-partition memory pool from 100MB to 150MB and sets the
sort spill reservation to 40MB (up from the DataFusion default of 10MB)
to give sort operations more headroom while spilling to disk (we should
still spill at roughly the same rate).

The previous defaults were 100MB / 10MB. This _usually_ worked but
certain patterns would lead to false memory exhaustion errors:

```
OSError: LanceError(IO): Resources exhausted: Additional allocation failed for ExternalSorterMerge[0] with top memory consumers (across reservations) as:
  ExternalSorterMerge[0]#1(can spill: false) consumed 58.5 MB, peak 58.5 MB,
  ExternalSorter[0]#0(can spill: true) consumed 41.4 MB, peak 89.9 MB.
Error: Failed to allocate additional 345.9 KB for ExternalSorterMerge[0] with 27.6 MB already allocated for this reservation - 92.2 KB remain available for the total pool, /home/pace/lance/rust/lance-datafusion/src/chunker.rs:49:46
```

The problem happens as follows:

1. The sort node accumulates batches of data without modifying them
until it determines a spill is needed. During this phase each batch
counts double against the pool reservation. This is meant to provide
overhead for the later steps. In our above example we can see spilling
was triggered at 41.4MB which is about half of the 90MB pool (half,
because each batch is counted double)
2. The sort node determines that spilling is needed. First, it must sort
the data that has accumulated in memory. Each batch is sorted by itself.
This batch sort is in-place and doesn't affect reservations much.
3. A cursor is created for each in-memory batch. The in-memory batches
are then fed into a merge sort.
4. The merge sort accumulates batches of data to send to the spill. Once
a batch is accumulated it is written to the spill file.

Both the cursors and the accumulation require additional space. This is
the `ExternalSorterMerge[0]` mentioned above. It is given the
overcounting described in step 1. In other words, once this starts, we
have half the reservation in `ExternalSorter[0]` and half the
reservation in `ExternalSorterMerge[0]`. This "additional space"
_should_ be about the same size as the input. This is why we count each
batch twice.

In practice, the `ExternalSorterMerge[0]` reservation ends up being
slightly higher (for various reasons). This is what the
`sort_spill_reservation_bytes` is supposed to account for. Datafusion
defaults this to 10MB. There is no guidance (and I can't get Claude to
come up with any good guidance) as to what this value should be set to.
However, 10MB seems like too little. This PR updates it to about 1/3 of
the memory pool size. In theory it shouldn't grow proportionally to the
memory pool but in practice it seems to. I also really don't want to
expose it as yet another knob that users have to tune so I'm hoping 1/3
is slightly conservative but good enough.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…under stable row ids (lance-format#7565)

## Summary

`ZONEMAP` and `BLOOMFILTER` scalar indices return silently incomplete
results (often empty) for filters on datasets created with
`enable_stable_row_ids=True`. Any value whose matching rows live in
fragments other than fragment 0 is partially or completely dropped. The
same query is correct with a `BTREE`/`BITMAP` index or with
`use_scalar_index=False`. This is a correctness bug (false negatives).

Fixes lance-format#7434.

## Root cause

Address-domain indices (zone map, bloom filter) are trained over
`_rowaddr` and their `search` returns physical row addresses
(`fragment_id << 32 | offset`). On a stable-row-id dataset a row's
stable id differs from its physical address in every fragment except
fragment 0. The filtered-scan path resolves index matches through the
fragment's stable-row-id sequence, so an address-domain result fails to
intersect and matching rows outside fragment 0 are silently dropped.
`BTREE`/`BITMAP` are trained with `_rowid`, so they are unaffected.

## Fix

Normalize address-domain results to the row-id domain at the
dataset/query layer, before they are combined or handed to the scan.

- Add `ScalarIndex::results_are_row_addresses()` (default `false`),
overridden to `true` for `ZoneMapIndex` and `BloomFilterIndex`.
- Add `ScalarIndexLoader::row_addr_result_to_row_ids()` (default
identity). `Dataset` implements it: for stable-row-id datasets it maps
each physical address to its stable row id via the per-fragment
`RowIdSequence` (zipping live physical offsets with the sequence,
skipping deleted rows); otherwise it returns the result unchanged.
- In `ScalarIndexExpr::evaluate_nullable`, translate a leaf's result
when the index is address-domain, so all downstream `AND`/`OR`/`NOT`
combination and scan consumption stay in the row-id domain. This also
handles queries that mix address-domain and row-id-domain indices.

This keeps zone map / bloom filter acceleration working under stable row
ids (no fallback to a full scan) and fixes the same latent bug in the
bloom filter index.

## Tests

- `test_address_domain_index_with_stable_row_ids[ZONEMAP|BLOOMFILTER]` —
reproduces the issue's 5-fragment non-adjacent layout and asserts the
index result equals a full scan.
- `test_zonemap_with_stable_row_ids_after_compaction` — covers deletions
+ compaction (physical address != stable id for surviving rows).
- Existing `test_scalar_index.py` (155) and the Rust zonemap/bloom unit
tests pass; `cargo fmt`, `clippy -D warnings`, and `ruff format` are
clean.

---------

Co-authored-by: Charles Huang <25107590+charleshuang119@users.noreply.github.com>
…oup (lance-format#7691)

Bumps the uv group in /python with 1 update:
[torch](https://github.com/pytorch/pytorch).

Updates `torch` from 2.12.1 to 2.13.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytorch/pytorch/releases">torch's
releases</a>.</em></p>
<blockquote>
<h1>PyTorch 2.13.0 Release Notes</h1>
<ul>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#highlights">Highlights</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#backwards-incompatible-changes">Backwards
Incompatible Changes</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#deprecations">Deprecations</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#new-features">New
Features</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#improvements">Improvements</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#bug-fixes">Bug
fixes</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#performance">Performance</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#documentation">Documentation</a></li>
<li><a
href="https://github.com/pytorch/pytorch/blob/HEAD/#developers">Developers</a></li>
</ul>
<h1>Highlights</h1>
<!-- raw HTML omitted -->
<p>For more details about these highlighted features, you can look at
the release blogpost. Below are the full release notes for this
release.</p>
<h1>Tracked Regressions</h1>
<h3>ROCm wheels break <code>torch.compile</code> on CPU in environments
without a GPU</h3>
<p>Running a <code>torch==2.13.0+rocm7.2</code> wheel in an environment
where no GPU is available (<code>torch.cuda.is_available()</code> is
<code>False</code>) breaks <code>torch.compile</code> on the CPU path:
the first compile raises <code>RuntimeError: Can't detect vectorized ISA
for CPU</code> (<a
href="https://redirect.github.com/pytorch/pytorch/issues/189194">#189194</a>).
This is a regression from <code>torch==2.12.1+rocm7.2</code>, which
compiles CPU code fine (detecting e.g. <code>VecAVX2</code>) in the same
setup. The 2.13 ROCm wheel appears to rely on something present in the
ROCm builder image to detect the CPU vectorized ISA, so it works when
run on a ROCm image but fails on a plain CPU-only image.</p>
<p>Workaround: run the <code>+rocm</code> wheel on a ROCm image, or
install a standard CPU/CUDA build for GPU-less environments.</p>
<h1>Backwards Incompatible Changes</h1>
<ul>
<li>
<p>Stop building CPython 3.13t (free-threaded) binaries (<a
href="https://redirect.github.com/pytorch/pytorch/issues/182951">#182951</a>)</p>
<p>Upstream <code>pypa/manylinux</code> removed CPython 3.13t
(free-threaded) on 2026-05-07, because 3.13t
was experimental and has been superseded by the now-non-experimental
CPython 3.14t. As a result,
PyTorch 2.13 no longer ships <code>cp313t</code> wheels (Linux, Triton,
and related artifacts). Users on the
free-threaded interpreter should move to Python 3.14t.</p>
<p>PyTorch 2.12:</p>
<pre lang="bash"><code># cp313t (free-threaded 3.13) wheels were
available
python3.13t -m pip install torch
</code></pre>
<p>PyTorch 2.13:</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytorch/pytorch/commit/cf30153c4c131c8164ee7798e5022d810682e2cb"><code>cf30153</code></a>
[release/2.13] Strip +PTX from CUDA arch list on release/RC builds (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188914">#188914</a>)
...</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/3e3e24bd95b010f8f74915f0c30476906e60d4fc"><code>3e3e24b</code></a>
[release/2.13] Restrict cuda-bindings to Python &lt; 3.15 for CUDA 12.9
builds (...</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/7986b068032abf5e22ea51fe7fea63ef5bcaf3b1"><code>7986b06</code></a>
[release/2.13] Bump binary build timeout 280 -&gt; 400 minutes (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188551">#188551</a>)</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/0bdbc268e08fba9debac8f35a8a12e9c008ec0fd"><code>0bdbc26</code></a>
[release/2.13] Add CUDA 12.9 to TORCH_CUDA_ARCH_LIST tables (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188443">#188443</a>)</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/9cabb45ca6e6ed3bb4645c929bcfd07691651f74"><code>9cabb45</code></a>
[release/2.13] Update manywheel docker image pin to 78e737ad (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188409">#188409</a>)</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/78e737ad29420ffc4800e677c51e2a852caf8359"><code>78e737a</code></a>
[release/2.13] Revert &quot;Tighten generalized scatter graph target (<a
href="https://redirect.github.com/pytorch/pytorch/issues/184075">#184075</a>)&quot;
(#...</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/0bb9b5bc24bed3278488372d62d9f2235e9e77e3"><code>0bb9b5b</code></a>
[release/2.13] Revert &quot;dynamo: round-trip torch.cuda.stream ctx mgr
across gr...</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/aaac2bfe460c04a4d41e83e03452d2347f7142b9"><code>aaac2bf</code></a>
[release/2.13] Revert &quot;[Reland] Port D104346887/PR 182675 for
index_add fast ...</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/933081368c3ab64fa2e953217e413b3ba52844e3"><code>9330813</code></a>
Fix build_with_debinfo.py broken by CONFIGURE_DEPENDS globbing (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188192">#188192</a>)</li>
<li><a
href="https://github.com/pytorch/pytorch/commit/4e077a7dcf29167db9e97d86cc62f431905e09f7"><code>4e077a7</code></a>
Remove setuptools upper bound (<a
href="https://redirect.github.com/pytorch/pytorch/issues/188190">#188190</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytorch/pytorch/compare/v2.12.1...v2.13.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=torch&package-manager=uv&previous-version=2.12.1&new-version=2.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the cargo group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [bytes](https://github.com/tokio-rs/bytes) | `1.12.0` | `1.12.1` |
| [crossbeam-queue](https://github.com/crossbeam-rs/crossbeam) |
`0.3.12` | `0.3.13` |
| [humantime](https://github.com/chronotope/humantime) | `2.3.0` |
`2.4.0` |
| [jieba-rs](https://github.com/messense/jieba-rs) | `0.10.1` | `0.10.2`
|
| [rustc-hash](https://github.com/rust-lang/rustc-hash) | `2.1.2` |
`2.1.3` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.65` | `1.2.66` |
| [sha2](https://github.com/RustCrypto/hashes) | `0.10.9` | `0.11.0` |
| [hmac](https://github.com/RustCrypto/MACs) | `0.12.1` | `0.13.0` |
| [quick-xml](https://github.com/tafia/quick-xml) | `0.38.4` | `0.40.1`
|

Updates `bytes` from 1.12.0 to 1.12.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/releases">bytes's
releases</a>.</em></p>
<blockquote>
<h2>Bytes v1.12.1</h2>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's
changelog</a>.</em></p>
<blockquote>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/bytes/commit/76c0fbb54ed4336caf9d2311658a2f4a5627c21d"><code>76c0fbb</code></a>
Release bytes v1.12.1 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/838">#838</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/924c82bf0053cb13a0fb5165925d564622b2092f"><code>924c82b</code></a>
Handle unwinding from Box::new (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
<li>See full diff in <a
href="https://github.com/tokio-rs/bytes/compare/v1.12.0...v1.12.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `crossbeam-queue` from 0.3.12 to 0.3.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crossbeam-rs/crossbeam/releases">crossbeam-queue's
releases</a>.</em></p>
<blockquote>
<h2>crossbeam-queue 0.3.13</h2>
<ul>
<li>Add <code>push_mut</code> and <code>pop_mut</code> to
<code>ArrayQueue</code> and <code>SegQueue</code>. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1191">#1191</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/9b56303b8aa9ff8ec5bbebb9d2da05e034977889"><code>9b56303</code></a>
Prepare for the next release</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/a078b17b7319ab49e53720ebeed8fa8a539a8e18"><code>a078b17</code></a>
ci: Sync config with main</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/508c29d3c27d7e27791244644dae2169a2f1678a"><code>508c29d</code></a>
Remove crossbeam-skiplist which is not published from this branch from
worksp...</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/6a20e57c492da6ba327b587bc5f38c7a4a3067ef"><code>6a20e57</code></a>
tests: Fix mismatched_lifetime_syntaxes</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c2d674f88af9501a0a939d8d4b0d52bdbc453ef9"><code>c2d674f</code></a>
epoch: Fix rustdoc::invalid_rust_codeblocks</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/bd6563e2118a5f2e9eec0f9e16006d428b82ffb0"><code>bd6563e</code></a>
Update no_atomic.rs</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/d3e1e364093763a40affe7ea3ff8368c7dc25ee9"><code>d3e1e36</code></a>
Make CachePadded&lt;T&gt; have C repr to allow casting to and from T (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1270">#1270</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c0c466e5c3b5f177884e1df5f8f2c8c939c31aab"><code>c0c466e</code></a>
channel: Use non-poison Mutex</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/8b3940f1063f2e0795e44d3f5dde973f08e2a50b"><code>8b3940f</code></a>
Add missing word to docs (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1208">#1208</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/df6eec0610f91de504a5834c9faa0de40e3aec83"><code>df6eec0</code></a>
docs: Link <code>select_biased!</code> from <code>select!</code> macro
(<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1202">#1202</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-queue-0.3.12...crossbeam-queue-0.3.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `humantime` from 2.3.0 to 2.4.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/chronotope/humantime/releases">humantime's
releases</a>.</em></p>
<blockquote>
<h2>2.4.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat: allow creating Duration in const context by <a
href="https://github.com/ctron"><code>@​ctron</code></a> in <a
href="https://redirect.github.com/chronotope/humantime/pull/70">chronotope/humantime#70</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/chronotope/humantime/commit/fc092817fa8689298eaac28ff49bd8bede4ff605"><code>fc09281</code></a>
chore: prepare release 2.4.0</li>
<li><a
href="https://github.com/chronotope/humantime/commit/8a022cce55a07da2be81721e7deaa5bd071add72"><code>8a022cc</code></a>
feat: allow creating Duration in const context</li>
<li><a
href="https://github.com/chronotope/humantime/commit/27a4f77519a436f4137d1c50ff2f3eb559292cfd"><code>27a4f77</code></a>
Explicitly set rust-version to 1.60</li>
<li><a
href="https://github.com/chronotope/humantime/commit/acc3c19658ecae06cf35467dfe03392a67dbf2b1"><code>acc3c19</code></a>
ci: upgrade to actions/checkout v7</li>
<li><a
href="https://github.com/chronotope/humantime/commit/3acf96bb886ebd16f9e2e8a37d7229e4bd30dd17"><code>3acf96b</code></a>
ci: fix workflow formatting</li>
<li>See full diff in <a
href="https://github.com/chronotope/humantime/compare/v2.3.0...v2.4.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `jieba-rs` from 0.10.1 to 0.10.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/messense/jieba-rs/releases">jieba-rs's
releases</a>.</em></p>
<blockquote>
<h2>v0.10.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Optimize jieba hot paths by <a
href="https://github.com/messense"><code>@​messense</code></a> in <a
href="https://redirect.github.com/messense/jieba-rs/pull/152">messense/jieba-rs#152</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2">https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/messense/jieba-rs/commit/c4acc5e63b4a9c17900bf6cf69afcbeb0dc6861f"><code>c4acc5e</code></a>
Bump version to 0.10.2</li>
<li><a
href="https://github.com/messense/jieba-rs/commit/c83a93c6a8242de680d84a9baa30665e05084852"><code>c83a93c</code></a>
Optimize jieba hot paths (<a
href="https://redirect.github.com/messense/jieba-rs/issues/152">#152</a>)</li>
<li><a
href="https://github.com/messense/jieba-rs/commit/1e77e50d0f1d62a545c535b8e2d2e00348c39e11"><code>1e77e50</code></a>
capi publish = false</li>
<li>See full diff in <a
href="https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `rustc-hash` from 2.1.2 to 2.1.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/rustc-hash/blob/main/CHANGELOG.md">rustc-hash's
changelog</a>.</em></p>
<blockquote>
<h1>2.1.3</h1>
<ul>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/77">Use
derive_const to fix <code>feature = &quot;nightly&quot;</code>
build</a></li>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/64">Internally
update to rand 0.9</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c13e7ccca705e6255387a2ebc6dca142d6881621"><code>c13e7cc</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/78">#78</a>
from Noratrieb/new-version-2-1-3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/4c3fabd983f96c2c5178512940e29a050edd07e9"><code>4c3fabd</code></a>
Bump to 2.1.3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/3f1c0994892f5c592fe17192811c3b46caa108ac"><code>3f1c099</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/64">#64</a>
from DaniPopes/rand-0.9</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/07c3f48480b2d1a143fe299f5a82812b311efea6"><code>07c3f48</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/77">#77</a>
from DaniPopes/const-update</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/cbf0baf6f900674cf88f266f96a4fa223895186b"><code>cbf0baf</code></a>
Use derive_const in nightly feature</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c74d2b3bb92563dbd32a9d7e6343af02d99dff25"><code>c74d2b3</code></a>
Update to rand 0.9</li>
<li>See full diff in <a
href="https://github.com/rust-lang/rustc-hash/compare/v2.1.2...v2.1.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `cc` from 1.2.65 to 1.2.66
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/releases">cc's
releases</a>.</em></p>
<blockquote>
<h2>cc-v1.2.66</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md">cc's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">1.2.66</a>
- 2026-07-05</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/9c53ddc649838c60f8b33aee77dbfec5f04c16dc"><code>9c53ddc</code></a>
chore(cc): release v1.2.66 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1777">#1777</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/f2836c0fc57c44ca833d0f3e822f94f523a00a6e"><code>f2836c0</code></a>
Fix target parsing (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1779">#1779</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/32996914ec656e0d37775571545029d31afd9df2"><code>3299691</code></a>
ci(test-wasm): do not download pre release of wasi-sdk (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1778">#1778</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/bfd1ac98d4d52e941fc71f844af8fc70e152dd5e"><code>bfd1ac9</code></a>
Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1775">#1775</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/1887a73fddabc77f7def580feefbcfbdba10ed1d"><code>1887a73</code></a>
Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1770">#1770</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/e4847e1720197e42d1d80934879e48188777335f"><code>e4847e1</code></a>
Bump actions/checkout from 6.0.3 to 7.0.0 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1767">#1767</a>)</li>
<li>See full diff in <a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">compare
view</a></li>
</ul>
</details>
<br />

Updates `sha2` from 0.10.9 to 0.11.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/RustCrypto/hashes/commit/ffe093984c004769747e998f77da8ff7c0e7a765"><code>ffe0939</code></a>
Release sha2 0.11.0 (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/806">#806</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/8991b65fe400c31c4cc189510f86ae642c470cd9"><code>8991b65</code></a>
Use the standard order of the <code>[package]</code> section fields (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/807">#807</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/3d2bc57db40fd6aeb25d6c6da98d67e2784c2985"><code>3d2bc57</code></a>
sha2: refactor backends (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/802">#802</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/faa55fb83697c8f3113636d88070e5f5edc8c335"><code>faa55fb</code></a>
sha3: bump <code>keccak</code> to v0.2 (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/803">#803</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/d3e6489e56f8486d4a93ceb7a8abf4924af1de7b"><code>d3e6489</code></a>
sha3 v0.11.0-rc.9 (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/801">#801</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/bbf6f51ff97f81ab15e6e5f6cf878bfbcb1f47c8"><code>bbf6f51</code></a>
sha2: tweak backend docs (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/800">#800</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/155dbbf2959dbec0ec75948a82590ddaede2d3bc"><code>155dbbf</code></a>
sha3: add default value for the <code>DS</code> generic parameter on
<code>TurboShake128/256</code>...</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/ed514f2b34526683b3b7c41670f1887982c3df64"><code>ed514f2</code></a>
Use published version of <code>keccak</code> v0.2 (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/799">#799</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/702bcd83735a49c928c0fc24506924f5c0aa22af"><code>702bcd8</code></a>
Migrate to closure-based <code>keccak</code> (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/796">#796</a>)</li>
<li><a
href="https://github.com/RustCrypto/hashes/commit/827c043f82d57666a0b146d156e91c39535c1305"><code>827c043</code></a>
sha3 v0.11.0-rc.8 (<a
href="https://redirect.github.com/RustCrypto/hashes/issues/794">#794</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/RustCrypto/hashes/compare/sha2-v0.10.9...sha2-v0.11.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `hmac` from 0.12.1 to 0.13.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/RustCrypto/MACs/commit/0236c8eb50098dd7f277a71ab89caaeb1e7314df"><code>0236c8e</code></a>
hmac v0.13.0 (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/263">#263</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/b895e50c852f58727b2fa6a480c4ec68cf99025f"><code>b895e50</code></a>
Migrate tests to the new blobby format (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/264">#264</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/3d1440b379457f680c58bc1ec0e2f8714a72df7e"><code>3d1440b</code></a>
Workspace-level lint configuration (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/261">#261</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/11d4f3624f3dfe95d57cfb8a3173d7071eb5a1b3"><code>11d4f36</code></a>
hmac: use release versions of <code>dev-dependencies</code> (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/260">#260</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/c40b82b2ac40bc0260d0c35d6a518f97e72411e5"><code>c40b82b</code></a>
hmac: bump <code>sha2</code> dev-dependency to v0.11 (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/259">#259</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/1fa0781413e3d07d18a9bb622f096754640dee53"><code>1fa0781</code></a>
Cut rc.5 prereleases (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/258">#258</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/a0082655c09ffe682a10640cbaefb67c8175010e"><code>a008265</code></a>
hmac v0.13.0-rc.6 (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/256">#256</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/da485cd7baf0b7f5e501f5b42644bf9ddd428c6b"><code>da485cd</code></a>
Use <code>(Reset)MacTraits</code> (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/254">#254</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/2c51e3b76e6f50c13d85577c3faac7df66e24306"><code>2c51e3b</code></a>
hmac: derive <code>Clone</code> instead of relying on
<code>(Reset)MacTraits</code> (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/253">#253</a>)</li>
<li><a
href="https://github.com/RustCrypto/MACs/commit/669d805394f5f4d0dc07ded010c0df9a3ab01629"><code>669d805</code></a>
Relax <code>Clone</code> bounds (<a
href="https://redirect.github.com/RustCrypto/MACs/issues/250">#250</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/RustCrypto/MACs/compare/hmac-v0.12.1...hmac-v0.13.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `quick-xml` from 0.38.4 to 0.40.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tafia/quick-xml/releases">quick-xml's
releases</a>.</em></p>
<blockquote>
<h2>v0.40.1 - Fix rarely possible serde deserialization panic</h2>
<h2>What's Changed</h2>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>:
Fix <code>unreachable!()</code> panic in the serde deserializer when a
DOCTYPE declaration appears between two text runs inside an element
(e.g. <code>&lt;a&gt;x&lt;!DOCTYPE y&gt;z&lt;/a&gt;</code>). The DOCTYPE
used to break <code>drain_text</code>'s consecutive-text merge, so two
<code>DeEvent::Text</code> events reached <code>read_text</code> and
tripped its &quot;Cannot be two consequent Text events&quot; invariant.
DOCTYPE is now treated as transparent during text drain — it still goes
through the entity resolver, but the surrounding text is merged into one
run. Discovered via libFuzzer on a real-world SAML deserializer
harness.</li>
</ul>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>:
<a
href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></p>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/williamareynolds"><code>@​williamareynolds</code></a>
made their first contribution in <a
href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/tafia/quick-xml/compare/v0.40.0...v0.40.1">https://github.com/tafia/quick-xml/compare/v0.40.0...v0.40.1</a></p>
<h2>v0.40.0 - UTF-16 and ISO-2022-JP encodings supported</h2>
<h2>What's Changed</h2>
<p>MSRV bumped to 1.79.</p>
<p>Now <code>quick-xml</code> supports the UTF-16 and ISO-2022-JP
encoded documents. See the new <code>DecodingReader</code> type.</p>
<h3>New Features</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/956">#956</a>:
Add <code>DecodingReader</code>, a <code>BufRead</code> adapter that
auto-detects encoding from BOM or XML declaration and transcodes to
UTF-8. Enabled by the <code>encoding</code> feature.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Add new enumeration <code>XmlVersion</code> and typified getter
<code>BytesDecl::xml_version()</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Add new error variant <code>IllFormedError::UnknownVersion</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>:
Add new error variant
<code>EscapeError::TooManyNestedEntities</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>:
Improved compliance with the XML attribute value normalization process
by adding</p>
<ul>
<li><code>Attribute::normalized_value()</code></li>
<li><code>Attribute::normalized_value_with()</code></li>
<li><code>Attribute::decoded_and_normalized_value()</code></li>
<li><code>Attribute::decoded_and_normalized_value_with()</code></li>
</ul>
<p>which ought to be used in place of deprecated</p>
<ul>
<li><code>Attribute::unescape_value()</code></li>
<li><code>Attribute::unescape_value_with()</code></li>
<li><code>Attribute::decode_and_unescape_value()</code></li>
<li><code>Attribute::decode_and_unescape_value_with()</code></li>
</ul>
<p>Deprecated functions now behaves the same as newly added.</p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Use correct rules for EOL normalization in <code>Deserializer</code>
when parse XML 1.0 documents. Previously XML 1.1. rules was
applied.</li>
</ul>
<h3>Misc Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/914">#914</a>:
Remove deprecated <code>.prefixes()</code>, <code>.resolve()</code>,
<code>.resolve_attribute()</code>, and <code>.resolve_element()</code>
of <code>NsReader</code>. Use <code>.resolver().&lt;...&gt;</code>
methods instead.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Now <code>BytesText::xml_content</code>,
<code>BytesCData::xml_content</code> and
<code>BytesRef::xml_content</code> accepts <code>XmlVersion</code>
parameter to apply correct EOL normalization rules.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/944">#944</a>:
<code>read_text()</code> now returns <code>BytesText</code> which allows
you to get the content with properly normalized EOLs. To get the
previous behavior use <code>.read_text().decode()?</code>.</li>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/956">#956</a>:
Bumped MSRV from 1.59 (Feb 2022) to 1.79 (June 2024)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tafia/quick-xml/blob/master/Changelog.md">quick-xml's
changelog</a>.</em></p>
<blockquote>
<h2>0.40.1 -- 2026-05-15</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>:
Fix <code>unreachable!()</code> panic in the serde deserializer when a
DOCTYPE
declaration appears between two text runs inside an element (e.g.
<code>&lt;a&gt;x&lt;!DOCTYPE y&gt;z&lt;/a&gt;</code>). The DOCTYPE used
to break <code>drain_text</code>'s
consecutive-text merge, so two <code>DeEvent::Text</code> events reached
<code>read_text</code> and tripped its &quot;Cannot be two consequent
Text events&quot;
invariant. DOCTYPE is now treated as transparent during text drain —
it still goes through the entity resolver, but the surrounding text
is merged into one run. Discovered via libFuzzer on a real-world
SAML deserializer harness.</li>
</ul>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>:
<a
href="https://redirect.github.com/tafia/quick-xml/pull/964">tafia/quick-xml#964</a></p>
<h3>Misc Changes</h3>
<h2>0.40.0 -- 2026-05-11</h2>
<p>MSRV bumped to 1.79.</p>
<p>Now <code>quick-xml</code> supports the UTF-16 encoded documents. See
the new <code>DecodingReader</code> type.</p>
<h3>New Features</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/956">#956</a>:
Add <code>DecodingReader</code>, a <code>BufRead</code> adapter that
auto-detects encoding
from BOM or XML declaration and transcodes to UTF-8. Enabled by the
<code>encoding</code> feature.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Add new enumeration <code>XmlVersion</code> and typified getter
<code>BytesDecl::xml_version()</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Add new error variant <code>IllFormedError::UnknownVersion</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>:
Add new error variant
<code>EscapeError::TooManyNestedEntities</code>.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/tafia/quick-xml/issues/371">#371</a>:
Improved compliance with the XML attribute value normalization process
by adding</p>
<ul>
<li><code>Attribute::normalized_value()</code></li>
<li><code>Attribute::normalized_value_with()</code></li>
<li><code>Attribute::decoded_and_normalized_value()</code></li>
<li><code>Attribute::decoded_and_normalized_value_with()</code></li>
</ul>
<p>which ought to be used in place of deprecated</p>
<ul>
<li><code>Attribute::unescape_value()</code></li>
<li><code>Attribute::unescape_value_with()</code></li>
<li><code>Attribute::decode_and_unescape_value()</code></li>
<li><code>Attribute::decode_and_unescape_value_with()</code></li>
</ul>
<p>Deprecated functions now behaves the same as newly added.</p>
</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/tafia/quick-xml/issues/938">#938</a>:
Use correct rules for EOL normalization in <code>Deserializer</code>
when parse XML 1.0 documents.
Previously XML 1.1. rules was applied.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tafia/quick-xml/commit/9aaea9281d346ec0249c679639a15eef8f9cbb18"><code>9aaea92</code></a>
Release 0.40.1</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/ce488bca4e85427e5ab431e7c9e6f15b9ed73135"><code>ce488bc</code></a>
Merge pull request <a
href="https://redirect.github.com/tafia/quick-xml/issues/964">#964</a>
from williamareynolds/fix/de-doctype-in-text-unreachable</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/e00ae5c749155ee3001bd4629a12282011a0fdfb"><code>e00ae5c</code></a>
Fix unreachable!() panic when DOCTYPE appears between text runs in
element co...</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/2778564d592ca25d6315ea20b5105c74addfce5e"><code>2778564</code></a>
Release 0.40.0</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/393db036811e7473b22d875109cd07acb183580f"><code>393db03</code></a>
Merge pull request <a
href="https://redirect.github.com/tafia/quick-xml/issues/962">#962</a>
from Mingun/prepare-0.40</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/a27709a457126f129b06d20309316be74056234c"><code>a27709a</code></a>
Fix misprint in code example</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/0c0c914bc753075abdab92dcd94fc95c6a195b25"><code>0c0c914</code></a>
Make some functions const and enable clippy::missing_const_for_fn
lint</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/bf4ffe5020cbe256c441c2cd26adf8716f6e5324"><code>bf4ffe5</code></a>
Fix clippy warning: use <code>.first()</code> instead of
<code>.get(0)</code></li>
<li><a
href="https://github.com/tafia/quick-xml/commit/d69baad385aeb489d4761469cc9738c21aa41c4f"><code>d69baad</code></a>
Fix clippy warning: remove unnecessary after
241f01e20ff679e9248f2ae424c9ba82...</li>
<li><a
href="https://github.com/tafia/quick-xml/commit/8e0ae4f7f4f2d0dda9f000f094bdf9b8e2b915a5"><code>8e0ae4f</code></a>
Fix clippy warning: use <code>strip_prefix</code> instead of manual
stripping</li>
<li>Additional commits viewable in <a
href="https://github.com/tafia/quick-xml/compare/v0.38.4...v0.40.1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Will Jones <willjones127@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rmat#7693)

Bumps the cargo group in /python with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [bytes](https://github.com/tokio-rs/bytes) | `1.12.0` | `1.12.1` |
| [crossbeam-queue](https://github.com/crossbeam-rs/crossbeam) |
`0.3.12` | `0.3.13` |
| [humantime](https://github.com/chronotope/humantime) | `2.3.0` |
`2.4.0` |
| [jieba-rs](https://github.com/messense/jieba-rs) | `0.10.1` | `0.10.2`
|
| [rustc-hash](https://github.com/rust-lang/rustc-hash) | `2.1.2` |
`2.1.3` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.65` | `1.2.66` |

Updates `bytes` from 1.12.0 to 1.12.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/releases">bytes's
releases</a>.</em></p>
<blockquote>
<h2>Bytes v1.12.1</h2>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's
changelog</a>.</em></p>
<blockquote>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/bytes/commit/76c0fbb54ed4336caf9d2311658a2f4a5627c21d"><code>76c0fbb</code></a>
Release bytes v1.12.1 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/838">#838</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/924c82bf0053cb13a0fb5165925d564622b2092f"><code>924c82b</code></a>
Handle unwinding from Box::new (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
<li>See full diff in <a
href="https://github.com/tokio-rs/bytes/compare/v1.12.0...v1.12.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `crossbeam-queue` from 0.3.12 to 0.3.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crossbeam-rs/crossbeam/releases">crossbeam-queue's
releases</a>.</em></p>
<blockquote>
<h2>crossbeam-queue 0.3.13</h2>
<ul>
<li>Add <code>push_mut</code> and <code>pop_mut</code> to
<code>ArrayQueue</code> and <code>SegQueue</code>. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1191">#1191</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/9b56303b8aa9ff8ec5bbebb9d2da05e034977889"><code>9b56303</code></a>
Prepare for the next release</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/a078b17b7319ab49e53720ebeed8fa8a539a8e18"><code>a078b17</code></a>
ci: Sync config with main</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/508c29d3c27d7e27791244644dae2169a2f1678a"><code>508c29d</code></a>
Remove crossbeam-skiplist which is not published from this branch from
worksp...</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/6a20e57c492da6ba327b587bc5f38c7a4a3067ef"><code>6a20e57</code></a>
tests: Fix mismatched_lifetime_syntaxes</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c2d674f88af9501a0a939d8d4b0d52bdbc453ef9"><code>c2d674f</code></a>
epoch: Fix rustdoc::invalid_rust_codeblocks</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/bd6563e2118a5f2e9eec0f9e16006d428b82ffb0"><code>bd6563e</code></a>
Update no_atomic.rs</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/d3e1e364093763a40affe7ea3ff8368c7dc25ee9"><code>d3e1e36</code></a>
Make CachePadded&lt;T&gt; have C repr to allow casting to and from T (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1270">#1270</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c0c466e5c3b5f177884e1df5f8f2c8c939c31aab"><code>c0c466e</code></a>
channel: Use non-poison Mutex</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/8b3940f1063f2e0795e44d3f5dde973f08e2a50b"><code>8b3940f</code></a>
Add missing word to docs (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1208">#1208</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/df6eec0610f91de504a5834c9faa0de40e3aec83"><code>df6eec0</code></a>
docs: Link <code>select_biased!</code> from <code>select!</code> macro
(<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1202">#1202</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-queue-0.3.12...crossbeam-queue-0.3.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `humantime` from 2.3.0 to 2.4.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/chronotope/humantime/releases">humantime's
releases</a>.</em></p>
<blockquote>
<h2>2.4.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat: allow creating Duration in const context by <a
href="https://github.com/ctron"><code>@​ctron</code></a> in <a
href="https://redirect.github.com/chronotope/humantime/pull/70">chronotope/humantime#70</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/chronotope/humantime/commit/fc092817fa8689298eaac28ff49bd8bede4ff605"><code>fc09281</code></a>
chore: prepare release 2.4.0</li>
<li><a
href="https://github.com/chronotope/humantime/commit/8a022cce55a07da2be81721e7deaa5bd071add72"><code>8a022cc</code></a>
feat: allow creating Duration in const context</li>
<li><a
href="https://github.com/chronotope/humantime/commit/27a4f77519a436f4137d1c50ff2f3eb559292cfd"><code>27a4f77</code></a>
Explicitly set rust-version to 1.60</li>
<li><a
href="https://github.com/chronotope/humantime/commit/acc3c19658ecae06cf35467dfe03392a67dbf2b1"><code>acc3c19</code></a>
ci: upgrade to actions/checkout v7</li>
<li><a
href="https://github.com/chronotope/humantime/commit/3acf96bb886ebd16f9e2e8a37d7229e4bd30dd17"><code>3acf96b</code></a>
ci: fix workflow formatting</li>
<li>See full diff in <a
href="https://github.com/chronotope/humantime/compare/v2.3.0...v2.4.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `jieba-rs` from 0.10.1 to 0.10.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/messense/jieba-rs/releases">jieba-rs's
releases</a>.</em></p>
<blockquote>
<h2>v0.10.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Optimize jieba hot paths by <a
href="https://github.com/messense"><code>@​messense</code></a> in <a
href="https://redirect.github.com/messense/jieba-rs/pull/152">messense/jieba-rs#152</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2">https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/messense/jieba-rs/commit/c4acc5e63b4a9c17900bf6cf69afcbeb0dc6861f"><code>c4acc5e</code></a>
Bump version to 0.10.2</li>
<li><a
href="https://github.com/messense/jieba-rs/commit/c83a93c6a8242de680d84a9baa30665e05084852"><code>c83a93c</code></a>
Optimize jieba hot paths (<a
href="https://redirect.github.com/messense/jieba-rs/issues/152">#152</a>)</li>
<li><a
href="https://github.com/messense/jieba-rs/commit/1e77e50d0f1d62a545c535b8e2d2e00348c39e11"><code>1e77e50</code></a>
capi publish = false</li>
<li>See full diff in <a
href="https://github.com/messense/jieba-rs/compare/v0.10.1...v0.10.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `rustc-hash` from 2.1.2 to 2.1.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/rustc-hash/blob/main/CHANGELOG.md">rustc-hash's
changelog</a>.</em></p>
<blockquote>
<h1>2.1.3</h1>
<ul>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/77">Use
derive_const to fix <code>feature = &quot;nightly&quot;</code>
build</a></li>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/64">Internally
update to rand 0.9</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c13e7ccca705e6255387a2ebc6dca142d6881621"><code>c13e7cc</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/78">#78</a>
from Noratrieb/new-version-2-1-3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/4c3fabd983f96c2c5178512940e29a050edd07e9"><code>4c3fabd</code></a>
Bump to 2.1.3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/3f1c0994892f5c592fe17192811c3b46caa108ac"><code>3f1c099</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/64">#64</a>
from DaniPopes/rand-0.9</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/07c3f48480b2d1a143fe299f5a82812b311efea6"><code>07c3f48</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/77">#77</a>
from DaniPopes/const-update</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/cbf0baf6f900674cf88f266f96a4fa223895186b"><code>cbf0baf</code></a>
Use derive_const in nightly feature</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c74d2b3bb92563dbd32a9d7e6343af02d99dff25"><code>c74d2b3</code></a>
Update to rand 0.9</li>
<li>See full diff in <a
href="https://github.com/rust-lang/rustc-hash/compare/v2.1.2...v2.1.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `cc` from 1.2.65 to 1.2.66
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/releases">cc's
releases</a>.</em></p>
<blockquote>
<h2>cc-v1.2.66</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md">cc's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">1.2.66</a>
- 2026-07-05</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/9c53ddc649838c60f8b33aee77dbfec5f04c16dc"><code>9c53ddc</code></a>
chore(cc): release v1.2.66 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1777">#1777</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/f2836c0fc57c44ca833d0f3e822f94f523a00a6e"><code>f2836c0</code></a>
Fix target parsing (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1779">#1779</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/32996914ec656e0d37775571545029d31afd9df2"><code>3299691</code></a>
ci(test-wasm): do not download pre release of wasi-sdk (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1778">#1778</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/bfd1ac98d4d52e941fc71f844af8fc70e152dd5e"><code>bfd1ac9</code></a>
Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1775">#1775</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/1887a73fddabc77f7def580feefbcfbdba10ed1d"><code>1887a73</code></a>
Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1770">#1770</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/e4847e1720197e42d1d80934879e48188777335f"><code>e4847e1</code></a>
Bump actions/checkout from 6.0.3 to 7.0.0 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1767">#1767</a>)</li>
<li>See full diff in <a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Will Jones <willjones127@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ance-format#7692)

Bumps the cargo group in /java/lance-jni with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [jni](https://github.com/jni-rs/jni-rs) | `0.21.1` | `0.22.4` |
| [bytes](https://github.com/tokio-rs/bytes) | `1.12.0` | `1.12.1` |
| [crossbeam-queue](https://github.com/crossbeam-rs/crossbeam) |
`0.3.12` | `0.3.13` |
| [rustc-hash](https://github.com/rust-lang/rustc-hash) | `2.1.2` |
`2.1.3` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.65` | `1.2.66` |

Updates `jni` from 0.21.1 to 0.22.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jni-rs/jni-rs/releases">jni's
releases</a>.</em></p>
<blockquote>
<h2>Release JNI 0.22.4</h2>
<h3>Added</h3>
<ul>
<li><code>JCharSequence</code> bindings for
<code>java.lang.CharSequence</code> (including
<code>AsRef&lt;JCharSequence&gt;</code> +
<code>.as_char_sequence()</code> for <code>JString</code>) (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/793">#793</a>)</li>
<li><code>bind_java_type</code> supports <code>non_null</code>
qualifier/property for methods and fields to map null references to
<code>Error::NullPtr</code> (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/795">#795</a>)</li>
<li><code>bind_java_type</code> supports <code>#[cfg()]</code>
attributes on methods and fields, to conditionally compile them based on
features or other cfg conditions (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/795">#797</a>)</li>
<li><code>JValueOwned::check_null()</code> + <code>::is_null()</code>
methods for ergonomic null checks on owned (returned) values (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/798">#798</a>)</li>
<li>More readable type accessors for <code>JValueOwned</code>, like
<code>.into_bool()</code> instead of <code>.z()</code>,
<code>.into_object()</code> instead of <code>.l()</code>, etc (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/798">#798</a>)</li>
</ul>
<h4>Fixed</h4>
<ul>
<li><code>jni_mangle</code> now includes
<code>docs/macros/jni_mangle.md</code> in the crate documentation, so
the macro's documentation is visible on docs.rs and in IDEs (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/799">#799</a>)</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jni-rs/jni-rs/compare/v0.22.3...v0.22.4">https://github.com/jni-rs/jni-rs/compare/v0.22.3...v0.22.4</a></p>
<h2>Release JNI 0.22.3</h2>
<p>No functional change in this release but it fixes the <a
href="https://docs.rs/jni/latest/jni/">docs.rs</a> build by bumping the
<code>simd_cesu8</code> dep to &gt;= 1.1.1 which no longer has an
automatically-enabled &quot;nightly&quot; feature that may affect the
docs.rs build (1.1.x is now also MSRV compatible).</p>
<p><em>Note: Technically we shouldn't need this release (since the
<code>simd_cesu8</code> release alone will have fixed the build issue)
but the other reason for the release is that the crates.io feature for
queuing docs.rs rebuilds is not currently usable in our situation.
docs.rs is currently fighting through a <a
href="https://docs.rs/releases/queue">huge backlog</a> of low-priority
build jobs that will likely to take over a week to clear (we moved about
500 spots in two days, out of ~3k crates queued).</em></p>
<h2>Release JNI 0.22.2</h2>
<p><em><em>Note</em>: although no breaking API change was made in this
release there were some important fixes made, including a few
non-trivial changes to how exceptions are handled and some important
safety / soundness fixes made in the re-exported
<code>jni-macros</code>.</em></p>
<p><em>For these reasons I'm going to <em>again</em> yank the previous
0.22.1 release after this is published, again taking into account that
0.22.1 was itself only released very recently and it should still be
relatively unlikely that anyone has strictly locked in a 0.22.1
dependency.</em></p>
<p><em>Another benefit to yanking 0.22.1 is that it allows me to pin the
<code>jni-macros</code> dependency via <code>=0.22.2</code> in this
release so that in future releases I don't need to be worried that a new
<code>jni-macros</code> release needs to be backwards compatible with
all prior <code>jni</code> releases (so macros can take advantage of new
<code>jni</code> features).</em></p>
<p><em>Hopefully things will be smoother moving forward, now that more
people have been starting to update to 0.22.x and there are more people
testing it.</em></p>
<h3>Added</h3>
<p>Adds bindings for the following <code>java.lang</code> errors /
exceptions (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/767">#767</a>):</p>
<ul>
<li><code>JArrayIndexOutOfBoundsException</code>
(<code>java.lang.ArrayIndexOutOfBoundsException</code>)</li>
<li><code>JArrayStoreException</code>
(<code>java.lang.ArrayStoreException</code>)</li>
<li><code>JClassCircularityError</code>
(<code>java.lang.ClassCircularityError</code>)</li>
<li><code>JClassFormatError</code>
(<code>java.lang.ClassFormatError</code>)</li>
<li><code>JExceptionInInitializerError</code>
(<code>java.lang.ExceptionInInitializerError</code>)</li>
<li><code>JClassNotFoundException</code>
(<code>java.lang.ClassNotFoundException</code>)</li>
<li><code>JIllegalArgumentException</code>
(<code>java.lang.IllegalArgumentException</code>)</li>
<li><code>JIllegalMonitorStateException</code>
(<code>java.lang.IllegalMonitorStateException</code>)</li>
<li><code>JInstantiationException</code>
(<code>java.lang.InstantiationException</code>)</li>
<li><code>JLinkageError</code>
(<code>java.lang.LinkageError</code>)</li>
<li><code>JNoClassDefFoundError</code>
(<code>java.lang.NoClassDefFoundError</code>)</li>
<li><code>JNoSuchFieldError</code>
(<code>java.lang.NoSuchFieldError</code>)</li>
<li><code>JNoSuchMethodError</code>
(<code>java.lang.NoSuchMethodError</code>)</li>
<li><code>JNumberFormatException</code>
(<code>java.lang.NumberFormatException</code>)</li>
<li><code>JOutOfMemoryError</code>
(<code>java.lang.OutOfMemoryError</code>)</li>
<li><code>JRuntimeException</code>
(<code>java.lang.RuntimeException</code>)</li>
<li><code>JSecurityException</code>
(<code>java.lang.SecurityException</code>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jni-rs/jni-rs/blob/master/CHANGELOG.md">jni's
changelog</a>.</em></p>
<blockquote>
<h2>[0.22.4] — 2026-03-16</h2>
<h3>Added</h3>
<ul>
<li><code>JCharSequence</code> bindings for
<code>java.lang.CharSequence</code> (including
<code>AsRef&lt;JCharSequence&gt;</code> +
<code>.as_char_sequence()</code> for <code>JString</code>) (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/793">#793</a>)</li>
<li><code>bind_java_type</code> supports <code>non_null</code>
qualifier/property for methods and fields to map null references to
<code>Error::NullPtr</code> (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/795">#795</a>)</li>
<li><code>bind_java_type</code> supports <code>#[cfg()]</code>
attributes on methods and fields, to conditionally compile them based on
features or other cfg conditions (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/795">#797</a>)</li>
<li><code>JValueOwned::check_null()</code> + <code>::is_null()</code>
methods for ergonomic null checks on owned (returned) values (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/798">#798</a>)</li>
<li>More readable type accessors for <code>JValueOwned</code>, like
<code>.into_bool()</code> instead of <code>.z()</code>,
<code>.into_object()</code> instead of <code>.l()</code>, etc (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/798">#798</a>)</li>
</ul>
<h4>Fixed</h4>
<ul>
<li><code>jni_mangle</code> now includes
<code>docs/macros/jni_mangle.md</code> in the crate documentation, so
the macro's documentation is visible on docs.rs and in IDEs (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/799">#799</a>)</li>
</ul>
<h2>[0.22.3] — 2026-03-05</h2>
<h4>Fixed</h4>
<ul>
<li>docs.rs build: Bumps <code>simd_cesu8</code> dep to &gt;= 1.1.1
which no longer has an automatically-enabled
&quot;nightly&quot; feature that may affect the docs.rs build (1.1.x is
now also MSRV compatible) (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/790">#790</a>)</li>
</ul>
<h2>[0.22.2] — 2026-03-01</h2>
<p><em><em>Note</em>: although no breaking API change was made in this
release there were some important fixes
made, including a few non-trivial changes to how exceptions are handled
and some important safety /
soundness fixes made in the re-exported
<code>jni-macros</code>.</em></p>
<p><em>For these reasons I'm going to <em>again</em> yank the previous
0.22.1 release after this is published,
again taking into account that 0.22.1 was itself only released very
recently and it should still be
relatively unlikely that anyone has strictly locked in a 0.22.1
dependency.</em></p>
<p><em>Another benefit to yanking 0.22.1 is that it allows me to pin the
<code>jni-macros</code> dependency via
<code>=0.22.2</code> in this release so that in future releases I don't
need to be worried that a new
<code>jni-macros</code> release needs to be backwards compatible with
all prior <code>jni</code> releases (so macros can
take advantage of new <code>jni</code> features).</em></p>
<p><em>Hopefully things will be smoother moving forward, now that more
people have been starting to update
to 0.22.x and there are more people testing it.</em></p>
<h3>Added</h3>
<p>Adds bindings for the following <code>java.lang</code> errors /
exceptions (<a
href="https://redirect.github.com/jni-rs/jni-rs/pull/767">#767</a>):</p>
<ul>
<li><code>JArrayIndexOutOfBoundsException</code>
(<code>java.lang.ArrayIndexOutOfBoundsException</code>)</li>
<li><code>JArrayStoreException</code>
(<code>java.lang.ArrayStoreException</code>)</li>
<li><code>JClassCircularityError</code>
(<code>java.lang.ClassCircularityError</code>)</li>
<li><code>JClassFormatError</code>
(<code>java.lang.ClassFormatError</code>)</li>
<li><code>JExceptionInInitializerError</code>
(<code>java.lang.ExceptionInInitializerError</code>)</li>
<li><code>JClassNotFoundException</code>
(<code>java.lang.ClassNotFoundException</code>)</li>
<li><code>JIllegalArgumentException</code>
(<code>java.lang.IllegalArgumentException</code>)</li>
<li><code>JIllegalMonitorStateException</code>
(<code>java.lang.IllegalMonitorStateException</code>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/5ae9458a4ec44c5318f37ddc7569c1d4ae8a69e7"><code>5ae9458</code></a>
Release jni 0.22.4</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/2f954cdf25ad43fd3656fba123fa8c0071b03d72"><code>2f954cd</code></a>
Fix copy&amp;paste error
s/JString::collection/JString::as_char_sequence/</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/33045a124105c939d1e2cbdcb5a39e5d868ffa03"><code>33045a1</code></a>
Release jni-macros 0.22.4</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/527703e044558c0604ebd1b29ba9f7fa2c6a7d0e"><code>527703e</code></a>
No longer recommend passing <code>&amp;mut Env</code> as the last
argument</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/ce7130b10b76aa0dfe54d6951c3416f32c0f18a1"><code>ce7130b</code></a>
Import docs/macros/jni_mangle.md docs for jni_mangle macro</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/d80bf234cfa44c716925ea8ce2097b22bbe2e451"><code>d80bf23</code></a>
Add more-ergonomic JValueOwned accessors</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/5ffd96a2aeb20b60ade1049c011e75b784d73c2a"><code>5ffd96a</code></a>
bind_java_type: Support #[cfg()] guarded methods/fields</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/b498e9f87018eb2821be08984c5288e170d799a0"><code>b498e9f</code></a>
bind_java_type: support non_null methods/fields</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/1f74e4b9c65acac8ee331be0be9df05431413fef"><code>1f74e4b</code></a>
Add <code>objects::JCharSequence</code> binding</li>
<li><a
href="https://github.com/jni-rs/jni-rs/commit/25f810ddd7ce8ac3c93c1c8e98eb6e854e8b2a7d"><code>25f810d</code></a>
Release jni 0.22.3</li>
<li>Additional commits viewable in <a
href="https://github.com/jni-rs/jni-rs/compare/v0.21.1...v0.22.4">compare
view</a></li>
</ul>
</details>
<br />

Updates `bytes` from 1.12.0 to 1.12.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/releases">bytes's
releases</a>.</em></p>
<blockquote>
<h2>Bytes v1.12.1</h2>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md">bytes's
changelog</a>.</em></p>
<blockquote>
<h1>1.12.1 (July 8th, 2026)</h1>
<h3>Fixed</h3>
<ul>
<li>Properly handle when <code>Box::new</code> panics (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/bytes/commit/76c0fbb54ed4336caf9d2311658a2f4a5627c21d"><code>76c0fbb</code></a>
Release bytes v1.12.1 (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/838">#838</a>)</li>
<li><a
href="https://github.com/tokio-rs/bytes/commit/924c82bf0053cb13a0fb5165925d564622b2092f"><code>924c82b</code></a>
Handle unwinding from Box::new (<a
href="https://redirect.github.com/tokio-rs/bytes/issues/837">#837</a>)</li>
<li>See full diff in <a
href="https://github.com/tokio-rs/bytes/compare/v1.12.0...v1.12.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `crossbeam-queue` from 0.3.12 to 0.3.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crossbeam-rs/crossbeam/releases">crossbeam-queue's
releases</a>.</em></p>
<blockquote>
<h2>crossbeam-queue 0.3.13</h2>
<ul>
<li>Add <code>push_mut</code> and <code>pop_mut</code> to
<code>ArrayQueue</code> and <code>SegQueue</code>. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1191">#1191</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/9b56303b8aa9ff8ec5bbebb9d2da05e034977889"><code>9b56303</code></a>
Prepare for the next release</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/a078b17b7319ab49e53720ebeed8fa8a539a8e18"><code>a078b17</code></a>
ci: Sync config with main</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/508c29d3c27d7e27791244644dae2169a2f1678a"><code>508c29d</code></a>
Remove crossbeam-skiplist which is not published from this branch from
worksp...</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/6a20e57c492da6ba327b587bc5f38c7a4a3067ef"><code>6a20e57</code></a>
tests: Fix mismatched_lifetime_syntaxes</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c2d674f88af9501a0a939d8d4b0d52bdbc453ef9"><code>c2d674f</code></a>
epoch: Fix rustdoc::invalid_rust_codeblocks</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/bd6563e2118a5f2e9eec0f9e16006d428b82ffb0"><code>bd6563e</code></a>
Update no_atomic.rs</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/d3e1e364093763a40affe7ea3ff8368c7dc25ee9"><code>d3e1e36</code></a>
Make CachePadded&lt;T&gt; have C repr to allow casting to and from T (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1270">#1270</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/c0c466e5c3b5f177884e1df5f8f2c8c939c31aab"><code>c0c466e</code></a>
channel: Use non-poison Mutex</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/8b3940f1063f2e0795e44d3f5dde973f08e2a50b"><code>8b3940f</code></a>
Add missing word to docs (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1208">#1208</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/df6eec0610f91de504a5834c9faa0de40e3aec83"><code>df6eec0</code></a>
docs: Link <code>select_biased!</code> from <code>select!</code> macro
(<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1202">#1202</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-queue-0.3.12...crossbeam-queue-0.3.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `rustc-hash` from 2.1.2 to 2.1.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/rustc-hash/blob/main/CHANGELOG.md">rustc-hash's
changelog</a>.</em></p>
<blockquote>
<h1>2.1.3</h1>
<ul>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/77">Use
derive_const to fix <code>feature = &quot;nightly&quot;</code>
build</a></li>
<li><a
href="https://redirect.github.com/rust-lang/rustc-hash/pull/64">Internally
update to rand 0.9</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c13e7ccca705e6255387a2ebc6dca142d6881621"><code>c13e7cc</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/78">#78</a>
from Noratrieb/new-version-2-1-3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/4c3fabd983f96c2c5178512940e29a050edd07e9"><code>4c3fabd</code></a>
Bump to 2.1.3</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/3f1c0994892f5c592fe17192811c3b46caa108ac"><code>3f1c099</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/64">#64</a>
from DaniPopes/rand-0.9</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/07c3f48480b2d1a143fe299f5a82812b311efea6"><code>07c3f48</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/rustc-hash/issues/77">#77</a>
from DaniPopes/const-update</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/cbf0baf6f900674cf88f266f96a4fa223895186b"><code>cbf0baf</code></a>
Use derive_const in nightly feature</li>
<li><a
href="https://github.com/rust-lang/rustc-hash/commit/c74d2b3bb92563dbd32a9d7e6343af02d99dff25"><code>c74d2b3</code></a>
Update to rand 0.9</li>
<li>See full diff in <a
href="https://github.com/rust-lang/rustc-hash/compare/v2.1.2...v2.1.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `cc` from 1.2.65 to 1.2.66
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/releases">cc's
releases</a>.</em></p>
<blockquote>
<h2>cc-v1.2.66</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md">cc's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">1.2.66</a>
- 2026-07-05</h2>
<h3>Other</h3>
<ul>
<li>Fix target parsing for aarch64-unknown-linux-pauthtest (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1779">#1779</a>)</li>
<li>Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1775">#1775</a>)</li>
<li>Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/pull/1770">#1770</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/9c53ddc649838c60f8b33aee77dbfec5f04c16dc"><code>9c53ddc</code></a>
chore(cc): release v1.2.66 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1777">#1777</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/f2836c0fc57c44ca833d0f3e822f94f523a00a6e"><code>f2836c0</code></a>
Fix target parsing (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1779">#1779</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/32996914ec656e0d37775571545029d31afd9df2"><code>3299691</code></a>
ci(test-wasm): do not download pre release of wasi-sdk (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1778">#1778</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/bfd1ac98d4d52e941fc71f844af8fc70e152dd5e"><code>bfd1ac9</code></a>
Support new QNX targets (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1775">#1775</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/1887a73fddabc77f7def580feefbcfbdba10ed1d"><code>1887a73</code></a>
Add kache to the supported compiler wrappers (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1770">#1770</a>)</li>
<li><a
href="https://github.com/rust-lang/cc-rs/commit/e4847e1720197e42d1d80934879e48188777335f"><code>e4847e1</code></a>
Bump actions/checkout from 6.0.3 to 7.0.0 (<a
href="https://redirect.github.com/rust-lang/cc-rs/issues/1767">#1767</a>)</li>
<li>See full diff in <a
href="https://github.com/rust-lang/cc-rs/compare/cc-v1.2.65...cc-v1.2.66">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Stacked on lance-format#7533 (`feat/object-store-metrics`). Exposes the Rust
`metrics`-crate metrics to Python's OpenTelemetry SDK.

## Approach

Lance core publishes metrics through the `metrics` crate facade without
choosing a backend. This PR installs a process-global
`metrics::Recorder` in the Python bindings that aggregates every facade
metric into lock-free cumulative storage, and registers OpenTelemetry
observable instruments that report those values into the user's
`MeterProvider`.

The bridge is **generic** — nothing is specific to object store metrics
(the first producer). New metrics are surfaced automatically with no
per-metric Python code, as long as they are described (via
`describe_*!`) and wired into the central `describe_all()` /
`register_bounds()` in `python/src/otel.rs`.

- **Pull model**: OpenTelemetry collects on its own schedule and invokes
observable-instrument callbacks at collection time; cumulative counters
map directly onto `ObservableCounter` semantics. The Python collection
thread pulls a snapshot (lock-free read, GIL released).
- **Discovery via describe-catalog**: metrics declare their
name/kind/unit through `describe_*!`; `instrument_lance_metrics()`
enumerates the catalog and creates one instrument per metric.
- **Histograms**: OpenTelemetry has no asynchronous histogram
instrument, so each histogram is aggregated into fixed Prometheus-style
`le` buckets and exported as `<name>_bucket` (with an `le` attribute),
`<name>_count`, and `<name>_sum` observable counters.

The recorder is process-global (a `metrics` limitation); if another
recorder is already installed, instrumentation is skipped with a warning
and `instrument_lance_metrics()` returns `False`.

## Usage

```python
from lance.otel import instrument_lance_metrics
instrument_lance_metrics()  # uses the global MeterProvider
```

Requires the OpenTelemetry SDK (`pip install pylance[otel]`).

## Tests

- 5 Rust unit tests (bucketing, cumulative `le` semantics, boundary
inclusivity, counter aggregation with labels, describe-catalog).
- Python integration test using an in-memory OTel `MetricReader`: a
local-FS dataset write/read produces `lance_object_store_*` series
including the histogram bucket/count/sum decomposition.

## Notes for review

- `describe_metrics()` / `histogram_bounds()` /
`REQUEST_DURATION_BOUNDS` were added to `lance-io` (single source of
truth). These could alternatively be folded into the base PR lance-format#7533.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

import lance / lancedb crashes with SIGILL on x86_64 CPUs without AVX2 (Sandy Bridge, Ivy Bridge, FX-7500-class AMDs)