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.

Reply via email to