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>
93 lines
4.2 KiB
Rust
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"]);
|