Check for union field accesses in THIR unsafeck

This commit is contained in:
Smitty 2021-05-13 10:42:25 -04:00
parent 969a6c2481
commit 74d0d74dae
69 changed files with 1083 additions and 71 deletions

View File

@ -26,6 +26,8 @@ struct UnsafetyVisitor<'a, 'tcx> {
/// calls to functions with `#[target_feature]` (RFC 2396).
body_target_features: &'tcx Vec<Symbol>,
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<LocalD
body_unsafety,
body_target_features,
is_const,
in_possible_lhs_union_assign: false,
in_union_destructure: false,
};
visitor.visit_expr(&thir[expr]);
}

View File

@ -153,8 +153,8 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(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);
}

View File

@ -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};

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(path_statements)]
#![allow(dead_code)]

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(unused_imports)]
// aux-build:union.rs

View File

@ -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`)

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
#![allow(unused)]

View File

@ -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`.

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: u64,

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
type Field1 = (i32, u32);
type Field2 = f32;

View File

@ -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 {

View File

@ -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) };
| ^^^^^

View File

@ -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)]

View File

@ -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

View File

@ -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<T: Copy + ?Sized> {
= 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<CloneNoCopy>`, but its trait bounds were not satisfied
--> $DIR/union-derive-clone.rs:35:15
--> $DIR/union-derive-clone.rs:38:15
|
LL | union U5<T> {
| -----------

View File

@ -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

View File

@ -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<T: Copy + ?Sized> {
| ---- 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<CloneNoCopy>`, but its trait bounds were not satisfied
--> $DIR/union-derive-clone.rs:38:15
|
LL | union U5<T> {
| -----------
| |
| method `clone` not found for this
| doesn't satisfy `U5<CloneNoCopy>: Clone`
...
LL | struct CloneNoCopy;
| ------------------- doesn't satisfy `CloneNoCopy: Copy`
...
LL | let w = u.clone();
| ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`CloneNoCopy: Copy`
which is required by `U5<CloneNoCopy>: 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`.

View File

@ -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`

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#[derive(Eq)] // OK
union U1 {
a: u8,

View File

@ -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<T: Eq + ?Sized> {
| -- 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`.

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
#![allow(unused_variables)]

View File

@ -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

View File

@ -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,
| ^^^^^

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![deny(dead_code)]
union U1 {

View File

@ -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

View File

@ -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;
| ^^^^^^^^^^^

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: u8,
b: u16,

View File

@ -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`.

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
use std::mem::ManuallyDrop;

View File

@ -1,5 +1,5 @@
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
--> $DIR/union-generic.rs:8:13
--> $DIR/union-generic.rs:11:13
|
LL | union U<T: Copy> {
| ---------------- required by `U`
@ -8,7 +8,7 @@ LL | let u = U { a: Rc::new(0u32) };
| ^ the trait `Copy` is not implemented for `Rc<u32>`
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
--> $DIR/union-generic.rs:10:13
--> $DIR/union-generic.rs:13:13
|
LL | union U<T: Copy> {
| ---------------- required by `U`

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::rc::Rc;
union U<T: Copy> {

View File

@ -0,0 +1,21 @@
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
--> $DIR/union-generic.rs:11:13
|
LL | union U<T: Copy> {
| ---------------- required by `U`
...
LL | let u = U { a: Rc::new(0u32) };
| ^ the trait `Copy` is not implemented for `Rc<u32>`
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
--> $DIR/union-generic.rs:13:13
|
LL | union U<T: Copy> {
| ---------------- required by `U`
...
LL | let u = U::<Rc<u32>> { a: Default::default() };
| ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: u8,

View File

@ -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)]
| ^^^^^^^^^

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![deny(dead_code)]
union Foo {

View File

@ -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

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(unused_variables)]
macro_rules! duplicate {

View File

@ -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;

View File

@ -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);
| ^^^^^^^^^^^

View File

@ -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)]

View File

@ -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<i32>`, 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`.

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]

View File

@ -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.

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#[repr(C)]
#[derive(Copy, Clone)]

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
#![allow(non_snake_case)]

View File

@ -1,4 +1,7 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
#![allow(illegal_floating_point_literal_pattern)]

View File

@ -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

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
principal: u8,
}

View File

@ -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`.

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::fmt;

View File

@ -1,4 +1,6 @@
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U {
a: (u8, u8),

View File

@ -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

View File

@ -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
}

View File

@ -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`.

View File

@ -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<str>,
| ^^^^ ^
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

View File

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
union U {

View File

@ -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<str>,
| ^^^^ ^
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<str>,
| ^^^^ ^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -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,
| ^^^^

View File

@ -1,4 +1,6 @@
#![feature(untagged_unions)]
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)]
union U {

View File

@ -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`.

View File

@ -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`.

View File

@ -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
}

View File

@ -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`.

View File

@ -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

View File

@ -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<PizzaTopping>
}
#[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);
}

View File

@ -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() {}

View File

@ -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

View File

@ -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: _ } => {},
};
}

View File

@ -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: _ | _ } => {},
}
}