Description
fn foo<T: Sized + ?Sized>() {}
The above results in no warning or error in 1.0 and 1.1.
While this may seem harmless, the Sized
bound can be propagated from a trait:
trait NotObjectSafe: Sized {...}
fn foo<T: NotObjectSafe + ?Sized>() {
is_sized::<T>();
}
fn is_sized<T: Sized>() {}
This is a backwards-compatibility hazard, as NotObjectSafe
cannot be made object-safe (by adding where Self: Sized
to each method which requires it) without causing NotObjectSafe + ?Sized
to start allowing unsized types for T
, where it previously wouldn't have.
A concrete example is trait Clone: Sized
which I believe could be object-safe if the Sized
bound was moved to its two methods.
Clone: Sized
prevents, e.g. [T]: Copy where T: Copy
which could be used to write constructors for Rc<[T]>
(and perhaps even for Rc<Trait+Copy>
).
It's also arguably unintuitive, as ?Sized
has no effect but it may show up in documentation, advertising an usecase which isn't actually supported.