传递生命周期时,泛型类型参数不受约束

Posted

技术标签:

【中文标题】传递生命周期时,泛型类型参数不受约束【英文标题】:Generic type parameter is not constrained when passing lifetime 【发布时间】:2021-05-24 07:28:48 【问题描述】:

为什么下面的不能编译?

trait A<'a> 
    type Typ;


trait B 

struct C<T> 
    _ph: std::marker::PhantomData<T>,


impl<'a, T, V> B for C<T> where
    T: A<'a, Typ=V>

playground

前面给出了错误“类型参数 V 不受 impl trait、self 类型或谓词的约束”。将关联类型更改为泛型类型也不会编译,并给出相同的错误。 但是,当生命周期被删除时,以下代码会编译。

trait A 
    type Typ;


trait B 

struct C<T> 
    _ph: std::marker::PhantomData<T>,


impl<T, V> B for C<T> where
    T: A<Typ=V>

playground

删除关联的类型也会编译。

trait A<'a> 

trait B 

struct C<T> 
    _ph: std::marker::PhantomData<T>,


impl<'a, T> B for C<T> where
    T: A<'a>

playground

看到删除生命周期如何导致代码编译(不以任何方式更改 V),我猜测错误消息不是真正的潜在错误。我不知道不编译的真正原因是什么。

这个出现的原始情况并不真正相关 - 这个问题更多的是关于奇怪的行为和错误消息,但如果你愿意,可以查看here。

【问题讨论】:

我认为这是因为泛型打开了满足T: A&lt;'a, Typ=V&gt;'aV 对(可能是无限的),这意味着只要给定类型C&lt;T&gt;,Rust 就不能决定使用什么通用impl 参数。由于没有生命周期并且只有对关联类型的约束,因此只能有一个 A impl,因此只有一个有效的 V 【参考方案1】:

它抱怨是因为你没有限制那个泛型。

这就像写作:

impl<A> SomeTrait for MyType 
// We aren't using A

这会很好用,因为它已经比 Typ 通用了:

impl<'a, T> B for C<T> where
    T: A<'a>,

    // you can refer to your V type as <T as A>::Typ

如果你确实想限制它,你可以:

use std::default::Default;

impl<'a, T> B for C<T> where
    T: A<'a>,
    <T as A<'a>>::Typ: Default,

    // now here you can call <T as A<'a>>::Typ::default()

【讨论】:

以上是关于传递生命周期时,泛型类型参数不受约束的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)?

uni-app页面生命与vue生命周期

uni-app生命周期

为啥作为参数传递的特征对象的生命周期需要更高等级的特征边界,而结构不需要?

生命周期函数

uniapp的生命周期