I have an existential type defined like this:
trait Collection {
type Element;
}
impl<T> Collection for Vec<T> {
type Element = T;
}
type Existential<T> = impl Collection<Element = T>;
A function, which takes a type implementing a trait with an associated type, returns this type. Why does this code work:
fn return_existential<I, T>(iter: I) -> Existential<T>
where
I: IntoIterator<Item = T>,
I::Item: Collection,
{
let item = iter.into_iter().next().unwrap();
vec![item]
}
while this does not:
fn return_existential<I>(iter: I) -> Existential<I::Item>
where
I: IntoIterator,
I::Item: Collection,
{
let item = iter.into_iter().next().unwrap();
vec![item]
}
error: type parameter `I` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> src/lib.rs:16:1
|
16 | / {
17 | | let item = iter.into_iter().next().unwrap();
18 | | vec![item]
19 | | }
| |_^
error: defining opaque type use does not fully define opaque type
--> src/lib.rs:12:1
|
12 | / fn return_existential<I>(iter: I) -> Existential<I::Item>
13 | | where
14 | | I: IntoIterator,
15 | | I::Item: Collection,
... |
18 | | vec![item]
19 | | }
| |_^
error: could not find defining uses
--> src/lib.rs:10:1
|
10 | type Existential<T> = impl Collection<Element = T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When using a Vec
directly, this works fine:
fn return_existential<I>(iter: I) -> Vec<I::Item>
where
I: IntoIterator,
I::Item: Collection,
{
let item = iter.into_iter().next().unwrap();
vec![item]
}
Note: Those examples are constructed while playing around with this feature. I won't use it anyway as long as my IDE is not aware of existential types. Additionally, the exact syntax is subject to change.
type Existential<T> = impl Collection<Element = T>;
does not compile on stable or nightly with the error "error: unconstrained opaque type" and "note:Existential
must be used in combination with a concrete type within the same item" – Kwapong