diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index dc5a58abe56d..e829baa22688 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -2,12 +2,13 @@ use crate::utils::{has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; use rustc::lint::in_external_macro; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, Constness, FnDecl, HirId}; +use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; use rustc_typeck::hir_ty_to_ty; +use std::matches; declare_clippy_lint! { /// **What it does:** @@ -90,8 +91,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingConstForFn { // Perform some preliminary checks that rule out constness on the Clippy side. This way we // can skip the actual const check and return early. match kind { - FnKind::ItemFn(_, _, header, ..) => { - if already_const(header) { + FnKind::ItemFn(_, generics, header, ..) => { + let has_const_generic_params = generics + .params + .iter() + .any(|param| matches!(param.kind, GenericParamKind::Const{ .. })); + + if already_const(header) || has_const_generic_params { return; } }, diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index f367279906fd..ba352ef9ee93 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -3,7 +3,8 @@ //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere. #![warn(clippy::missing_const_for_fn)] -#![feature(start)] +#![allow(incomplete_features)] +#![feature(start, const_generics)] struct Game; @@ -90,3 +91,13 @@ mod with_drop { } } } + +fn const_generic_params(t: &[T; N]) -> &[T; N] { + t +} + +fn const_generic_return(t: &[T]) -> &[T; N] { + let p = t.as_ptr() as *const [T; N]; + + unsafe { &*p } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 9a73dcbe99f1..c6f44b7daa34 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,5 +1,6 @@ #![warn(clippy::missing_const_for_fn)] -#![allow(clippy::let_and_return)] +#![allow(incomplete_features, clippy::let_and_return)] +#![feature(const_generics)] use std::mem::transmute; @@ -12,6 +13,10 @@ impl Game { 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 diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 165b8a030771..8dde56cd79f4 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> $DIR/could_be_const.rs:12:5 + --> $DIR/could_be_const.rs:13:5 | LL | / pub fn new() -> Self { LL | | Self { guess: 42 } @@ -9,7 +9,15 @@ LL | | } = note: `-D clippy::missing-const-for-fn` implied by `-D warnings` error: this could be a `const fn` - --> $DIR/could_be_const.rs:18:1 + --> $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 @@ -17,7 +25,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:23:1 + --> $DIR/could_be_const.rs:28:1 | LL | / fn two() -> i32 { LL | | let abc = 2; @@ -26,7 +34,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:29:1 + --> $DIR/could_be_const.rs:34:1 | LL | / fn string() -> String { LL | | String::new() @@ -34,7 +42,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:34:1 + --> $DIR/could_be_const.rs:39:1 | LL | / unsafe fn four() -> i32 { LL | | 4 @@ -42,7 +50,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:39:1 + --> $DIR/could_be_const.rs:44:1 | LL | / fn generic(t: T) -> T { LL | | t @@ -50,7 +58,7 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:43:1 + --> $DIR/could_be_const.rs:48:1 | LL | / fn sub(x: u32) -> usize { LL | | unsafe { transmute(&x) } @@ -58,12 +66,12 @@ LL | | } | |_^ error: this could be a `const fn` - --> $DIR/could_be_const.rs:62:9 + --> $DIR/could_be_const.rs:67:9 | LL | / pub fn b(self, a: &A) -> B { LL | | B LL | | } | |_________^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors