binding-less matches on borrowed data are incorrectly allowed · Issue #45045 · rust-lang/rust (original) (raw)
This is actually an unsoundness in AST borrowck: AST borrowck doesn't check things that are matched on for conflicting borrows unless there are actually pattern bindings, e.g. this compiles:
enum Xyz { A, B, }
fn main() { let mut e = Xyz::A; let f = &mut e; match e { Xyz::A => println!("a"), Xyz::B => println!("b"), }; *f = Xyz::B; }
That is unsound because of e.g. data races. For example, this code compiles and runs, and semi-reliably segfaults:
#![feature(test)] use std::{thread, time};
extern crate crossbeam; extern crate test;
enum Xyz<'a> { A(&'a usize), B(usize), }
fn main() { let mut e = Xyz::A(&0); crossbeam::scope(|scope| { scope.spawn(|| { let now = time::Instant::now(); let ten_millis = time::Duration::from_millis(50); while now.elapsed() < ten_millis { for _ in 0..1000000 { e = Xyz::A(&0); test::black_box(()); // compiler barrier e = Xyz::B(0xaaaaaaaa); } } }); let ten_millis = time::Duration::from_millis(10); thread::sleep(ten_millis); match e { Xyz::A(&0) => println!("a"), _ => println!("b"), }; }); }