The borrow checker is a bit smart and a bit stupid, and so is Polonius

⚓ Rust    📅 2025-04-27    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 116 days ago. The information described in this article may have changed.

I think at least //Err after will compile, but even with Polonius it doesn't.

use std::collections::HashMap;

struct X<'a> {
    v: &'a str,
}

struct XS<'a> {
    v: &'a str,
    s: String,
}

struct MF<'a, 'b> {
    fa: &'a str,
    fb: &'b str,
    fc: String,
    fd: String,
}

fn pl() {
    println!("-----------------");
}

fn main() {
    polonius();
    pl();

    s();
    pl();

    s_s();
    pl();

    x();
    pl();

    xx();
    pl();

    xs();
    pl();

    xs_ok_b();
    pl();

    m_f();
    pl();

    m_f_ok_b();
    pl();
}

fn s() {
    let s = String::from("s");
    let s_2 = String::from("s_2");

    let s2 = String::from("s2");
    let s2_2 = String::from("s2_2");

    let s3 = String::from("s3");
    let s3_str = "s3_str";

    let mut a = &s;
    let mut b = &s2;
    let mut c = &s3[..];
    println!("{:6} {:6} {:6}", a, b, c);

    a = &s_2;
    drop(s); //Ok after

    drop(s2); //Ok before
    b = &s2_2;

    drop(s3);
    c = &s3_str;

    println!("{:6} {:6} {:6}", a, b, c);
}

fn s_s() {
    let s = String::from("s");
    let s_2 = String::from("s_2");

    let s2 = String::from("s2");
    let s2_2 = String::from("s2_2");

    let s3 = String::from("s3");
    let s3_str = "s3_str";

    let mut a = &s;
    let mut b = &s2;
    let mut c = &s3[..];
    println!("{:6} {:6} {:6}", a, b, c);

    *(&mut a) = &s_2;
    //drop(s); //Err after

    //drop(s2); //Err before
    *(&mut b) = &s2_2;

    *(&mut c) = &s3_str;
    //drop(s3); //Err after

    println!("{:6} {:6} {:6}", a, b, c);
}

fn x() {
    let x = String::from("x");
    let x_2 = String::from("x_2");

    let x2 = String::from("x2");
    let x2_2 = String::from("x2_2");

    let x_str = "x_str";

    let mut a = X { v: &x };
    let mut b = X { v: &x2 };
    println!("{:6} {:6}", a.v, b.v);

    a.v = &x_2;
    //drop(x); //Err after

    //drop(x2); //Err before
    b.v = &x2_2;
    println!("{:6} {:6}", a.v, b.v);

    a.v = &x_str;
    //drop(x_2); //Err after
    println!("{:6} {:6}", a.v, b.v);
}

fn xx() {
    let xx = String::from("xx");
    let xx_2 = String::from("xx_2");

    let xx2 = String::from("xx2");
    let xx2_2 = String::from("xx2_2");

    let mut a = X { v: &xx };
    let mut b = X { v: &xx2 };
    println!("{:6} {:6}", a.v, b.v);

    a = X { v: &xx_2 };
    drop(xx); //Ok after

    drop(xx2); //Ok before
    b = X { v: &xx2_2 };
    println!("{:6} {:6}", a.v, b.v);
}

fn xs() {
    let xs = String::from("xs");
    let xs_2 = String::from("xs_2");

    let xs2 = String::from("xs2");
    let xs2_2 = String::from("xs2_2");

    let s = String::from("s");
    let s2 = String::from("s2");

    let mut a = XS { v: &xs, s };
    let mut b = XS { v: &xs2, s: s2 };
    println!("{:6} {:6} {:6} {:6}", a.v, a.s, b.v, b.s);

    //a = XS { v: &xs_2, s}; //cannot, s has moved into a
    //a = XS { v: &xs_2, s: a.s }; //can
    a = XS { v: &xs_2, ..a };
    drop(xs); //Ok after

    //drop(xs2); //Err before
    b = XS { v: &xs2_2, ..b };

    println!("{:6} {:6} {:6} {:6}", a.v, a.s, b.v, b.s);
}

