Closed
Description
For example,
#![feature(asm)]
fn main() {
let y: &mut isize;
let x = &mut 0isize;
unsafe {
asm!("mov $1, $0" : "=r"(y) : "r"(x));
}
println!("{} {}", x, y);
}
This errors out in this way (with MIR borrowck enabled):
error[E0382]: use of moved value: `x` (Ast)
--> fail.rs:9:23
|
7 | asm!("mov $1, $0" : "=r"(y) : "r"(x));
| - value moved here
8 | }
9 | println!("{} {}", x, y);
| ^ value used here after move
|
= note: move occurs because `x` has type `&mut isize`, which does not implement the `Copy` trait
error[E0381]: borrow of possibly uninitialized variable: `x` (Mir)
--> fail.rs:9:23
|
9 | println!("{} {}", x, y);
| ^ use of possibly uninitialized `x`
error[E0381]: borrow of possibly uninitialized variable: `y` (Mir)
--> fail.rs:9:26
|
9 | println!("{} {}", x, y);
| ^ use of possibly uninitialized `y`
error: aborting due to 3 previous errors
Where only x
is uninitialized with the AST borrowck, but both are uninitialized with MIR borrowck
Also, if there's a destructor for an input, it will run right after the asm statement is executed, which doesn't make any sense (the assertion there should fail, not succeed)
#![feature(asm)]
use std::cell::Cell;
#[repr(C)]
struct NoisyDrop<'a>(&'a Cell<&'static str>);
impl<'a> Drop for NoisyDrop<'a> {
fn drop(&mut self) {
self.0.set("destroyed!");
}
}
fn main() {
let status = Cell::new("alive");
let _y: Box<NoisyDrop>;
let x = Box::new(NoisyDrop(&status));
unsafe {
asm!("mov $1, $0" : "=r"(_y) : "r"(x));
}
assert_eq!(status.get(), "destroyed!"); // this makes 0 sense
}
This is because move checking just ignores inline asm, while it should treat them like AST borrowck does (inputs move data out, outputs move data in)