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

When can function pointers be transmuted? #81

Closed
RalfJung opened this issue Jan 11, 2019 · 7 comments
Closed

When can function pointers be transmuted? #81

RalfJung opened this issue Jan 11, 2019 · 7 comments
Labels
A-validity Topic: Related to validity invariants C-open-question Category: An open question that we should revisit S-pending-team-decision Status: There is broad agreement on the question

Comments

@RalfJung
Copy link
Member

On Zulip, @ubsan was asking about function pointer transmutes:

Can you transmute<fn(*const T), fn(*const ())>(x)(p)?

(I assume we have T: Sized here.)

I would say we can modularize the problem (but this goes deep into validity invariant territory):

  1. The actual cast is always okay, because the validity invariant for function pointers does not talk about the signature. Maybe it just says "non-NULL", maybe it also says "points to executable memory", but I think it should not take the signature into account.
  2. The call, then, is when things may become UB if the signatures are wrong. We probably need some definition of "ABI compatible" here: Which "mismatches" we allow between the caller and callee signature will depend not just on layout but also on ABI concerns. For example, CTFE/miri currently say that either the type must be exactly the same, or else both types must have Scalar ABI that may differ only in its valid_range. In your example, the second condition is satisfied. If the mismatch is not allowed, we have UB.
  3. The behavior of allowed argument mismatches, then, is the same as that of a transmute, of union-based type punning, and of type punning through changing pointer types: In your case, I would say your code is equivalent to x(mem::transmute<*const T, *const ()>(p)).

(Taken from #45 (comment) )

@rodrimati1992
Copy link

rodrimati1992 commented Mar 28, 2019

It would be very valuable if this were defined,because I need to cast extern fn(&T) to extern fn(&SomeZSTStruct) to implement ffi-safe trait objects.

I may be able to get around this problem by just taking a struct that always erases the type:

/**
This takes a *const R/*mut R/&R/&mut R as a type parameter.

Here are examples of function types taking it:
    -extern fn(Erase<&T>)
    -extern fn(Erase<&mut T>)
    -extern fn(Erase<*const T>)
    -extern fn(Erase<*mut T>)
*/
#[repr(transparent)]
pub struct Erase<T> {
    pointer: *const c_void,
    type_: PhantomData<T>,
}



@RalfJung RalfJung added C-open-question Category: An open question that we should revisit A-validity Topic: Related to validity invariants labels Aug 14, 2019
@rosekunkel
Copy link

I would also like to know this. More specifically, when can unsafe function pointers be transmuted into safe ones? That is, which (if any) of these are valid:

mem::transmute::<unsafe extern "Rust" fn(A) -> B, extern "Rust" fn(A) -> B>(foo)
mem::transmute::<unsafe extern "C" fn(A) -> B, extern "C" fn(A) -> B>(foo)
mem::transmute::<unsafe extern "C" fn(A, ...) -> B, extern "C" fn(A, ...) -> B>(foo)

I would expect at least the extern "C" casts to be valid.

@bjorn3
Copy link
Member

bjorn3 commented Mar 30, 2021

I would expect it to be valid, but only sound when you now that the function is always safe to call.

@RalfJung
Copy link
Member Author

Yeah, unsafe does not affect the call ABI in any way.

@rosekunkel
Copy link

It would be nice if there was a less error-prone way to do this than just mem::transmute, like a rule that allows you to cast unsafe function pointers to safe ones inside an unsafe block, much like you can call unsafe functions in unsafe blocks.

@JakobDegen JakobDegen added the S-pending-team-decision Status: There is broad agreement on the question label Jul 25, 2023
@JakobDegen
Copy link
Contributor

For triage: Clarifying that we are interpreting this as a question about validity of function pointers, not about ABI.

@RalfJung
Copy link
Member Author

This was closed as a duplicate of #72 and #280

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-validity Topic: Related to validity invariants C-open-question Category: An open question that we should revisit S-pending-team-decision Status: There is broad agreement on the question
Projects
None yet
Development

No branches or pull requests

5 participants