Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Withlifetime trait #57

Open
CeleritasCelery opened this issue Jan 9, 2024 · 0 comments
Open

Withlifetime trait #57

CeleritasCelery opened this issue Jan 9, 2024 · 0 comments
Labels
unsound? Unsure if this unsafe code is sound

Comments

@CeleritasCelery
Copy link
Owner

pub(crate) trait WithLifetime<'new> {
type Out: 'new;
unsafe fn with_lifetime(self) -> Self::Out;
}

The WithLifetime trait is a unsafe trait that let's us be generic over changing the lifetime of some type. This is equivalent to

let x: &'old = &T;
&'new *(x as *const T)

However lifetimes can also be type parameters of generic types. For example T could be a Vec<&'a i32>, but in generic code you don't have access to the lifetime parameters. So we create this new trait that lets us transmute the lifetime. However the problem with this trait is that the output type is different then the input type, even though they are really the same type but with different lifetime parameters.

For example here is the implementation for a GcManaged reference.

impl<'new, 'old, T: GcManaged + 'new> WithLifetime<'new> for &'old T {
type Out = &'new T;
unsafe fn with_lifetime(self) -> Self::Out {
&*(self as *const T)
}
}

why this is sound

This trait is only safe to implement for types that are managed by the GC. The output type must only be the input type with the lifetime set to 'new. And even then we have to take care when calling it. The Out GAT is constrained to the 'new lifetime, and that lifetime is a parameter of the trait bounds. Here is an example usage

    pub(crate) fn bind<'ob>(&self, _: &'ob Context) -> <T as WithLifetime<'ob>>::Out
    where
        T: WithLifetime<'ob> + Copy,
    {
        // SAFETY: We are holding a reference to the context
        unsafe { self.inner.with_lifetime() }
    }

Here the output of this functions is <T as WithLifetime<'ob>>::Out and the trait bounds specify the lifetime we want to transmute it to. Since T implements WithLifetime we know that is is safe to bind to the lifetime of the Context because it will not be dropped as long as that immutable reference exists.

@CeleritasCelery CeleritasCelery added the unsound? Unsure if this unsafe code is sound label Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unsound? Unsure if this unsafe code is sound
Projects
None yet
Development

No branches or pull requests

1 participant