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.
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...
Most helpful comment
I have code like that:
And clippy gives me warning:
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...