From 74d0d74dae5ddde15de0201d689d56b794aa0e86 Mon Sep 17 00:00:00 2001 From: Smitty Date: Thu, 13 May 2021 10:42:25 -0400 Subject: [PATCH 1/3] Check for union field accesses in THIR unsafeck --- .../rustc_mir_build/src/check_unsafety.rs | 130 +++++++++++++++++- compiler/rustc_mir_build/src/thir/visit.rs | 6 +- src/test/ui/union/union-align.rs | 3 + src/test/ui/union/union-backcomp.rs | 3 + src/test/ui/union/union-basic.rs | 3 + ...ow-move-parent-sibling.mirunsafeck.stderr} | 10 +- .../union/union-borrow-move-parent-sibling.rs | 3 + ...ow-move-parent-sibling.thirunsafeck.stderr | 60 ++++++++ src/test/ui/union/union-const-codegen.rs | 2 + src/test/ui/union/union-const-eval-field.rs | 2 + src/test/ui/union/union-const-eval.rs | 3 + ....stderr => union-deref.mirunsafeck.stderr} | 12 +- src/test/ui/union/union-deref.rs | 3 + .../ui/union/union-deref.thirunsafeck.stderr | 56 ++++++++ ... => union-derive-clone.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-derive-clone.rs | 3 + .../union-derive-clone.thirunsafeck.stderr | 36 +++++ ...err => union-derive-eq.mirunsafeck.stderr} | 2 +- src/test/ui/union/union-derive-eq.rs | 3 + .../union/union-derive-eq.thirunsafeck.stderr | 16 +++ src/test/ui/union/union-derive-rpass.rs | 3 + .../ui/union/union-drop.thirunsafeck.stderr | 22 +++ ...derr => union-fields-1.mirunsafeck.stderr} | 10 +- src/test/ui/union/union-fields-1.rs | 3 + .../union/union-fields-1.thirunsafeck.stderr | 32 +++++ ...derr => union-fields-2.mirunsafeck.stderr} | 26 ++-- src/test/ui/union/union-fields-2.rs | 3 + .../union/union-fields-2.thirunsafeck.stderr | 84 +++++++++++ src/test/ui/union/union-generic-rpass.rs | 3 + ...tderr => union-generic.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-generic.rs | 3 + .../union/union-generic.thirunsafeck.stderr | 21 +++ src/test/ui/union/union-inherent-method.rs | 2 + ...> union-lint-dead-code.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-lint-dead-code.rs | 3 + .../union-lint-dead-code.thirunsafeck.stderr | 14 ++ src/test/ui/union/union-macro.rs | 3 + src/test/ui/union/union-manuallydrop-rpass.rs | 5 +- ...e.stderr => union-move.mirunsafeck.stderr} | 6 +- src/test/ui/union/union-move.rs | 3 + .../ui/union/union-move.thirunsafeck.stderr | 35 +++++ src/test/ui/union/union-nodrop.rs | 2 + src/test/ui/union/union-nonzero.rs | 3 + src/test/ui/union/union-overwrite.rs | 2 + src/test/ui/union/union-packed.rs | 3 + src/test/ui/union/union-pat-refutability.rs | 3 + ...=> union-suggest-field.mirunsafeck.stderr} | 6 +- src/test/ui/union/union-suggest-field.rs | 3 + .../union-suggest-field.thirunsafeck.stderr | 27 ++++ src/test/ui/union/union-trait-impl.rs | 2 + src/test/ui/union/union-transmute.rs | 2 + ...-unsafe.stderr => union-unsafe.mir.stderr} | 22 +-- src/test/ui/union/union-unsafe.rs | 8 +- src/test/ui/union/union-unsafe.thir.stderr | 75 ++++++++++ ...tderr => union-unsized.mirunsafeck.stderr} | 4 +- src/test/ui/union/union-unsized.rs | 3 + .../union/union-unsized.thirunsafeck.stderr | 39 ++++++ ...union-with-drop-fields.mirunsafeck.stderr} | 12 +- src/test/ui/union/union-with-drop-fields.rs | 4 +- ...union-with-drop-fields.thirunsafeck.stderr | 39 ++++++ .../ui/unsafe/access_union_field.mir.stderr | 19 +++ src/test/ui/unsafe/access_union_field.rs | 15 ++ .../ui/unsafe/access_union_field.thir.stderr | 19 +++ src/test/ui/unsafe/union.mir.stderr | 16 +++ src/test/ui/unsafe/union.rs | 80 +++++++++++ .../ui/unsafe/union_access_through_block.rs | 18 +++ .../ui/unsafe/union_destructure.mir.stderr | 16 +++ src/test/ui/unsafe/union_destructure.rs | 51 +++++++ src/test/ui/unsafe/union_wild_or_wild.rs | 12 ++ 69 files changed, 1083 insertions(+), 71 deletions(-) rename src/test/ui/union/{union-borrow-move-parent-sibling.stderr => union-borrow-move-parent-sibling.mirunsafeck.stderr} (89%) create mode 100644 src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr rename src/test/ui/union/{union-deref.stderr => union-deref.mirunsafeck.stderr} (91%) create mode 100644 src/test/ui/union/union-deref.thirunsafeck.stderr rename src/test/ui/union/{union-derive-clone.stderr => union-derive-clone.mirunsafeck.stderr} (94%) create mode 100644 src/test/ui/union/union-derive-clone.thirunsafeck.stderr rename src/test/ui/union/{union-derive-eq.stderr => union-derive-eq.mirunsafeck.stderr} (94%) create mode 100644 src/test/ui/union/union-derive-eq.thirunsafeck.stderr create mode 100644 src/test/ui/union/union-drop.thirunsafeck.stderr rename src/test/ui/union/{union-fields-1.stderr => union-fields-1.mirunsafeck.stderr} (77%) create mode 100644 src/test/ui/union/union-fields-1.thirunsafeck.stderr rename src/test/ui/union/{union-fields-2.stderr => union-fields-2.mirunsafeck.stderr} (85%) create mode 100644 src/test/ui/union/union-fields-2.thirunsafeck.stderr rename src/test/ui/union/{union-generic.stderr => union-generic.mirunsafeck.stderr} (90%) create mode 100644 src/test/ui/union/union-generic.thirunsafeck.stderr rename src/test/ui/union/{union-lint-dead-code.stderr => union-lint-dead-code.mirunsafeck.stderr} (72%) create mode 100644 src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr rename src/test/ui/union/{union-move.stderr => union-move.mirunsafeck.stderr} (92%) create mode 100644 src/test/ui/union/union-move.thirunsafeck.stderr rename src/test/ui/union/{union-suggest-field.stderr => union-suggest-field.mirunsafeck.stderr} (86%) create mode 100644 src/test/ui/union/union-suggest-field.thirunsafeck.stderr rename src/test/ui/union/{union-unsafe.stderr => union-unsafe.mir.stderr} (92%) create mode 100644 src/test/ui/union/union-unsafe.thir.stderr rename src/test/ui/union/{union-unsized.stderr => union-unsized.mirunsafeck.stderr} (95%) create mode 100644 src/test/ui/union/union-unsized.thirunsafeck.stderr rename src/test/ui/union/{union-with-drop-fields.stderr => union-with-drop-fields.mirunsafeck.stderr} (74%) create mode 100644 src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/access_union_field.mir.stderr create mode 100644 src/test/ui/unsafe/access_union_field.rs create mode 100644 src/test/ui/unsafe/access_union_field.thir.stderr create mode 100644 src/test/ui/unsafe/union.mir.stderr create mode 100644 src/test/ui/unsafe/union.rs create mode 100644 src/test/ui/unsafe/union_access_through_block.rs create mode 100644 src/test/ui/unsafe/union_destructure.mir.stderr create mode 100644 src/test/ui/unsafe/union_destructure.rs create mode 100644 src/test/ui/unsafe/union_wild_or_wild.rs diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 9bef8ac2413d6..0aec63182952e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -26,6 +26,8 @@ struct UnsafetyVisitor<'a, 'tcx> { /// calls to functions with `#[target_feature]` (RFC 2396). body_target_features: &'tcx Vec, is_const: bool, + in_possible_lhs_union_assign: bool, + in_union_destructure: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -158,14 +160,115 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } + fn visit_pat(&mut self, pat: &Pat<'tcx>) { + use PatKind::*; + + if self.in_union_destructure { + match *pat.kind { + // binding to a variable allows getting stuff out of variable + Binding { .. } + // match is conditional on having this value + | Constant { .. } + | Variant { .. } + | Leaf { .. } + | Deref { .. } + | Range { .. } + | Slice { .. } + | Array { .. } => { + self.requires_unsafe(pat.span, AccessToUnionField); + return; // don't walk pattern + } + // wildcard doesn't take anything + Wild | + // these just wrap other patterns + Or { .. } | + AscribeUserType { .. } => {} + } + }; + + if let ty::Adt(adt_def, _) = pat.ty.kind() { + // check for extracting values from union via destructuring + if adt_def.is_union() { + match *pat.kind { + // assigning the whole union is okay + // let x = Union { ... }; + // let y = x; // safe + Binding { .. } | + // binding to wildcard is okay since that never reads anything and stops double errors + // with implict wildcard branches from `if let`s + Wild | + // doesn't have any effect on semantics + AscribeUserType { .. } | + // creating a union literal + Constant { .. } => {}, + Variant { .. } | Leaf { .. } | Or { .. } => { + // pattern matching with a union and not doing something like v = Union { bar: 5 } + self.in_union_destructure = true; + visit::walk_pat(self, pat); + self.in_union_destructure = false; + return; // don't walk pattern + } + Deref { .. } | Range { .. } | Slice { .. } | Array { .. } => + unreachable!("impossible union destructuring type"), + } + } + } + + visit::walk_pat(self, pat); + } + fn visit_expr(&mut self, expr: &Expr<'tcx>) { + // could we be in a the LHS of an assignment of a union? + match expr.kind { + ExprKind::Field { .. } + | ExprKind::VarRef { .. } + | ExprKind::UpvarRef { .. } + | ExprKind::Scope { .. } + | ExprKind::Cast { .. } => {} + + ExprKind::AddressOf { .. } + | ExprKind::Adt { .. } + | ExprKind::Array { .. } + | ExprKind::Binary { .. } + | ExprKind::Block { .. } + | ExprKind::Borrow { .. } + | ExprKind::Literal { .. } + | ExprKind::ConstBlock { .. } + | ExprKind::Deref { .. } + | ExprKind::Index { .. } + | ExprKind::NeverToAny { .. } + | ExprKind::PlaceTypeAscription { .. } + | ExprKind::ValueTypeAscription { .. } + | ExprKind::Pointer { .. } + | ExprKind::Repeat { .. } + | ExprKind::StaticRef { .. } + | ExprKind::ThreadLocalRef { .. } + | ExprKind::Tuple { .. } + | ExprKind::Unary { .. } + | ExprKind::Call { .. } + | ExprKind::Assign { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Break { .. } + | ExprKind::Closure { .. } + | ExprKind::Continue { .. } + | ExprKind::Return { .. } + | ExprKind::Yield { .. } + | ExprKind::Loop { .. } + | ExprKind::Match { .. } + | ExprKind::Box { .. } + | ExprKind::If { .. } + | ExprKind::InlineAsm { .. } + | ExprKind::LlvmInlineAsm { .. } + | ExprKind::LogicalOp { .. } + | ExprKind::Use { .. } => self.in_possible_lhs_union_assign = false, + }; match expr.kind { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => { let prev_id = self.hir_context; self.hir_context = hir_id; self.visit_expr(&self.thir[value]); self.hir_context = prev_id; - return; + return; // don't visit the whole expression } ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { @@ -246,9 +349,29 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { // Unsafe blocks can be used in closures, make sure to take it into account self.safety_context = closure_visitor.safety_context; } + ExprKind::Field { lhs, .. } => { + // assigning to union field is okay for AccessToUnionField + if let ty::Adt(adt_def, _) = &self.thir[lhs].ty.kind() { + if adt_def.is_union() { + if self.in_possible_lhs_union_assign { + // FIXME: trigger AssignToDroppingUnionField unsafety if needed + } else { + self.requires_unsafe(expr.span, AccessToUnionField); + } + } + } + } + // don't have any special handling for AssignOp since it causes a read *and* write to lhs + ExprKind::Assign { lhs, rhs } => { + // assigning to a union is safe, check here so it doesn't get treated as a read later + self.in_possible_lhs_union_assign = true; + visit::walk_expr(self, &self.thir()[lhs]); + self.in_possible_lhs_union_assign = false; + visit::walk_expr(self, &self.thir()[rhs]); + return; // don't visit the whole expression + } _ => {} } - visit::walk_expr(self, expr); } } @@ -296,7 +419,6 @@ enum UnsafeOpKind { DerefOfRawPointer, #[allow(dead_code)] // FIXME AssignToDroppingUnionField, - #[allow(dead_code)] // FIXME AccessToUnionField, #[allow(dead_code)] // FIXME MutationOfLayoutConstrainedField, @@ -417,6 +539,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam>(visitor: &mut V, expr: &Exp } pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) { - match stmt.kind { - StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]), + match &stmt.kind { + StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]), StmtKind::Let { initializer, remainder_scope: _, @@ -163,7 +163,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm lint_level: _, } => { if let Some(init) = initializer { - visitor.visit_expr(&visitor.thir()[init]); + visitor.visit_expr(&visitor.thir()[*init]); } visitor.visit_pat(pattern); } diff --git a/src/test/ui/union/union-align.rs b/src/test/ui/union/union-align.rs index 1340ae43cd6af..6a44f27dbb2a4 100644 --- a/src/test/ui/union/union-align.rs +++ b/src/test/ui/union/union-align.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] use std::mem::{size_of, size_of_val, align_of, align_of_val}; diff --git a/src/test/ui/union/union-backcomp.rs b/src/test/ui/union/union-backcomp.rs index 4efd4c4d3d3aa..b19eab9f52b52 100644 --- a/src/test/ui/union/union-backcomp.rs +++ b/src/test/ui/union/union-backcomp.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(path_statements)] #![allow(dead_code)] diff --git a/src/test/ui/union/union-basic.rs b/src/test/ui/union/union-basic.rs index 73cc9793f2c4c..dcc552ac75c89 100644 --- a/src/test/ui/union/union-basic.rs +++ b/src/test/ui/union/union-basic.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(unused_imports)] // aux-build:union.rs diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr similarity index 89% rename from src/test/ui/union/union-borrow-move-parent-sibling.stderr rename to src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr index 8ba155bafb0b9..e785a2ee7335d 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:53:13 + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 | LL | let a = &mut u.x.0; | ---------- mutable borrow occurs here (via `u.x.0`) @@ -11,7 +11,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:60:13 + --> $DIR/union-borrow-move-parent-sibling.rs:63:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -21,7 +21,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:66:13 + --> $DIR/union-borrow-move-parent-sibling.rs:69:13 | LL | let a = &mut (u.x.0).0; | -------------- mutable borrow occurs here (via `u.x.0.0`) @@ -33,7 +33,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:73:13 + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -43,7 +43,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:79:13 + --> $DIR/union-borrow-move-parent-sibling.rs:82:13 | LL | let a = &mut *u.y; | --- mutable borrow occurs here (via `u.y`) diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index edf08e6ca678f..e56d87255dbaf 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.rs +++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] #![allow(unused)] diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr new file mode 100644 index 0000000000000..e785a2ee7335d --- /dev/null +++ b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr @@ -0,0 +1,60 @@ +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 + | +LL | let a = &mut u.x.0; + | ---------- mutable borrow occurs here (via `u.x.0`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:63:13 + | +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = u.x.0; + | ----- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) + --> $DIR/union-borrow-move-parent-sibling.rs:69:13 + | +LL | let a = &mut (u.x.0).0; + | -------------- mutable borrow occurs here (via `u.x.0.0`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 + | +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = (u.x.0).0; + | --------- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:82:13 + | +LL | let a = &mut *u.y; + | --- mutable borrow occurs here (via `u.y`) +LL | let b = &u.x; + | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-const-codegen.rs b/src/test/ui/union/union-const-codegen.rs index d5b3055959563..32a546cf35f2c 100644 --- a/src/test/ui/union/union-const-codegen.rs +++ b/src/test/ui/union/union-const-codegen.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: u64, diff --git a/src/test/ui/union/union-const-eval-field.rs b/src/test/ui/union/union-const-eval-field.rs index 15a20899a78d1..ca48785cd9f5a 100644 --- a/src/test/ui/union/union-const-eval-field.rs +++ b/src/test/ui/union/union-const-eval-field.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck type Field1 = (i32, u32); type Field2 = f32; diff --git a/src/test/ui/union/union-const-eval.rs b/src/test/ui/union/union-const-eval.rs index 90af8de447dfd..0b6788b4226ab 100644 --- a/src/test/ui/union/union-const-eval.rs +++ b/src/test/ui/union/union-const-eval.rs @@ -1,4 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(const_fn_union)] union U { diff --git a/src/test/ui/union/union-deref.stderr b/src/test/ui/union/union-deref.mirunsafeck.stderr similarity index 91% rename from src/test/ui/union/union-deref.stderr rename to src/test/ui/union/union-deref.mirunsafeck.stderr index 6af050bc4b79d..ff37e6fd9177a 100644 --- a/src/test/ui/union/union-deref.stderr +++ b/src/test/ui/union/union-deref.mirunsafeck.stderr @@ -1,5 +1,5 @@ error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:14:14 + --> $DIR/union-deref.rs:17:14 | LL | unsafe { u.f.0 = Vec::new() }; | ^^^ @@ -8,7 +8,7 @@ LL | unsafe { u.f.0 = Vec::new() }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:16:19 + --> $DIR/union-deref.rs:19:19 | LL | unsafe { &mut u.f.0 }; | ^^^ @@ -17,7 +17,7 @@ LL | unsafe { &mut u.f.0 }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:18:14 + --> $DIR/union-deref.rs:21:14 | LL | unsafe { u.f.0.push(0) }; | ^^^ @@ -26,7 +26,7 @@ LL | unsafe { u.f.0.push(0) }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:22:14 + --> $DIR/union-deref.rs:25:14 | LL | unsafe { u.f.0.0 = Vec::new() }; | ^^^^^ @@ -35,7 +35,7 @@ LL | unsafe { u.f.0.0 = Vec::new() }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:24:19 + --> $DIR/union-deref.rs:27:19 | LL | unsafe { &mut u.f.0.0 }; | ^^^^^ @@ -44,7 +44,7 @@ LL | unsafe { &mut u.f.0.0 }; = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor error: not automatically applying `DerefMut` on `ManuallyDrop` union field - --> $DIR/union-deref.rs:26:14 + --> $DIR/union-deref.rs:29:14 | LL | unsafe { u.f.0.0.push(0) }; | ^^^^^ diff --git a/src/test/ui/union/union-deref.rs b/src/test/ui/union/union-deref.rs index 48f5b36bd17f3..4bf2ba2f1bfce 100644 --- a/src/test/ui/union/union-deref.rs +++ b/src/test/ui/union/union-deref.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + //! Test the part of RFC 2514 that is about not applying `DerefMut` coercions //! of union fields. #![feature(untagged_unions)] diff --git a/src/test/ui/union/union-deref.thirunsafeck.stderr b/src/test/ui/union/union-deref.thirunsafeck.stderr new file mode 100644 index 0000000000000..ff37e6fd9177a --- /dev/null +++ b/src/test/ui/union/union-deref.thirunsafeck.stderr @@ -0,0 +1,56 @@ +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:17:14 + | +LL | unsafe { u.f.0 = Vec::new() }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:19:19 + | +LL | unsafe { &mut u.f.0 }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:21:14 + | +LL | unsafe { u.f.0.push(0) }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:25:14 + | +LL | unsafe { u.f.0.0 = Vec::new() }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:27:19 + | +LL | unsafe { &mut u.f.0.0 }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:29:14 + | +LL | unsafe { u.f.0.0.push(0) }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr similarity index 94% rename from src/test/ui/union/union-derive-clone.stderr rename to src/test/ui/union/union-derive-clone.mirunsafeck.stderr index 789bcc92fc6ae..41e828c6d9515 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `U1: Copy` is not satisfied - --> $DIR/union-derive-clone.rs:3:10 + --> $DIR/union-derive-clone.rs:6:10 | LL | #[derive(Clone)] | ^^^^^ the trait `Copy` is not implemented for `U1` @@ -12,7 +12,7 @@ LL | pub struct AssertParamIsCopy { = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied - --> $DIR/union-derive-clone.rs:35:15 + --> $DIR/union-derive-clone.rs:38:15 | LL | union U5 { | ----------- diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 7ab19edb47179..7aa62146e5490 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + use std::mem::ManuallyDrop; #[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr new file mode 100644 index 0000000000000..41e828c6d9515 --- /dev/null +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | + ::: $SRC_DIR/core/src/clone.rs:LL:COL + | +LL | pub struct AssertParamIsCopy { + | ---- required by this bound in `AssertParamIsCopy` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied + --> $DIR/union-derive-clone.rs:38:15 + | +LL | union U5 { + | ----------- + | | + | method `clone` not found for this + | doesn't satisfy `U5: Clone` +... +LL | struct CloneNoCopy; + | ------------------- doesn't satisfy `CloneNoCopy: Copy` +... +LL | let w = u.clone(); + | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `CloneNoCopy: Copy` + which is required by `U5: Clone` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-derive-eq.stderr b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr similarity index 94% rename from src/test/ui/union/union-derive-eq.stderr rename to src/test/ui/union/union-derive-eq.mirunsafeck.stderr index 3198e97552d32..9477d8470fc6f 100644 --- a/src/test/ui/union/union-derive-eq.stderr +++ b/src/test/ui/union/union-derive-eq.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied - --> $DIR/union-derive-eq.rs:13:5 + --> $DIR/union-derive-eq.rs:16:5 | LL | a: PartialEqNotEq, | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` diff --git a/src/test/ui/union/union-derive-eq.rs b/src/test/ui/union/union-derive-eq.rs index e689f8c27d772..b7e7f343f8a28 100644 --- a/src/test/ui/union/union-derive-eq.rs +++ b/src/test/ui/union/union-derive-eq.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #[derive(Eq)] // OK union U1 { a: u8, diff --git a/src/test/ui/union/union-derive-eq.thirunsafeck.stderr b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr new file mode 100644 index 0000000000000..9477d8470fc6f --- /dev/null +++ b/src/test/ui/union/union-derive-eq.thirunsafeck.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied + --> $DIR/union-derive-eq.rs:16:5 + | +LL | a: PartialEqNotEq, + | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` + | + ::: $SRC_DIR/core/src/cmp.rs:LL:COL + | +LL | pub struct AssertParamIsEq { + | -- required by this bound in `AssertParamIsEq` + | + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-derive-rpass.rs b/src/test/ui/union/union-derive-rpass.rs index db18a81c1f665..8276bc635fc74 100644 --- a/src/test/ui/union/union-derive-rpass.rs +++ b/src/test/ui/union/union-derive-rpass.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(unused_variables)] diff --git a/src/test/ui/union/union-drop.thirunsafeck.stderr b/src/test/ui/union/union-drop.thirunsafeck.stderr new file mode 100644 index 0000000000000..9766ae4e435f2 --- /dev/null +++ b/src/test/ui/union/union-drop.thirunsafeck.stderr @@ -0,0 +1,22 @@ +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:27:9 + | +LL | unsafe { CHECK += 1; } + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:33:9 + | +LL | unsafe { CHECK += 1; } + | ^^^^^^ unnecessary `unsafe` block + +warning: unnecessary `unsafe` block + --> $DIR/union-drop.rs:40:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 3 warnings emitted + diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr similarity index 77% rename from src/test/ui/union/union-fields-1.stderr rename to src/test/ui/union/union-fields-1.mirunsafeck.stderr index 87621cc01b1b9..9f1e2947c8699 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.mirunsafeck.stderr @@ -1,29 +1,29 @@ error: field is never read: `c` - --> $DIR/union-fields-1.rs:6:5 + --> $DIR/union-fields-1.rs:9:5 | LL | c: u8, | ^^^^^ | note: the lint level is defined here - --> $DIR/union-fields-1.rs:1:9 + --> $DIR/union-fields-1.rs:4:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ error: field is never read: `a` - --> $DIR/union-fields-1.rs:9:5 + --> $DIR/union-fields-1.rs:12:5 | LL | a: u8, | ^^^^^ error: field is never read: `a` - --> $DIR/union-fields-1.rs:13:20 + --> $DIR/union-fields-1.rs:16:20 | LL | union NoDropLike { a: u8 } | ^^^^^ error: field is never read: `c` - --> $DIR/union-fields-1.rs:18:5 + --> $DIR/union-fields-1.rs:21:5 | LL | c: u8, | ^^^^^ diff --git a/src/test/ui/union/union-fields-1.rs b/src/test/ui/union/union-fields-1.rs index edef41de159ba..3d3e2355a26f2 100644 --- a/src/test/ui/union/union-fields-1.rs +++ b/src/test/ui/union/union-fields-1.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![deny(dead_code)] union U1 { diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr new file mode 100644 index 0000000000000..9f1e2947c8699 --- /dev/null +++ b/src/test/ui/union/union-fields-1.thirunsafeck.stderr @@ -0,0 +1,32 @@ +error: field is never read: `c` + --> $DIR/union-fields-1.rs:9:5 + | +LL | c: u8, + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/union-fields-1.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: field is never read: `a` + --> $DIR/union-fields-1.rs:12:5 + | +LL | a: u8, + | ^^^^^ + +error: field is never read: `a` + --> $DIR/union-fields-1.rs:16:20 + | +LL | union NoDropLike { a: u8 } + | ^^^^^ + +error: field is never read: `c` + --> $DIR/union-fields-1.rs:21:5 + | +LL | c: u8, + | ^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.mirunsafeck.stderr similarity index 85% rename from src/test/ui/union/union-fields-2.stderr rename to src/test/ui/union/union-fields-2.mirunsafeck.stderr index 48654347285d3..867bf75dfdc0b 100644 --- a/src/test/ui/union/union-fields-2.stderr +++ b/src/test/ui/union/union-fields-2.mirunsafeck.stderr @@ -1,17 +1,17 @@ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:7:13 + --> $DIR/union-fields-2.rs:10:13 | LL | let u = U {}; | ^ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:9:13 + --> $DIR/union-fields-2.rs:12:13 | LL | let u = U { a: 0, b: 1 }; | ^ error[E0560]: union `U` has no field named `c` - --> $DIR/union-fields-2.rs:10:29 + --> $DIR/union-fields-2.rs:13:29 | LL | let u = U { a: 0, b: 1, c: 2 }; | ^ `U` does not have this field @@ -19,61 +19,61 @@ LL | let u = U { a: 0, b: 1, c: 2 }; = note: available fields are: `a`, `b` error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:10:13 + --> $DIR/union-fields-2.rs:13:13 | LL | let u = U { a: 0, b: 1, c: 2 }; | ^ error: union expressions should have exactly one field - --> $DIR/union-fields-2.rs:12:13 + --> $DIR/union-fields-2.rs:15:13 | LL | let u = U { ..u }; | ^ error[E0436]: functional record update syntax requires a struct - --> $DIR/union-fields-2.rs:12:19 + --> $DIR/union-fields-2.rs:15:19 | LL | let u = U { ..u }; | ^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:15:9 + --> $DIR/union-fields-2.rs:18:9 | LL | let U {} = u; | ^^^^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:17:9 + --> $DIR/union-fields-2.rs:20:9 | LL | let U { a, b } = u; | ^^^^^^^^^^ error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:18:9 + --> $DIR/union-fields-2.rs:21:9 | LL | let U { a, b, c } = u; | ^^^^^^^^^^^^^ error[E0026]: union `U` does not have a field named `c` - --> $DIR/union-fields-2.rs:18:19 + --> $DIR/union-fields-2.rs:21:19 | LL | let U { a, b, c } = u; | ^ union `U` does not have this field error: union patterns should have exactly one field - --> $DIR/union-fields-2.rs:20:9 + --> $DIR/union-fields-2.rs:23:9 | LL | let U { .. } = u; | ^^^^^^^^ error: `..` cannot be used in union patterns - --> $DIR/union-fields-2.rs:20:9 + --> $DIR/union-fields-2.rs:23:9 | LL | let U { .. } = u; | ^^^^^^^^ error: `..` cannot be used in union patterns - --> $DIR/union-fields-2.rs:22:9 + --> $DIR/union-fields-2.rs:25:9 | LL | let U { a, .. } = u; | ^^^^^^^^^^^ diff --git a/src/test/ui/union/union-fields-2.rs b/src/test/ui/union/union-fields-2.rs index 71b204fcdc5b8..e738b18470337 100644 --- a/src/test/ui/union/union-fields-2.rs +++ b/src/test/ui/union/union-fields-2.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + union U { a: u8, b: u16, diff --git a/src/test/ui/union/union-fields-2.thirunsafeck.stderr b/src/test/ui/union/union-fields-2.thirunsafeck.stderr new file mode 100644 index 0000000000000..867bf75dfdc0b --- /dev/null +++ b/src/test/ui/union/union-fields-2.thirunsafeck.stderr @@ -0,0 +1,84 @@ +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:10:13 + | +LL | let u = U {}; + | ^ + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:12:13 + | +LL | let u = U { a: 0, b: 1 }; + | ^ + +error[E0560]: union `U` has no field named `c` + --> $DIR/union-fields-2.rs:13:29 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ `U` does not have this field + | + = note: available fields are: `a`, `b` + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:13:13 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ + +error: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:15:13 + | +LL | let u = U { ..u }; + | ^ + +error[E0436]: functional record update syntax requires a struct + --> $DIR/union-fields-2.rs:15:19 + | +LL | let u = U { ..u }; + | ^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:18:9 + | +LL | let U {} = u; + | ^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:20:9 + | +LL | let U { a, b } = u; + | ^^^^^^^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:21:9 + | +LL | let U { a, b, c } = u; + | ^^^^^^^^^^^^^ + +error[E0026]: union `U` does not have a field named `c` + --> $DIR/union-fields-2.rs:21:19 + | +LL | let U { a, b, c } = u; + | ^ union `U` does not have this field + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:25:9 + | +LL | let U { a, .. } = u; + | ^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0026, E0436, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/src/test/ui/union/union-generic-rpass.rs b/src/test/ui/union/union-generic-rpass.rs index 69837f31cab27..25f1f5050f99b 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] use std::mem::ManuallyDrop; diff --git a/src/test/ui/union/union-generic.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr similarity index 90% rename from src/test/ui/union/union-generic.stderr rename to src/test/ui/union/union-generic.mirunsafeck.stderr index c418b27ce65e1..fcd0bdec25833 100644 --- a/src/test/ui/union/union-generic.stderr +++ b/src/test/ui/union/union-generic.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Rc: Copy` is not satisfied - --> $DIR/union-generic.rs:8:13 + --> $DIR/union-generic.rs:11:13 | LL | union U { | ---------------- required by `U` @@ -8,7 +8,7 @@ LL | let u = U { a: Rc::new(0u32) }; | ^ the trait `Copy` is not implemented for `Rc` error[E0277]: the trait bound `Rc: Copy` is not satisfied - --> $DIR/union-generic.rs:10:13 + --> $DIR/union-generic.rs:13:13 | LL | union U { | ---------------- required by `U` diff --git a/src/test/ui/union/union-generic.rs b/src/test/ui/union/union-generic.rs index ff877892579b9..3d68ecb87d8d6 100644 --- a/src/test/ui/union/union-generic.rs +++ b/src/test/ui/union/union-generic.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + use std::rc::Rc; union U { diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr new file mode 100644 index 0000000000000..fcd0bdec25833 --- /dev/null +++ b/src/test/ui/union/union-generic.thirunsafeck.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:11:13 + | +LL | union U { + | ---------------- required by `U` +... +LL | let u = U { a: Rc::new(0u32) }; + | ^ the trait `Copy` is not implemented for `Rc` + +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:13:13 + | +LL | union U { + | ---------------- required by `U` +... +LL | let u = U::> { a: Default::default() }; + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-inherent-method.rs b/src/test/ui/union/union-inherent-method.rs index 2e75cce7b108b..b0fd22da73adc 100644 --- a/src/test/ui/union/union-inherent-method.rs +++ b/src/test/ui/union/union-inherent-method.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: u8, diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr similarity index 72% rename from src/test/ui/union/union-lint-dead-code.stderr rename to src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr index 7de70ec33801f..22d4428c902c8 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr @@ -1,11 +1,11 @@ error: field is never read: `b` - --> $DIR/union-lint-dead-code.rs:5:5 + --> $DIR/union-lint-dead-code.rs:8:5 | LL | b: bool, | ^^^^^^^ | note: the lint level is defined here - --> $DIR/union-lint-dead-code.rs:1:9 + --> $DIR/union-lint-dead-code.rs:4:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/union/union-lint-dead-code.rs b/src/test/ui/union/union-lint-dead-code.rs index ae5337c618a75..64c28d72e9eaa 100644 --- a/src/test/ui/union/union-lint-dead-code.rs +++ b/src/test/ui/union/union-lint-dead-code.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![deny(dead_code)] union Foo { diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr new file mode 100644 index 0000000000000..22d4428c902c8 --- /dev/null +++ b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr @@ -0,0 +1,14 @@ +error: field is never read: `b` + --> $DIR/union-lint-dead-code.rs:8:5 + | +LL | b: bool, + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/union-lint-dead-code.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/union/union-macro.rs b/src/test/ui/union/union-macro.rs index e938cd5a614e9..7fd9d8221c612 100644 --- a/src/test/ui/union/union-macro.rs +++ b/src/test/ui/union/union-macro.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(unused_variables)] macro_rules! duplicate { diff --git a/src/test/ui/union/union-manuallydrop-rpass.rs b/src/test/ui/union/union-manuallydrop-rpass.rs index 977d12f108602..826bdf07cef5e 100644 --- a/src/test/ui/union/union-manuallydrop-rpass.rs +++ b/src/test/ui/union/union-manuallydrop-rpass.rs @@ -1,5 +1,8 @@ -#![allow(dead_code)] // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] use std::mem::needs_drop; use std::mem::ManuallyDrop; diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr similarity index 92% rename from src/test/ui/union/union-move.stderr rename to src/test/ui/union/union-move.mirunsafeck.stderr index 5679192b64194..f55fbea6336e3 100644 --- a/src/test/ui/union/union-move.stderr +++ b/src/test/ui/union/union-move.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/union-move.rs:26:18 + --> $DIR/union-move.rs:29:18 | LL | fn test1(x: U1) { | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait @@ -10,7 +10,7 @@ LL | move_out(x.f2_nocopy); | ^^^^^^^^^^^ value used here after move error[E0382]: use of moved value: `x` - --> $DIR/union-move.rs:42:18 + --> $DIR/union-move.rs:45:18 | LL | fn test3(x: U1) { | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait @@ -21,7 +21,7 @@ LL | move_out(x.f3_copy); | ^^^^^^^^^ value used here after move error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait - --> $DIR/union-move.rs:49:18 + --> $DIR/union-move.rs:52:18 | LL | move_out(x.f1_nocopy); | ^^^^^^^^^^^ diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs index a0a2d0d659837..8f78c30d67a55 100644 --- a/src/test/ui/union/union-move.rs +++ b/src/test/ui/union/union-move.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + //! Test the behavior of moving out of non-`Copy` union fields. //! Avoid types that `Drop`, we want to focus on moving. #![feature(untagged_unions)] diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr new file mode 100644 index 0000000000000..f55fbea6336e3 --- /dev/null +++ b/src/test/ui/union/union-move.thirunsafeck.stderr @@ -0,0 +1,35 @@ +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:29:18 + | +LL | fn test1(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f1_nocopy); + | ----------- value moved here +LL | move_out(x.f2_nocopy); + | ^^^^^^^^^^^ value used here after move + +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:45:18 + | +LL | fn test3(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f2_nocopy); + | ----------- value moved here +LL | move_out(x.f3_copy); + | ^^^^^^^^^ value used here after move + +error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait + --> $DIR/union-move.rs:52:18 + | +LL | move_out(x.f1_nocopy); + | ^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `x.f1_nocopy` has type `RefCell`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0509. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index bc58c5995cb80..6e6b105a73e9f 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/union/union-nodrop.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck #![allow(dead_code)] diff --git a/src/test/ui/union/union-nonzero.rs b/src/test/ui/union/union-nonzero.rs index bd84b46bf3d23..d29e7a97180cf 100644 --- a/src/test/ui/union/union-nonzero.rs +++ b/src/test/ui/union/union-nonzero.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] // Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. diff --git a/src/test/ui/union/union-overwrite.rs b/src/test/ui/union/union-overwrite.rs index 399ed9ae458b8..0eea14d9de0fc 100644 --- a/src/test/ui/union/union-overwrite.rs +++ b/src/test/ui/union/union-overwrite.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/test/ui/union/union-packed.rs b/src/test/ui/union/union-packed.rs index 9cde44c06bd47..9c6398bf5aa63 100644 --- a/src/test/ui/union/union-packed.rs +++ b/src/test/ui/union/union-packed.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(non_snake_case)] diff --git a/src/test/ui/union/union-pat-refutability.rs b/src/test/ui/union/union-pat-refutability.rs index ebb0672664716..d628a200a076e 100644 --- a/src/test/ui/union/union-pat-refutability.rs +++ b/src/test/ui/union/union-pat-refutability.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] #![allow(illegal_floating_point_literal_pattern)] diff --git a/src/test/ui/union/union-suggest-field.stderr b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr similarity index 86% rename from src/test/ui/union/union-suggest-field.stderr rename to src/test/ui/union/union-suggest-field.mirunsafeck.stderr index 461db1712064f..26fc25b96bd42 100644 --- a/src/test/ui/union/union-suggest-field.stderr +++ b/src/test/ui/union/union-suggest-field.mirunsafeck.stderr @@ -1,17 +1,17 @@ error[E0560]: union `U` has no field named `principle` - --> $DIR/union-suggest-field.rs:10:17 + --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; | ^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0609]: no field `principial` on type `U` - --> $DIR/union-suggest-field.rs:14:15 + --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; | ^^^^^^^^^^ help: a field with a similar name exists: `principal` error[E0615]: attempted to take value of method `calculate` on type `U` - --> $DIR/union-suggest-field.rs:18:15 + --> $DIR/union-suggest-field.rs:21:15 | LL | let y = u.calculate; | ^^^^^^^^^ method, not a field diff --git a/src/test/ui/union/union-suggest-field.rs b/src/test/ui/union/union-suggest-field.rs index 71b93e873c220..601a22a060048 100644 --- a/src/test/ui/union/union-suggest-field.rs +++ b/src/test/ui/union/union-suggest-field.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + union U { principal: u8, } diff --git a/src/test/ui/union/union-suggest-field.thirunsafeck.stderr b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr new file mode 100644 index 0000000000000..26fc25b96bd42 --- /dev/null +++ b/src/test/ui/union/union-suggest-field.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0560]: union `U` has no field named `principle` + --> $DIR/union-suggest-field.rs:13:17 + | +LL | let u = U { principle: 0 }; + | ^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0609]: no field `principial` on type `U` + --> $DIR/union-suggest-field.rs:17:15 + | +LL | let w = u.principial; + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0615]: attempted to take value of method `calculate` on type `U` + --> $DIR/union-suggest-field.rs:21:15 + | +LL | let y = u.calculate; + | ^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let y = u.calculate(); + | ^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0560, E0609, E0615. +For more information about an error, try `rustc --explain E0560`. diff --git a/src/test/ui/union/union-trait-impl.rs b/src/test/ui/union/union-trait-impl.rs index 8a7ac81724040..6134e91f31e49 100644 --- a/src/test/ui/union/union-trait-impl.rs +++ b/src/test/ui/union/union-trait-impl.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck use std::fmt; diff --git a/src/test/ui/union/union-transmute.rs b/src/test/ui/union/union-transmute.rs index be8062f6276fd..1a3b32d55f321 100644 --- a/src/test/ui/union/union-transmute.rs +++ b/src/test/ui/union/union-transmute.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck union U { a: (u8, u8), diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.mir.stderr similarity index 92% rename from src/test/ui/union/union-unsafe.stderr rename to src/test/ui/union/union-unsafe.mir.stderr index a25c09144f742..84a7eb2ef2e72 100644 --- a/src/test/ui/union/union-unsafe.stderr +++ b/src/test/ui/union/union-unsafe.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:31:5 + --> $DIR/union-unsafe.rs:34:5 | LL | *(u.p) = 13; | ^^^^^^^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:35:5 + --> $DIR/union-unsafe.rs:39:5 | LL | u.a = (RefCell::new(0), 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping @@ -15,7 +15,7 @@ LL | u.a = (RefCell::new(0), 1); = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: assignment to union field that might need dropping is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:36:5 + --> $DIR/union-unsafe.rs:40:5 | LL | u.a.0 = RefCell::new(0); | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping @@ -23,7 +23,7 @@ LL | u.a.0 = RefCell::new(0); = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:43:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | *u3.a = T::default(); = 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-unsafe.rs:49:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -39,7 +39,7 @@ LL | *u3.a = T::default(); = 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-unsafe.rs:57:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -47,7 +47,7 @@ LL | let a = u1.a; = 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-unsafe.rs:60:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -55,7 +55,7 @@ LL | let U1 { a } = u1; = 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-unsafe.rs:61:20 + --> $DIR/union-unsafe.rs:65:20 | LL | if let U1 { a: 12 } = u1 {} | ^^ access to union field @@ -63,7 +63,7 @@ LL | if let U1 { a: 12 } = u1 {} = 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-unsafe.rs:66:6 + --> $DIR/union-unsafe.rs:70:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -71,7 +71,7 @@ LL | *u2.a = String::from("new"); = 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-unsafe.rs:70:6 + --> $DIR/union-unsafe.rs:74:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -79,7 +79,7 @@ LL | *u3.a = 1; = 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-unsafe.rs:74:6 + --> $DIR/union-unsafe.rs:78:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index 6adf0ac59b93c..e8414903d548f 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -1,3 +1,6 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] use std::mem::ManuallyDrop; use std::cell::RefCell; @@ -32,8 +35,9 @@ fn deref_union_field(mut u: URef) { } fn assign_noncopy_union_field(mut u: URefCell) { - u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping - u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping + // FIXME(thir-unsafeck) + u.a = (RefCell::new(0), 1); //[mir]~ ERROR assignment to union field that might need dropping + u.a.0 = RefCell::new(0); //[mir]~ ERROR assignment to union field that might need dropping u.a.1 = 1; // OK } diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr new file mode 100644 index 0000000000000..51f19879c8195 --- /dev/null +++ b/src/test/ui/union/union-unsafe.thir.stderr @@ -0,0 +1,75 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:34:6 + | +LL | *(u.p) = 13; + | ^^^^^ 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-unsafe.rs:47:6 + | +LL | *u3.a = T::default(); + | ^^^^ 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-unsafe.rs:53:6 + | +LL | *u3.a = T::default(); + | ^^^^ 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-unsafe.rs:61:13 + | +LL | let a = u1.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-unsafe.rs:64:14 + | +LL | let U1 { a } = u1; + | ^ 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-unsafe.rs:65:20 + | +LL | if let U1 { a: 12 } = u1 {} + | ^^ 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-unsafe.rs:70:6 + | +LL | *u2.a = String::from("new"); + | ^^^^ 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-unsafe.rs:74:6 + | +LL | *u3.a = 1; + | ^^^^ 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-unsafe.rs:78:6 + | +LL | *u3.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/union/union-unsized.stderr b/src/test/ui/union/union-unsized.mirunsafeck.stderr similarity index 95% rename from src/test/ui/union/union-unsized.stderr rename to src/test/ui/union/union-unsized.mirunsafeck.stderr index 454580dcbab01..86a13c1e7ca90 100644 --- a/src/test/ui/union/union-unsized.stderr +++ b/src/test/ui/union/union-unsized.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/union-unsized.rs:4:8 + --> $DIR/union-unsized.rs:7:8 | LL | a: str, | ^^^ doesn't have a size known at compile-time @@ -17,7 +17,7 @@ LL | a: Box, | ^^^^ ^ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/union-unsized.rs:12:8 + --> $DIR/union-unsized.rs:15:8 | LL | b: str, | ^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/union/union-unsized.rs b/src/test/ui/union/union-unsized.rs index 16f2a73d42570..e9792f527dc71 100644 --- a/src/test/ui/union/union-unsized.rs +++ b/src/test/ui/union/union-unsized.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(untagged_unions)] union U { diff --git a/src/test/ui/union/union-unsized.thirunsafeck.stderr b/src/test/ui/union/union-unsized.thirunsafeck.stderr new file mode 100644 index 0000000000000..86a13c1e7ca90 --- /dev/null +++ b/src/test/ui/union/union-unsized.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:7:8 + | +LL | a: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | a: &str, + | ^ +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | a: Box, + | ^^^^ ^ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:15:8 + | +LL | b: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | b: &str, + | ^ +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr similarity index 74% rename from src/test/ui/union/union-with-drop-fields.stderr rename to src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr index 0e77279be616a..2062fb7473faa 100644 --- a/src/test/ui/union/union-with-drop-fields.stderr +++ b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -1,35 +1,35 @@ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:9:5 + --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:9:5 + --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:17:5 + --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:17:5 + --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ error[E0740]: unions may not contain fields that need dropping - --> $DIR/union-with-drop-fields.rs:22:5 + --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/union-with-drop-fields.rs:22:5 + --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ diff --git a/src/test/ui/union/union-with-drop-fields.rs b/src/test/ui/union/union-with-drop-fields.rs index e3c63a6d5b5a2..96c293418b629 100644 --- a/src/test/ui/union/union-with-drop-fields.rs +++ b/src/test/ui/union/union-with-drop-fields.rs @@ -1,4 +1,6 @@ -#![feature(untagged_unions)] +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![allow(dead_code)] union U { diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr new file mode 100644 index 0000000000000..2062fb7473faa --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/unsafe/access_union_field.mir.stderr b/src/test/ui/unsafe/access_union_field.mir.stderr new file mode 100644 index 0000000000000..98bc4077793e3 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ 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/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/access_union_field.rs b/src/test/ui/unsafe/access_union_field.rs new file mode 100644 index 0000000000000..5c4e695df58f2 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.rs @@ -0,0 +1,15 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![allow(unused_variables)] + +union Foo { + bar: i8, + baz: u8, +} + +fn main() { + let foo = Foo { bar: 5 }; + let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block + let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block +} diff --git a/src/test/ui/unsafe/access_union_field.thir.stderr b/src/test/ui/unsafe/access_union_field.thir.stderr new file mode 100644 index 0000000000000..98bc4077793e3 --- /dev/null +++ b/src/test/ui/unsafe/access_union_field.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ 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/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +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.mir.stderr b/src/test/ui/unsafe/union.mir.stderr new file mode 100644 index 0000000000000..f7bd411a74416 --- /dev/null +++ b/src/test/ui/unsafe/union.mir.stderr @@ -0,0 +1,16 @@ +warning: unnecessary `unsafe` block + --> $DIR/union.rs:61:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union.rs:66:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs new file mode 100644 index 0000000000000..0130fa67f2328 --- /dev/null +++ b/src/test/ui/unsafe/union.rs @@ -0,0 +1,80 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(untagged_unions)] + +union Foo { + bar: i8, + zst: (), + pizza: Pizza, +} + +struct Pizza { + topping: Option +} + +#[allow(dead_code)] +enum PizzaTopping { + Cheese, + 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 } => {}, + } + } + unsafe { + match foo { + Foo { + pizza: Pizza { + topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None + } + } => {}, + } + } + // 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_access_through_block.rs b/src/test/ui/unsafe/union_access_through_block.rs new file mode 100644 index 0000000000000..e4c0976b82659 --- /dev/null +++ b/src/test/ui/unsafe/union_access_through_block.rs @@ -0,0 +1,18 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +pub struct Foo { a: bool } + +pub union Bar { + a: Foo, + b: u32, +} +pub fn baz(mut bar: Bar) { + unsafe { + { bar.a }.a = true; + } +} + +fn main() {} diff --git a/src/test/ui/unsafe/union_destructure.mir.stderr b/src/test/ui/unsafe/union_destructure.mir.stderr new file mode 100644 index 0000000000000..818f5ce03b54d --- /dev/null +++ b/src/test/ui/unsafe/union_destructure.mir.stderr @@ -0,0 +1,16 @@ +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:35:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:41:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/src/test/ui/unsafe/union_destructure.rs b/src/test/ui/unsafe/union_destructure.rs new file mode 100644 index 0000000000000..6c88344b5fdee --- /dev/null +++ b/src/test/ui/unsafe/union_destructure.rs @@ -0,0 +1,51 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +#[allow(dead_code)] +struct Pie { + slices: u8, + size: u8, +} + +union Foo { + #[allow(dead_code)] + bar: i8, + baz: Pie +} + +fn main() { + let u = Foo { bar: 5 }; + let (Some(Foo { bar: _ }) | None) = Some(u); + let u = Foo { bar: 6 }; + let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u); + unsafe { + let u = Foo { bar: 7 }; + let (Foo { bar } | Foo { bar }) = u; + assert_eq!(bar, 7) + } + let u = Foo { bar: 8 }; + match Some(u) { + Some(Foo { bar: _ }) => 3, + None => 4, + }; + + let u = Foo { bar: 9 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { .. } } => {}, + }; + } + let u = Foo { bar: 10 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { slices: _, size: _ } } => {}, + }; + } + + let u = Foo { bar: 11 }; + match u { + Foo { baz: _ } => {}, + }; +} diff --git a/src/test/ui/unsafe/union_wild_or_wild.rs b/src/test/ui/unsafe/union_wild_or_wild.rs new file mode 100644 index 0000000000000..52a0a7abf274b --- /dev/null +++ b/src/test/ui/unsafe/union_wild_or_wild.rs @@ -0,0 +1,12 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +union X { a: i8 } + +fn main() { + let x = X { a: 5 }; + match x { + X { a: _ | _ } => {}, + } +} From df3e003378b8b896a9e4eecbd944c83d38d831f4 Mon Sep 17 00:00:00 2001 From: Smitty Date: Tue, 25 May 2021 10:35:24 -0400 Subject: [PATCH 2/3] Don't stub out part of test --- src/test/ui/issues/issue-47412.mir.stderr | 2 +- src/test/ui/issues/issue-47412.rs | 3 +-- src/test/ui/issues/issue-47412.thir.stderr | 12 ++++++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/test/ui/issues/issue-47412.mir.stderr b/src/test/ui/issues/issue-47412.mir.stderr index 96e50ba67991c..305f482e8c21d 100644 --- a/src/test/ui/issues/issue-47412.mir.stderr +++ b/src/test/ui/issues/issue-47412.mir.stderr @@ -7,7 +7,7 @@ LL | match u.void {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/issue-47412.rs:21:11 + --> $DIR/issue-47412.rs:20:11 | LL | match *ptr {} | ^^^^ dereference of raw pointer diff --git a/src/test/ui/issues/issue-47412.rs b/src/test/ui/issues/issue-47412.rs index d395285eee0a0..df6d6e4222e82 100644 --- a/src/test/ui/issues/issue-47412.rs +++ b/src/test/ui/issues/issue-47412.rs @@ -12,8 +12,7 @@ fn union_field() { union Union { unit: (), void: Void } let u = Union { unit: () }; match u.void {} - //[mir]~^ ERROR access to union field is unsafe - // FIXME(thir-unsafeck): AccessToUnionField unimplemented + //~^ ERROR access to union field is unsafe } fn raw_ptr_deref() { diff --git a/src/test/ui/issues/issue-47412.thir.stderr b/src/test/ui/issues/issue-47412.thir.stderr index 66a0cfcd710f0..305f482e8c21d 100644 --- a/src/test/ui/issues/issue-47412.thir.stderr +++ b/src/test/ui/issues/issue-47412.thir.stderr @@ -1,11 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:14:11 + | +LL | match u.void {} + | ^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/issue-47412.rs:21:11 + --> $DIR/issue-47412.rs:20:11 | LL | match *ptr {} | ^^^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. From b86ed4a425b3fa830fa031ed7fe7187728403440 Mon Sep 17 00:00:00 2001 From: Smitty Date: Fri, 9 Jul 2021 15:22:12 -0400 Subject: [PATCH 3/3] panic when trying to destructure union as enum --- compiler/rustc_mir_build/src/check_unsafety.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 0aec63182952e..c3af98fae9d59 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -201,14 +201,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { AscribeUserType { .. } | // creating a union literal Constant { .. } => {}, - Variant { .. } | Leaf { .. } | Or { .. } => { + Leaf { .. } | Or { .. } => { // pattern matching with a union and not doing something like v = Union { bar: 5 } self.in_union_destructure = true; visit::walk_pat(self, pat); self.in_union_destructure = false; return; // don't walk pattern } - Deref { .. } | Range { .. } | Slice { .. } | Array { .. } => + Variant { .. } | Deref { .. } | Range { .. } | Slice { .. } | Array { .. } => unreachable!("impossible union destructuring type"), } }