Why trait is not implemented for fixed size slice?

Hello. What is wrong with this? How to make it working?

fn main() 
{
  trait Trait1 {}
  fn does_implement_trait1( _ : &impl Trait1 ) -> bool { true }
  impl< T : Sized > Trait1 for &[ T ] {}
  assert_eq!( does_implement_trait1( &[ 1, 2, 3 ] ), true ); /* does not work */
//   /* but that works : */
//   let src : &[ i32 ] = &[ 1, 2, 3 ];
//   assert_eq!( does_implement_trait1( &src ), true );
}

Output:

error[E0277]: the trait bound `[{integer}; 3]: Trait1` is not satisfied
 --> src/main.rs:6:38
  |
6 |   assert_eq!( does_implement_trait1( &[ 1, 2, 3 ] ), true ); /* does not work */
  |               ---------------------  ^^^^^^^^^^^^ the trait `Trait1` is not implemented for `[{integer}; 3]`
  |               |
  |               required by a bound introduced by this call
  |
  = help: the following implementations were found:
            <&[T] as Trait1>
note: required by a bound in `does_implement_trait1`
 --> src/main.rs:4:39
  |
4 |   fn does_implement_trait1( _ : &impl Trait1 ) -> bool { true }
  |                                       ^^^^^^ required by this bound in `does_implement_trait1`

For more information about this error, try `rustc --explain E0277`.

Playground

Well you can add the missing impl.

impl<T: Sized, const N: usize> Trait1 for [T; N] {}
3 Likes

To add some context, your literal is of type &[u32; 3]. At certain places, the compiler will coerce this to &[u32] for you; this is what happens in your commented-out example.

When you're calling a generic function, however, this coercion can't happen due to forward-compatibility concerns: If the implementation @alice refers to gets added later, then the call's behavior could change unexpectedly.

1 Like

@alice thank you for the reply, but seems it does not work. Must be one more element of puzzle is missing.

Playground

In addition to what the others said, there's something else to note that is similar to another recent thread (yours?) where there are multiple references going on.

  // This takes a reference to things that implement `Trait1`
  fn does_implement_trait1( _ : &impl Trait1 ) -> bool { true }
  // This is an implementation for &[T]
  impl< T : Sized > Trait1 for &[ T ] {}

Taken together, that means the function takes &&[T] for any Sized T. Note the nested reference.

Here are some variations that work.

  // unchanged
  fn does_implement_trait1( _ : &impl Trait1) -> bool { true }
  // unchanged
  impl< T : Sized > Trait1 for &[ T ] {}
  // Added:                          v            vvvv
  assert_eq!( does_implement_trait1( &&[ 1, 2, 3 ][..] ), true );
  // Removed reference         v
  fn does_implement_trait1( _ : impl Trait1) -> bool { true }
  // unchanged
  impl< T : Sized > Trait1 for &[ T ] {}
  // Added:                                      vvvv
  assert_eq!( does_implement_trait1( &[ 1, 2, 3 ][..] ), true );
  // Allowed non-`Sized`         v           vvvvvvvvvv
  fn does_implement_trait1( _ : &(impl Trait1 + ?Sized)) -> bool { true }
  // Removed reference        v
  impl< T : Sized > Trait1 for [ T ] {}
  // Added:                                      vvvv
  assert_eq!( does_implement_trait1( &[ 1, 2, 3 ][..] ), true );
3 Likes

You did not write my code as I did it. Yours has an extra & on the type.

3 Likes

@alice. I see. That works! :smiley: Thanks

Yes. Thank you! :smiley:

@2e71828 Thank you for the clarification :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.