0

I'm currently diving into rust and writing a little math library. The problem I like to solve is quite simple, I want to model fields and rings, but I can't get the lifetimes right.

here's the code:

ring.rs:

pub trait Ring {
    fn characteristic() -> int;

    fn is_unit(&self) -> bool;

    fn is_field() -> bool;
}

field.rs:

use ring::Ring;

pub trait Field : Ring {
    fn some_field_method() -> bool {
        true
    }
}

impl Ring for Field {
    fn is_field() -> bool {
        true
    }
}

when compiling I get the following error:

/src/field.rs:9:15: 9:20 error: explicit lifetime bound required
/src/field.rs:9 impl Ring for Field {
                              ^~~~~

I read the rust documentation, with the lifetime section and the rust-by-example section about it. The motivation behind lifetimes is obvious to me and I understand all the given examples. But here, I'm totally lost.

Btw: this is the minified version, I tried giving the Field a named lifetime, also the impl and Ring and various combinations of said.

May anyone explain what is happening here, or, if this is too specific, how to work with lifetimes and traits.

Thanks

  • 1
    What are you trying to do exactly ? Implementing the trait `Ring` for `Field` trait objects, while `Field` already derives from `Ring` ? – Levans Nov 13 '14 at 19:21
  • @Levans I want to partially implement Ring in Field. Maybe another example clarifies it: I have a Animal trait with should have get_leg_number and get_color and then I wanna have a Cow trait which implements the Animal traits but defaults the get_leg_number to 4. – Florian Rohm Nov 13 '14 at 19:38
  • i should add that there shall exist animals which are not further specialized like the cow. So a ring needs to exist on it's own. But a field has to be a ring every time – Florian Rohm Nov 13 '14 at 20:06

1 Answers1

2

You are trying to do some king of inheritance-like pattern with trait, which is not really how they work.

You can think of traits as somehow similar to interfaces provided by some languages : they are only a guaranty that your struct will provide some methods.

The syntax trait Foo : Bar does not mean that somehow the trait Foo is a superset of trait Bar, and that implementing Foo for a struct will implement Bar as well. It only states that trait Foo can only be implemented for structs already implementing trait Bar. You still need to implement both traits yourself.

Following your example, your approach would be something like this :

First, define the trait Ring:

pub trait Ring {
    fn characteristic(&self) -> int;

    fn is_unit(&self) -> bool;

    fn is_field(&self) -> bool {
        // Default value : not every Ring is a Field
        false
    }
}

Then, the trait Field, which requires the trait Ring

pub trait Field : Ring {
    fn some_field_method(&self) -> bool {
        // This is a default value as well
        true
    }
}

Then, your struct which will be both a Ring and a Field

struct MyField;

// First, implement Ring for MyField
impl Ring for MyField {
    fn characteristic(&self) -> int {
        2i
    }

    fn is_unit(&self) -> bool {
        false
    }

    fn is_field(&self) -> bool {
        // We override the default value : MyField is a Field
        true
    }
}

// Then we can implement Field for MyField
impl Field for MyField {
    // Nothing here if we keep default implementation of some_field_method
}

Now, some explanations about this strange error with lifetimes.

When you wrote impl Ring for Field {...}, you where actually trying to implement the trait Ring for trait object Field.

A trait object is what you get when you use a reference to a struct like a reference to one of its traits, and they are quite peculiar to use, and require some playing with lifetimes.

However, in most situation you won't need to play with them, and classic generics will suffice.

You can have a look to my answer here, where I explain it with more details.

Community
  • 1
  • 1
Levans
  • 14,196
  • 3
  • 49
  • 53
  • thanks for the fast answer. I also read your other answer; gave me lots of new insights but I have to tinker a bit more with it to fully understand the reasons behind. For now I can go on :) – Florian Rohm Nov 13 '14 at 20:24