I'm trying to assign an associated const defined in one trait to another trait which doesn't work as expected. Here's a minimal example with 3 traits and one struct:
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() {}
The corresponding compiler error is:
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;
| ^^^^^^^^^^^^^^^^^
The explanation for E0283
tells me what the code reveals: I can assign from a concrete type but not the trait itself. But where the E0283
example uses an undefined function I have an already defined value. Why is that so and how can this be bypassed?
The problem is that any struct
that implements A
could define its own value for X
. Thus, simply stating A::X
in the context of trait B
does not offer enough information for the compiler as to which impl
of A
should be chosen.
If you want that something that impl
ements B
also impl
ements A
, you can try the following (I have no compiler at hand, but the idea should be clear):
trait B : A {
const Y: i32 = <Self as A>::X;
}
Traits are supposed to be implemented by a concrete type, and are not supposed to define a constant on their own that can't be changed in implementors. What you specified is a default value, rather than a value all implementors must adhere to. You wouldn't need a trait if all types must have the same X
value.
Therefore A::X
is not a well defined value.
Here is an example showing why:
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);
}
What you are doing is similar to trying to call a default function on a trait, here the error 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());
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.