title: How can I have a collection of objects that differ by their associated type?
body: <p>I have a program that involves examining a complex data structure to see if it has any defects. (It's quite complicated, so I'm posting example code.) All of the checks are unrelated to each other, and will all have their own modules and tests.</p>
  
  <p>More importantly, each check has its own error type that contains different information about how the check failed for each number. I'm doing it this way instead of just returning an error string so I can test the errors (it's why <code>Error</code> relies on <code>PartialEq</code>).</p>
  
  <h2>My Code So Far</h2>
  
  <p>I have traits for <code>Check</code> and <code>Error</code>:</p>
  
  <pre><code>trait Check {
      type Error;
      fn check_number(&amp;self, number: i32) -&gt; Option&lt;Self::Error&gt;;
  }
  
  trait Error: std::fmt::Debug + PartialEq {
      fn description(&amp;self) -&gt; String;
  }
  </code></pre>
  
  <p>And two example checks, with their error structs. In this example, I want to show errors if a number is negative or even:</p>
  
  <pre><code>
  #[derive(PartialEq, Debug)]
  struct EvenError {
      number: i32,
  }
  struct EvenCheck;
  
  impl Check for EvenCheck {
      type Error = EvenError;
  
      fn check_number(&amp;self, number: i32) -&gt; Option&lt;EvenError&gt; {
          if number &lt; 0 {
              Some(EvenError { number: number })
          } else {
              None
          }
      }
  }
  
  impl Error for EvenError {
      fn description(&amp;self) -&gt; String {
          format!("{} is even", self.number)
      }
  }
  
  #[derive(PartialEq, Debug)]
  struct NegativeError {
      number: i32,
  }
  struct NegativeCheck;
  
  impl Check for NegativeCheck {
      type Error = NegativeError;
  
      fn check_number(&amp;self, number: i32) -&gt; Option&lt;NegativeError&gt; {
          if number &lt; 0 {
              Some(NegativeError { number: number })
          } else {
              None
          }
      }
  }
  
  impl Error for NegativeError {
      fn description(&amp;self) -&gt; String {
          format!("{} is negative", self.number)
      }
  }
  </code></pre>
  
  <p>I know that in this example, the two structs look identical, but in my code, there are many different structs, so I can't merge them. Lastly, an example <code>main</code> function, to illustrate the kind of thing I want to do:</p>
  
  <pre><code>fn main() {
      let numbers = vec![1, -4, 64, -25];
      let checks = vec![
          Box::new(EvenCheck) as Box&lt;Check&lt;Error = Error&gt;&gt;,
          Box::new(NegativeCheck) as Box&lt;Check&lt;Error = Error&gt;&gt;,
      ]; // What should I put for this Vec's type?
  
      for number in numbers {
          for check in checks {
              if let Some(error) = check.check_number(number) {
                  println!("{:?} - {}", error, error.description())
              }
          }
      }
  }
  </code></pre>
  
  <p>You can see the code in <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2015&amp;gist=1804e0f83d0183de071b05cf040d7a2a" rel="noreferrer">the Rust playground</a>.</p>
  
  <h2>Solutions I've Tried</h2>
  
  <p>The closest thing I've come to a solution is to remove the associated types and have the checks return <code>Option&lt;Box&lt;Error&gt;&gt;</code>. However, I get this error instead:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0038]: the trait `Error` cannot be made into an object
   --&gt; src/main.rs:4:55
    |
  4 |     fn check_number(&amp;self, number: i32) -&gt; Option&lt;Box&lt;Error&gt;&gt;;
    |                                                       ^^^^^ the trait `Error` cannot be made into an object
    |
    = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
  </code></pre>
  
  <p>because of the <code>PartialEq</code> in the <code>Error</code> trait. Rust has been great to me thus far, and I really hope I'm able to bend the type system into supporting something like this!</p>