On Sun May 17, 2026 at 9:01 AM JST, Danilo Krummrich wrote:
<snip>
> +/// This is intended to be an "unsafe-to-refer-to" type.
> +///
> +/// Must only be used by the `ForLt!` macro.
> +///
> +/// `T` is the magic `dyn for<'a> WithLt<'a, TypeThatUse<'a>>` generated by
> macro.
> +///
> +/// `WF` is a type that the macro can use to assert some specific type is
> well-formed.
> +///
> +/// `N` is to provide the macro a place to emit arbitrary items, in case it
> needs to prove
> +/// additional properties.
> +#[doc(hidden)]
> +pub struct UnsafeForLtImpl<T: ?Sized, WF, const N: usize>(PhantomData<(WF,
> T)>);
Although the documentation makes it clear this should never be
referenced directly, doing so is still possible, which creates a
loophole for breaking covariance using only safe code.
For instance (untested, and based on my limited understanding of the
patch):
type Bad = UnsafeForLtImpl<
dyn for<'a> WithLt<'a, Of = Cell<&'a u8>>,
(),
0,
>;
The blanket `ForLt` implementation applies, and now we can store a
shorter-lived reference into the `Cell` and potentially observe it after
its lifetime.
This could be worked around by defining the type implementing `ForLt`
locally, at the cost of ergonomics since the `ForLt` type would be
declared separately:
// Defines `DataLt` and implements `ForLt` on it after emitting
// covariance proof.
define_for_lt!(DataLt = for<'a> Data<'a>);
...
something: Devres<auxiliary::Registration<DataLt>>
I'm not claiming this is better; but imho the tradeoff is worth
considering.