makepad/libs/relax/compiler/tests/fullcheck_fnptr_debug.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

93 lines
4.2 KiB
Rust

// Function-pointer Debug prints the address, independently of ABI, safety,
// arity, and the traits implemented by its argument and return types.
macro_rules! check_callback {
($function:ident, $ty:ty) => {{
#[derive(Clone, Copy, Debug)]
struct Callback {
function: Option<$ty>,
}
let pointer: $ty = $function;
let address = format!("{:p}", pointer as *const ());
assert_eq!(format!("{:?}", pointer), address);
assert_eq!(format!("{:p}", pointer), address);
assert_eq!(format!("{:?}", &pointer as &dyn std::fmt::Debug), address);
let value = Some(pointer);
let expected = format!("Some({})", address);
assert_eq!(format!("{:?}", value), expected);
assert_eq!(format!("{:?}", &value as &dyn std::fmt::Debug), expected);
let callback = Callback { function: value };
let cloned = callback.clone();
assert_eq!(format!("{:?}", cloned), format!("Callback {{ function: {} }}", expected));
assert_eq!(format!("{:?}", &callback as &dyn std::fmt::Debug), format!("{:?}", cloned));
assert!(callback.function.is_some());
let empty: Option<$ty> = None;
assert_eq!(format!("{:?}", empty), "None");
assert_eq!(format!("{:?}", &empty as &dyn std::fmt::Debug), "None");
assert_eq!(format!("{:?}", Callback { function: empty }), "Callback { function: None }");
}};
}
macro_rules! callback_suite {
($module:ident, [$($qualifier:tt)*]) => {
mod $module {
use std::ffi::c_void;
// Deliberately do not implement Debug/Clone/Copy for these types.
#[repr(C)]
enum Scope {
Object,
}
#[repr(C)]
struct Opaque {
_value: u8,
}
$($qualifier)* fn f0() -> u32 {
let _ = Scope::Object;
0
}
$($qualifier)* fn f1(_data: *mut c_void) -> u32 { 0 }
$($qualifier)* fn f2(_data: *const Opaque, _out: *mut *const Opaque) {}
$($qualifier)* fn f3(data: *mut c_void, _size: usize, _scope: Scope) -> *mut c_void {
data
}
$($qualifier)* fn f4(data: *mut c_void, _size: usize, _align: usize, _scope: Scope) -> *mut c_void {
data
}
$($qualifier)* fn f5(_data: *mut c_void, original: *mut c_void, _size: usize, _align: usize, _scope: Scope) -> *mut c_void {
original
}
$($qualifier)* fn f6(_severity: u32, _kind: u32, _info: *const Opaque, _data: *mut c_void, _size: usize, _out: *mut *const Opaque) -> u32 {
0
}
$($qualifier)* fn f12(_a: u8, _b: u8, _c: u8, _d: u8, _e: u8, _f: u8, _g: u8, _h: u8, _i: u8, _j: u8, _k: u8, _l: *mut c_void) {}
#[test]
fn debug_callbacks() {
check_callback!(f0, $($qualifier)* fn() -> u32);
check_callback!(f1, $($qualifier)* fn(*mut c_void) -> u32);
check_callback!(f2, $($qualifier)* fn(*const Opaque, *mut *const Opaque));
check_callback!(f3, $($qualifier)* fn(*mut c_void, usize, Scope) -> *mut c_void);
check_callback!(f4, $($qualifier)* fn(*mut c_void, usize, usize, Scope) -> *mut c_void);
check_callback!(f5, $($qualifier)* fn(*mut c_void, *mut c_void, usize, usize, Scope) -> *mut c_void);
check_callback!(f6, $($qualifier)* fn(u32, u32, *const Opaque, *mut c_void, usize, *mut *const Opaque) -> u32);
check_callback!(f12, $($qualifier)* fn(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, *mut c_void));
}
}
};
}
callback_suite!(rust_safe, []);
callback_suite!(rust_unsafe, [unsafe]);
callback_suite!(c_safe, [extern "C"]);
callback_suite!(c_unsafe, [unsafe extern "C"]);
callback_suite!(system_safe, [extern "system"]);
callback_suite!(system_unsafe, [unsafe extern "system"]);
callback_suite!(c_unwind_safe, [extern "C-unwind"]);
callback_suite!(c_unwind_unsafe, [unsafe extern "C-unwind"]);
callback_suite!(system_unwind_safe, [extern "system-unwind"]);
callback_suite!(system_unwind_unsafe, [unsafe extern "system-unwind"]);