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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .claude/knowledge/abi-ownership-and-handles.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,38 @@ the `Arena`/segment lifetime as nested *inside* the resource's own lifetime,
so Java's own bookkeeping fails fast on a use-after-close even before the
call reaches Rust (belt-and-braces, not a substitute for the Rust-side
check).

## Rust 1.99 (2026-10-10): what the C-ABI changes do and do not buy here

MEASURED on 1.99.0 / LLVM 23. lgj-abi is clippy-clean with `-D warnings`. All
four Java suites pass (`AllTests` 612, consumers 70 + 68 + 3 + 12) against a
`liblgj_abi.so` built by 1.99. lgj-abi's graph contains no lance, lancedb or
arrow, so the lance 13 move does not reach this crate.

- **`UnsafeCell` contents may be accessed without `get` (newly guaranteed).**
This does NOT change the soundness of the writable mask lane.
- `lgj_mask_describe` hands Java the address of `MaskWords.words`. That is
a boxed heap buffer, not the inside of the lock's `UnsafeCell`. Java writes
to it through the segment, outside the lock.
- It is sound today because no Rust reference to those words is live while
Java writes. The one production writer, `RowStore.importRows`, writes a
mask whose handle has not been returned to anyone yet. Every Rust op
re-borrows through the lock.
- A concurrent Java writer would still be a data race, and the guarantee
does not make a race defined. That needs `AtomicU64` words plus a
documented protocol, which this ABI deliberately does not define.
- Possible hardening, not done: take the address under the write guard
(`as_mut_ptr`), so it carries write provenance. Not done because
`write_mask` also invalidates `resolved_carving`, so every describe would
drop the carving cache. That is a behaviour change for no reachable
defect.
- **C-variadic definitions / `VaList` (stabilized):** not applicable. The ABI
is fixed-arity and bulk-only (`docs/abi.md` §6), and `no-c-ever.md` holds.
- **`no_mangle` on generic items is now a hard error:** the 30 `#[no_mangle]`
exports are all non-generic.
- **Extern statics no longer promoted:** none are referenced.
- **`Box::into_non_null` / `Vec::from_parts`:** no site here. Handles are
registry ids, never raw boxes.

REVISIT WHEN: the ABI grows a concurrent-writer protocol (then: atomic word
lanes), or a Java writer other than `importRows` appears.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ no `cbindgen`, no `jextract`, no JNI. See `docs/abi.md` §1 and

## Toolchains

- Rust: **1.97.1** stable, matching `ndarray`/`lance-graph`'s pin.
- Rust: stable, pinned in `native/lgj-abi/rust-toolchain.toml` (the version
lives there only, matching `ndarray`/`lance-graph`'s pin).
- Production JDK: **JDK 28** (`/opt/jdks/jdk-28+16`). Panama FFM is final
there and needs no flag; Valhalla (JEP 401) is preview-gated and production
uses it, so `--enable-preview` is required — for the value classes, never
Expand Down
2 changes: 1 addition & 1 deletion native/lgj-abi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "lgj-abi"
version = "0.1.0"
edition = "2021"
rust-version = "1.98.1"
rust-version = "1.99.0"
license = "MIT OR Apache-2.0"
publish = false
description = "The lance-graph-java machine membrane: a self-describing, versioned, bulk-only psABI surface. No C, no JNI, no headers."
Expand Down
8 changes: 7 additions & 1 deletion native/lgj-abi/rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Stable only. Matches ndarray / lance-graph / the rest of the AdaWorldAPI
# stack. No nightly features anywhere in this crate — in particular no
# `core::simd` / portable-simd (abi.md §8).
channel = "1.98.1"
channel = "1.99.0"
components = ["clippy", "rustfmt"]

# Bump log (append one line per bump; the version itself is the `channel`
Expand All @@ -11,6 +11,12 @@ components = ["clippy", "rustfmt"]
# carried by ndarray / lance-graph / OGAR. Forced, not
# optional: ndarray 0.17.2 now declares rustc 1.98, so
# a 1.97.1 build of this crate fails to resolve at all.
# 1.98.1 → 1.99.0 2026-10-10: workspace-wide sweep (lance-graph #1437).
# Must merge BEFORE the ndarray / lance-graph bumps: CI
# checks the siblings out at main, and once they declare
# rust-version 1.99 a 1.98 build here no longer resolves.
# Measured: clippy -D warnings clean; AllTests 612 +
# consumers 153 green against a 1.99-built .so.
#
# This is THE toolchain file for this repo. A second one briefly existed at
# the repository root; it was removed rather than kept in sync, because two
Expand Down
Loading