Почему возможно реализовать черту как для "T: Display", так и "str"?
Пока нет никакой специализации в стабильной Rust, так что это не работает:
trait X {}
impl<T> X for T {}
impl X for u32 {} // conflicting implementation
Никаких сюрпризов нет: X
реализован для любого типа T
и мы не можем реализовать его снова для u32
.
Удивительно, но следующий фрагмент успешно компилируется:
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() {}
Я бы не ожидал, что этот код будет компилироваться, потому что Display
реализован для str
, поэтому универсальный impl должен реализовать Show
for str
и конфликтовать с конкретным им.
Почему impl Show for str
не конфликтует с impl<T: Display> Show for T
?
Ответы
Ответ 1
Ограниченный <T: Display>
неявно предполагает, что T
должен быть размерным типом. Однако str
не поддерживается. Поэтому два имплана не конфликтуют друг с другом.
Если вам нужно также покрывать нестандартные типы, такие как str
, вам нужно уменьшить требование Sized, добавив T:?Sized
:
impl<T: Display + ?Sized> Show for T {}
// ^~~~~~~~