Skip to content

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

Closed

Description

@joshlf

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?

Activity

  1. digama0 commented on May 29, 2023

    @digama0

    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.

  2. joshlf commented on May 30, 2023

    @joshlf
    Author

    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 🙂

  3. RalfJung commented on May 30, 2023

    @RalfJung
    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.

  4. RalfJung commented on May 30, 2023

    @RalfJung
    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions