Home > Mobile >  "no field on type" error with generic type implementations
"no field on type" error with generic type implementations

Time:06-22

I'm trying to make a project but I can't make progress due to an error that keeps popping up. I've tried to abstract it to give you a simpler example. Can anyone tell me why, in the get_value function, within the implementation for Element, it is not possible to get the values of the Element. It should, right? Since I'm explicitly saying the implementation is for Element...

struct Element<T> {
    value: T,
}

trait HasValue<T> {
    fn get_value(&self) -> T;
}

impl<Element> HasValue<Element> for Element {
    fn get_value(&self) -> Element {
        self.value // Error!
    }
}
error[E0609]: no field `value` on type `&Element`
  --> src/lib.rs:11:14
   |
9  | impl<Element> HasValue<Element> for Element {
   |      ------- type parameter 'Element' declared here
10 |     fn get_value(&self) -> Element {
11 |         self.value // Error!
   |              ^^^^^

CodePudding user response:

This compiles, either using generics:

struct Element<T: Copy> {
    value: T,
}

trait HasValue<T>{
    fn get_value(&self) -> T;
}

impl<T: Copy> HasValue<T> for Element<T> {
    fn get_value(&self) -> T {
        self.value
    }
}

or with concrete types:

struct Element<T> {
    value: T,
}

trait HasValue<T>{
    fn get_value(&self) -> T;
}

impl HasValue<String> for Element<String> {
    fn get_value(&self) -> String {
        self.value.clone().replace("t", "est")
    }
}

impl HasValue<u64> for Element<u64> {
    fn get_value(&self) -> u64 {
        self.value
    }
}

CodePudding user response:

Element is not Element. That is, this Element:

struct Element<T> {
//     ^^^^^^^

Is not the same as these Elements:

impl<Element> HasValue<Element> for Element {
//   ^^^^^^^           ^^^^^^^      ^^^^^^^
    fn get_value(&self) -> Element {
    //                     ^^^^^^^

The first is a concrete (well, generic) struct with the name Element. The second is a generic parameter with the name Element, that can be the struct Element but can also be any other type, such as i32 or String. You can rename either without affecting the other.

The generic parameter shadows the struct because it has the same name, and within the impl Element will refer to it and not the struct. Because it can be any type, it doesn't necessarily have a value field - and thus the compiler is complaining.

I suppose what you actually want is not "for any type", but "for any Element<T> type". That is, only T should be generic, not the type itself. To express that you should write:

impl<T> HasValue<T> for Element<T> {
    fn get_value(&self) -> T {
        self.value
    }
}

Now you'll get another error because you're moving self.value, but that is a different thing.

  • Related