diff --git a/src/test/ui/unsafe/union-modification.rs b/src/test/ui/unsafe/union-modification.rs new file mode 100644 index 00000000000..5c70b78df7c --- /dev/null +++ b/src/test/ui/unsafe/union-modification.rs @@ -0,0 +1,39 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(untagged_unions)] + +union Foo { + bar: i8, + _blah: isize, + _zst: (), +} + +struct FooHolder { + inner_foo: Foo +} + +fn do_nothing(_x: &mut Foo) {} + +pub fn main() { + let mut foo = Foo { bar: 5 }; + do_nothing(&mut foo); + foo.bar = 6; + unsafe { foo.bar += 1; } + assert_eq!(unsafe { foo.bar }, 7); + unsafe { + let Foo { bar: inner } = foo; + assert_eq!(inner, 7); + } + + let foo = Foo { bar: 5 }; + let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo }; + + let (_foo2, _random) = (foo, 42); + + let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } }; + foo_holder.inner_foo.bar = 4; + assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4); + drop(foo_holder); +} diff --git a/src/test/ui/unsafe/union.mir.stderr b/src/test/ui/unsafe/union.mir.stderr index f7bd411a744..787714cdd2d 100644 --- a/src/test/ui/unsafe/union.mir.stderr +++ b/src/test/ui/unsafe/union.mir.stderr @@ -1,16 +1,19 @@ -warning: unnecessary `unsafe` block - --> $DIR/union.rs:61:5 +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:30:20 | -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block +LL | Foo { bar: _a } => {}, + | ^^ access to union field | - = note: `#[warn(unused_unsafe)]` on by default + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: unnecessary `unsafe` block - --> $DIR/union.rs:66:5 +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:32:11 | -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block +LL | match foo { + | ^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -warning: 2 warnings emitted +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs index 0130fa67f23..5fe09933cfc 100644 --- a/src/test/ui/unsafe/union.rs +++ b/src/test/ui/unsafe/union.rs @@ -1,4 +1,3 @@ -// run-pass // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck @@ -20,61 +19,35 @@ enum PizzaTopping { Pineapple, } -struct FooHolder { - inner_foo: Foo -} - fn do_nothing(_x: &mut Foo) {} pub fn main() { let mut foo = Foo { bar: 5 }; do_nothing(&mut foo); - foo.bar = 6; - unsafe { foo.bar += 1; } - assert_eq!(unsafe { foo.bar }, 7); - unsafe { - let Foo { bar: inner } = foo; - assert_eq!(inner, 7); - } - let foo = if let true = true { foo } else { foo }; - unsafe { - match foo { - Foo { bar: _a } => {}, - } + // This is UB, so this test isn't run + match foo { + Foo { bar: _a } => {}, //~ ERROR access to union field is unsafe } - unsafe { - match foo { - Foo { - pizza: Pizza { - topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None - } - } => {}, - } + match foo { //[mir]~ ERROR access to union field is unsafe + Foo { + pizza: Pizza { //[thir]~ ERROR access to union field is unsafe + topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None + } + } => {}, } + + // MIR unsafeck incorrectly thinks that no unsafe block is needed to do these + match foo { + Foo { zst: () } => {}, //[thir]~ ERROR access to union field is unsafe + } + match foo { + Foo { pizza: Pizza { .. } } => {}, //[thir]~ ERROR access to union field is unsafe + } + // binding to wildcard is okay match foo { Foo { bar: _ } => {}, } let Foo { bar: _ } = foo; - // MIR unsafeck incorrectly thinks that it is safe to do these - unsafe { //[mir]~ WARNING - match foo { - Foo { zst: () } => {}, - } - } - unsafe { //[mir]~ WARNING - match foo { - Foo { pizza: Pizza { .. } } => {}, - } - } - let foo = Foo { bar: 5 }; - let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo }; - - let (_foo2, _random) = (foo, 42); - - let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } }; - foo_holder.inner_foo.bar = 4; - assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4); - drop(foo_holder); } diff --git a/src/test/ui/unsafe/union.thir.stderr b/src/test/ui/unsafe/union.thir.stderr new file mode 100644 index 00000000000..e1a1bd634de --- /dev/null +++ b/src/test/ui/unsafe/union.thir.stderr @@ -0,0 +1,38 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:30:20 + | +LL | Foo { bar: _a } => {}, + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:34:20 + | +LL | pizza: Pizza { + | ____________________^ +LL | | topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None +LL | | } + | |_____________^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:42:20 + | +LL | Foo { zst: () } => {}, + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:45:22 + | +LL | Foo { pizza: Pizza { .. } } => {}, + | ^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`.