From 513bcf3e4a103a2ff0383bf104287948982b1cb5 Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 12:46:57 -0800 Subject: [PATCH 1/6] ci: fix MSRV check --- .github/workflows/rust.yml | 2 +- java/lance-jni/Cargo.toml | 2 +- python/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 01a9b8363e2..e37f269be53 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -268,8 +268,8 @@ jobs: - name: Install ${{ matrix.msrv }} run: | rustup toolchain install ${{ matrix.msrv }} - rustup default ${{ matrix.msrv }} - name: cargo +${{ matrix.msrv }} check + env: RUSTUP_TOOLCHAIN=${{ matrix.msrv }} run: | ALL_FEATURES=`cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | .features | keys | .[]' | grep -v -e protoc -e slow_tests | sort | uniq | paste -s -d "," -` cargo check --profile ci --workspace --tests --benches --features ${ALL_FEATURES} diff --git a/java/lance-jni/Cargo.toml b/java/lance-jni/Cargo.toml index 9b67e6b8047..64fcfb3d609 100644 --- a/java/lance-jni/Cargo.toml +++ b/java/lance-jni/Cargo.toml @@ -3,7 +3,7 @@ name = "lance-jni" version = "2.1.0-beta.0" edition = "2021" authors = ["Lance Devs "] -rust-version = "1.80" +rust-version = "1.82" license = "Apache-2.0" repository = "https://github.com/lance-format/lance" readme = "../../README.md" diff --git a/python/Cargo.toml b/python/Cargo.toml index be49dacec7e..2b7c643e6fb 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -3,7 +3,7 @@ name = "pylance" version = "2.1.0-beta.0" edition = "2021" authors = ["Lance Devs "] -rust-version = "1.80" +rust-version = "1.82" exclude = ["python/lance/conftest.py"] publish = false From ac43512850014d8f1c7531d164967bd2cf13ffdf Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 12:50:44 -0800 Subject: [PATCH 2/6] format fix --- .github/workflows/rust.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e37f269be53..13783769e8f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -269,7 +269,8 @@ jobs: run: | rustup toolchain install ${{ matrix.msrv }} - name: cargo +${{ matrix.msrv }} check - env: RUSTUP_TOOLCHAIN=${{ matrix.msrv }} + env: + RUSTUP_TOOLCHAIN: ${{ matrix.msrv }} run: | ALL_FEATURES=`cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | .features | keys | .[]' | grep -v -e protoc -e slow_tests | sort | uniq | paste -s -d "," -` cargo check --profile ci --workspace --tests --benches --features ${ALL_FEATURES} From e6406db2236e47466047ff8584dadf6bfa0313c8 Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 12:58:22 -0800 Subject: [PATCH 3/6] match DataFusion's MSRV --- .github/workflows/rust.yml | 2 +- Cargo.toml | 2 +- java/lance-jni/Cargo.toml | 2 +- python/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 13783769e8f..17eae173579 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -251,7 +251,7 @@ jobs: runs-on: ubuntu-24.04 strategy: matrix: - msrv: ["1.82.0"] # This should match up with rust-version in Cargo.toml + msrv: ["1.88.0"] # This should match up with rust-version in Cargo.toml env: # Need up-to-date compilers for kernels CC: clang diff --git a/Cargo.toml b/Cargo.toml index cf0e62130b2..d7643ddab69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ categories = [ "development-tools", "science", ] -rust-version = "1.82.0" +rust-version = "1.88.0" [workspace.dependencies] libc = "0.2.176" diff --git a/java/lance-jni/Cargo.toml b/java/lance-jni/Cargo.toml index 64fcfb3d609..966a8042e16 100644 --- a/java/lance-jni/Cargo.toml +++ b/java/lance-jni/Cargo.toml @@ -3,7 +3,7 @@ name = "lance-jni" version = "2.1.0-beta.0" edition = "2021" authors = ["Lance Devs "] -rust-version = "1.82" +rust-version = "1.88" license = "Apache-2.0" repository = "https://github.com/lance-format/lance" readme = "../../README.md" diff --git a/python/Cargo.toml b/python/Cargo.toml index 2b7c643e6fb..5337ec992c2 100644 --- a/python/Cargo.toml +++ b/python/Cargo.toml @@ -3,7 +3,7 @@ name = "pylance" version = "2.1.0-beta.0" edition = "2021" authors = ["Lance Devs "] -rust-version = "1.82" +rust-version = "1.88" exclude = ["python/lance/conftest.py"] publish = false From 3c0c65efddbdde2032d063770cdc96c63687597a Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 13:15:46 -0800 Subject: [PATCH 4/6] clippy --- rust/lance-encoding/src/buffer.rs | 4 ++-- rust/lance-encoding/src/data.rs | 2 +- rust/lance-encoding/src/encodings/physical/bitpacking.rs | 4 ++-- rust/lance-encoding/src/encodings/physical/rle.rs | 2 +- rust/lance-encoding/src/encodings/physical/value.rs | 4 ++-- .../src/previous/encodings/physical/bitpack.rs | 6 +++--- rust/lance-index/src/scalar/bloomfilter/sbbf.rs | 2 +- rust/lance-index/src/scalar/inverted/index.rs | 2 +- rust/lance-index/src/vector/pq.rs | 2 +- rust/lance-index/src/vector/pq/utils.rs | 2 +- rust/lance/src/dataset/cleanup.rs | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/rust/lance-encoding/src/buffer.rs b/rust/lance-encoding/src/buffer.rs index 651d5938ba2..e8bcb8a3ea2 100644 --- a/rust/lance-encoding/src/buffer.rs +++ b/rust/lance-encoding/src/buffer.rs @@ -153,7 +153,7 @@ impl LanceBuffer { pub fn borrow_to_typed_slice(&self) -> ScalarBuffer { let align = std::mem::align_of::(); let is_aligned = self.as_ptr().align_offset(align) == 0; - if self.len() % std::mem::size_of::() != 0 { + if !self.len().is_multiple_of(std::mem::size_of::()) { panic!("attempt to borrow_to_typed_slice to data type of size {} but we have {} bytes which isn't evenly divisible", std::mem::size_of::(), self.len()); } @@ -184,7 +184,7 @@ impl LanceBuffer { /// carefully reviewed. pub fn borrow_to_typed_view(&self) -> Cow<'_, [T]> { let align = std::mem::align_of::(); - if self.len() % std::mem::size_of::() != 0 { + if !self.len().is_multiple_of(std::mem::size_of::()) { panic!("attempt to view data type of size {} but we have {} bytes which isn't evenly divisible", std::mem::size_of::(), self.len()); } diff --git a/rust/lance-encoding/src/data.rs b/rust/lance-encoding/src/data.rs index 52c8e1fa568..8828673326f 100644 --- a/rust/lance-encoding/src/data.rs +++ b/rust/lance-encoding/src/data.rs @@ -307,7 +307,7 @@ struct FixedWidthDataBlockBuilder { impl FixedWidthDataBlockBuilder { fn new(bits_per_value: u64, estimated_size_bytes: u64) -> Self { - assert!(bits_per_value % 8 == 0); + assert!(bits_per_value.is_multiple_of(8)); Self { bits_per_value, bytes_per_value: bits_per_value / 8, diff --git a/rust/lance-encoding/src/encodings/physical/bitpacking.rs b/rust/lance-encoding/src/encodings/physical/bitpacking.rs index 9e22e47d745..207219b58f0 100644 --- a/rust/lance-encoding/src/encodings/physical/bitpacking.rs +++ b/rust/lance-encoding/src/encodings/physical/bitpacking.rs @@ -126,7 +126,7 @@ impl InlineBitpacking { } // Handle the last chunk - let last_chunk_elem_num = if data.num_values % ELEMS_PER_CHUNK == 0 { + let last_chunk_elem_num = if data.num_values.is_multiple_of(ELEMS_PER_CHUNK) { ELEMS_PER_CHUNK } else { data.num_values % ELEMS_PER_CHUNK @@ -162,7 +162,7 @@ impl InlineBitpacking { } fn chunk_data(&self, data: FixedWidthDataBlock) -> (MiniBlockCompressed, CompressiveEncoding) { - assert!(data.bits_per_value % 8 == 0); + assert!(data.bits_per_value.is_multiple_of(8)); assert_eq!(data.bits_per_value, self.uncompressed_bit_width); let bits_per_value = data.bits_per_value; let compressed = match bits_per_value { diff --git a/rust/lance-encoding/src/encodings/physical/rle.rs b/rust/lance-encoding/src/encodings/physical/rle.rs index f1cbb455c48..ae17ccea71d 100644 --- a/rust/lance-encoding/src/encodings/physical/rle.rs +++ b/rust/lance-encoding/src/encodings/physical/rle.rs @@ -453,7 +453,7 @@ impl RleMiniBlockDecompressor { } } - if values_buffer.len() % type_size != 0 || lengths_buffer.is_empty() { + if !values_buffer.len().is_multiple_of(type_size) || lengths_buffer.is_empty() { return Err(Error::InvalidInput { location: location!(), source: format!( diff --git a/rust/lance-encoding/src/encodings/physical/value.rs b/rust/lance-encoding/src/encodings/physical/value.rs index 6c8e6dbd787..a0ea0c5ba2d 100644 --- a/rust/lance-encoding/src/encodings/physical/value.rs +++ b/rust/lance-encoding/src/encodings/physical/value.rs @@ -53,7 +53,7 @@ impl ValueEncoder { // or FSL we might have some number of bits per value that isn't // divisible by 8. In this case, to avoid chunking in the middle of a byte // we calculate how many 8-value words we can fit in a chunk. - let (bytes_per_word, values_per_word) = if data.bits_per_value % 8 == 0 { + let (bytes_per_word, values_per_word) = if data.bits_per_value.is_multiple_of(8) { (data.bits_per_value / 8, 1) } else { (data.bits_per_value, 8) @@ -192,7 +192,7 @@ impl ValueEncoder { } // It's an estimate because validity buffers may have some padding bits let cum_bits_per_value = data.bits_per_value * cum_dim; - let (cum_bytes_per_word, vals_per_word) = if cum_bits_per_value % 8 == 0 { + let (cum_bytes_per_word, vals_per_word) = if cum_bits_per_value.is_multiple_of(8) { (cum_bits_per_value / 8, 1) } else { (cum_bits_per_value, 8) diff --git a/rust/lance-encoding/src/previous/encodings/physical/bitpack.rs b/rust/lance-encoding/src/previous/encodings/physical/bitpack.rs index 69fea9a8771..5d018469645 100644 --- a/rust/lance-encoding/src/previous/encodings/physical/bitpack.rs +++ b/rust/lance-encoding/src/previous/encodings/physical/bitpack.rs @@ -802,7 +802,7 @@ fn pack_bits( // we also want to the next location in src, unless we wrote something // byte-aligned in which case the logic above would have already advanced let mut to_next_byte = 1; - if num_bits % 8 == 0 { + if num_bits.is_multiple_of(8) { to_next_byte = 0; } @@ -853,7 +853,7 @@ impl PageScheduler for BitpackedScheduler { .map(|range| { let start_byte_offset = range.start * self.bits_per_value / 8; let mut end_byte_offset = range.end * self.bits_per_value / 8; - if range.end * self.bits_per_value % 8 != 0 { + if !(range.end * self.bits_per_value).is_multiple_of(8) { // If the end of the range is not byte-aligned, we need to read one more byte end_byte_offset += 1; @@ -1026,7 +1026,7 @@ impl PrimitivePageDecoder for BitpackedPageDecoder { // unless we wrote something byte-aligned in which case the logic above // would have already advanced dst_idx let mut to_next_byte = 1; - if self.bits_per_value % 8 == 0 { + if self.bits_per_value.is_multiple_of(8) { to_next_byte = 0; } let next_dst_idx = diff --git a/rust/lance-index/src/scalar/bloomfilter/sbbf.rs b/rust/lance-index/src/scalar/bloomfilter/sbbf.rs index 7f506f796f3..50574768050 100644 --- a/rust/lance-index/src/scalar/bloomfilter/sbbf.rs +++ b/rust/lance-index/src/scalar/bloomfilter/sbbf.rs @@ -243,7 +243,7 @@ pub struct Sbbf { impl Sbbf { /// Create a new SBBF from raw bitset data pub fn new(bitset: &[u8]) -> Result { - if bitset.len() % 32 != 0 { + if !bitset.len().is_multiple_of(32) { return Err(SbbfError::InvalidData { message: format!( "Bitset length must be a multiple of 32, got {}", diff --git a/rust/lance-index/src/scalar/inverted/index.rs b/rust/lance-index/src/scalar/inverted/index.rs index 37d3f28ddb8..dab83131f8a 100644 --- a/rust/lance-index/src/scalar/inverted/index.rs +++ b/rust/lance-index/src/scalar/inverted/index.rs @@ -2247,7 +2247,7 @@ impl DocSet { max_score = f32::MIN; } } - if length % BLOCK_SIZE > 0 { + if !length.is_multiple_of(BLOCK_SIZE) { max_score *= idf_scale; block_max_scores.push(max_score); } diff --git a/rust/lance-index/src/vector/pq.rs b/rust/lance-index/src/vector/pq.rs index 8a5d0923530..bbe0dd6ff45 100644 --- a/rust/lance-index/src/vector/pq.rs +++ b/rust/lance-index/src/vector/pq.rs @@ -129,7 +129,7 @@ impl ProductQuantizer { })?; let num_sub_vectors = self.num_sub_vectors; let dim = self.dimension; - if NUM_BITS == 4 && num_sub_vectors % 2 != 0 { + if NUM_BITS == 4 && !num_sub_vectors.is_multiple_of(2) { return Err(Error::Index { message: format!( "PQ: num_sub_vectors must be divisible by 2 for num_bits=4, but got {}", diff --git a/rust/lance-index/src/vector/pq/utils.rs b/rust/lance-index/src/vector/pq/utils.rs index 0db0d4dada7..95d3b3396e3 100644 --- a/rust/lance-index/src/vector/pq/utils.rs +++ b/rust/lance-index/src/vector/pq/utils.rs @@ -19,7 +19,7 @@ where PrimitiveArray: From>, { let dim = fsl.value_length() as usize; - if dim % m != 0 { + if !dim.is_multiple_of(m) { return Err(Error::invalid_input( format!( "num_sub_vectors must divide vector dimension {}, but got {}", diff --git a/rust/lance/src/dataset/cleanup.rs b/rust/lance/src/dataset/cleanup.rs index dc948c251b8..fc1f54cc1b3 100644 --- a/rust/lance/src/dataset/cleanup.rs +++ b/rust/lance/src/dataset/cleanup.rs @@ -669,7 +669,7 @@ pub async fn auto_cleanup_hook( } }; - if interval != 0 && manifest.version % interval != 0 { + if interval != 0 && !manifest.version.is_multiple_of(interval) { return Ok(None); } } else { From ebbf594c38ad3498739c9c96b7444e2102e7cfdf Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 13:26:04 -0800 Subject: [PATCH 5/6] clippy examples --- rust/examples/src/llm_dataset_creation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/examples/src/llm_dataset_creation.rs b/rust/examples/src/llm_dataset_creation.rs index 43ae2f88d6e..6a5ebbc0dd6 100644 --- a/rust/examples/src/llm_dataset_creation.rs +++ b/rust/examples/src/llm_dataset_creation.rs @@ -92,7 +92,7 @@ impl WikiTextBatchReader { } token_builder.append(true); self.cur_samples_cnt += 1; - if self.cur_samples_cnt % 5000 == 0 { + if self.cur_samples_cnt.is_multiple_of(5000) { println!("Processed {} rows", self.cur_samples_cnt); } if self.cur_samples_cnt >= self.num_samples { From 1109ef3e65b4dffa445d5fc67b996bbf8a3fc0ba Mon Sep 17 00:00:00 2001 From: Will Jones Date: Fri, 23 Jan 2026 15:51:48 -0800 Subject: [PATCH 6/6] Java too --- java/lance-jni/src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/lance-jni/src/utils.rs b/java/lance-jni/src/utils.rs index 78677599215..56ff617c821 100644 --- a/java/lance-jni/src/utils.rs +++ b/java/lance-jni/src/utils.rs @@ -276,7 +276,7 @@ pub fn get_vector_index_params( let jarray: JFloatArray = centroids_obj.into(); let length = env.get_array_length(&jarray)?; if length > 0 { - if (length as usize) % num_partitions != 0 { + if !(length as usize).is_multiple_of(num_partitions) { return Err(Error::input_error(format!( "Invalid IVF centroids: length {} is not divisible by num_partitions {}", length, num_partitions