makepad/libs/relax/compiler/tests/borrowck/polonius_reject.rs

71 lines
1.7 KiB
Rust

// Polonius (relaxed Rust A2): still rejected in relaxed crates. Polonius accepts only what is
// sound: real aliasing, use after move, dangling borrows and a borrow used on every path stay errors.
//@ relaxed
use std::collections::HashMap;
fn alias() {
let mut v = vec![1];
let a = &mut v;
let b = &mut v; //~ ERROR E0499
a.push(1);
b.push(2);
}
fn use_after_move() {
let s = String::from("x");
let t = s;
drop((s, t)); //~ ERROR E0382
}
fn dangle() -> &'static String {
let s = String::new();
&s //~ ERROR E0515
}
fn scoped() {
let r;
{
let x = 5;
r = &x; //~ ERROR E0597
}
drop(r);
}
// the lookup's borrow is used after the insert on the same path
fn used_after(map: &mut HashMap<u32, String>) -> &mut String {
let v = map.get_mut(&0);
map.insert(1, String::new()); //~ ERROR E0499
v.unwrap()
}
// the borrow is returned on both paths, the mutation is between
fn both_paths(v: &mut Vec<u32>, c: bool) -> &u32 {
let first = &v[0];
if c {
v.push(1); //~ ERROR E0502
}
first
}
// assigning to a borrowed place while the borrow is live on that path
fn assign_borrowed(mut n: u32) -> u32 {
let r = &n;
n = 3; //~ ERROR E0506
*r + n
}
// a loop that keeps the borrow of the previous iteration alive
fn keep_across_iterations(v: &mut Vec<u32>) {
let mut last: Option<&mut u32> = None;
for _ in 0..2 {
v.push(0); //~ ERROR E0499
if let Some(l) = last { *l += 1; }
last = v.last_mut();
}
}
fn main() {
alias(); use_after_move(); let _ = dangle(); scoped();
let mut m = HashMap::new(); used_after(&mut m);
let mut v = vec![1]; both_paths(&mut v, true); assign_borrowed(1); keep_across_iterations(&mut v);
}