Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement PartialEq for an enum?

Tags:

rust

I have the following definition:

enum Either<T, U> {     Left(T),     Right(U), } 

How would I get the equivalent of #[derive(PartialEq)] for this type? I would like to use a match expression, like:

impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {     fn eq(&self, other: &Either<T, U>) -> bool {         use Either::*;         match (*self, *other) {             (Left(ref a), Left(ref b)) => a == b,             (Right(ref a), Right(ref b)) => a == b,             _ => false,         }     } } 

This consumes both *self and *other, even though I only need it for the match expression, causing the error:

error[E0507]: cannot move out of borrowed content  --> src/lib.rs:9:16   | 9 |         match (*self, *other) {   |                ^^^^^ cannot move out of borrowed content  error[E0507]: cannot move out of borrowed content  --> src/lib.rs:9:23   | 9 |         match (*self, *other) {   |                       ^^^^^^ cannot move out of borrowed content 
like image 942
Mario Carneiro Avatar asked Mar 30 '16 00:03

Mario Carneiro


1 Answers

Normally, you would just use #[derive(PartialEq)], like so:

#[derive(PartialEq)] enum Either<T, U> {     Left(T),     Right(U), } 

This will generate the code to implement the trait for you. The Rust Programming Language describes the implementation details.


Sometimes, you want to implement the trait directly. This may be because the default version is either too specific or too generic.

The error in your case is that you you need to pattern match the references instead of trying to dereference them:

impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {     fn eq(&self, other: &Self) -> bool {         use Either::*;          match (self, other) {             (&Left(ref a), &Left(ref b)) => a == b,             (&Right(ref a), &Right(ref b)) => a == b,             _ => false,         }     } } 

When you create a tuple, you would be moving the dereferenced item into the tuple, giving up ownership. When you have a match *foo, you don't have to give up the ownership.

In modern Rust, you can write the same thing with less noise because more implicit referencing / dereferencing occurs when pattern matching:

impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {     fn eq(&self, other: &Self) -> bool {         use Either::*;         match (self, other) {             (Left(a), Left(b)) => a == b,             (Right(a), Right(b)) => a == b,             _ => false,         }     } } 
like image 114
Shepmaster Avatar answered Sep 23 '22 00:09

Shepmaster