Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"error: trait bounds are not allowed in structure definitions" when attempting to use polymorphism

Editor's note: This question was asked before Rust 1.0 and before certain features were implemented. The code as-is works today.

I'm writing a board game AI in Rust. There are multiple rulesets for the game and I'd like to have the rules logic separated from the board layout (they are currently mixed). In a language like Ruby, I'd have the separate rule sets implement the same interface. In Rust I thought about using a trait and parameterizing the Board with the ruleset I want to use (e.g. Board<Rules1>::new()).

Saving an object that implements this trait in a struct (like Board) is not allowed. I could turn the Rules into an enum, but it looks a bit messy to me because I can't define separate implementations for the members of the enum. Using pattern matching would work, but that splits the functionality along the function axis and not along the struct axis. Is this just something I have to live with or there some way?

The following code is what I'd like to use:

pub struct Rules1;
pub struct Rules2;

trait Rules {
    fn move_allowed() -> bool;
}

impl Rules for Rules1 {
    fn move_allowed() -> bool {
        true
    }
}

impl Rules for Rules2 {
    fn move_allowed() -> bool {
        false
    }
}

struct Board<R: Rules> {
    rules: R
}

fn main() {}

It produces the following error:

test.rs:20:1: 22:2 error: trait bounds are not allowed in structure definitions
test.rs:20 struct Board<R: Rules> {
test.rs:21     rules: R
test.rs:22 }
error: aborting due to previous error
like image 669
ujh Avatar asked Jun 23 '14 10:06

ujh


1 Answers

The code presented in the question works on all recent versions of Rust, trait bounds on structs are now allowed. The original answer is also still valid.


You need to refine that in the trait implementation, not the struct definition.

pub struct Rules1;
pub struct Rules2;

trait Rules {
    fn move_allowed(&self) -> bool;
}

impl Rules for Rules1 {
    fn move_allowed(&self) -> bool {
        true
    }
}

impl Rules for Rules2 {
    fn move_allowed(&self) -> bool {
        false
    }
}

struct Board<R> {
    rules: R,
}

impl<R: Rules> Board<R> {
    fn move_allowed(&self) -> bool {
        self.rules.move_allowed()
    }
}

fn main() {
    let board = Board { rules: Rules2 };
    assert!(!board.move_allowed());
}
like image 198
Skade Avatar answered Nov 11 '22 12:11

Skade