Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
18 changes: 15 additions & 3 deletions clippy_lints/src/types/type_complexity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ use rustc_abi::ExternAbi;
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt as _, walk_ty};
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, TyKind};
use rustc_lint::LateContext;
use rustc_span::Span;
use rustc_span::{Span, sym};

use super::TYPE_COMPLEXITY;

pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool {
let score = {
let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
let mut visitor = TypeComplexityVisitor {
score: 0,
nest: 1,
type_alias_impl_trait_enabled: cx.tcx.features().enabled(sym::type_alias_impl_trait),
};
visitor.visit_ty_unambig(ty);
visitor.score
};
Expand All @@ -33,6 +37,8 @@ struct TypeComplexityVisitor {
score: u64,
/// current nesting level
nest: u64,
/// whether opaque `impl Trait` types can be named through `type_alias_impl_trait`
type_alias_impl_trait_enabled: bool,
}

impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
Expand All @@ -42,6 +48,10 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
}

fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_, AmbigArg>) {
// Opaque `impl Trait` types cannot be extracted into type aliases on stable. Skip
// their subtree only when `type_alias_impl_trait` is not enabled for this crate.
let skip_nested_type = matches!(ty.kind, TyKind::OpaqueDef(..)) && !self.type_alias_impl_trait_enabled;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you just inline it below?
I think the code would be simpler to read for future readers given the negations of negations going on here.


let (add_score, sub_nest) = match ty.kind {
// &x and *x have only small overhead; don't mess with nesting level
TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0),
Expand Down Expand Up @@ -72,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
};
self.score += add_score;
self.nest += sub_nest;
walk_ty(self, ty);
if !skip_nested_type {
walk_ty(self, ty);
}
self.nest -= sub_nest;
}
}
24 changes: 24 additions & 0 deletions tests/ui/type_complexity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,28 @@ struct D {
),
}

// Should not warn, because factoring `impl Trait` into a type alias is not stable (#17195).
fn issue_17195<I, J>(
left: I,
right: J,
) -> std::iter::Map<std::iter::Zip<I::IntoIter, J::IntoIter>, impl FnMut((I::Item, I::Item)) -> [I::Item; 2]>
where
I: IntoIterator,
J: IntoIterator<Item = I::Item>,
{
left.into_iter().zip(right).map(<[I::Item; 2]>::from)
}

// Complexity inside an opaque type cannot be factored into a type alias either.
fn complex_opaque_bound() -> impl Fn(Vec<Vec<Box<(u32, u32, u32, u32)>>>) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Why can't it?
as far as I tried this, it defitively can..

Is there maybe a typo in the comment or what do you mean here?

type Foo = Vec<Vec<Box<(u32, u32, u32, u32)>>>;

fn complex_opaque_bound() -> impl Fn(Foo) {
   |_|{}
}

|_| {}
}

// The presence of an opaque type must not hide complexity in a sibling type that can be factored
// out.
fn complex_after_opaque() -> (impl Iterator<Item = u32>, Vec<Vec<Box<(u32, u32, u32, u32)>>>) {
//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the rest of the code

Suggested change
//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions
//~^ type_complexity

(std::iter::empty(), vec![])
}

fn main() {}
8 changes: 7 additions & 1 deletion tests/ui/type_complexity.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,11 @@ error: very complex type used. Consider factoring parts into `type` definitions
LL | let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 15 previous errors
error: very complex type used. Consider factoring parts into `type` definitions
--> tests/ui/type_complexity.rs:108:30
|
LL | fn complex_after_opaque() -> (impl Iterator<Item = u32>, Vec<Vec<Box<(u32, u32, u32, u32)>>>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 16 previous errors

9 changes: 9 additions & 0 deletions tests/ui/type_complexity_type_alias_impl_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![feature(type_alias_impl_trait)]
#![warn(clippy::type_complexity)]

fn complex_opaque_bound() -> impl Fn(Vec<Vec<Box<(u32, u32, u32, u32)>>>) {
//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//~^ ERROR: very complex type used. Consider factoring parts into `type` definitions
//~^ type_complexity

|_| {}
}

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/type_complexity_type_alias_impl_trait.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: very complex type used. Consider factoring parts into `type` definitions
--> tests/ui/type_complexity_type_alias_impl_trait.rs:4:30
|
LL | fn complex_opaque_bound() -> impl Fn(Vec<Vec<Box<(u32, u32, u32, u32)>>>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::type-complexity` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::type_complexity)]`

error: aborting due to 1 previous error