为什么Rust的const从特征到特征的赋值不起作用?

时间:2019-06-22 19:15:57

标签: rust

我试图将在一个特征中定义的关联常量分配给无法按预期工作的另一个特征。 这是一个具有3个特征和一个结构的最小示例:

trait A {
    const X: i32 = 1;
}

struct S;

impl A for S {}

trait B {
    const Y: i32 = A::X;
}

trait C {
    const Y: i32 = S::X;
}

fn main() {}

相应的编译器错误为:

error[E0283]: type annotations required: cannot resolve `_: A`
  --> src/main.rs:10:20
   |
10 |     const Y: i32 = A::X;
   |                    ^^^^
   |
note: required by `A::X`
  --> src/main.rs:2:5
   |
2  |     const X: i32 = 1;
   |     ^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0283`.

对E0283的解释告诉我代码揭示了什么:我可以从具体类型进行分配,但不能从特征本身进行分配。但是在E0283示例使用未定义函数的情况下,我已经定义了值。 为什么会这样,又如何绕开呢?

2 个答案:

答案 0 :(得分:3)

问题在于,实现struct的任何A都可以为X定义自己的值。因此,仅在A::X的上下文中说明trait B并不能为编译器提供足够的信息来选择impl中的A

如果您希望同时implB个和implA个东西,可以尝试以下方法(我手边没有编译器,但是这个想法应该清楚):

trait B : A {
    const Y: i32 = <Self as A>::X;
}

答案 1 :(得分:2)

特性应该由具体类型实现,而不应该自己定义一个常量,而常量不能在实现者中更改。您指定的是默认值,而不是所有实现者都必须遵守的值。如果所有类型都必须具有相同的X值,则不需要特征。

因此,A::X的定义不明确。

以下是显示原因的示例:

trait A {
    const X: i32 = 1;
}

struct S;

impl A for S {}

struct R;

impl A for R {
    const X: i32 = 42;
}

fn main() {
    println!("S: {}", S::X);
    println!("R: {}", R::X);
    println!("S: {}", <S as A>::X); // A::X alone is ambiguous
    println!("R: {}", <R as A>::X);
}

(link to playground)

您正在做的事情类似于尝试对特征调用默认函数,这里出现错误E0283:

trait A {
    fn get_x() -> i32 {
        1
    }
}

struct S;

impl A for S {}

struct R;

impl A for R {
    fn get_x() -> i32 {
        42
    }
}

fn main() {
    // A::get_x() is ambiguous but there are not:
    println!("S: {}", S::get_x());
    println!("R: {}", R::get_x());
    println!("S: {}", <S as A>::get_x());
    println!("R: {}", <R as A>::get_x());
}

(link to playground)