4 ms·
fn trust_me_i_dont_need_a_borrow_checker<'a, 'b> (x: &'a mut u32) -> &'b mut u32 { unsafe { core::mem::transmute(x) } } fn main() { let
by defen 3y ago
fn trust_me_i_dont_need_a_borrow_checker<'a, 'b> (x: &'a mut u32) -> &'b mut u32 {
unsafe { core::mem::transmute(x) }
}
fn main() {
let mut owned = vec![40, 2];
let mut_1 = trust_me_i_dont_need_a_borrow_checker(&mut owned[0]);
let mut_2 = trust_me_i_dont_need_a_borrow_checker(&mut owned[1]);
drop(owned);
let undefined = *mut_1 + *mut_2;
println!("The answer is {undefined}");
}
- tialaramex 3y agoIf unsafe disabled the borrow checker, you wouldn't have needed that transmute. But it doesn't, so you needed the unsafe transmute to make this work.
- defen 3y agoI don't consider myself a Rust expert, but this feels like a semantic argument? You can use `unsafe` to erase lifetimes, right? I'm not saying it's a good practice, and it's not globally disabling the borrow checker or anything like that, but in theory it's possible to produce unbounded lifetimes that are incorrect. In practice it probably doesn't happen very often. Certainly less often than UB in C or C++
- tialaramex 3y agoI don't consider this a semantic argument. The exact same code, without the transmute (just returning x directly from an unsafe block), fails a type check related to borrowing. Specifically, the compiler can't see why (without a transmute) it should believe that the reference x now has a different lifetime 'b instead of 'a. Which is fair because it doesn't. The transmute is you claiming it does, and since transmute is an unsafe function that's entirely on you to make sure you're right about that. So, lying has the expected effect. The borrow checks aren't magic, they can't look into your soul - but they are running inside unsafe code too. * Edited to make explicit that the alternative is still marked unsafe and yet doesn't work