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

84 lines
2.3 KiB
Rust

// `return` / `break` / `continue` / `?` from inside an `if let` / `match` / `while` drop the
// temporaries of the statement being evaluated (Reference destructors.md
// [destructors.scope.nesting]; boot lane: makepad-script ip_to_loc's
// `if let Some(b) = self.bodies.borrow().get(i) { .. return .. }` left the RefCell borrowed).
// rustc: all pass.
use std::cell::{Cell, RefCell};
struct C {
bodies: RefCell<Vec<u32>>,
}
impl C {
fn loc(&self, i: usize) -> Option<u32> {
if let Some(b) = self.bodies.borrow().get(i) {
if *b > 1 {
return Some(*b);
}
}
None
}
fn via_match(&self, i: usize) -> u32 {
match self.bodies.borrow().get(i) {
Some(b) if *b > 1 => return *b,
_ => {}
}
0
}
fn via_try(&self, i: usize) -> Option<u32> {
let v = *self.bodies.borrow().get(i)?;
Some(v)
}
fn in_loop(&self) -> u32 {
let mut n = 0;
for i in 0..4usize {
if let Some(b) = self.bodies.borrow().get(i) {
if *b == 1 {
continue;
}
if *b == 9 {
break;
}
n += *b;
}
}
n
}
}
struct Noisy<'a>(u32, &'a Cell<u32>);
impl Drop for Noisy<'_> {
fn drop(&mut self) {
self.1.set(self.1.get() * 10 + self.0);
}
}
fn make<'a>(id: u32, log: &'a Cell<u32>) -> Noisy<'a> {
Noisy(id, log)
}
fn order(log: &Cell<u32>) -> u32 {
let _a = Noisy(1, log);
if let Noisy(2, _) = make(2, log) {
let _b = Noisy(3, log);
return 7;
}
0
}
#[test]
fn temporaries_dropped_on_jumps() {
let c = C { bodies: RefCell::new(vec![5, 1, 9, 4]) };
assert!(c.loc(0) == Some(5));
assert!(c.bodies.try_borrow_mut().is_ok());
assert!(c.loc(1).is_none());
assert!(c.via_match(0) == 5 && c.via_match(1) == 0);
assert!(c.bodies.try_borrow_mut().is_ok());
assert!(c.via_try(3) == Some(4) && c.via_try(7).is_none());
assert!(c.bodies.try_borrow_mut().is_ok());
assert!(c.in_loop() == 5);
assert!(c.bodies.try_borrow_mut().is_ok());
let log = Cell::new(0);
assert!(order(&log) == 7);
// the inner local, then the scrutinee temporary, then the outer local
assert!(log.get() == 321);
}