diff options
Diffstat (limited to 'src/tools/clippy/tests/ui/missing_const_for_fn')
4 files changed, 295 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs new file mode 100644 index 000000000..7b9dc76b8 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs @@ -0,0 +1,8 @@ +// This file provides a const function that is unstably const forever. + +#![feature(staged_api)] +#![stable(feature = "1", since = "1.0.0")] + +#[stable(feature = "1", since = "1.0.0")] +#[rustc_const_unstable(feature = "foo", issue = "none")] +pub const fn unstably_const_fn() {} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs new file mode 100644 index 000000000..aa60d0504 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -0,0 +1,121 @@ +//! False-positive tests to ensure we don't suggest `const` for things where it would cause a +//! compilation error. +//! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. + +// aux-build:helper.rs + +#![warn(clippy::missing_const_for_fn)] +#![feature(start)] +#![feature(custom_inner_attributes)] + +extern crate helper; + +struct Game; + +// This should not be linted because it's already const +const fn already_const() -> i32 { + 32 +} + +impl Game { + // This should not be linted because it's already const + pub const fn already_const() -> i32 { + 32 + } +} + +// Allowing on this function, because it would lint, which we don't want in this case. +#[allow(clippy::missing_const_for_fn)] +fn random() -> u32 { + 42 +} + +// We should not suggest to make this function `const` because `random()` is non-const +fn random_caller() -> u32 { + random() +} + +static Y: u32 = 0; + +// We should not suggest to make this function `const` because const functions are not allowed to +// refer to a static variable +fn get_y() -> u32 { + Y + //~^ ERROR E0013 +} + +// Don't lint entrypoint functions +#[start] +fn init(num: isize, something: *const *const u8) -> isize { + 1 +} + +trait Foo { + // This should not be suggested to be made const + // (rustc doesn't allow const trait methods) + fn f() -> u32; + + // This should not be suggested to be made const either + fn g() -> u32 { + 33 + } +} + +// Don't lint in external macros (derive) +#[derive(PartialEq, Eq)] +struct Point(isize, isize); + +impl std::ops::Add for Point { + type Output = Self; + + // Don't lint in trait impls of derived methods + fn add(self, other: Self) -> Self { + Point(self.0 + other.0, self.1 + other.1) + } +} + +mod with_drop { + pub struct A; + pub struct B; + impl Drop for A { + fn drop(&mut self) {} + } + + impl A { + // This can not be const because the type implements `Drop`. + pub fn b(self) -> B { + B + } + } + + impl B { + // This can not be const because `a` implements `Drop`. + pub fn a(self, a: A) -> B { + B + } + } +} + +fn const_generic_params<T, const N: usize>(t: &[T; N]) -> &[T; N] { + t +} + +fn const_generic_return<T, const N: usize>(t: &[T]) -> &[T; N] { + let p = t.as_ptr() as *const [T; N]; + + unsafe { &*p } +} + +// Do not lint this because it calls a function whose constness is unstable. +fn unstably_const_fn() { + helper::unstably_const_fn() +} + +mod const_fn_stabilized_after_msrv { + #![clippy::msrv = "1.46.0"] + + // Do not lint this because `u8::is_ascii_digit` is stabilized as a const function in 1.47.0. + fn const_fn_stabilized_after_msrv(byte: u8) { + byte.is_ascii_digit(); + } +} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs new file mode 100644 index 000000000..88f6935d2 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs @@ -0,0 +1,81 @@ +#![warn(clippy::missing_const_for_fn)] +#![allow(incomplete_features, clippy::let_and_return)] +#![feature(custom_inner_attributes)] + +use std::mem::transmute; + +struct Game { + guess: i32, +} + +impl Game { + // Could be const + pub fn new() -> Self { + Self { guess: 42 } + } + + fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { + b + } +} + +// Could be const +fn one() -> i32 { + 1 +} + +// Could also be const +fn two() -> i32 { + let abc = 2; + abc +} + +// Could be const (since Rust 1.39) +fn string() -> String { + String::new() +} + +// Could be const +unsafe fn four() -> i32 { + 4 +} + +// Could also be const +fn generic<T>(t: T) -> T { + t +} + +fn sub(x: u32) -> usize { + unsafe { transmute(&x) } +} + +fn generic_arr<T: Copy>(t: [T; 1]) -> T { + t[0] +} + +mod with_drop { + pub struct A; + pub struct B; + impl Drop for A { + fn drop(&mut self) {} + } + + impl B { + // This can be const, because `a` is passed by reference + pub fn b(self, a: &A) -> B { + B + } + } +} + +mod const_fn_stabilized_before_msrv { + #![clippy::msrv = "1.47.0"] + + // This could be const because `u8::is_ascii_digit` is a stable const function in 1.47. + fn const_fn_stabilized_before_msrv(byte: u8) { + byte.is_ascii_digit(); + } +} + +// Should not be const +fn main() {} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr new file mode 100644 index 000000000..3eb52b682 --- /dev/null +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -0,0 +1,85 @@ +error: this could be a `const fn` + --> $DIR/could_be_const.rs:13:5 + | +LL | / pub fn new() -> Self { +LL | | Self { guess: 42 } +LL | | } + | |_____^ + | + = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:17:5 + | +LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] { +LL | | b +LL | | } + | |_____^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:23:1 + | +LL | / fn one() -> i32 { +LL | | 1 +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:28:1 + | +LL | / fn two() -> i32 { +LL | | let abc = 2; +LL | | abc +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:34:1 + | +LL | / fn string() -> String { +LL | | String::new() +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:39:1 + | +LL | / unsafe fn four() -> i32 { +LL | | 4 +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:44:1 + | +LL | / fn generic<T>(t: T) -> T { +LL | | t +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:52:1 + | +LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T { +LL | | t[0] +LL | | } + | |_^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:65:9 + | +LL | / pub fn b(self, a: &A) -> B { +LL | | B +LL | | } + | |_________^ + +error: this could be a `const fn` + --> $DIR/could_be_const.rs:75:5 + | +LL | / fn const_fn_stabilized_before_msrv(byte: u8) { +LL | | byte.is_ascii_digit(); +LL | | } + | |_____^ + +error: aborting due to 10 previous errors + |