mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Check for union field accesses in THIR unsafeck
This commit is contained in:
parent
969a6c2481
commit
74d0d74dae
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(path_statements)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
// aux-build:union.rs
|
||||
|
@ -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`)
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![feature(untagged_unions)]
|
||||
#![allow(unused)]
|
||||
|
||||
|
@ -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`.
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
union U {
|
||||
a: u64,
|
||||
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
type Field1 = (i32, u32);
|
||||
type Field2 = f32;
|
||||
|
@ -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 {
|
||||
|
@ -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) };
|
||||
| ^^^^^
|
@ -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)]
|
||||
|
56
src/test/ui/union/union-deref.thirunsafeck.stderr
Normal file
56
src/test/ui/union/union-deref.thirunsafeck.stderr
Normal 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
|
||||
|
@ -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> {
|
||||
| -----------
|
@ -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
|
||||
|
36
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
Normal file
36
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
Normal 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`.
|
@ -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`
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#[derive(Eq)] // OK
|
||||
union U1 {
|
||||
a: u8,
|
||||
|
16
src/test/ui/union/union-derive-eq.thirunsafeck.stderr
Normal file
16
src/test/ui/union/union-derive-eq.thirunsafeck.stderr
Normal 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`.
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
|
22
src/test/ui/union/union-drop.thirunsafeck.stderr
Normal file
22
src/test/ui/union/union-drop.thirunsafeck.stderr
Normal 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
|
||||
|
@ -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,
|
||||
| ^^^^^
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
||||
union U1 {
|
||||
|
32
src/test/ui/union/union-fields-1.thirunsafeck.stderr
Normal file
32
src/test/ui/union/union-fields-1.thirunsafeck.stderr
Normal 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
|
||||
|
@ -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;
|
||||
| ^^^^^^^^^^^
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
union U {
|
||||
a: u8,
|
||||
b: u16,
|
||||
|
84
src/test/ui/union/union-fields-2.thirunsafeck.stderr
Normal file
84
src/test/ui/union/union-fields-2.thirunsafeck.stderr
Normal 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`.
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::mem::ManuallyDrop;
|
||||
|
@ -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`
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
union U<T: Copy> {
|
||||
|
21
src/test/ui/union/union-generic.thirunsafeck.stderr
Normal file
21
src/test/ui/union/union-generic.thirunsafeck.stderr
Normal 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`.
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
union U {
|
||||
a: u8,
|
||||
|
@ -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)]
|
||||
| ^^^^^^^^^
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
||||
union Foo {
|
||||
|
14
src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
Normal file
14
src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
Normal 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
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
macro_rules! duplicate {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
| ^^^^^^^^^^^
|
@ -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)]
|
||||
|
35
src/test/ui/union/union-move.thirunsafeck.stderr
Normal file
35
src/test/ui/union/union-move.thirunsafeck.stderr
Normal 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`.
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -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.
|
||||
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(illegal_floating_point_literal_pattern)]
|
||||
|
||||
|
@ -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
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
union U {
|
||||
principal: u8,
|
||||
}
|
||||
|
27
src/test/ui/union/union-suggest-field.thirunsafeck.stderr
Normal file
27
src/test/ui/union/union-suggest-field.thirunsafeck.stderr
Normal 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`.
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
use std::fmt;
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
union U {
|
||||
a: (u8, u8),
|
||||
|
@ -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
|
@ -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
|
||||
}
|
||||
|
||||
|
75
src/test/ui/union/union-unsafe.thir.stderr
Normal file
75
src/test/ui/union/union-unsafe.thir.stderr
Normal 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`.
|
@ -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
|
@ -1,3 +1,6 @@
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
union U {
|
||||
|
39
src/test/ui/union/union-unsized.thirunsafeck.stderr
Normal file
39
src/test/ui/union/union-unsized.thirunsafeck.stderr
Normal 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`.
|
@ -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,
|
||||
| ^^^^
|
@ -1,4 +1,6 @@
|
||||
#![feature(untagged_unions)]
|
||||
// revisions: mirunsafeck thirunsafeck
|
||||
// [thirunsafeck]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
union U {
|
||||
|
39
src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr
Normal file
39
src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr
Normal 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`.
|
19
src/test/ui/unsafe/access_union_field.mir.stderr
Normal file
19
src/test/ui/unsafe/access_union_field.mir.stderr
Normal 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`.
|
15
src/test/ui/unsafe/access_union_field.rs
Normal file
15
src/test/ui/unsafe/access_union_field.rs
Normal 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
|
||||
}
|
19
src/test/ui/unsafe/access_union_field.thir.stderr
Normal file
19
src/test/ui/unsafe/access_union_field.thir.stderr
Normal 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`.
|
16
src/test/ui/unsafe/union.mir.stderr
Normal file
16
src/test/ui/unsafe/union.mir.stderr
Normal 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
|
||||
|
80
src/test/ui/unsafe/union.rs
Normal file
80
src/test/ui/unsafe/union.rs
Normal 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);
|
||||
}
|
18
src/test/ui/unsafe/union_access_through_block.rs
Normal file
18
src/test/ui/unsafe/union_access_through_block.rs
Normal 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() {}
|
16
src/test/ui/unsafe/union_destructure.mir.stderr
Normal file
16
src/test/ui/unsafe/union_destructure.mir.stderr
Normal 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
|
||||
|
51
src/test/ui/unsafe/union_destructure.rs
Normal file
51
src/test/ui/unsafe/union_destructure.rs
Normal 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: _ } => {},
|
||||
};
|
||||
}
|
12
src/test/ui/unsafe/union_wild_or_wild.rs
Normal file
12
src/test/ui/unsafe/union_wild_or_wild.rs
Normal 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: _ | _ } => {},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user