chore: update msrv to 1.91.1

This commit is contained in:
Nicolas Sarlin
2025-11-18 14:27:28 +01:00
committed by Nicolas Sarlin
parent 071e70c037
commit edb435bd46
57 changed files with 164 additions and 133 deletions

View File

@@ -24,7 +24,7 @@ exclude = [
]
[workspace.package]
rust-version = "1.85"
rust-version = "1.91.1"
[workspace.dependencies]
aligned-vec = { version = "0.6", default-features = false }

View File

@@ -427,10 +427,10 @@ clippy_rustdoc: install_rs_check_toolchain
echo "WARNING: skipped clippy_rustdoc, unsupported OS $(OS)"; \
exit 0; \
fi && \
CARGO_TERM_QUIET=true CLIPPYFLAGS="-D warnings" RUSTDOCFLAGS="--no-run --nocapture --test-builder ./scripts/clippy_driver.sh -Z unstable-options" \
CARGO_TERM_QUIET=true CLIPPYFLAGS="-D warnings" RUSTDOCFLAGS="--no-run --test-builder ./scripts/clippy_driver.sh -Z unstable-options" \
cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" test --doc \
--features=boolean,shortint,integer,zk-pok,pbs-stats,strings,experimental \
-p tfhe
-p tfhe -- --nocapture
.PHONY: clippy_rustdoc_gpu # Run clippy lints on doctests enabling the boolean, shortint, integer and zk-pok
clippy_rustdoc_gpu: install_rs_check_toolchain
@@ -438,10 +438,10 @@ clippy_rustdoc_gpu: install_rs_check_toolchain
echo "WARNING: skipped clippy_rustdoc_gpu, unsupported OS $(OS)"; \
exit 0; \
fi && \
CARGO_TERM_QUIET=true CLIPPYFLAGS="-D warnings" RUSTDOCFLAGS="--no-run --nocapture --test-builder ./scripts/clippy_driver.sh -Z unstable-options" \
CARGO_TERM_QUIET=true CLIPPYFLAGS="-D warnings" RUSTDOCFLAGS="--no-run --test-builder ./scripts/clippy_driver.sh -Z unstable-options" \
cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" test --doc \
--features=boolean,shortint,integer,zk-pok,pbs-stats,strings,experimental,gpu \
-p tfhe
-p tfhe -- --nocapture
.PHONY: clippy_c_api # Run clippy lints enabling the boolean, shortint and the C API
clippy_c_api: install_rs_check_toolchain
@@ -649,11 +649,19 @@ build_web_js_api: install_rs_build_toolchain install_wasm_pack
-- --features=boolean-client-js-wasm-api,shortint-client-js-wasm-api,integer-client-js-wasm-api,zk-pok,extended-types
.PHONY: build_web_js_api_parallel # Build the js API targeting the web browser with parallelism support
# parallel wasm requires specific build options, see https://github.com/rust-lang/rust/pull/147225
build_web_js_api_parallel: install_rs_check_toolchain install_wasm_pack
cd tfhe && \
rustup component add rust-src --toolchain $(RS_CHECK_TOOLCHAIN) && \
RUSTFLAGS="$(WASM_RUSTFLAGS) -C target-feature=+atomics,+bulk-memory" rustup run $(RS_CHECK_TOOLCHAIN) \
wasm-pack build --release --target=web \
RUSTFLAGS="$(WASM_RUSTFLAGS) -C target-feature=+atomics,+bulk-memory \
-Clink-arg=--shared-memory \
-Clink-arg=--max-memory=1073741824 \
-Clink-arg=--import-memory \
-Clink-arg=--export=__wasm_init_tls \
-Clink-arg=--export=__tls_size \
-Clink-arg=--export=__tls_align \
-Clink-arg=--export=__tls_base" \
rustup run $(RS_CHECK_TOOLCHAIN) wasm-pack build --release --target=web \
-- --features=boolean-client-js-wasm-api,shortint-client-js-wasm-api,integer-client-js-wasm-api,parallel-wasm-api,zk-pok,extended-types \
-Z build-std=panic_abort,std && \
find pkg/snippets -type f -iname workerHelpers.js -exec sed -i "s|const pkg = await import('..\/..\/..');|const pkg = await import('..\/..\/..\/tfhe.js');|" {} \;

View File

