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>
75 lines
2.3 KiB
Rust
75 lines
2.3 KiB
Rust
// `let`-extended temporaries (`let r = R { c: &D(..) };`, `let x = &D(..);`) drop in reverse
|
|
// declaration order together with the block's locals: after the locals declared later, before
|
|
// the `let`'s own bindings and earlier locals (rustc schedules the temporary's drop when the
|
|
// initializer makes it). Relax dropped them after every local of the block (silent order bug,
|
|
// tests/ui closures/2229_closure_analysis/preserve_field_drop_order2.rs). Sequences = rustc.
|
|
use std::cell::RefCell;
|
|
thread_local! { static LOG: RefCell<Vec<String>> = RefCell::new(Vec::new()); }
|
|
fn take() -> String { LOG.with(|l| std::mem::take(&mut *l.borrow_mut())).join(",") }
|
|
struct D(&'static str);
|
|
impl Drop for D { fn drop(&mut self) { LOG.with(|l| l.borrow_mut().push(self.0.to_string())); } }
|
|
struct R<'a> { c: &'a D, d: &'a D }
|
|
|
|
fn blocks() {
|
|
let _a = D("a");
|
|
let r = R { c: &D("ext1"), d: &D("ext1b") };
|
|
let _b = D("b");
|
|
let x = &D("ext2");
|
|
let _c = D("c");
|
|
{
|
|
let _i = D("i");
|
|
let y = &D("ext3");
|
|
let _j = D("j");
|
|
let _ = y.0;
|
|
}
|
|
let _ = (r.c.0, r.d.0, x.0);
|
|
}
|
|
fn early(n: u32) -> u32 {
|
|
let _a = D("ea");
|
|
let r = R { c: &D("e1"), d: &D("e2") };
|
|
let _b = D("eb");
|
|
if n == 1 { return 1; }
|
|
let x = &D("e3");
|
|
let _c = D("ec");
|
|
if n == 2 { return 2; }
|
|
let _ = (r.c.0, r.d.0, x.0);
|
|
0
|
|
}
|
|
fn in_loop() {
|
|
let mut i = 0;
|
|
loop {
|
|
let _l = D("l");
|
|
let y = &D("lt");
|
|
let _m = D("m");
|
|
i += 1;
|
|
if i == 2 { break; }
|
|
let _ = y.0;
|
|
}
|
|
}
|
|
fn unwinds() {
|
|
let _a = D("ua");
|
|
let _x = &D("ut");
|
|
let _b = D("ub");
|
|
panic!("p");
|
|
}
|
|
|
|
#[test]
|
|
fn extended_temps_in_declaration_order() {
|
|
blocks();
|
|
assert_eq!(take(), "j,ext3,i,c,ext2,b,ext1b,ext1,a");
|
|
let mut s = Vec::new();
|
|
for n in 0..3 { early(n); s.push(take()); }
|
|
assert_eq!(s, ["ec,e3,eb,e2,e1,ea", "eb,e2,e1,ea", "ec,e3,eb,e2,e1,ea"]);
|
|
in_loop();
|
|
assert_eq!(take(), "m,lt,l,m,lt,l");
|
|
std::panic::set_hook(Box::new(|_| {}));
|
|
let _ = std::panic::catch_unwind(|| unwinds());
|
|
assert_eq!(take(), "ub,ut,ua");
|
|
{
|
|
let (a, b) = (&D("t1"), D("v1"));
|
|
let s: &[D] = &[D("s1"), D("s2")];
|
|
let _k = D("k");
|
|
let _ = (a.0, b.0, s.len());
|
|
}
|
|
assert_eq!(take(), "k,s1,s2,v1,t1");
|
|
}
|