0

Before starting, I wasn't able to adapt neither how to match on data type in Rust nor the updated version of Shepmaster to another question I had.


I would like to be able to implement the Token trait for each variant of the enum BinOp.

#[derive(Debug, std::cmp::PartialEq)]
enum BinOp {
    Add,
    Sub
}

trait Token {
    fn regex() -> &'static str;
}

Neither this works (this is what I would have like to write)

EDIT: fix typo: impl Token for BinOp instead of impl Token for BinOp::Add

impl Token for BinOp {
    fn regex() -> &'static str{
        match Self {
            BinOp::Add => "\\+",
            BinOp::Sub => "-"
        }
    }
}
        match Self {
              ^^^^ 
the `Self` constructor can only be used with tuple or unit structs


the `Self` constructor can only be used with tuple or unit structs

Nor that

impl Token for BinOp::Add {
    fn regex() -> &'static str{
         "\\+"
    }
}
impl Token for BinOp::Add {
               ^^^^^^^^^^ not a type
expected type, found variant `BinOp::Add`

If the above code could be written, I would have liked to be able to use it like this

let add: BinOp = BinOp::Add;
let regex: &str = BinOp::Add::regex();

Is there a better way than doing the following (witch is way too much verbose)?

#[derive(Debug, std::cmp::PartialEq)]
struct Add;
#[derive(Debug, std::cmp::PartialEq)]
struct Sub;
#[derive(Debug, std::cmp::PartialEq)]
enum BinOp {
    Add(Add),
    Sub(Sub)
}

trait Token {
    fn regex() -> &'static str;
}

impl Token for Add {
    fn regex() -> &'static str{
         "\\+"
    }
}
impl Token for Sub {
    fn regex() -> &'static str{
         "-"
    }
}
let add: BinOp = BinOp::Add(Add);
let regex: &str = Add::regex();

Is this unfortunately a current limitation of Rust? Is there a workaround?

Robin
  • 423
  • 3
  • 10

1 Answers1

4

Unfortunately, an enum variant is not a type in Rust, so you must stick with your "verbose" version.

There is an RFC that would make variants as types, but even if it is implemented, (if I read it correctly) you won't be able to make them implement a trait anyway.


However, in your very case, since your variants don't hold any value, you can write something like that:

#[derive(Debug, std::cmp::PartialEq, Clone, Copy)]
enum BinOp {
    Add,
    Sub
}

trait Token {
    fn regex(self) -> &'static str;
}

impl Token for BinOp {
    fn regex(self) -> &'static str {
        match self {
            BinOp::Add => "\\+",
            BinOp::Sub => "-",
        }
    }
}

fn main() {
    assert_eq!(BinOp::Add.regex(), "\\+");
    assert_eq!(BinOp::Sub.regex(), "-");
}
Boiethios
  • 38,438
  • 19
  • 134
  • 183