Skip to content

[False Positive] Regarding adding const to a function that can't be const #14658

Open
@leonardo-m

Description

@leonardo-m

Summary

If I have this little Rust program (probably it's not minimized, but it's short enough):

#![feature(const_trait_impl)]
#![feature(nonzero_internals)]
#![allow(internal_features)]

#![warn(clippy::all)]
#![warn(clippy::missing_const_for_fn)]

use std::num::{NonZero, ZeroablePrimitive};

//- - - - - - - -

trait NarrowRem<Out: ZeroablePrimitive> {
    fn narrowing_rem(&self, den: NonZero<Out>) -> Out;
}


impl NarrowRem<u32> for u64 {
    #[inline(always)]
    fn narrowing_rem(&self, den: NonZero<u32>) -> u32 {
        (*self % NonZero::from(den)) as _
    }
}

//- - - - - - - -

#[const_trait]
trait MulModCast where Self: ZeroablePrimitive {
    fn mul_mod(self, b: Self, m: NonZero<Self>) -> Self;
}

impl MulModCast for u32 {
    #[inline]
    fn mul_mod(self, b: Self, m: NonZero<Self>) -> Self {
        (u64::from(self) * u64::from(b)).narrowing_rem(m)
    }
}

//- - - - - - - -

const fn pow_mod(mut a: u32, mut x: u32, nz: NonZero<u32>) -> u32
where u32: MulModCast {
    let mut r: u32 = 1;
    while x != 0 {
        if (x & 1) == 1 {
            r = a.mul_mod(r, nz);
        }
        x >>= 1;
        a = a.mul_mod(a, nz);
    }
    r
}

fn main() {
    assert_eq!(pow_mod(19, 11, NonZero::new(7).unwrap()), 3);
}

Clippy gives me this warning:

  --> ...\main.rs:40:1
   |
40 | / fn pow_mod(mut a: u32, mut x: u32, nz: NonZero<u32>) -> u32
41 | | where u32: MulModCast {
42 | |     let mut r: u32 = 1;
43 | |     while x != 0 {
...  |
50 | |     r
51 | | }
   | |_^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
note: the lint level is defined here
  --> ...\main.rs:6:9
   |
6  | #![warn(clippy::missing_const_for_fn)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: make the function `const`
   |
40 | const fn pow_mod(mut a: u32, mut x: u32, nz: NonZero<u32>) -> u32
   | +++++

But if I add const to pow_mod, the rustc compiler (1.88.0-nightly 2025-04-19) gives me:

error[E0277]: the trait bound `u32: ~const MulModCast` is not satisfied
  --> C:\lavoro\metti_a_posto\progettini_in_corso\eulers\many_solutions\test1\src\main.rs:45:17
   |
45 |             r = a.mul_mod(r, nz);
   |                 ^

error[E0277]: the trait bound `u32: ~const MulModCast` is not satisfied
  --> C:\lavoro\metti_a_posto\progettini_in_corso\eulers\many_solutions\test1\src\main.rs:48:13
   |
48 |         a = a.mul_mod(a, nz);
   |             ^

(I have other examples of false positives of clippy::missing_const_for_fn).

Lint Name

No response

Reproducer

I tried this code:

<code>

I saw this happen:

<output>

I expected to see this happen:

Version


Additional Labels

No response

Metadata

Metadata

Assignees

Labels

C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't have

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions