Improve ergonomics of platform_support's Instant (#17577)

# Objective

- Make working with `bevy_time` more ergonomic in `no_std` environments.

Currently `bevy_time` expects the getter in environments where time
can't be obtained automatically via the instruction set or the standard
library to be of type `*mut fn() -> Duration`.
[`fn()`](https://doc.rust-lang.org/beta/std/primitive.fn.html) is
already a function pointer, so `*mut fn()` is a _pointer to a function
pointer_. This is harder to use and error prone since creating a pointer
out of something like `&mut fn() -> Duration` when the lifetime of the
reference isn't static will lead to an undefined behavior once the
reference is freed

## Solution

- Accept a `fn() -> Duration` instead

## Testing

- I made a whole game on the Playdate that relies on `bevy_time`
heavily, see:
[bevydate_time](1b4f02adcd/src/lib.rs (L510-L546))
for usage of the Instant's getter.

---

## Showcase

<details>
  <summary>Click to view showcase</summary>


https://github.com/user-attachments/assets/f687847f-6b62-4322-95f3-c908ada3db30

</details>

## Migration Guide

This is a breaking change but it's not for people coming from Bevy v0.15

### Small thank you note
Thanks to my friend https://github.com/repnop for helping me understand
how to deal with function pointers in `unsafe` environments

Co-authored-by: Wesley Norris <repnop@repnop.dev>
This commit is contained in:
Mathspy 2025-02-02 10:50:48 -05:00 committed by GitHub
parent 9165fb020a
commit 469b218f20
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -30,7 +30,7 @@ mod fallback {
time::Duration,
};
static ELAPSED_GETTER: AtomicPtr<fn() -> Duration> = AtomicPtr::new(unset_getter as *mut _);
static ELAPSED_GETTER: AtomicPtr<()> = AtomicPtr::new(unset_getter as *mut _);
/// Fallback implementation of `Instant` suitable for a `no_std` environment.
///
@ -53,7 +53,7 @@ mod fallback {
let getter = ELAPSED_GETTER.load(Ordering::Acquire);
// SAFETY: Function pointer is always valid
let getter = unsafe { *getter };
let getter = unsafe { core::mem::transmute::<_, fn() -> Duration>(getter) };
Self((getter)())
}
@ -66,8 +66,8 @@ mod fallback {
/// - The function provided must accurately represent the elapsed time.
/// - The function must preserve all invariants of the [`Instant`] type.
/// - The pointer to the function must be valid whenever [`Instant::now`] is called.
pub unsafe fn set_elapsed(getter: *mut fn() -> Duration) {
ELAPSED_GETTER.store(getter, Ordering::Release);
pub unsafe fn set_elapsed(getter: fn() -> Duration) {
ELAPSED_GETTER.store(getter as *mut _, Ordering::Release);
}
/// Returns the amount of time elapsed from another instant to this one,