I was reading the RFC on "expanding" impl Trait when I came upon the following:
By contrast, a programmer who first learned:
fn take_iter(t: impl Iterator)
and then tried:fn give_iter() -> impl Iterator
would be successful, without any rigorous understanding that they just transitioned from a universal to an existential.
While I understand universal vs existential from a logic perspective, what makes the first one above universal and the second one existential?
The RFC defines the terms multiple times in multiple manners:
TL;DR:
fn take_iter(t: impl Iterator)
— the person callingtake_iter
picks the concrete type. The function has to work for the entire "universe" of types that implement the trait.fn give_iter() -> impl Iterator
— the implementation ofgive_iter
picks the concrete type. There is some type which "exists" and implements the trait that will be returned by the function.