1
Fork 0

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). /// calls to functions with `#[target_feature]` (RFC 2396).
body_target_features: &'tcx Vec<Symbol>, body_target_features: &'tcx Vec<Symbol>,
is_const: bool, is_const: bool,
in_possible_lhs_union_assign: bool,
in_union_destructure: bool,
} }
impl<'tcx> UnsafetyVisitor<'_, 'tcx> { 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>) { 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 { match expr.kind {
ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
let prev_id = self.hir_context; let prev_id = self.hir_context;
self.hir_context = hir_id; self.hir_context = hir_id;
self.visit_expr(&self.thir[value]); self.visit_expr(&self.thir[value]);
self.hir_context = prev_id; self.hir_context = prev_id;
return; return; // don't visit the whole expression
} }
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { 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 // Unsafe blocks can be used in closures, make sure to take it into account
self.safety_context = closure_visitor.safety_context; 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); visit::walk_expr(self, expr);
} }
} }
@ -296,7 +419,6 @@ enum UnsafeOpKind {
DerefOfRawPointer, DerefOfRawPointer,
#[allow(dead_code)] // FIXME #[allow(dead_code)] // FIXME
AssignToDroppingUnionField, AssignToDroppingUnionField,
#[allow(dead_code)] // FIXME
AccessToUnionField, AccessToUnionField,
#[allow(dead_code)] // FIXME #[allow(dead_code)] // FIXME
MutationOfLayoutConstrainedField, MutationOfLayoutConstrainedField,
@ -417,6 +539,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
body_unsafety, body_unsafety,
body_target_features, body_target_features,
is_const, is_const,
in_possible_lhs_union_assign: false,
in_union_destructure: false,
}; };
visitor.visit_expr(&thir[expr]); 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>) { pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
match stmt.kind { match &stmt.kind {
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]), StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
StmtKind::Let { StmtKind::Let {
initializer, initializer,
remainder_scope: _, remainder_scope: _,
@ -163,7 +163,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
lint_level: _, lint_level: _,
} => { } => {
if let Some(init) = initializer { if let Some(init) = initializer {
visitor.visit_expr(&visitor.thir()[init]); visitor.visit_expr(&visitor.thir()[*init]);
} }
visitor.visit_pat(pattern); visitor.visit_pat(pattern);
} }

View file

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

View file

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

View file

@ -1,4 +1,7 @@
// run-pass // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(unused_imports)] #![allow(unused_imports)]
// aux-build:union.rs // 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`) 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; LL | let a = &mut u.x.0;
| ---------- mutable borrow occurs here (via `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` = 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` 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()) }; 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 | - 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 | ^^^ 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`) 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; LL | let a = &mut (u.x.0).0;
| -------------- mutable borrow occurs here (via `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` = 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` 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()) }; 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 | - 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 | ^^^ 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`) 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; LL | let a = &mut *u.y;
| --- mutable borrow occurs here (via `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)] #![feature(untagged_unions)]
#![allow(unused)] #![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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U { union U {
a: u64, a: u64,

View file

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

View file

@ -1,4 +1,7 @@
// build-pass (FIXME(62277): could be check-pass?) // build-pass (FIXME(62277): could be check-pass?)
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(const_fn_union)] #![feature(const_fn_union)]
union U { union U {

View file

@ -1,5 +1,5 @@
error: not automatically applying `DerefMut` on `ManuallyDrop` union field 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() }; 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 = 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 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 }; 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 = 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 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) }; 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 = 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 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() }; 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 = 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 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 }; 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 = 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 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) }; 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 //! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
//! of union fields. //! of union fields.
#![feature(untagged_unions)] #![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 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)] LL | #[derive(Clone)]
| ^^^^^ the trait `Copy` is not implemented for `U1` | ^^^^^ 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) = 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 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> { LL | union U5<T> {
| ----------- | -----------

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
#[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied #[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 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, LL | a: PartialEqNotEq,
| ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `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 #[derive(Eq)] // OK
union U1 { union U1 {
a: u8, 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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)] #![allow(dead_code)]
#![allow(unused_variables)] #![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` error: field is never read: `c`
--> $DIR/union-fields-1.rs:6:5 --> $DIR/union-fields-1.rs:9:5
| |
LL | c: u8, LL | c: u8,
| ^^^^^ | ^^^^^
| |
note: the lint level is defined here 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)] LL | #![deny(dead_code)]
| ^^^^^^^^^ | ^^^^^^^^^
error: field is never read: `a` error: field is never read: `a`
--> $DIR/union-fields-1.rs:9:5 --> $DIR/union-fields-1.rs:12:5
| |
LL | a: u8, LL | a: u8,
| ^^^^^ | ^^^^^
error: field is never read: `a` 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 } LL | union NoDropLike { a: u8 }
| ^^^^^ | ^^^^^
error: field is never read: `c` error: field is never read: `c`
--> $DIR/union-fields-1.rs:18:5 --> $DIR/union-fields-1.rs:21:5
| |
LL | c: u8, LL | c: u8,
| ^^^^^ | ^^^^^

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![deny(dead_code)] #![deny(dead_code)]
union U1 { 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 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 {}; LL | let u = U {};
| ^ | ^
error: union expressions should have exactly one field 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 }; LL | let u = U { a: 0, b: 1 };
| ^ | ^
error[E0560]: union `U` has no field named `c` 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 }; LL | let u = U { a: 0, b: 1, c: 2 };
| ^ `U` does not have this field | ^ `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` = note: available fields are: `a`, `b`
error: union expressions should have exactly one field 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 }; LL | let u = U { a: 0, b: 1, c: 2 };
| ^ | ^
error: union expressions should have exactly one field 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 }; LL | let u = U { ..u };
| ^ | ^
error[E0436]: functional record update syntax requires a struct 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 }; LL | let u = U { ..u };
| ^ | ^
error: union patterns should have exactly one field 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; LL | let U {} = u;
| ^^^^ | ^^^^
error: union patterns should have exactly one field 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; LL | let U { a, b } = u;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: union patterns should have exactly one field 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; LL | let U { a, b, c } = u;
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0026]: union `U` does not have a field named `c` 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; LL | let U { a, b, c } = u;
| ^ union `U` does not have this field | ^ union `U` does not have this field
error: union patterns should have exactly one 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; LL | let U { .. } = u;
| ^^^^^^^^ | ^^^^^^^^
error: `..` cannot be used in union patterns 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; LL | let U { .. } = u;
| ^^^^^^^^ | ^^^^^^^^
error: `..` cannot be used in union patterns 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; LL | let U { a, .. } = u;
| ^^^^^^^^^^^ | ^^^^^^^^^^^

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U { union U {
a: u8, a: u8,
b: u16, 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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)] #![allow(dead_code)]
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied 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> { LL | union U<T: Copy> {
| ---------------- required by `U` | ---------------- required by `U`
@ -8,7 +8,7 @@ LL | let u = U { a: Rc::new(0u32) };
| ^ the trait `Copy` is not implemented for `Rc<u32>` | ^ the trait `Copy` is not implemented for `Rc<u32>`
error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied 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> { LL | union U<T: Copy> {
| ---------------- required by `U` | ---------------- required by `U`

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::rc::Rc; use std::rc::Rc;
union U<T: Copy> { 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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U { union U {
a: u8, a: u8,

View file

@ -1,11 +1,11 @@
error: field is never read: `b` 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, LL | b: bool,
| ^^^^^^^ | ^^^^^^^
| |
note: the lint level is defined here 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)] LL | #![deny(dead_code)]
| ^^^^^^^^^ | ^^^^^^^^^

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![deny(dead_code)] #![deny(dead_code)]
union Foo { 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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(unused_variables)] #![allow(unused_variables)]
macro_rules! duplicate { macro_rules! duplicate {

View file

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

View file

@ -1,5 +1,5 @@
error[E0382]: use of moved value: `x` error[E0382]: use of moved value: `x`
--> $DIR/union-move.rs:26:18 --> $DIR/union-move.rs:29:18
| |
LL | fn test1(x: U1) { LL | fn test1(x: U1) {
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait | - 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 | ^^^^^^^^^^^ value used here after move
error[E0382]: use of moved value: `x` error[E0382]: use of moved value: `x`
--> $DIR/union-move.rs:42:18 --> $DIR/union-move.rs:45:18
| |
LL | fn test3(x: U1) { LL | fn test3(x: U1) {
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait | - 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 | ^^^^^^^^^ value used here after move
error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait 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); 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. //! Test the behavior of moving out of non-`Copy` union fields.
//! Avoid types that `Drop`, we want to focus on moving. //! Avoid types that `Drop`, we want to focus on moving.
#![feature(untagged_unions)] #![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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)] #![allow(dead_code)]

View file

@ -1,4 +1,7 @@
// run-pass // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)] #![allow(dead_code)]
// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. // Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.

View file

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

View file

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

View file

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

View file

@ -1,17 +1,17 @@
error[E0560]: union `U` has no field named `principle` 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 }; LL | let u = U { principle: 0 };
| ^^^^^^^^^ help: a field with a similar name exists: `principal` | ^^^^^^^^^ help: a field with a similar name exists: `principal`
error[E0609]: no field `principial` on type `U` 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; LL | let w = u.principial;
| ^^^^^^^^^^ help: a field with a similar name exists: `principal` | ^^^^^^^^^^ help: a field with a similar name exists: `principal`
error[E0615]: attempted to take value of method `calculate` on type `U` 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; LL | let y = u.calculate;
| ^^^^^^^^^ method, not a field | ^^^^^^^^^ method, not a field

View file

@ -1,3 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
union U { union U {
principal: u8, 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 // run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
use std::fmt; use std::fmt;

View file

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

View file

@ -1,5 +1,5 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block 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; LL | *(u.p) = 13;
| ^^^^^^^^^^^ access to union field | ^^^^^^^^^^^ 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 = 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 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); LL | u.a = (RefCell::new(0), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 = 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 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); LL | u.a.0 = RefCell::new(0);
| ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping | ^^^^^^^^^^^^^^^^^^^^^^^ 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 = 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 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(); LL | *u3.a = T::default();
| ^^^^ access to union field | ^^^^ 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 = 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 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(); LL | *u3.a = T::default();
| ^^^^ access to union field | ^^^^ 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 = 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 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; LL | let a = u1.a;
| ^^^^ access to union field | ^^^^ 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 = 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 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; LL | let U1 { a } = u1;
| ^ access to union field | ^ 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 = 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 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 {} LL | if let U1 { a: 12 } = u1 {}
| ^^ access to union field | ^^ 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 = 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 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"); LL | *u2.a = String::from("new");
| ^^^^ access to union field | ^^^^ 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 = 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 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; LL | *u3.a = 1;
| ^^^^ access to union field | ^^^^ 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 = 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 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"); LL | *u3.a = String::from("new");
| ^^^^ access to union field | ^^^^ access to union field

View file

@ -1,3 +1,6 @@
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)] #![feature(untagged_unions)]
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::cell::RefCell; use std::cell::RefCell;
@ -32,8 +35,9 @@ fn deref_union_field(mut u: URef) {
} }
fn assign_noncopy_union_field(mut u: URefCell) { fn assign_noncopy_union_field(mut u: URefCell) {
u.a = (RefCell::new(0), 1); //~ ERROR assignment to union field that might need dropping // FIXME(thir-unsafeck)
u.a.0 = RefCell::new(0); //~ ERROR assignment to union field that might need dropping 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 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 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, LL | a: str,
| ^^^ doesn't have a size known at compile-time | ^^^ 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 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, LL | b: str,
| ^^^ doesn't have a size known at compile-time | ^^^ 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)] #![feature(untagged_unions)]
union U { 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 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, LL | a: String,
| ^^^^^^^^^ | ^^^^^^^^^
| |
note: `std::mem::ManuallyDrop` can be used to wrap the type 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, LL | a: String,
| ^^^^^^^^^ | ^^^^^^^^^
error[E0740]: unions may not contain fields that need dropping 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, LL | a: S,
| ^^^^ | ^^^^
| |
note: `std::mem::ManuallyDrop` can be used to wrap the type 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, LL | a: S,
| ^^^^ | ^^^^
error[E0740]: unions may not contain fields that need dropping 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, LL | a: T,
| ^^^^ | ^^^^
| |
note: `std::mem::ManuallyDrop` can be used to wrap the type 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, LL | a: T,
| ^^^^ | ^^^^

View file

@ -1,4 +1,6 @@
#![feature(untagged_unions)] // revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![allow(dead_code)] #![allow(dead_code)]
union U { 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: _ | _ } => {},
}
}