On Tue May 19, 2026 at 12:07 PM BST, Alexandre Courbot wrote:
> 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.

I'm aware. That's why it has `Unsafe` in the name. But there's no way to create
unsafe-to-name types, and without adt_const_params only integers can be used as
const generic parameters and thus I cannot use a unsafe-to-create const
parameter for this.

>
> 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>);

An earlier version of this series have `ForLt!()` being quite ubiquitous, so I
want to avoid this approach as this'll be need everywhere. But now we switch to
use GAT for driver data, so perhaps this isn't too terrible anymore (only
driver-core and aux device registration would need this).

This could even be extended to support generic types, such as

    define_for_lt!(DataLt<T> = for<'a> Data<'a, T>);

This does also have th benefit of not having the `type_complexity` issue.

Danilo, what do you think?

---

I suppose If we're going down the new type approach, I also have some idea about
generalizing this further to a generic utility that annotate GAT about variance.

    #[variance_check]
    trait MyTrait {
        type MyGat<#[covariant] 'a>;
    }

    #[variance_check]
    impl MyTrait for MyFoo {
        type MyGat<#[covariant] 'a> = Bar;
    }

Then the expansion of `define_for_lt!` would just be

    struct DataLt<T>(PhantomData<T>);

    #[variance_check]
    impl<T> ForLt for DataLt<T> {
        type Of<#[covariant] 'a> = Data<'a, T>;
    }

Best,
Gary

Reply via email to