涉及相关类型的不满意特征限制

时间:2017-06-27 22:00:04

标签: rust traits

代码

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()
    }
}

使用第(1)行或通用类型I成功,因此在这些情况下确实会假设T::F : Q<bool>

为什么使用第(1)行或泛型类型自动假设特征约束,而不是第(2)行?

每次我们使用where T::F: Q<bool>时,我们是否可以在不附加T: A<I=bool>的情况下修复上述代码?

1 个答案:

答案 0 :(得分:4)

从Rust 1.18开始,编译器要求您编写这些边界,以使类型格式正确。基本上,为了使绑定的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>
}

然后Y格式不正确,因为绑定的T::F: Q<bool>不成立(实际上,编译器会在impl上给出错误)。但令人沮丧的是,目前,只要绑定的T::F: Q<bool>出现,就必须明确给出绑定的T: A<I = bool>。在某种程度上,它让编译器放心,嘿,T::I = bool也在那里!

  

为什么使用第(1)行或泛型类型自动假设特征约束,而不是第(2)行?

使用第(1)行,绑定为T::F: Q<T::I>正好 A的要求(T替换为Self })。实际上,我们也可以像这样编写绑定:

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

使用第(2)行,绑定的T::F: Q<bool>可能看起来只是用T::I替换bool,但这种差异对编译器很重要; T::I是关联类型,而bool是具体类型。

Rust开发人员正在考虑改进编译器,这样就不必在having the compiler infer those bounds之间重复这样的界限了。