fn xs_ok_b() {
    println!("xs_ok_b");
    let xs = String::from("xs");
    let xs_2 = String::from("xs_2");

    let xs2 = String::from("xs2");
    let xs2_2 = String::from("xs2_2");

    let s = String::from("s");
    let s2 = String::from("s2");

    let mut a = XS { v: &xs, s };
    let mut b = XS { v: &xs2, s: s2 };
    println!("{:6} {:6} {:6} {:6}", a.v, a.s, b.v, b.s);

    a = XS { v: &xs_2, ..a };
    drop(xs); //Ok after

    let s2 = b.s;
    drop(xs2); //Ok before
    b = XS { v: &xs2_2, s: s2 };

    println!("{:6} {:6} {:6} {:6}", a.v, a.s, b.v, b.s);
}

fn m_f() {
    let fa = String::from("fa");
    let fa_2 = String::from("fa_2");

    let fb = String::from("fb");
    let fb_2 = String::from("fb_2");

    let fc = String::from("fc");
    let fd = String::from("fd");

    let fa2 = String::from("fa2");
    let fa2_2 = String::from("fa2_2");

    let fb2 = String::from("fb2");
    let fb2_2 = String::from("fb2_2");

    let fc2 = String::from("fc2");
    let fd2 = String::from("fd2");

    let mut a = MF {
        fa: &fa,
        fb: &fb,
        fc,
        fd,
    };

    let mut b = MF {
        fa: &fa2,
        fb: &fb2,
        fc: fc2,
        fd: fd2,
    };

    println!(
        "{:6} {:6} {:6} {:6} {:6} {:6} {:6} {:6}",
        a.fa, a.fb, a.fc, a.fd, b.fa, b.fb, b.fc, b.fd
    );

    a = MF {
        fa: &fa_2,
        fb: &fb_2,
        ..a
    };
    drop(fa); //Ok after
    drop(fb); //Ok after

    //drop(fa2); // Err before
    //drop(fb2); // Err before
    b = MF {
        fa: &fa2_2,
        fb: &fb2_2,
        ..b
    };

    println!(
        "{:6} {:6} {:6} {:6} {:6} {:6} {:6} {:6}",
        a.fa, a.fb, a.fc, a.fd, b.fa, b.fb, b.fc, b.fd
    );
}

fn m_f_ok_b() {
    println!("m_f_ok_b");
    let fa = String::from("fa");
    let fa_2 = String::from("fa_2");

    let fb = String::from("fb");
    let fb_2 = String::from("fb_2");

    let fc = String::from("fc");
    let fd = String::from("fd");

    let fa2 = String::from("fa2");
    let fa2_2 = String::from("fa2_2");

    let fb2 = String::from("fb2");
    let fb2_2 = String::from("fb2_2");

    let fc2 = String::from("fc2");
    let fd2 = String::from("fd2");

    let mut a = MF {
        fa: &fa,
        fb: &fb,
        fc,
        fd,
    };

    let mut b = MF {
        fa: &fa2,
        fb: &fb2,
        fc: fc2,
        fd: fd2,
    };

    println!(
        "{:6} {:6} {:6} {:6} {:6} {:6} {:6} {:6}",
        a.fa, a.fb, a.fc, a.fd, b.fa, b.fb, b.fc, b.fd
    );

    a = MF {
        fa: &fa_2,
        fb: &fb_2,
        ..a
    };
    drop(fa); //Ok after
    drop(fb); //Ok after

    let t = (b.fc, b.fd);
    drop(fa2); // Ok before
    drop(fb2); // Ok before
    b = MF {
        fa: &fa2_2,
        fb: &fb2_2,
        fc: t.0,
        fd: t.1,
    };

    println!(
        "{:6} {:6} {:6} {:6} {:6} {:6} {:6} {:6}",
        a.fa, a.fb, a.fc, a.fd, b.fa, b.fb, b.fc, b.fd
    );
}

fn get_or_insert(map: &'_ mut HashMap<u32, String>) -> &'_ String {
    if let Some(v) = map.get(&22) {
        return v;
    }
    map.insert(22, String::from("hi, polonius works fine"));
    &map[&22]
}

fn polonius() {
    let mut map = HashMap::new();
    get_or_insert(&mut map);
    println!("{}", map.get(&22).unwrap());
}

2 posts - 2 participants

Read full topic

🏷️ rust_feed