Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it possible to implement a trait for both `T: Display` and `str`?

Tags:

rust

There is no specialization in stable Rust yet, so this does not work:

trait X {}

impl<T> X for T {}
impl X for u32 {}  // conflicting implementation

No surprises there: X is implemented for any type T and we can't implement it again for u32.

Surprisingly, the following snippet compiles successfuly:

use std::fmt::Display;

pub trait Show {}

impl<T: Display> Show for T {}

impl Show for str {}

// These impls would cause "conflicting implementation" errors:
// impl<'a> Show for &'a str
// impl Show for String

fn main() {}

I would not expect this code to compile because Display is implemented for str, so the generic impl should implement Show for str and conflict with the specific impl.

Why does impl Show for str not conflict with impl<T: Display> Show for T?

like image 266
MB-F Avatar asked Sep 28 '18 09:09

MB-F


1 Answers

The bound <T: Display> implicitly assumes T must be a Sized type. However str is unsized. Therefore the two impls are not in conflict with each other.

If you need to cover unsized types like str as well, you need to relax the Sized requirement by adding T: ?Sized:

impl<T: Display + ?Sized> Show for T {}
//              ^~~~~~~~
like image 157
kennytm Avatar answered Oct 01 '22 18:10

kennytm