Recognize generic struct as being always 'static (GAT)

Hello, I have the following code:

struct MustWrapStatic<'a, T: 'static>(&'a mut T);

struct OnlyContainsStaticFields<T: TraitItselfIsNotStatic>{
    static_field: T::Static
}

trait TraitItselfIsNotStatic{
    type Static: 'static;
}

trait Foo<'a, T: TraitItselfIsNotStatic>{
    type Bar;
}

impl<'a, T: TraitItselfIsNotStatic> Foo<'a, T> for (){
    type Bar = MustWrapStatic<'a, OnlyContainsStaticFields<T>>; //error
}

Which produces this error:

error[E0309]: the parameter type T may not live long enough

While suggesting to bound T with : 'static. That is not possible in my use case, also it should not be required as OnlyContainsStaticFields only contains a static field.

The user Globi on the Rust Discord suggested this fix which works:

impl<'a, T: TraitItselfIsNotStatic> Foo<'a, T> for ()
where OnlyContainsStaticFields<T>: 'static{
    type Bar = MustWrapStatic<'a, OnlyContainsStaticFields<T>>;
}

However, I currently experiment with GATs. Foo and it's impl would change to this:

trait Foo{
    type Bar<'a, T: TraitItselfIsNotStatic>;
}
impl Foo for (){
    type Bar<'a, T: TraitItselfIsNotStatic> = 
        MustWrapStatic<'a, OnlyContainsStaticFields<T>>; //error
}

And for that this does not work as I can't bound the impl to a GAT.

I could even do...

struct OnlyContainsStaticFields<T: TraitItselfIsNotStatic>
    where Self: 'static

...or...

struct OnlyContainsStaticFields<T: TraitItselfIsNotStatic>
    where OnlyContainsStaticFields<T>: 'static

...which gets entirely ignored by the compiler. :joy:

Does someone have a suggestion how to fix it in this case?

OnlyContainsStaticFields<T>: 'static and T: 'static are essentially equivalent AFAIK.

The way SomeStruct<Args…>: 'static works is not that it requires all fields of SomeStruct<Args…> to be “: 'static”, but instead it requires all of Args… to be “: 'static”.

Oh, why so?

The issue for me is that I need Bar to be unique to be used as a Bevy resource or component. These have to be a unique type or else are overwritten if attempted to insert multiple times.

Defining OnlyContainsStaticFields as

struct OnlyContainsStaticFields<T>{
    static_field: T::Static
}

...and...

type Bar<'a, T: TraitItselfIsNotStatic> = 
    MustWrapStatic<'a, OnlyContainsStaticFields<T::Static>>; 

...would be bad because multiple impl of this trait might have the same type as Bar.

I explained that in the subsequent part of my response :wink:

Or do you mean why it’s designed that way? IDK, presumably some combination of

  • it works commonly well enough to work with this “conservative” approach
  • in particular, not considering the fields also settles some questions around privacy / exposing the fields of a Struct in the behavior of Struct<Args>: 'lifetime bounds
  • nobody has come up with a complete sound model of doing it differently, as far as I’m aware

As far as I know, there are however plans to try and make fn(…) -> … (function pointer) types 'static, regardless of the argument types, so there’s presumably some design work on how to find (sound) approaches of how to now always require this “nominal/syntactic” behavior of : 'lifetime bounds.

1 Like

If T isn't 'static, neither will GenericStruct<T>, regardless of the types of the fields themselves (RFC 1214). Example.

...which gets entirely ignored by the compiler. :joy:

It's not implied so you have to repeat it, but it's not ignored. It's enforced on creation. See also RFC 2089 (not implemented and will be a pain to implement without breaking something I think).

Does someone have a suggestion how to fix it in this case?

Some T: 'static bounds. Optionally on OnlyConstainsStaticFields too.

1 Like