Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

rust - Impl trait with generic associated type in return position causes lifetime error

I need to store a fn(I) -> O (where I & O can be references) in a 'static struct. O needs to be a trait with an 'static generic associated type, that associated type is also stored in the struct. Neither I nor O itself get stored inside of the struct, so their lifetime shouldn't matter. But the compiler is still complaining about I not living long enough.

trait IntoState {
    type State: 'static;

    fn into_state(self) -> Self::State;
}

impl IntoState for &str {
    type State = String;

    fn into_state(self) -> Self::State {
        self.to_string()
    }
}

struct Container<F, S> {
    func: F,
    state: S,
}

impl<I, O> Container<fn(I) -> O, O::State>
where
    O: IntoState,
{
    fn new(input: I, func: fn(I) -> O) -> Self {
        // I & O lives only in the next line of code. O gets converted into
        // a `'static` (`String`), that is stored in `Container`.
        let state = func(input).into_state();
        Container { func, state }
    }
}

fn map(i: &str) -> impl '_ + IntoState {
    i
}

fn main() {
    let _ = {
        // create a temporary value
        let s = "foo".to_string();

        // the temporary actually only needs to live in `new`. It is
        // never stored in `Container`.
        Container::new(s.as_str(), map)
        // ERR:        ^ borrowed value does not live long enough
    };
    // ERR: `s` dropped here while still borrowed
}

playground

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As far as I can tell, the compiler's error message is misleading, what it actually requires is an explicitly defined associated type:

fn map(i: &str) -> impl '_ + IntoState<State = String> {
    i
}

The excellent answer given to the quesion: Why does the compiler not infer the concrete type of an associated type of an impl trait return value? provides enough information on why this is actually needed.

See also Rust issue #42940 - impl-trait return type is bounded by all input type parameters, even when unnecessary

You can use a generic type parameter instead of returning an impl in which case you don't have to specify the associated type:

fn map<T: IntoState>(i: T) -> T {
    i
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...