itertools icon indicating copy to clipboard operation
itertools copied to clipboard

[Question] Why concrete return types?

Open Iizuki opened this issue 3 months ago • 4 comments

Summary

Why the iterator combinators in this crate (and elsewhere) return concrete public types like Interleave<I, J> instead of opaque impl Traits?

Musing

I've been using itertools for a long time without thinking twice about the actual types returned by the different combinators etc. They're basically never seen, only existing between the lines. Seems like they might as well be opaque types and I wouldn't even notice. impl Iterator<...> or something.

It's not like I have anything against the current design. I would just like to understand the reasons behind it.

Guesses

Some ideas of what might be part of the of the reasoning:

  • Backward compatibility: Maybe this was the only stable way at some time in the past?
  • Type inference: Perhaps the opaque types cause undue burden on the compiler?

PS's

PS. I got here hoping to find the answer in CONTRIBUTING.md, so perhaps we could close this issue by adding a paragraph :)

PPS. This has to be one of the best crates in the rust ecosystem. Thanks to everyone who contributed!

Iizuki avatar Sep 03 '25 10:09 Iizuki

I think our minimum required rust version does not allow to return impl.

Moreover, sometimes a concrete type is better, because it automatically brings you all implemented traits (otherwise you'd have to return impl iterator + DoubleEndedIterator + ExactSizeIterator or similar).

phimuemue avatar Sep 03 '25 12:09 phimuemue

For iterators adapters, there's no way with impl Iterator to do the "our adapter is ExactSizeIterator when the original iterator was ExactSizeIterator" kind of things. That's only possible with returning named iterators.

scottmcm avatar Sep 03 '25 23:09 scottmcm

@phimuemue

I think our minimum required rust version does not allow to return impl.

Right so this would fall into the backwards compatibility basket.

Moreover, sometimes a concrete type is better, because it automatically brings you all implemented traits (otherwise you'd have to return impl iterator + DoubleEndedIterator + ExactSizeIterator or similar).

Good point. One less thing to remember.

@scottmcm

For iterators adapters, there's no way with impl Iterator to do the "our adapter is ExactSizeIterator when the original iterator was ExactSizeIterator" kind of things. That's only possible with returning named iterators.

You mean like Itertools::get?

Yeah I think that's true about return position impl Traits, but perhaps that was a bit of a red herring as here the return type in fact does appear to be an opaque Iterator type. Just done with type params instead.

So I gather that this kind of opaqueness is considered harmless?

Iizuki avatar Sep 04 '25 06:09 Iizuki

An advantage of existential return types is that for itertools adaptors which can be expressed as a composition of other adaptors, we could implement them simply as that composition, and the returned types would get all the specialization benefits of their constituent parts. Today, missing specializations are a common Itertools footgun, and implementing Iterator for even simple adaptors can be subtly complex.

I wouldn't want to dabble in this until we got TAITs, becaused naming the return type is useful both for ergonomics and for backward compatibility.

jswrenn avatar Sep 04 '25 06:09 jswrenn