涉及相关类型的不满足特质限制

3

代码

pub trait Q<S> {
    fn f();
}

pub trait A {
    type I;
    type F: Q<Self::I>;
}

// this works (1)
//
// pub struct S<T>
// where
//     T: A
// {                 

// unsatisfied trait bound (2)
pub struct S<T>                                  
where
    T: A<I = bool>,
{

    t: T,
}

编译失败:

error[E0277]: the trait bound `<T as A>::F: Q<bool>` is not satisfied
  --> src/main.rs:18:1
   |
18 | / pub struct S<T>                                  
19 | | where
20 | |     T: A<I = bool>,
21 | | {
22 | |     t: T,
23 | | }
   | |_^ the trait `Q<bool>` is not implemented for `<T as A>::F`
   |
   = help: consider adding a `where <T as A>::F: Q<bool>` bound
   = note: required by `A`

有趣的是,如果你使用注释掉的第一行(1)而不是第二行(2),它也可以工作。如果你把相关类型I变成一个泛型类型(写trait A<I>A<bool>),它也可以工作。

impl<T> S<T>
    where T: A
{
    fn g() {
        T::F::f()
    }
}

如果在第一行或泛型类型 I 中成功,那么在这些情况下确实假定了 T::F : Q<bool>

为什么会自动假定具有第一行或泛型类型的特质边界,但不假定第二行呢?

我们能否在使用 T: A<I=bool> 时修复上述代码,而无需每次附加 where T::F: Q<bool>

1个回答

4
自 Rust 1.18 版本起,编译器要求您编写这些约束条件以使类型“well-formed”(即正确形成)。基本上,为了满足约束条件 T: A<I = bool>,需要满足约束条件 T::F: Q<bool>。例如,如果某个类型尝试以以下方式实现 A
struct Y;
struct Z;

impl A for Y {
    type I = bool;
    type F = Z; // Z does not implement Q<bool>
}

如果没有符合要求的绑定T::F: Q<bool>,那么Y就不是规范形式(并且实际上,编译器会在impl上报错)。但令人沮丧的是,目前只有当出现绑定T: A<I = bool>时,才必须明确给出绑定T::F: Q<bool>。在某种程度上,这可以向编译器保证,“嘿,这里也有T::I = bool!”

为什么泛型类型或行(1)自动假定了trait bound,而行(2)没有呢?

对于行(1),绑定将是T::F: Q<T::I>,这正是A的要求(用Self替换T)。实际上,我们还可以这样等价地编写绑定:
pub trait A
where
    Self::F: Q<Self::I>,
{
    type I;
    type F;
}

通过第二行代码,限制条件T::F: Q<bool>看起来似乎只需要将T::I替换为bool,但是这个差别对于编译器很重要;T::I是一个关联类型,而bool是一个具体类型。
Rust开发者正在考虑改进编译器,使得像这样的限制条件不必在所有地方都重复出现,通过让编译器推断这些限制条件来实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接