Skip to content
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

Type complexity should not be considered when defining an associated type #1013

Closed
malbarbo opened this issue Jun 15, 2016 · 5 comments · Fixed by #8030
Closed

Type complexity should not be considered when defining an associated type #1013

malbarbo opened this issue Jun 15, 2016 · 5 comments · Fixed by #8030
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy

Comments

@malbarbo
Copy link

Consider this example:

use std::vec::IntoIter;
use std::iter::{Map, Filter};

struct S;

impl IntoIterator for S {
    type Item = i32;
    type IntoIter = Filter<Map<IntoIter<i32>, fn(i32) -> i32>, fn(&i32) -> bool>;

    fn into_iter(self) -> Self::IntoIter {
        fn m(a: i32) -> i32 { a }
        fn p(_: &i32) -> bool { true }
        vec![1i32, 2, 3].into_iter().map(m as fn(_) -> _).filter(p)
    }
}

Clippy warns that Filter<Map<IntoIter<i32>, fn(i32) -> i32>, fn(&i32) -> bool> is a very complex type and suggest creating a type definition, but it already is type definition.

@mcarton mcarton added good-first-issue These issues are a good way to get started with Clippy C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages labels Jun 15, 2016
@llogiq
Copy link
Contributor

llogiq commented Jun 16, 2016

use std::vec::IntoIter;
use std::iter::{Map, Filter};

struct S;

type IntIntFn = fn(i32) -> i32;
type IntPred = fn(&i32) -> bool;
type IntIntMap = Map<IntoIter<i32>, IntIntFn>;

impl IntoIterator for S {
    type Item = i32;
    type IntoIter = Filter<IntIntMap, IntPred>;

    fn into_iter(self) -> Self::IntoIter {
        fn m(a: i32) -> i32 { a }
        fn p(_: &i32) -> bool { true }
        vec![1i32, 2, 3].into_iter().map(m as fn(_) -> _).filter(p)
    }
}

But we should probably improve the warning to suggest how to factor the type.

@mcarton
Copy link
Member

mcarton commented Jun 16, 2016

@llogiq this is overkill, I would be fine with just one type declaration in the impl.

@llogiq
Copy link
Contributor

llogiq commented Jun 16, 2016

@mcarton you can always #[allow(type_complexity)]. And my point was that it's possible, even if a bit overkill in that case, to avoid triggering the lint. Also I think that being an associated type is not the right distinction to make; one can return a complex iterator type from a normal function, too. Perhaps we should carve out an exemption for typical iterator types (like Map, Filter, etc.), at least until impl trait makes those types unnecessary?

@WaffleLapkin
Copy link
Member

I have code like that:

impl<U, L, M, T, I, O, N, J> Add<U> for Unit<L, M, T, I, O, N, J>
where
    U: UnitTrait,
    L: Add<U::Length>,
    M: Add<U::Mass>,
    T: Add<U::Time>,
    I: Add<U::ElectricCurrent>,
    O: Add<U::ThermodynamicTemperature>,
    N: Add<U::AmountOfSubstance>,
    J: Add<U::LuminousIntensity>,
{
    type Output = Unit<
        <L as Add<U::Length>>::Output,
        <M as Add<U::Mass>>::Output,
        <T as Add<U::Time>>::Output,
        <I as Add<U::ElectricCurrent>>::Output,
        <O as Add<U::ThermodynamicTemperature>>::Output,
        <N as Add<U::AmountOfSubstance>>::Output,
        <J as Add<U::LuminousIntensity>>::Output,
    >;

    fn add(self, _rhs: U) -> Self::Output {
        Unit::new()
    }
}

And clippy gives me warning:

warning: very complex type used. Consider factoring parts into `type` definitions
   --> src/unit.rs:115:19
    |
115 |       type Output = Unit<
    |  ___________________^
116 | |         <L as Add<U::Length>>::Output,
117 | |         <M as Add<U::Mass>>::Output,
118 | |         <T as Add<U::Time>>::Output,
...   |
122 | |         <J as Add<U::LuminousIntensity>>::Output,
123 | |     >;
    | |_____^
    |
    = note: `#[warn(clippy::type_complexity)]` on by default
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity

Indeed, it's very complex, but is there any way to simplify it with type aliases as clippy suggests?

Maybe Clippy shouldn't warn about this at least when there is nothing to move into type alias...

@Diggsey
Copy link

Diggsey commented Nov 24, 2021

Yeah, I hit this as well, with the following associated type:

type State = Option<(Option<Rc<Q::Response>>, Rc<QueryLimits>)>;

I think this lint should just not fire when already defining a type alias / associated type, since splitting it out is not necessarily an improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy
Projects
None yet
6 participants