How to implement a trait when one of the associated types is impossible to name?
Asked Answered
B

1

10

I have a function that returns an impl Trait so I don't have access to the concrete return type. I need to use the return value of that function as an associated type in a trait. How do I do that?

Here is a simplified example:

fn f() -> impl Iterator<Item = u8> {
    std::iter::empty()
}

struct S;

impl IntoIterator for S {
    type Item = u8;
    type IntoIter = (); // What can I write here ?

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}

Is it even possible to do (without resorting to boxing the iterator)?

Bajaj answered 16/4, 2019 at 15:37 Comment(1)
Kudos on a well-phrased question with an appropriate MCVE!Soileau
C
8

Unfortunately, you can't. At least not yet.

There is an RFC, Named existentials and impl Trait variable declarations (tracking issue), which would allow you to declare a public type name at the module level, whose type definition is inferred from how it used within the module. Users of the module can refer to this type by its public name and it can be used as an associated type.

It's difficult to guess when a new feature will stabilise and in the meantime there really aren't many good options. Aside from things that might only work because of specifics of your use-case, the general workaround is to use a trait object:

impl IntoIterator for S {
    type Item = u8;
    type IntoIter = Box<dyn Iterator<Item = u8>>;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(f())
    }
}

If it is acceptable to use nightly features, you can help test out the RFC before it stabilises:

#![feature(existential_type)]

impl IntoIterator for S {
    type Item = u8;
    existential type IntoIter: Iterator<Item = u8>;

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}
Concertmaster answered 16/4, 2019 at 15:58 Comment(1)
Thank you for this clear answer. I'm going to use a Box, then. And feel betrayed by rust, who promised me zero cost abstractions :pBajaj

© 2022 - 2024 — McMap. All rights reserved.