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

Are (non-free) generic constants guaranteed to be evaluated? #409

Closed
joshlf opened this issue May 29, 2023 · 4 comments
Closed

Are (non-free) generic constants guaranteed to be evaluated? #409

joshlf opened this issue May 29, 2023 · 4 comments

Comments

@joshlf
Copy link

joshlf commented May 29, 2023

Thanks to this suggestion by @gootorov, we're considering doing something like the following in zerocopy:

pub trait MaybeTransmutableInto<T: FromBytes>: Sized + AsBytes {
    const REF_TRANSMUTABLE_INTO: () = assert!(
        mem::size_of::<Self>() == mem::size_of::<T>()
            && mem::align_of::<Self>() >= mem::align_of::<T>()
    );

    fn transmute_ref_into(&self) -> &T {
        let _: () = <Self as MaybeTransmutableInto<T>>::REF_TRANSMUTABLE_INTO;
        unsafe { mem::transmute(self) }
    }
}

The nightly reference guarantees that "free constants are always evaluated at compile time." However, that's not quite what we have here - we evaluate the constant REF_TRANSMUTABLE_INTO but assign it to a runtime variable (let _: () = ...). If we replaced let _ with const _, that would be a free constant, but it would never compile (even when we wanted it to) because a constant in a function body isn't allowed to reference types which are generic in that context.

What I want to know is: Is this constant guaranteed to be evaluated so long as transmute_ref_into is used?

@digama0
Copy link

digama0 commented May 29, 2023

This code is equivalent to an assert at the beginning of the function, so it definitely will never be callable without a panic, i.e. as far as protecting the transmute is concerned you should be fine. Because the assert is in a const body, it must be evaluated at compile time if it ends up in the binary at all, so yes, I think you will get the desired behavior that if transmute_ref_into is used then any errors will happen at compile time (post-monomorphization time, more precisely). If transmute_ref_into is not used (in some sense of 'used') I don't know if we will promise anything here.

This isn't really an unsafe code question though, it's probably t-lang.

@joshlf
Copy link
Author

joshlf commented May 30, 2023

Okay sounds good, thanks! It makes sense to me too that it would be guaranteed, but I'll ask t-lang just to be sure 🙂

@RalfJung
Copy link
Member

We guarantee that every constant mentioned syntactically within a function that executes at runtime, has been previously executed at compiletime. So I agree with @digama0. I don't know if and where we document that guarantee, though.

@RalfJung
Copy link
Member

Closing in favor of rust-lang/rust#112090.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants