繁体   English   中英

在返回位置具有泛型关联类型的 Impl 特征导致生命周期错误

[英]Impl trait with generic associated type in return position causes lifetime error

我需要在'static结构'static存储fn(I) -> O (其中I & O可以是引用)。 O需要是具有'static泛型关联类型”的特征,该关联类型也存储在结构中。 IO本身都不会存储在结构体中,因此它们的生命周期无关紧要。 但是编译器仍然抱怨I活得不够久。

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
}

操场

据我所知,编译器的错误消息具有误导性,它实际需要的是显式定义的关联类型:

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

对这个问题的出色回答:为什么编译器不推断 impl trait 返回值的关联类型的具体类型? 提供了足够的信息,说明为什么实际上需要这样做。

另请参阅Rust 问题 #42940 - impl-trait 返回类型受所有输入类型参数的限制,即使是不必要的

您可以使用泛型类型参数而不是返回impl在这种情况下,您不必指定关联类型:

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

显然,对于这里到底发生了什么仍然有些困惑,所以我会尽量把我的评论变成一个简短的答案。

这里的问题是函数map()的原型:

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

这指定map()的返回类型是某种实现IntoState类型,具有未指定的关联类型State 返回类型有一个生命周期参数,参数为i的生命周期; 让我们称之为生命周期'a ,以及完整的返回类型T<'a> 此返回类型的关联类型State现在是<T<'a> as IntoState>::State ,它由'a参数化。 尽管特征定义中有'static声明'static ,但编译器目前无法从关联类型中消除此生命周期参数。 通过将关联类型显式指定为String ,编译器将简单地使用显式指定的类型String而不是<T<'a> as IntoState>::State ,因此生命周期参数消失了,我们不再收到错误.

这个编译器的缺点在这个 Github 问题中讨论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM