Description
The concept of implicit bound was introduced together with dynamic sized type. While having a : Sized
bound is more specialized than no bound at all, we expect that : Sized
is much more common, and thus should be present by default. We introduced the : ?Sized
syntax in #490 to opt-out of this default bound. The syntax : ?Sized
is called "relaxed bound".
Later, new RFCs and PRs tried to introduce more traits like Sized
which the common case is "this should be implemented", e.g.
- Immovable types #1858 and Immovable types prototype where the Move trait is builtin rust#44917 introduced the
?Move
bound, since most types do not contain internal references and thus can be freely moved around. - Opaque Data structs for FFI #1993 and Add DynSized trait (rebase of #44469) rust#46108 introduced the
?DynSized
bound, since most types have known size and alignment at runtime. - https://gankro.github.io/blah/linear-rust (semiseriously) introduced the
?Leave
bound, since most types can bedrop
'ed.
These traits themselves are often necessary at language level beyond trait bounds, e.g. Move
is needed for immovable generators (for lack of a better solution), DynSized
is needed to reject struct tails without known alignment, and Leave
is needed to support linear type.
However, the expansion of implicit bounds experienced push back from lang team due to ergonomic cost, that
-
?Sized
itself being a "negative feature" confuses users, adding?Move
and?DynSized
will only make the situation worse, -
introducing new relaxed bound means downstream packages will need to reevaluate every API to see if adding
: ?Trait
makes sense, and this needs to be done for every new relaxed bound. -
the necessity of
Move
andDynSized
is orthogonal to whether they need to be default. -
the backward-compatibility may be a lie 🍰 — Relaxing the bounds in associated type, in particular
FnOnce::Output
, means the user of the trait will get less promises, which is a breaking change:let should_be_movable: Closure::Output = closure(); let but_it_errored = should_be_movable;
Essentially, the bounds on an associated type cannot be added (which breaks implementers) or removed (which breaks users).
So the questions are,
- Should we embrace
?Trait
and allow language to grow more similar traits, despite the stated problems above? - If we decide to stop at
?Sized
, what else should we do regardingMove
andDynSized
? - Would there be a balanced solution in the middle of the two extremes?
I am filing this issue here to Move the discussion from those two different PRs to a potentially more proper place, as it seems having a non-Sized
relaxed bound itself should require more discussion around the language design.