error: Undefined Behavior: not granting access to tag <286> because that would remove [SharedReadOnly for <294>] which is strongly protected

MIRI においてスタックから削除したアイテムが保護中だった場合のエラー。

検出方法

このエラーは『UB - 削除済のアイテムの利用』と似ている。ただし、そのエラーではアイテムの削除時にはエラーにならず、実際にそれが利用されるまでは保留していた。一方、こちらのエラーは保護されたアイテムの削除時にすぐ発生する。

保護されるのは、呼出中の関数の引数に紐づくアイテムで、それらを他のアイテムを利用するために削除しようとすると UB になる。

サンプル

以下では、callback の呼出中に var_ref に紐づくアイテムを保護している。しかし、同じアドレスを指す var_mtp の使用のためにそれを除去しようとしてエラーになる。


fn main() {
    let mut var = 0;
    let var_mtp = &mut var as *mut _;
    let var_ref = unsafe { &*var_mtp };
    callback(var_ref, || unsafe { *var_mtp = 1; });
}

fn callback(x: &i32, f: impl FnOnce()) {
    f();
    assert_eq!(*x, 1);
}

error: Undefined Behavior: not granting access to tag <286> because that would remove [SharedReadOnly for <294>] which is strongly protected
 --> src\main.rs:5:35
  |
5 |     callback(var_ref, || unsafe { *var_mtp = 1; });
  |                                   ^^^^^^^^^^^^ Undefined Behavior occurred here
  |
  = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
  = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <286> was created by a SharedReadWrite retag at offsets [0x0..0x4]
 --> src\main.rs:3:19
  |
3 |     let var_mtp = &mut var as *mut _;
  |                   ^^^^^^^^
help: <294> is this argument
 --> src\main.rs:8:17
  |
8 | pub fn callback(x: &i32, f: impl FnOnce()) {
  |                 ^
  = note: BACKTRACE (of the first span):
  = note: inside closure at src\main.rs:5:35: 5:47
note: inside `callback::<{closure@src\main.rs:5:23: 5:25}>`
 --> src\main.rs:9:5
  |
9 |     f();
  |     ^^^
note: inside `main`
 --> src\main.rs:5:5
  |
5 |     callback(var_ref, || unsafe { *var_mtp = 1; });
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^