makepad/libs/relax/compiler/tests/borrowck/fv_reject.rs
Admin 19651a3740 makepad run / Relax: the MIR borrow checker is the only borrow checker
The rustc C-NLL port on MIR replaces the old BIR checker, which is deleted:
- MIR built for every body (THIR, matches, scopes), check_consts + promotion,
  the NLL type checker, region inference, and rustc's borrowck diagnostics
- coroutine and async bodies are borrow-checked
- relaxed mode's field views and missing-mut edits work on MIR places
- every body of counter, calculator, platform, draw, widgets, wm-all and
  Stage checks with 0 errors; borrowck stays lazy on the run path
- casts of a &mut place to &mut dyn Trait reborrow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:13:13 +02:00

92 lines
3 KiB
Rust

// Field views (relaxed Rust): rejected -- the summaries overlap, or field views cannot see.
//@ relaxed
use std::cell::RefCell;
struct Cb { id: u32 }
struct S { callbacks: Vec<Cb>, counter: u32, cell: RefCell<u32>, ptr: *mut u32, inner: Box<Vec<u32>> }
trait Tr { fn touch(&mut self); }
impl Tr for S { fn touch(&mut self) { self.counter += 1; } }
impl S {
fn clear_callbacks(&mut self) { self.callbacks.clear(); }
fn via_callee(&mut self) { self.clear_callbacks(); }
fn recurse(&mut self, n: u32) { if n > 0 { self.recurse(n - 1) } else { self.callbacks.clear() } }
fn read_cell(&self) -> u32 { *self.cell.borrow() }
fn raw(&mut self) { unsafe { *self.ptr += 1 } }
fn items_mut(&mut self) -> &mut Vec<Cb> { &mut self.callbacks }
fn whole(&mut self) -> &mut S { self }
fn overlap(&mut self) -> u32 {
let first = &self.callbacks[0];
self.clear_callbacks(); //~ ERROR E0502
first.id
}
fn overlap_transitive(&mut self) -> u32 {
let first = &self.callbacks[0];
self.via_callee(); //~ ERROR E0502
first.id
}
fn overlap_recursive(&mut self) -> u32 {
let first = &self.callbacks[0];
self.recurse(3); //~ ERROR E0502
first.id
}
fn interior_mutability(&mut self) -> u32 {
let c = &mut self.cell;
let v = self.read_cell(); //~ ERROR E0502
*c.get_mut() + v
}
fn raw_pointer(&mut self) -> u32 {
let first = &self.callbacks[0];
self.raw(); //~ ERROR E0502
first.id
}
fn dyn_call(&mut self, t: &mut dyn Tr) -> u32 {
let first = &self.callbacks[0];
let me: &mut dyn Tr = self; //~ ERROR E0502
me.touch();
let _ = t;
first.id
}
fn returned_ref(&mut self) -> u32 {
let items = self.items_mut();
let first = &self.callbacks[0]; //~ ERROR E0502
items.clear();
first.id
}
fn escaping_self(&mut self) -> u32 {
let first = &self.callbacks[0];
let w = self.whole(); //~ ERROR E0502
w.counter += 1;
first.id
}
fn closure_overlap(&mut self) {
let first = &self.callbacks[0];
let mut f = || self.clear_callbacks(); //~ ERROR E0500
f();
let _ = first.id;
}
}
// a receiver reached through fields of a `&mut` parameter
struct Vm { heap: Vec<u32>, log: Vec<String> }
impl Vm { fn note(&mut self, s: &str) { self.log.push(s.to_string()); } }
struct Cx { vm: Vm }
fn field_receiver_overlap(cx: &mut Cx) -> usize {
let l = &cx.vm.log;
cx.vm.note("x"); //~ ERROR E0502
l.len()
}
// a reference into a container's buffer: the buffer is owned through a raw pointer, so any
// use of the container (here `pop`) overlaps it
fn into_buffer(v: &mut Vec<Vec<u32>>) {
v[0].push(v.pop().unwrap().len() as u32); //~ ERROR E0499
}
// extended two-phase borrows: the meanwhile borrow is still live at the call
impl Vm { fn first(&mut self) -> &mut u32 { &mut self.heap[0] } }
fn reserved_then_live(vm: &mut Vm) {
std::mem::swap(vm.first(), vm.first()); //~ ERROR E0499
}
fn main() {}