Skip to content

Prevent missing_const_for_fn on functions with const generic params #5216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions clippy_lints/src/missing_const_for_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:**
Expand Down Expand Up @@ -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;
}
},
Expand Down
13 changes: 12 additions & 1 deletion tests/ui/missing_const_for_fn/cant_be_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -90,3 +91,13 @@ mod with_drop {
}
}
}

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 }
}
7 changes: 6 additions & 1 deletion tests/ui/missing_const_for_fn/could_be_const.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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
Expand Down
26 changes: 17 additions & 9 deletions tests/ui/missing_const_for_fn/could_be_const.stderr
Original file line number Diff line number Diff line change
@@ -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 }
Expand All @@ -9,15 +9,23 @@ 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
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;
Expand All @@ -26,44 +34,44 @@ 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()
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
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) -> T {
LL | | t
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) }
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