@@ -659,6 +659,7 @@ pub fn iop_div_corev(
}
remain_a = Vec::new();
#[allow(clippy::needless_range_loop)]
for i in 0..block_nb {
remain_tmp_v[0][i] = &remain_tmp_v[0][i] + &remain_tmp_v[1][i];
remain_tmp_v[2][i] = &remain_tmp_v[2][i] + &remain_tmp_v[3][i];

View File

@@ -54,7 +54,7 @@ pub const H1Y: f64 = -0.38268343236508984f64;
struct AssertC64Vec<T>(PhantomData<T>);
impl<T> AssertC64Vec<T> {
pub const VALID: () = {
assert!(core::mem::size_of::<T>() % core::mem::size_of::<c64>() == 0);
assert!(core::mem::size_of::<T>().is_multiple_of(core::mem::size_of::<c64>()));
};
}

View File

@@ -73,8 +73,6 @@
clippy::too_many_arguments,
non_camel_case_types
)]
// Should be removed when we raise MSRV above 1.87
#![allow(clippy::manual_is_multiple_of)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(rustdoc::broken_intra_doc_links)]

View File

@@ -83,18 +83,18 @@ pub const fn is_prime64(n: u64) -> bool {
// hand-unrolled for the compiler to optimize divisions
#[rustfmt::skip]
{
if n % 2 == 0 { return n == 2; }
if n % 3 == 0 { return n == 3; }
if n % 5 == 0 { return n == 5; }
if n % 7 == 0 { return n == 7; }
if n % 11 == 0 { return n == 11; }
if n % 13 == 0 { return n == 13; }
if n % 17 == 0 { return n == 17; }
if n % 19 == 0 { return n == 19; }
if n % 23 == 0 { return n == 23; }
if n % 29 == 0 { return n == 29; }
if n % 31 == 0 { return n == 31; }
if n % 37 == 0 { return n == 37; }
if n.is_multiple_of(2) { return n == 2; }
if n.is_multiple_of(3) { return n == 3; }
if n.is_multiple_of(5) { return n == 5; }
if n.is_multiple_of(7) { return n == 7; }
if n.is_multiple_of(11) { return n == 11; }
if n.is_multiple_of(13) { return n == 13; }
if n.is_multiple_of(17) { return n == 17; }
if n.is_multiple_of(19) { return n == 19; }
if n.is_multiple_of(23) { return n == 23; }
if n.is_multiple_of(29) { return n == 29; }
if n.is_multiple_of(31) { return n == 31; }
if n.is_multiple_of(37) { return n == 37; }
};
// deterministic miller rabin test, works for any n < 2^64
@@ -104,7 +104,7 @@ pub const fn is_prime64(n: u64) -> bool {
let mut s = 0;
let mut d = n - 1;
while d % 2 == 0 {
while d.is_multiple_of(2) {
s += 1;
d /= 2;
}

View File

@@ -156,7 +156,7 @@ impl Plan {
factors: impl AsRef<[u64]>,
) -> Option<Self> {
fn try_new_impl(polynomial_size: usize, modulus: u64, primes: &mut [u64]) -> Option<Plan> {
if polynomial_size % 2 != 0 {
if !polynomial_size.is_multiple_of(2) {
return None;
}

View File

@@ -7,7 +7,7 @@ pub const fn get_q_s64(p: Div64) -> (u64, u64) {
let p = p.divisor();
let mut q = p - 1;
let mut s = 0;
while q % 2 == 0 {
while q.is_multiple_of(2) {
q /= 2;
s += 1;
}

View File

@@ -226,7 +226,7 @@ pub fn four_squares(v: u128, sanity_check_mode: ProofSanityCheckMode) -> [u64; 4
let mut d = p - 1;
let mut s = 0u32;
while d % 2 == 0 {
while d.is_multiple_of(2) {
d /= 2;
s += 1;
}

View File

@@ -8,7 +8,7 @@
pub fn pad_sha256_input(input: &str) -> Vec<bool> {
let bytes = if input.starts_with("0x") && is_valid_hex(&input[2..]) {
let no_prefix = &input[2..];
let hex_input = if no_prefix.len() % 2 == 0 {
let hex_input = if no_prefix.len().is_multiple_of(2) {
// hex value can be converted to bytes
no_prefix.to_string()
} else {

View File

@@ -18,7 +18,7 @@ pub fn check_ptr_is_non_null_and_aligned<T>(ptr: *const T) -> Result<(), String>
return Err(format!("pointer is null, got: {ptr:p}"));
}
let expected_alignment = std::mem::align_of::<T>();
if ptr as usize % expected_alignment != 0 {
if !(ptr as usize).is_multiple_of(expected_alignment) {
return Err(format!(
"pointer is misaligned, expected {expected_alignment} bytes alignment, got pointer: \
{ptr:p}. You May have mixed some pointers in your function call. If that's not the \

View File

@@ -67,7 +67,7 @@ impl ListSizeConstraint {
if self.group_size == 0 {
size == 0
} else {
size % self.group_size == 0
size.is_multiple_of(self.group_size)
&& size >= self.min_inclusive_group_count * self.group_size
&& size <= self.max_inclusive_group_count * self.group_size
}

View File

@@ -400,7 +400,7 @@ pub fn polynomial_wrapping_monic_monomial_div_assign<Scalar, OutputCont>(
OutputCont: ContainerMut<Element = Scalar>,
{
let full_cycles_count = monomial_degree.0 / output.as_ref().container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
output
.as_mut()
.iter_mut()
@@ -425,7 +425,7 @@ pub fn polynomial_wrapping_monic_monomial_div_assign_custom_mod<Scalar, OutputCo
OutputCont: ContainerMut<Element = Scalar>,
{
let full_cycles_count = monomial_degree.0 / output.as_ref().container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
output
.as_mut()
.iter_mut()
@@ -467,7 +467,7 @@ pub fn polynomial_wrapping_monic_monomial_mul_assign<Scalar, OutputCont>(
OutputCont: ContainerMut<Element = Scalar>,
{
let full_cycles_count = monomial_degree.0 / output.as_ref().container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
output
.as_mut()
.iter_mut()
@@ -491,7 +491,7 @@ pub fn polynomial_wrapping_monic_monomial_mul_assign_custom_mod<Scalar, OutputCo
OutputCont: ContainerMut<Element = Scalar>,
{
let full_cycles_count = monomial_degree.0 / output.as_ref().container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
output
.as_mut()
.iter_mut()
@@ -561,7 +561,7 @@ pub fn polynomial_wrapping_monic_monomial_div<Scalar, OutputCont, InputCont>(
let remaining_degree = monomial_degree.0 % polynomial_size;
let full_cycles_count = monomial_degree.0 / polynomial_size;
if full_cycles_count % 2 == 0 {
if full_cycles_count.is_multiple_of(2) {
copy_without_neg(
&mut output[..polynomial_size - remaining_degree],
&input[remaining_degree..],
@@ -625,7 +625,7 @@ pub fn polynomial_wrapping_monic_monomial_mul<Scalar, OutputCont, InputCont>(
let remaining_degree = monomial_degree.0 % polynomial_size;
let full_cycles_count = monomial_degree.0 / polynomial_size;
if full_cycles_count % 2 == 0 {
if full_cycles_count.is_multiple_of(2) {
copy_with_neg(
&mut output[..remaining_degree],
&input[polynomial_size - remaining_degree..],
@@ -701,7 +701,7 @@ pub(crate) fn polynomial_wrapping_monic_monomial_mul_and_subtract<Scalar, Output
let remaining_degree = monomial_degree.0 % polynomial_size;
let full_cycles_count = monomial_degree.0 / polynomial_size;
if full_cycles_count % 2 == 0 {
if full_cycles_count.is_multiple_of(2) {
copy_with_neg_and_subtract(
&mut output[..remaining_degree],
&input[polynomial_size - remaining_degree..],

View File

@@ -46,7 +46,7 @@ fn test_parallel_and_seeded_multi_bit_bsk_gen_equivalence<
let noise_distribution =
DynamicDistribution::new_gaussian_from_std_dev(StandardDev::from_standard_dev(10.));
while lwe_dim.0 % grouping_factor.0 != 0 {
while !lwe_dim.0.is_multiple_of(grouping_factor.0) {
lwe_dim = LweDimension(lwe_dim.0 + 1);
}

View File

@@ -233,7 +233,7 @@ pub trait ContiguousEntityContainer: AsRef<[Self::Element]> {
) -> ChunksExactWrappingLendingIterator<'_, Self::Element, Self::SelfView<'_>> {
let entity_count = self.entity_count();
assert!(
entity_count % chunk_size == 0,
entity_count.is_multiple_of(chunk_size),
"The current container has {entity_count} entities, which is not dividable by the \
requested chunk_size: {chunk_size}, preventing chunks_exact from returning an iterator."
);
@@ -297,7 +297,7 @@ pub trait ContiguousEntityContainer: AsRef<[Self::Element]> {
{
let entity_count = self.entity_count();
assert!(
entity_count % chunk_size == 0,
entity_count.is_multiple_of(chunk_size),
"The current container has {entity_count} entities, which is not dividable by the \
requested chunk_size: {chunk_size}, preventing chunks_exact from returning an iterator."
);
@@ -435,7 +435,7 @@ pub trait ContiguousEntityContainerMut: ContiguousEntityContainer + AsMut<[Self:
) -> ChunksExactWrappingLendingIteratorMut<'_, Self::Element, Self::SelfMutView<'_>> {
let entity_count = self.entity_count();
assert!(
entity_count % chunk_size == 0,
entity_count.is_multiple_of(chunk_size),
"The current container has {entity_count} entities, which is not dividable by the \
requested chunk_size: {chunk_size}, preventing chunks_exact_mut from returning an \
iterator."
@@ -515,7 +515,7 @@ pub trait ContiguousEntityContainerMut: ContiguousEntityContainer + AsMut<[Self:
{
let entity_count = self.entity_count();
assert!(
entity_count % chunk_size == 0,
entity_count.is_multiple_of(chunk_size),
"The current container has {entity_count} entities, which is not dividable by the \
requested chunk_size: {chunk_size}, preventing chunks_exact from returning an iterator."
);

View File

@@ -406,7 +406,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GgswCiphertext<C>
"Got an empty container to create a GgswCiphertext"
);
assert!(
container.container_len() % (glwe_size.0 * glwe_size.0 * polynomial_size.0) == 0,
container
.container_len()
.is_multiple_of(glwe_size.0 * glwe_size.0 * polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by glwe_size * glwe_size * polynomial_size: {}. \
Got container length: {} and glwe_size: {glwe_size:?}, \

View File

@@ -173,9 +173,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GgswCiphertextList
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len()
% (decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0)
== 0,
container.container_len().is_multiple_of(
decomp_level_count.0 * glwe_size.0 * glwe_size.0 * polynomial_size.0
),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * glwe_size * glwe_size * polynomial_size: \
{}.Got container length: {} and decomp_level_count: {decomp_level_count:?}, \

View File

@@ -141,7 +141,7 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GlweMask<C> {
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len() % polynomial_size.0 == 0,
container.container_len().is_multiple_of(polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by polynomial_size. \
Got container length: {} and polynomial_size: {polynomial_size:?}.",
@@ -414,7 +414,7 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GlweCiphertext<C>
"Got an empty container to create a GlweCiphertext"
);
assert!(
container.container_len() % polynomial_size.0 == 0,
container.container_len().is_multiple_of(polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by polynomial_size. \
Got container length: {} and polynomial_size: {polynomial_size:?}.",

View File

@@ -126,7 +126,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GlweCiphertextList
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len() % glwe_ciphertext_size(glwe_size, polynomial_size) == 0,
container
.container_len()
.is_multiple_of(glwe_ciphertext_size(glwe_size, polynomial_size)),
"The provided container length is not valid. \
It needs to be dividable by glwe_size * polynomial_size. \
Got container length: {}, glwe_size: {glwe_size:?}, polynomial_size: {polynomial_size:?}.",

View File

@@ -195,13 +195,13 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GlweKeyswitchKey<C
"Got an empty container to create a GlweKeyswitchKey"
);
assert!(
container.container_len()
% glwe_keyswitch_key_input_key_element_encrypted_size(
container.container_len().is_multiple_of(
glwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_glwe_size,
poly_size
)
== 0,
),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_glwe_size * output_poly_size: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}, \

View File

@@ -88,7 +88,7 @@ impl<Scalar, C: Container<Element = Scalar>> GlweSecretKey<C> {
"Got an empty container to create a GlweSecretKey"
);
assert!(
container.container_len() % polynomial_size.0 == 0,
container.container_len().is_multiple_of(polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by polynomial_size. \
Got container length: {} and polynomial_size: {polynomial_size:?}",

View File

@@ -382,7 +382,7 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweMaskList<C> {
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
assert!(
container.container_len() % lwe_dimension.0 == 0,
container.container_len().is_multiple_of(lwe_dimension.0),
"The provided container length is not valid. \
It needs to be dividable by lwe_dimension. \
Got container length: {} and lwe_dimension: {lwe_dimension:?}.",

View File

@@ -144,7 +144,7 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweCiphertextList<
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len() % lwe_size.0 == 0,
container.container_len().is_multiple_of(lwe_size.0),
"The provided container length is not valid. \
It needs to be dividable by lwe_size. \
Got container length: {} and lwe_size: {lwe_size:?}.",

View File

@@ -48,7 +48,7 @@ pub fn lwe_compact_ciphertext_list_mask_count(
) -> LweMaskCount {
LweMaskCount(
lwe_ciphertext_count.0 / lwe_dimension.0
+ if lwe_ciphertext_count.0 % lwe_dimension.0 == 0 {
+ if lwe_ciphertext_count.0.is_multiple_of(lwe_dimension.0) {
0
} else {
1

View File

@@ -188,12 +188,12 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweKeyswitchKey<C>
"Got an empty container to create an LweKeyswitchKey"
);
assert!(
container.container_len()
% lwe_keyswitch_key_input_key_element_encrypted_size(
container.container_len().is_multiple_of(
lwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_lwe_size
)
== 0,
),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_lwe_size: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}, \

View File

@@ -122,12 +122,12 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweKeyswitchKeyChu
"Got an empty container to create an LweKeyswitchKeyChunk"
);
assert!(
container.container_len()
% lwe_keyswitch_key_input_key_element_encrypted_size(
container.container_len().is_multiple_of(
lwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_lwe_size
)
== 0,
),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_lwe_size: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}, \

View File

@@ -37,7 +37,7 @@ impl<C: Container<Element = c64>> FourierLweMultiBitBootstrapKey<C> {
grouping_factor: LweBskGroupingFactor,
) -> Self {
assert!(
input_lwe_dimension.0 % grouping_factor.0 == 0,
input_lwe_dimension.0.is_multiple_of(grouping_factor.0),
"Multi Bit BSK requires input LWE dimension to be a multiple of {}",
grouping_factor.0
);
@@ -182,7 +182,7 @@ impl FourierLweMultiBitBootstrapKeyOwned {
grouping_factor: LweBskGroupingFactor,
) -> Self {
assert!(
input_lwe_dimension.0 % grouping_factor.0 == 0,
input_lwe_dimension.0.is_multiple_of(grouping_factor.0),
"Multi Bit BSK requires input LWE dimension ({}) to be a multiple of {}",
input_lwe_dimension.0,
grouping_factor.0

View File

@@ -26,7 +26,7 @@ pub fn equivalent_multi_bit_lwe_dimension(
input_lwe_dimension: LweDimension,
grouping_factor: LweBskGroupingFactor,
) -> Result<LweDimension, &'static str> {
if input_lwe_dimension.0 % grouping_factor.0 != 0 {
if !input_lwe_dimension.0.is_multiple_of(grouping_factor.0) {
return Err("equivalent_multi_bit_lwe_dimension error: \
input_lwe_dimension is required to be a multiple of grouping_factor");
}

View File

@@ -196,7 +196,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweMultiBitBootstr
grouping_factor,
};
assert!(
bsk.input_lwe_dimension().0 % grouping_factor.0 == 0,
bsk.input_lwe_dimension()
.0
.is_multiple_of(grouping_factor.0),
"Input LWE dimension ({}) of the bootstrap key needs to be a multiple of {}",
bsk.input_lwe_dimension().0,
grouping_factor.0,
@@ -333,7 +335,7 @@ impl<Scalar: UnsignedInteger> LweMultiBitBootstrapKeyOwned<Scalar> {
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
assert!(
input_lwe_dimension.0 % grouping_factor.0 == 0,
input_lwe_dimension.0.is_multiple_of(grouping_factor.0),
"Multi Bit BSK requires input LWE dimension ({}) to be a multiple of {}",
input_lwe_dimension.0,
grouping_factor.0

View File

@@ -144,13 +144,13 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LwePackingKeyswitc
"Got an empty container to create an LwePackingKeyswitchKey"
);
assert!(
container.container_len()
% lwe_packing_keyswitch_key_input_key_element_encrypted_size(
container.container_len().is_multiple_of(
lwe_packing_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_glwe_size,
output_polynomial_size
)
== 0,
),
"The provided container length is not valid. \
It needs to be dividable by: {}. Got container length: {} and decomp_level_count: \
{decomp_level_count:?}, output_glwe_size: {output_glwe_size:?}, output_polynomial_size: \

View File

@@ -211,13 +211,13 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>>
"Got an empty container to create an LweKeyswitchKey"
);
assert!(
container.container_len()
% lwe_pfpksk_input_key_element_encrypted_size(
container
.container_len()
.is_multiple_of(lwe_pfpksk_input_key_element_encrypted_size(
decomp_level_count,
output_glwe_size,
output_polynomial_size
)
== 0,
)),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_glwe_size * output_polynomial_size:\
{}. Got container length: {} and decomp_level_count: {decomp_level_count:?}, \

View File

@@ -144,14 +144,12 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>>
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len()
% lwe_pfpksk_size(
container.container_len().is_multiple_of(lwe_pfpksk_size(
input_lwe_size,
decomp_level_count,
output_glwe_size,
output_polynomial_size
)
== 0,
)),
"The provided container length is not valid. \
It needs to be dividable by input_lwe_size * decomp_level_count * output_glwe_size * \
output_polynomial_size: {}. Got container length: {} and input_lwe_size: {input_lwe_size:?}\

View File

@@ -109,9 +109,11 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> NttGgswCiphertextL
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
assert!(
data.container_len()
% ggsw_ciphertext_size(glwe_size, polynomial_size, decomposition_level_count)
== 0,
data.container_len().is_multiple_of(ggsw_ciphertext_size(
glwe_size,
polynomial_size,
decomposition_level_count
)),
"The provided container length is not valid. \
It needs to be dividable by the size of a GGSW ciphertext: {}. \
Got container length: {}.",

View File

@@ -63,7 +63,7 @@ impl<Scalar, C: Container<Element = Scalar>> PolynomialList<C> {
/// ```
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> Self {
assert!(
container.container_len() % polynomial_size.0 == 0,
container.container_len().is_multiple_of(polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by polynomial_size. \
Got container length: {} and polynomial_size: {polynomial_size:?}.",

View File

@@ -165,7 +165,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededGgswCipherte
"Got an empty container to create a SeededGgswCiphertext"
);
assert!(
container.container_len() % (glwe_size.0 * polynomial_size.0) == 0,
container
.container_len()
.is_multiple_of(glwe_size.0 * polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by glwe_size * polynomial_size: {}. \
Got container length: {} and glwe_size: {glwe_size:?}, \

View File

@@ -142,8 +142,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededGgswCipherte
);
assert!(
container.container_len() % (decomp_level_count.0 * glwe_size.0 * polynomial_size.0)
== 0,
container
.container_len()
.is_multiple_of(decomp_level_count.0 * glwe_size.0 * polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * glwe_size * polynomial_size: \
{}.Got container length: {} and decomp_level_count: {decomp_level_count:?}, \
@@ -487,7 +488,11 @@ impl<Scalar: UnsignedInteger> TryFrom<&MultiBitBootstrapKeyConformanceParams<Sca
type Error = ();
fn try_from(value: &MultiBitBootstrapKeyConformanceParams<Scalar>) -> Result<Self, ()> {
if value.input_lwe_dimension.0 % value.grouping_factor.0 != 0 {
if !value
.input_lwe_dimension
.0
.is_multiple_of(value.grouping_factor.0)
{
return Err(());
}

View File

@@ -149,7 +149,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLweKeyswitch
"Got an empty container to create an SeededLweKeyswitchKey"
);
assert!(
container.container_len() % (decomp_level_count.0) == 0,
container
.container_len()
.is_multiple_of(decomp_level_count.0),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}.",

View File

@@ -142,7 +142,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLweKeyswitch
"Got an empty container to create a SeededLweKeyswitchKeyChunk"
);
assert!(
container.container_len() % (decomp_level_count.0) == 0,
container
.container_len()
.is_multiple_of(decomp_level_count.0),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}.",

View File

@@ -203,7 +203,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLweMultiBitB
};
assert!(
bsk.input_lwe_dimension().0 % grouping_factor.0 == 0,
bsk.input_lwe_dimension()
.0
.is_multiple_of(grouping_factor.0),
"Input LWE dimension ({}) of the bootstrap key needs to be a multiple of {}",
bsk.input_lwe_dimension().0,
grouping_factor.0,
@@ -421,7 +423,7 @@ impl<Scalar: UnsignedInteger> SeededLweMultiBitBootstrapKeyOwned<Scalar> {
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
assert!(
input_lwe_dimension.0 % grouping_factor.0 == 0,
input_lwe_dimension.0.is_multiple_of(grouping_factor.0),
"Multi Bit BSK requires input LWE dimension ({}) to be a multiple of {}",
input_lwe_dimension.0,
grouping_factor.0

View File

@@ -174,7 +174,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> SeededLwePackingKe
"Got an empty container to create an SeededLwePackingKeyswitchKey"
);
assert!(
container.container_len() % (decomp_level_count.0 * output_polynomial_size.0) == 0,
container
.container_len()
.is_multiple_of(decomp_level_count.0 * output_polynomial_size.0),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_polynomial_size: {}. \
Got container length: {} decomp_level_count: {decomp_level_count:?} \

View File

@@ -270,9 +270,9 @@ impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> PseudoGgswCipherte
"Got an empty container to create a PseudoGgswCiphertext"
);
assert!(
container.container_len()
% (input_glwe_size.to_glwe_dimension().0 * output_glwe_size.0 * polynomial_size.0)
== 0,
container.container_len().is_multiple_of(
input_glwe_size.to_glwe_dimension().0 * output_glwe_size.0 * polynomial_size.0
),
"The provided container length is not valid. \
It needs to be dividable by glwe_dimension_in * output_glwe_size * polynomial_size: {}. \
Got container length: {} and glwe_dimension_in: {:?}, output_glwe_size: \

View File

@@ -20,7 +20,7 @@ pub fn polynomial_wrapping_monic_monomial_mul_assign_split(
let output_lo = output_lo.into_container();
let output_hi = output_hi.into_container();
let full_cycles_count = monomial_degree.0 / output_lo.container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
izip_eq!(&mut *output_lo, &mut *output_hi)
.for_each(|(lo, hi)| (*lo, *hi) = wrapping_neg((*lo, *hi)));
}
@@ -40,7 +40,7 @@ pub fn polynomial_wrapping_monic_monomial_div_assign_split(
let output_lo = output_lo.into_container();
let output_hi = output_hi.into_container();
let full_cycles_count = monomial_degree.0 / output_lo.container_len();
if full_cycles_count % 2 != 0 {
if !full_cycles_count.is_multiple_of(2) {
izip_eq!(&mut *output_lo, &mut *output_hi)
.for_each(|(lo, hi)| (*lo, *hi) = wrapping_neg((*lo, *hi)));
}

View File

@@ -585,9 +585,10 @@ impl<C: ContainerMut<Element = c64>> FourierPolynomialList<C> {
pub fn iter_mut(
&mut self,
) -> impl DoubleEndedIterator<Item = FourierPolynomial<&'_ mut [c64]>> {
assert!(
self.data.container_len() % self.polynomial_size.to_fourier_polynomial_size().0 == 0
);
assert!(self
.data
.container_len()
.is_multiple_of(self.polynomial_size.to_fourier_polynomial_size().0));
self.data
.as_mut()
.chunks_exact_mut(self.polynomial_size.to_fourier_polynomial_size().0)

View File

@@ -964,7 +964,7 @@ fn num_bits_to_strict_num_blocks(
message_modulus: MessageModulus,
) -> crate::Result<usize> {
let bits_per_block = message_modulus.0.ilog2();
if num_bits as u32 % bits_per_block != 0 {
if !(num_bits as u32).is_multiple_of(bits_per_block) {
let message = format!("Number of bits must be a multiple of the parameter's MessageModulus.ilog2 ({bits_per_block} here)");
return Err(crate::Error::new(message));
}

View File

@@ -261,9 +261,10 @@ mod gpu {
}
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub enum CudaGpuChoice {
Single(GpuIndex),
#[default]
Multi,
Custom(CustomMultiGpuIndexes),
}
@@ -295,12 +296,6 @@ mod gpu {
}
}
}
impl Default for CudaGpuChoice {
fn default() -> Self {
Self::Multi
}
}
}
#[cfg(feature = "hpu")]

View File

@@ -65,7 +65,7 @@ fn unpack_and_sanitize(
unpacked.push(block.clone());
unpacked.push(block);
}
if block_count % 2 == 0 {
if block_count.is_multiple_of(2) {
unpacked.push(packed_blocks[0].clone());
}
unpacked.push(packed_blocks.pop().unwrap());

View File

@@ -412,7 +412,7 @@ impl ServerKey {
// to trim out bits which should not be there
let mut trim_last_interesting_divisor_bits = || {
if ((msb_bit_set + 1) % num_bits_in_message as usize) == 0 {
if (msb_bit_set + 1).is_multiple_of(num_bits_in_message as usize) {
return;
}
// The last block of the interesting part of the remainder
@@ -441,7 +441,7 @@ impl ServerKey {
let mut trim_first_divisor_ms_bits = || {
if divisor_ms_blocks.blocks.is_empty()
|| ((msb_bit_set + 1) % num_bits_in_message as usize) == 0
|| (msb_bit_set + 1).is_multiple_of(num_bits_in_message as usize)
{
return;
}

View File

@@ -76,7 +76,7 @@ impl ServerKey {
let len = blocks.len();
if len % 2 == 0 {
if len.is_multiple_of(2) {
paired_blocks = blocks;
last_block = None;
} else {

View File

@@ -393,8 +393,8 @@ pub(crate) mod test {
};
let prf = |x| {
let a = (negacyclic_part(x) + p_prime - 1) % (2 * output_p);
assert!(a % 2 == 0);
let a: u64 = (negacyclic_part(x) + p_prime - 1) % (2 * output_p);
assert!(a.is_multiple_of(2));
a / 2
};

View File

@@ -69,7 +69,7 @@ impl Compactable for &ClearString {
if let Some(n) = num_blocks {
assert!(
n as u32 % blocks_per_char == 0,
(n as u32).is_multiple_of(blocks_per_char),
"Inconsistent num block would split the string inside a a character"
);
}

View File

@@ -26,7 +26,6 @@
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -393,7 +392,6 @@
"integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/template": "^7.25.0",
"@babel/types": "^7.25.6"
@@ -2133,6 +2131,7 @@
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2392,6 +2391,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001646",
"electron-to-chromium": "^1.5.4",
@@ -2714,8 +2714,7 @@
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/core-js-compat": {
"version": "3.38.1",
@@ -3004,7 +3003,6 @@
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -3308,7 +3306,6 @@
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"json5": "lib/cli.js"
},
@@ -3882,6 +3879,7 @@
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -4401,6 +4399,7 @@
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "^1.0.5",
"@webassemblyjs/ast": "^1.12.1",
@@ -4448,6 +4447,7 @@
"integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^2.1.1",

View File

@@ -1 +1 @@
nightly-2025-08-26
nightly-2025-11-19

View File

@@ -382,7 +382,7 @@ fn main() {
"crate::shortint::parameters::{old_param_dir_name}::{old_param_prefix}{current_normalized_param_ident_str}"
)).unwrap();
param.expr = Box::new(old_param_path_expr);
*param.expr = old_param_path_expr;
modified_item_count += 1;
}

View File

@@ -9,7 +9,7 @@ publish = false
crate-type = ["cdylib"]
[dependencies]
clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "334fb906aef13d20050987b13448f37391bb97a2" }
clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "c936595d17413c1f08e162e117e504fb4ed126e4" }
dylint_linting = "4.1.0"
[dev-dependencies]

View File

@@ -27,3 +27,13 @@ Use instead:
#[versionize(MyStructVersions)]
pub struct MyStruct {}
```
## Updating to new toolchains
The dylint library is frequently updated to support new toolchains. To update the tool to the
latest supported toolchain, simply run the following command in this folder:
```
cargo dylint upgrade
```
Since the tool uses the Rust compiler API, which is unstable, manual adjustments to the code may be
necessary.

View File

@@ -1,4 +1,4 @@
[toolchain]
channel = "nightly-2025-08-07"
channel = "nightly-2025-10-31"
components = ["llvm-tools-preview", "rustc-dev"]
profile = "default"

View File

@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for SerializeWithoutVersionize {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
// If the currently checked item is a trait impl
if let ItemKind::Impl(Impl {
of_trait: Some(ref trait_ref),
of_trait: Some(trait_ref),
..
}) = item.kind
{
@@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for SerializeWithoutVersionize {
}
// Check if the implemented trait is `Serialize`
if let Some(def_id) = trait_ref.trait_def_id() {
if let Some(def_id) = trait_ref.trait_ref.trait_def_id() {
let path = cx.get_def_path(def_id);
if path == symbols_list_from_str(&SERIALIZE_TRAIT)
|| path == symbols_list_from_str(&SERIALIZE_TRAIT_LEGACY)
@@ -97,10 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for SerializeWithoutVersionize {
cx.tcx
.for_each_relevant_impl(versionize_trait, ty, |impl_id| {
if !found_impl {
let trait_ref = cx
.tcx
.impl_trait_ref(impl_id)
.expect("must be a trait implementation");
let trait_ref = cx.tcx.impl_trait_ref(impl_id);
if trait_ref.instantiate_identity().args.type_at(0) == ty {
found_impl = true;