Rust-clippy: Type complexity should not be considered when defining an associated type

Created on 15 Jun 2016  路  4Comments  路  Source: rust-lang/rust-clippy

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.

L-enhancement good-first-issue hacktoberfest

Most helpful comment

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...

All 4 comments

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.

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

@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?

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...

Was this page helpful?
0 / 5 - 0 ratings