title: How to get Deref coercion when using impl Trait (take 2)
body: <p>Here is a trait (simplified for the question) which I'd like to implement for every type that behaves like a slice:</p>
  
  <pre><code>trait SliceLike {
      type Item;
  
      /// Computes and returns (owned) the first item in a collection.
      fn first_item(&amp;self) -&gt; Self::Item;
  }
  </code></pre>
  
  <p>Note that the <code>Item</code> type is an associated type; I want each type that is <code>SliceLike</code> to have a unique element type.</p>
  
  <p>Here is an attempt at a blanket implementation:</p>
  
  <pre><code>use std::ops::Deref;
  
  impl&lt;T: Clone, U: Deref&lt;Target = [T]&gt;&gt; SliceLike for U {
      type Item = T;
  
      fn first_item(&amp;self) -&gt; Self::Item {
          self[0].clone()
      }
  }
  </code></pre>
  
  <p>For example, this compiles and runs:</p>
  
  <pre><code>let data: Vec&lt;usize&gt; = vec![3, 4];
  assert_eq!(data.first_item(), 3);
  
  let data: &amp;[usize] = &amp;[3, 4];
  assert_eq!(data.first_item(), 3);
  
  let data: Box&lt;[usize]&gt; = Box::new([3, 4]);
  assert_eq!(data.first_item(), 3);
  
  let data: Rc&lt;[usize]&gt; = Rc::new([3, 4]);
  assert_eq!((&amp;data).first_item(), 3);
  </code></pre>
  
  <p>This also compiles and runs:</p>
  
  <pre><code>fn stub(x: &amp;[usize]) -&gt; usize {
      x.first_item()
  }
  
  let data: [usize; 2] = [3, 4];
  assert_eq!(stub(&amp;data), 3);
  
  assert_eq!(stub(&amp;[3, 4]), 3);
  </code></pre>
  
  <p>But if I inline <code>stub()</code> it fails to compile:</p>
  
  <pre><code>let data: [usize; 2] = [3, 4];
  assert_eq!(data.first_item(), 3); // Fails.
  
  assert_eq!([3, 4].first_item(), 3); // Fails.
  </code></pre>
  
  <p>The blanket implementation uses the <code>Deref</code> trait that the compiler itself uses to turn other types into slices. It will catch all third-party types that also behave like a slice.</p>
  
  <p>The error message is:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0599]: no method named `first_item` found for type `[usize; 2]` in the current scope
    --&gt; src/lib.rs:20:21
     |
  20 |     assert_eq!(data.first_item(), 3); // Fails.
     |                     ^^^^^^^^^^
     |
     = note: the method `first_item` exists but the following trait bounds were not satisfied:
             `[usize; 2] : SliceLike`
             `[usize] : SliceLike`
     = help: items from traits can only be used if the trait is implemented and in scope
     = note: the following trait defines an item `first_item`, perhaps you need to implement it:
             candidate #1: `SliceLike`
  </code></pre>
  
  <p>In <a href="https://stackoverflow.com/questions/54400803/how-to-get-deref-coercion-when-using-impl-trait/54400887#54400887">take 1</a> of this question, I was advised to use <code>AsRef</code> instead of <code>Deref</code>. That solution won't work here, because some type might implement <code>AsRef</code> for more than one element type.</p>
  
  <p>I think I understand what is going on. For each type <code>T</code> there is a unique type <code>&lt;T as Deref&gt;::Target</code>. When <code>T</code> is <code>&amp;[usize; 2]</code> the target is <code>[usize; 2]</code>, not <code>[usize]</code>. The compiler is able to coerce <code>&amp;[T; 2]</code> to <code>&amp;[T]</code> if I explicitly ask it to, e.g. by using <code>let</code> or <code>stub()</code>, but if I don't then it's not able to work out that the coercion is required.</p>
  
  <p>But it's frustrating: it's perfectly obvious to a human what the failing calls are intended to do, and the compiler understands what's required for <code>Vec&lt;usize&gt;</code>, <code>Box&lt;[usize]&gt;</code>, <code>Rc&lt;[usize]&gt;</code>, <code>&amp;[usize]</code> and so on, so it doesn't seem unreasonable to try to make it work for <code>[usize; 2]</code> as well.</p>
  
  <p>Is there a convenient way to write <code>first()</code> so that the last two calls work too? If not, is there a syntax to ask the compiler to coerce a <code>&amp;[usize; 2]</code> to a <code>&amp;[usize]</code> inline, <em>i.e.</em> without using <code>let</code> or <code>stub()</code>?</p>
  
  <p><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=3b24bfc8774e2c464f9246295b79c593" rel="nofollow noreferrer">Playground</a></p>