Skip to content

Commit 5ef3cc8

Browse files
committed
Auto merge of #10197 - blyxyas:impl_trait_param, r=Jarcho
Add `impl_trait_in_params` lint As this is a lint about style, and using `impl Trait` is purely cosmetical (even with downsides), a lot of unrelated files needed to allow this lint. --- Resolves #10030 changelog: New lint: [`impl_trait_in_params`] [10197](#10197) <!-- changelog_checked -->
2 parents b1cf1e7 + 89fde4a commit 5ef3cc8

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4430,6 +4430,7 @@ Released 2018-09-13
44304430
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
44314431
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
44324432
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
4433+
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
44334434
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
44344435
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
44354436
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
179179
crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
180180
crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
181181
crate::functions::DOUBLE_MUST_USE_INFO,
182+
crate::functions::IMPL_TRAIT_IN_PARAMS_INFO,
182183
crate::functions::MISNAMED_GETTERS_INFO,
183184
crate::functions::MUST_USE_CANDIDATE_INFO,
184185
crate::functions::MUST_USE_UNIT_INFO,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use clippy_utils::{diagnostics::span_lint_and_then, is_in_test_function};
2+
3+
use rustc_hir::{intravisit::FnKind, Body, HirId};
4+
use rustc_lint::LateContext;
5+
use rustc_span::Span;
6+
7+
use super::IMPL_TRAIT_IN_PARAMS;
8+
9+
pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
10+
if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() && !is_in_test_function(cx.tcx, hir_id)
11+
{
12+
if let FnKind::ItemFn(ident, generics, _) = kind {
13+
for param in generics.params {
14+
if param.is_impl_trait() {
15+
// No generics with nested generics, and no generics like FnMut(x)
16+
span_lint_and_then(
17+
cx,
18+
IMPL_TRAIT_IN_PARAMS,
19+
param.span,
20+
"'`impl Trait` used as a function parameter'",
21+
|diag| {
22+
if let Some(gen_span) = generics.span_for_param_suggestion() {
23+
diag.span_suggestion_with_style(
24+
gen_span,
25+
"add a type paremeter",
26+
format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
27+
rustc_errors::Applicability::HasPlaceholders,
28+
rustc_errors::SuggestionStyle::ShowAlways,
29+
);
30+
} else {
31+
diag.span_suggestion_with_style(
32+
Span::new(
33+
body.params[0].span.lo() - rustc_span::BytePos(1),
34+
ident.span.hi(),
35+
ident.span.ctxt(),
36+
ident.span.parent(),
37+
),
38+
"add a type paremeter",
39+
format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
40+
rustc_errors::Applicability::HasPlaceholders,
41+
rustc_errors::SuggestionStyle::ShowAlways,
42+
);
43+
}
44+
},
45+
);
46+
}
47+
}
48+
}
49+
}
50+
}

clippy_lints/src/functions/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod impl_trait_in_params;
12
mod misnamed_getters;
23
mod must_use;
34
mod not_unsafe_ptr_arg_deref;
@@ -327,6 +328,32 @@ declare_clippy_lint! {
327328
"getter method returning the wrong field"
328329
}
329330

331+
declare_clippy_lint! {
332+
/// ### What it does
333+
/// Lints when `impl Trait` is being used in a function's paremeters.
334+
/// ### Why is this bad?
335+
/// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
336+
///
337+
/// ### Example
338+
/// ```rust
339+
/// trait MyTrait {}
340+
/// fn foo(a: impl MyTrait) {
341+
/// // [...]
342+
/// }
343+
/// ```
344+
/// Use instead:
345+
/// ```rust
346+
/// trait MyTrait {}
347+
/// fn foo<T: MyTrait>(a: T) {
348+
/// // [...]
349+
/// }
350+
/// ```
351+
#[clippy::version = "1.68.0"]
352+
pub IMPL_TRAIT_IN_PARAMS,
353+
restriction,
354+
"`impl Trait` is used in the function's parameters"
355+
}
356+
330357
#[derive(Copy, Clone)]
331358
pub struct Functions {
332359
too_many_arguments_threshold: u64,
@@ -354,6 +381,7 @@ impl_lint_pass!(Functions => [
354381
RESULT_UNIT_ERR,
355382
RESULT_LARGE_ERR,
356383
MISNAMED_GETTERS,
384+
IMPL_TRAIT_IN_PARAMS,
357385
]);
358386

359387
impl<'tcx> LateLintPass<'tcx> for Functions {
@@ -371,6 +399,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
371399
too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
372400
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, def_id);
373401
misnamed_getters::check_fn(cx, kind, decl, body, span);
402+
impl_trait_in_params::check_fn(cx, &kind, body, hir_id);
374403
}
375404

376405
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {

tests/ui/impl_trait_in_params.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![allow(unused)]
2+
#![warn(clippy::impl_trait_in_params)]
3+
4+
pub trait Trait {}
5+
pub trait AnotherTrait<T> {}
6+
7+
// Should warn
8+
pub fn a(_: impl Trait) {}
9+
pub fn c<C: Trait>(_: C, _: impl Trait) {}
10+
fn d(_: impl AnotherTrait<u32>) {}
11+
12+
// Shouldn't warn
13+
14+
pub fn b<B: Trait>(_: B) {}
15+
fn e<T: AnotherTrait<u32>>(_: T) {}
16+
17+
fn main() {}

tests/ui/impl_trait_in_params.stderr

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error: '`impl Trait` used as a function parameter'
2+
--> $DIR/impl_trait_in_params.rs:8:13
3+
|
4+
LL | pub fn a(_: impl Trait) {}
5+
| ^^^^^^^^^^
6+
|
7+
= note: `-D clippy::impl-trait-in-params` implied by `-D warnings`
8+
help: add a type paremeter
9+
|
10+
LL | pub fn a<{ /* Generic name */ }: Trait>(_: impl Trait) {}
11+
| +++++++++++++++++++++++++++++++
12+
13+
error: '`impl Trait` used as a function parameter'
14+
--> $DIR/impl_trait_in_params.rs:9:29
15+
|
16+
LL | pub fn c<C: Trait>(_: C, _: impl Trait) {}
17+
| ^^^^^^^^^^
18+
|
19+
help: add a type paremeter
20+
|
21+
LL | pub fn c<C: Trait, { /* Generic name */ }: Trait>(_: C, _: impl Trait) {}
22+
| +++++++++++++++++++++++++++++++
23+
24+
error: aborting due to 2 previous errors
25+

0 commit comments

Comments
 (0)