blob: 95bf63ed1df6f988fd0a949b50990d943ece1166 [file] [log] [blame]
#![warn(clippy::missing_const_for_fn)]
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
#![feature(const_trait_impl)]
use std::mem::transmute;
struct Game {
guess: i32,
}
impl Game {
// Could be const
pub const fn new() -> Self {
//~^ missing_const_for_fn
Self { guess: 42 }
}
const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
//~^ missing_const_for_fn
b
}
}
// Could be const
const fn one() -> i32 {
//~^ missing_const_for_fn
1
}
// Could also be const
const fn two() -> i32 {
//~^ missing_const_for_fn
let abc = 2;
abc
}
// Could be const (since Rust 1.39)
const fn string() -> String {
//~^ missing_const_for_fn
String::new()
}
// Could be const
const unsafe fn four() -> i32 {
//~^ missing_const_for_fn
4
}
// Could also be const
const fn generic<T>(t: T) -> T {
//~^ missing_const_for_fn
t
}
fn sub(x: u32) -> usize {
unsafe { transmute(&x) }
}
const fn generic_arr<T: Copy>(t: [T; 1]) -> T {
//~^ missing_const_for_fn
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 const fn b(self, a: &A) -> B {
//~^ missing_const_for_fn
B
}
}
}
#[clippy::msrv = "1.47.0"]
mod const_fn_stabilized_before_msrv {
// This could be const because `u8::is_ascii_digit` is a stable const function in 1.47.
const fn const_fn_stabilized_before_msrv(byte: u8) {
//~^ missing_const_for_fn
byte.is_ascii_digit();
}
}
#[clippy::msrv = "1.45"]
fn msrv_1_45() -> i32 {
45
}
#[clippy::msrv = "1.46"]
const fn msrv_1_46() -> i32 {
//~^ missing_const_for_fn
46
}
// Should not be const
fn main() {}
struct D;
/* FIXME(const_trait_impl)
impl const Drop for D {
fn drop(&mut self) {
todo!();
}
}
*/
// Lint this, since it can be dropped in const contexts
// FIXME(const_trait_impl)
const fn d(this: D) {}
//~^ missing_const_for_fn
mod msrv {
struct Foo(*const u8, &'static u8);
impl Foo {
#[clippy::msrv = "1.58"]
const fn deref_ptr_can_be_const(self) -> usize {
//~^ missing_const_for_fn
unsafe { *self.0 as usize }
}
const fn deref_copied_val(self) -> usize {
//~^ missing_const_for_fn
*self.1 as usize
}
}
union Bar {
val: u8,
}
#[clippy::msrv = "1.56"]
const fn union_access_can_be_const() {
//~^ missing_const_for_fn
let bar = Bar { val: 1 };
let _ = unsafe { bar.val };
}
#[clippy::msrv = "1.62"]
mod with_extern {
const unsafe extern "C" fn c() {}
//~^ missing_const_for_fn
#[rustfmt::skip]
#[allow(missing_abi)]
const extern fn implicit_c() {}
//~^ missing_const_for_fn
// any item functions in extern block won't trigger this lint
unsafe extern "C" {
fn c_in_block();
}
}
}
mod issue12677 {
pub struct Wrapper {
pub strings: Vec<String>,
}
impl Wrapper {
#[must_use]
pub const fn new(strings: Vec<String>) -> Self {
//~^ missing_const_for_fn
Self { strings }
}
#[must_use]
pub const fn empty() -> Self {
//~^ missing_const_for_fn
Self { strings: Vec::new() }
}
}
pub struct Other {
pub text: String,
pub vec: Vec<String>,
}
impl Other {
pub const fn new(text: String) -> Self {
//~^ missing_const_for_fn
let vec = Vec::new();
Self { text, vec }
}
}
}
mod with_ty_alias {
trait FooTrait {
type Foo: std::fmt::Debug;
fn bar(_: Self::Foo) {}
}
impl FooTrait for () {
type Foo = i32;
}
// NOTE: When checking the type of a function param, make sure it is not an alias with
// `AliasTyKind::Projection` before calling `TyCtxt::type_of` to find out what the actual type
// is. Because the associate ty could have no default, therefore would cause ICE, as demonstrated
// in this test.
const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
//~^ missing_const_for_fn
}
mod extern_fn {
const extern "C-unwind" fn c_unwind() {}
//~^ missing_const_for_fn
const extern "system" fn system() {}
//~^ missing_const_for_fn
const extern "system-unwind" fn system_unwind() {}
//~^ missing_const_for_fn
}
const fn mut_add(x: &mut i32) {
//~^ missing_const_for_fn
*x += 1;
}
mod issue_15079 {
pub trait Trait {}
pub struct Struct<T: Trait> {
_t: Option<T>,
}
impl<T: Trait> Struct<T> {
#[clippy::msrv = "1.60"]
pub fn new_1_60() -> Self {
Self { _t: None }
}
#[clippy::msrv = "1.61"]
pub const fn new_1_61() -> Self {
//~^ missing_const_for_fn
Self { _t: None }
}
}
pub struct S2<T> {
_t: Option<T>,
}
impl<T> S2<T> {
#[clippy::msrv = "1.60"]
pub const fn new_1_60() -> Self {
//~^ missing_const_for_fn
Self { _t: None }
}
#[clippy::msrv = "1.61"]
pub const fn new_1_61() -> Self {
//~^ missing_const_for_fn
Self { _t: None }
}
}
pub struct S3<T: ?Sized + 'static> {
_t: Option<&'static T>,
}
impl<T: ?Sized + 'static> S3<T> {
#[clippy::msrv = "1.60"]
pub const fn new_1_60() -> Self {
//~^ missing_const_for_fn
Self { _t: None }
}
#[clippy::msrv = "1.61"]
pub const fn new_1_61() -> Self {
//~^ missing_const_for_fn
Self { _t: None }
}
}
}