makepad/libs/relax/compiler/tests/temp_partial_moves.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

112 lines
2.5 KiB
Rust

// Partial moves out of temporaries (commercial lane's Stage/P(DOOM) find, 2026-10-04): what is not
// moved out of a temporary drops at the end of its statement, once. "| " lines = rustc --test.
use std::sync::atomic::{AtomicUsize, Ordering};
static DROPS: AtomicUsize = AtomicUsize::new(0);
static LOG: std::sync::Mutex<Vec<u32>> = std::sync::Mutex::new(Vec::new());
struct D(u32);
impl Drop for D {
fn drop(&mut self) {
DROPS.fetch_add(self.0 as usize, Ordering::Relaxed);
LOG.lock().unwrap().push(self.0);
}
}
struct P {
a: D,
b: D,
}
struct Q {
p: P,
c: D,
}
fn drops() -> usize {
DROPS.swap(0, Ordering::Relaxed)
}
fn order() -> Vec<u32> {
std::mem::take(&mut *LOG.lock().unwrap())
}
fn make() -> P {
P { a: D(1), b: D(10) }
}
fn make_q() -> Q {
Q { p: make(), c: D(100) }
}
fn take(d: D) -> u32 {
d.0
}
#[test]
fn t01_field_of_call() {
drops();
let a = make().a;
println!("| make().a: rest {}", drops());
drop(a);
println!("| then a {}", drops());
}
#[test]
fn t02_field_of_box_deref() {
drops();
let a = (*Box::new(make())).a;
println!("| (*box).a: rest {}", drops());
drop(a);
drops();
let o = Some(Box::new(make()));
let b = (*o.unwrap()).b;
println!("| (*o.unwrap()).b: rest {}", drops());
drop(b);
drops();
}
#[test]
fn t03_nested_fields() {
drops();
order();
let a = make_q().p.a;
println!("| make_q().p.a: rest {} order {:?}", drops(), order());
drop(a);
drops();
order();
}
#[test]
fn t04_tuple_and_arg() {
drops();
let x = (D(2), D(20)).1;
println!("| tuple.1: rest {}", drops());
drop(x);
drops();
let n = take(make().b);
println!("| take(make().b): {} rest {}", n, drops());
}
#[test]
fn t05_in_branches() {
for c in [true, false] {
drops();
let d = if c { make().a } else { D(5) };
println!("| branch {}: before end {}", c, drops());
drop(d);
drops();
}
}
#[test]
fn t06_match_temp_box() {
drops();
let o = Some(Box::new(make()));
let n = match *o.unwrap() {
P { a, b } => a.0 + b.0,
};
println!("| match *tmp all: {} dropped {}", n, drops());
let o = Some(Box::new(make()));
let n = match *o.unwrap() {
P { a, .. } => take(a),
};
println!("| match *tmp part: {} dropped {}", n, drops());
let o = Some(Box::new(make()));
let n = match *o.unwrap() {
P { ref a, .. } if a.0 == 1 => a.0,
_ => 0,
};
println!("| match *tmp ref: {} dropped {}", n, drops());
}