【问题标题】:Why does Rust assignment of const from trait to trait not work?为什么 Rust 将 const 从 trait 分配到 trait 不起作用?
【发布时间】:2019-06-22 19:15:57
【问题描述】:

我正在尝试将一个特征中定义的关联 const 分配给另一个不能按预期工作的特征。这是一个包含 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;
   |     ^^^^^^^^^^^^^^^^^

E0283 的解释告诉我代码揭示了什么:我可以从具体类型分配,但不能从特征本身分配。但是在E0283 示例使用未定义函数的地方,我有一个已经定义的值。为什么会这样?如何绕过?

【问题讨论】:

    标签: rust


    【解决方案1】:

    问题是任何实现Astruct 都可以为X 定义自己的值。因此,在trait B 的上下文中简单地声明A::X 并不能为编译器提供足够的信息来确定应该选择A 中的哪个impl

    如果你想要 implements Bimplements A 的东西,你可以尝试以下方法(我手头没有编译器,但想法应该很清楚):

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

    【讨论】:

    【解决方案2】:

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

    因此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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 2021-10-01
      相关资源
      最近更新 更多