Auto merge of #97995 - RalfJung:union-more-nodrop, r=Mark-Simulacrum

allow unions with mutable references and tuples of allowed types

We currently allow shared references in unions, but not mutable references. That seems somewhat inconsistent. So let's allow all references, and while we are at it, let's make sure the set of allowed types is closed under tuples.

This will need T-lang FCP (at least).

Then remove the `tagged_unions` feature, since we do not plan to stabilize any more of it.
Closes https://github.com/rust-lang/rust/issues/55149
This commit is contained in:
bors 2022-07-13 23:42:05 +00:00
commit cbb07c27a4
66 changed files with 507 additions and 529 deletions

View file

@ -525,13 +525,6 @@ declare_features! (
(incomplete, unsized_locals, "1.30.0", Some(48055), None),
/// Allows unsized tuple coercion.
(active, unsized_tuple_coercion, "1.20.0", Some(42877), None),
/// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields
/// that don't implement `Copy` as long as they don't have any drop glue.
/// This is checked recursively. On encountering type variable where no progress can be made,
/// `T: Copy` is used as a substitute for "no drop glue".
///
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
(active, untagged_unions, "1.13.0", Some(55149), None),
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
(active, used_with_arg, "1.60.0", Some(93798), None),
/// Allows `extern "wasm" fn`

View file

@ -180,6 +180,9 @@ declare_features! (
/// Allows using items which are missing stability attributes
(removed, unmarked_api, "1.0.0", None, None, None),
(removed, unsafe_no_drop_flag, "1.0.0", None, None, None),
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
(removed, untagged_unions, "1.13.0", Some(55149), None,
Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),
/// Allows `#[unwind(..)]`.
///
/// Permits specifying whether a function should permit unwinding or abort on unwind.

View file

@ -35,7 +35,6 @@ pub enum UnsafetyViolationDetails {
UseOfMutableStatic,
UseOfExternStatic,
DerefOfRawPointer,
AssignToDroppingUnionField,
AccessToUnionField,
MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField,
@ -78,11 +77,6 @@ impl UnsafetyViolationDetails {
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
and cause data races: all of these are undefined behavior",
),
AssignToDroppingUnionField => (
"assignment to union field that might need dropping",
"the previous content of the field will be dropped, which causes undefined \
behavior if the field was not properly initialized",
),
AccessToUnionField => (
"access to union field",
"the field may not be properly initialized: using uninitialized data will cause \

View file

@ -431,16 +431,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
let lhs = &self.thir[lhs];
if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
if let Some((assigned_ty, assignment_span)) = self.assignment_info {
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
if !(assigned_ty
.ty_adt_def()
.map_or(false, |adt| adt.is_manually_drop())
|| assigned_ty
.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env))
{
self.requires_unsafe(assignment_span, AssignToDroppingUnionField);
} else {
// write to non-drop union field, safe
if assigned_ty.needs_drop(self.tcx, self.tcx.param_env(adt_def.did())) {
// This would be unsafe, but should be outright impossible since we reject such unions.
self.tcx.sess.delay_span_bug(assignment_span, "union fields that need dropping should be impossible");
}
} else {
self.requires_unsafe(expr.span, AccessToUnionField);
@ -537,7 +530,6 @@ enum UnsafeOpKind {
UseOfMutableStatic,
UseOfExternStatic,
DerefOfRawPointer,
AssignToDroppingUnionField,
AccessToUnionField,
MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField,
@ -555,7 +547,6 @@ impl UnsafeOpKind {
UseOfMutableStatic => "use of mutable static",
UseOfExternStatic => "use of extern static",
DerefOfRawPointer => "dereference of raw pointer",
AssignToDroppingUnionField => "assignment to union field that might need dropping",
AccessToUnionField => "access to union field",
MutationOfLayoutConstrainedField => "mutation of layout constrained field",
BorrowOfLayoutConstrainedField => {
@ -600,11 +591,6 @@ impl UnsafeOpKind {
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
and cause data races: all of these are undefined behavior",
),
AssignToDroppingUnionField => (
Cow::Borrowed(self.simple_description()),
"the previous content of the field will be dropped, which causes undefined \
behavior if the field was not properly initialized",
),
AccessToUnionField => (
Cow::Borrowed(self.simple_description()),
"the field may not be properly initialized: using uninitialized data will cause \

View file

@ -219,22 +219,15 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
// We have to check the actual type of the assignment, as that determines if the
// old value is being dropped.
let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty;
// To avoid semver hazard, we only consider `Copy` and `ManuallyDrop` non-dropping.
let manually_drop = assigned_ty
.ty_adt_def()
.map_or(false, |adt_def| adt_def.is_manually_drop());
let nodrop = manually_drop
|| assigned_ty.is_copy_modulo_regions(
self.tcx.at(self.source_info.span),
self.param_env,
if assigned_ty.needs_drop(
self.tcx,
self.tcx.param_env(base_ty.ty_adt_def().unwrap().did()),
) {
// This would be unsafe, but should be outright impossible since we reject such unions.
self.tcx.sess.delay_span_bug(
self.source_info.span,
"union fields that need dropping should be impossible",
);
if !nodrop {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::AssignToDroppingUnionField,
);
} else {
// write to non-drop union field, safe
}
} else {
self.require_unsafe(

View file

@ -13,13 +13,12 @@ use rustc_hir::{FieldDef, Generics, HirId, Item, ItemKind, TraitRef, Ty, TyKind,
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::ty::{self, query::Providers, TyCtxt};
use rustc_middle::ty::{query::Providers, TyCtxt};
use rustc_session::lint;
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use std::cmp::Ordering;
@ -766,39 +765,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
}
}
// There's no good place to insert stability check for non-Copy unions,
// so semi-randomly perform it here in stability.rs
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
let ty = self.tcx.type_of(item.def_id);
let ty::Adt(adt_def, substs) = ty.kind() else { bug!() };
// Non-`Copy` fields are unstable, except for `ManuallyDrop`.
let param_env = self.tcx.param_env(item.def_id);
for field in &adt_def.non_enum_variant().fields {
let field_ty = field.ty(self.tcx, substs);
if !field_ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
&& !field_ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
{
if field_ty.needs_drop(self.tcx, param_env) {
// Avoid duplicate error: This will error later anyway because fields
// that need drop are not allowed.
self.tcx.sess.delay_span_bug(
item.span,
"union should have been rejected due to potentially dropping field",
);
} else {
feature_err(
&self.tcx.sess.parse_sess,
sym::untagged_unions,
self.tcx.def_span(field.did),
"unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable",
)
.emit();
}
}
}
}
_ => (/* pass */),
}
intravisit::walk_item(self, item);

View file

@ -402,11 +402,37 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
let item_type = tcx.type_of(item_def_id);
if let ty::Adt(def, substs) = item_type.kind() {
assert!(def.is_union());
let fields = &def.non_enum_variant().fields;
fn allowed_union_field<'tcx>(
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> bool {
// We don't just accept all !needs_drop fields, due to semver concerns.
match ty.kind() {
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
ty::Tuple(tys) => {
// allow tuples of allowed types
tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env, span))
}
ty::Array(elem, _len) => {
// Like `Copy`, we do *not* special-case length 0.
allowed_union_field(*elem, tcx, param_env, span)
}
_ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| ty.is_copy_modulo_regions(tcx.at(span), param_env)
}
}
}
let param_env = tcx.param_env(item_def_id);
for field in fields {
for field in &def.non_enum_variant().fields {
let field_ty = field.ty(tcx, substs);
if field_ty.needs_drop(tcx, param_env) {
if !allowed_union_field(field_ty, tcx, param_env, span) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span),
@ -433,6 +459,9 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
)
.emit();
return false;
} else if field_ty.needs_drop(tcx, param_env) {
// This should never happen. But we can get here e.g. in case of name resolution errors.
tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields");
}
}
} else {

View file

@ -72,6 +72,7 @@ This API is completely unstable and subject to change.
#![feature(once_cell)]
#![feature(slice_partition_dedup)]
#![feature(try_blocks)]
#![feature(is_some_with)]
#![recursion_limit = "256"]
#[macro_use]

View file

@ -1,8 +1,8 @@
#![feature(associated_type_bounds)]
#![feature(type_alias_impl_trait)]
#![feature(untagged_unions)]
use std::iter;
use std::mem::ManuallyDrop;
struct SI1<T: Iterator<Item: Copy, Item: Send>> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
@ -74,36 +74,36 @@ where
union UI1<T: Iterator<Item: Copy, Item: Send>> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
f: T,
f: ManuallyDrop<T>,
}
union UI2<T: Iterator<Item: Copy, Item: Copy>> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
f: T,
f: ManuallyDrop<T>,
}
union UI3<T: Iterator<Item: 'static, Item: 'static>> {
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
f: T,
f: ManuallyDrop<T>,
}
union UW1<T>
where
T: Iterator<Item: Copy, Item: Send>,
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
{
f: T,
f: ManuallyDrop<T>,
}
union UW2<T>
where
T: Iterator<Item: Copy, Item: Copy>,
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
{
f: T,
f: ManuallyDrop<T>,
}
union UW3<T>
where
T: Iterator<Item: 'static, Item: 'static>,
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
{
f: T,
f: ManuallyDrop<T>,
}
fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}

View file

@ -1,5 +1,6 @@
#![feature(associated_type_bounds)]
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
struct S1 { f: dyn Iterator<Item: Copy> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
@ -17,12 +18,12 @@ enum E3 { V(dyn Iterator<Item: 'static>) }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
union U1 { f: dyn Iterator<Item: Copy> }
union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
union U2 { f: Box<dyn Iterator<Item: Copy>> }
union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
union U3 { f: dyn Iterator<Item: 'static> }
union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`

View file

@ -1,59 +1,59 @@
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:4:29
--> $DIR/inside-adt.rs:5:29
|
LL | struct S1 { f: dyn Iterator<Item: Copy> }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:6:33
--> $DIR/inside-adt.rs:7:33
|
LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:8:29
--> $DIR/inside-adt.rs:9:29
|
LL | struct S3 { f: dyn Iterator<Item: 'static> }
| ^^^^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:11:26
--> $DIR/inside-adt.rs:12:26
|
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:14:30
--> $DIR/inside-adt.rs:15:30
|
LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:16:26
--> $DIR/inside-adt.rs:17:26
|
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
| ^^^^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:20:28
--> $DIR/inside-adt.rs:21:41
|
LL | union U1 { f: dyn Iterator<Item: Copy> }
| ^^^^^^^^^^
LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:23:32
--> $DIR/inside-adt.rs:24:45
|
LL | union U2 { f: Box<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^
LL | union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
| ^^^^^^^^^^
error: associated type bounds are not allowed within structs, enums, or unions
--> $DIR/inside-adt.rs:25:28
--> $DIR/inside-adt.rs:26:41
|
LL | union U3 { f: dyn Iterator<Item: 'static> }
| ^^^^^^^^^^^^^
LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
| ^^^^^^^^^^^^^
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
--> $DIR/inside-adt.rs:11:13
--> $DIR/inside-adt.rs:12:13
|
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -71,7 +71,7 @@ LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
| ++++ +
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
--> $DIR/inside-adt.rs:16:13
--> $DIR/inside-adt.rs:17:13
|
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -89,40 +89,42 @@ LL | enum E3 { V(Box<dyn Iterator<Item: 'static>>) }
| ++++ +
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
--> $DIR/inside-adt.rs:20:15
--> $DIR/inside-adt.rs:21:15
|
LL | union U1 { f: dyn Iterator<Item: Copy> }
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
= note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`
= 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 | union U1 { f: &dyn Iterator<Item: Copy> }
LL | union U1 { f: &ManuallyDrop<dyn Iterator<Item: Copy>> }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | union U1 { f: Box<dyn Iterator<Item: Copy>> }
| ++++ +
LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
| ++++ +
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
--> $DIR/inside-adt.rs:25:15
--> $DIR/inside-adt.rs:26:15
|
LL | union U3 { f: dyn Iterator<Item: 'static> }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
= note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`
= 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 | union U3 { f: &dyn Iterator<Item: 'static> }
LL | union U3 { f: &ManuallyDrop<dyn Iterator<Item: 'static>> }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | union U3 { f: Box<dyn Iterator<Item: 'static>> }
| ++++ +
LL | union U3 { f: Box<ManuallyDrop<dyn Iterator<Item: 'static>>> }
| ++++ +
error: aborting due to 13 previous errors

View file

@ -1,7 +1,6 @@
// run-pass
#![feature(associated_type_bounds)]
#![feature(untagged_unions)]
#![allow(unused_assignments)]

View file

@ -3,9 +3,9 @@
// captures the behavior of how `_` bindings are handled with respect to how we
// flag expressions that are meant to request unsafe blocks.
#![feature(untagged_unions)]
#[derive(Copy, Clone)]
struct I(i64);
#[derive(Copy, Clone)]
struct F(f64);
union U { a: I, b: F }

View file

@ -1,31 +1,31 @@
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
// Non-copy
struct A;
struct B;
union U {
a: A,
b: B,
a: ManuallyDrop<A>,
b: ManuallyDrop<B>,
}
fn main() {
unsafe {
{
let mut u = U { a: A };
let mut u = U { a: ManuallyDrop::new(A) };
let a = u.a;
let a = u.a; //~ ERROR use of moved value: `u`
}
{
let mut u = U { a: A };
let mut u = U { a: ManuallyDrop::new(A) };
let a = u.a;
u.a = A;
u.a = ManuallyDrop::new(A);
let a = u.a; // OK
}
{
let mut u = U { a: A };
let mut u = U { a: ManuallyDrop::new(A) };
let a = u.a;
u.b = B;
u.b = ManuallyDrop::new(B);
let a = u.a; // OK
}
}

View file

@ -1,7 +1,7 @@
error[E0382]: use of moved value: `u`
--> $DIR/borrowck-union-move-assign.rs:17:21
|
LL | let mut u = U { a: A };
LL | let mut u = U { a: ManuallyDrop::new(A) };
| ----- move occurs because `u` has type `U`, which does not implement the `Copy` trait
LL | let a = u.a;
| --- value moved here

View file

@ -1,12 +1,12 @@
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
#[derive(Clone, Copy)]
struct Copy;
struct NonCopy;
union Unn {
n1: NonCopy,
n2: NonCopy,
n1: ManuallyDrop<NonCopy>,
n2: ManuallyDrop<NonCopy>,
}
union Ucc {
c1: Copy,
@ -14,24 +14,24 @@ union Ucc {
}
union Ucn {
c: Copy,
n: NonCopy,
n: ManuallyDrop<NonCopy>,
}
fn main() {
unsafe {
// 2 NonCopy
{
let mut u = Unn { n1: NonCopy };
let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
let a = u.n1;
let a = u.n1; //~ ERROR use of moved value: `u`
}
{
let mut u = Unn { n1: NonCopy };
let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
let a = u.n1;
let a = u; //~ ERROR use of moved value: `u`
}
{
let mut u = Unn { n1: NonCopy };
let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
let a = u.n1;
let a = u.n2; //~ ERROR use of moved value: `u`
}

View file

@ -1,7 +1,7 @@
error[E0382]: use of moved value: `u`
--> $DIR/borrowck-union-move.rs:26:21
|
LL | let mut u = Unn { n1: NonCopy };
LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
| ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
LL | let a = u.n1;
| ---- value moved here
@ -11,7 +11,7 @@ LL | let a = u.n1;
error[E0382]: use of moved value: `u`
--> $DIR/borrowck-union-move.rs:31:21
|
LL | let mut u = Unn { n1: NonCopy };
LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
| ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
LL | let a = u.n1;
| ---- value moved here
@ -21,7 +21,7 @@ LL | let a = u;
error[E0382]: use of moved value: `u`
--> $DIR/borrowck-union-move.rs:36:21
|
LL | let mut u = Unn { n1: NonCopy };
LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) };
| ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait
LL | let a = u.n1;
| ---- value moved here

View file

@ -1,8 +1,6 @@
// Moving from a reference/raw pointer should be an error, even when they're
// the field of a union.
#![feature(untagged_unions)]
union Pointers {
a: &'static String,
b: &'static mut String,

View file

@ -1,23 +1,23 @@
error[E0507]: cannot move out of `*u.a` which is behind a shared reference
--> $DIR/move-from-union-field-issue-66500.rs:14:5
--> $DIR/move-from-union-field-issue-66500.rs:12:5
|
LL | *u.a
| ^^^^ move occurs because `*u.a` has type `String`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `*u.b` which is behind a mutable reference
--> $DIR/move-from-union-field-issue-66500.rs:18:5
--> $DIR/move-from-union-field-issue-66500.rs:16:5
|
LL | *u.b
| ^^^^ move occurs because `*u.b` has type `String`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `*u.c` which is behind a raw pointer
--> $DIR/move-from-union-field-issue-66500.rs:22:5
--> $DIR/move-from-union-field-issue-66500.rs:20:5
|
LL | *u.c
| ^^^^ move occurs because `*u.c` has type `String`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
--> $DIR/move-from-union-field-issue-66500.rs:26:5
--> $DIR/move-from-union-field-issue-66500.rs:24:5
|
LL | *u.d
| ^^^^ move occurs because `*u.d` has type `String`, which does not implement the `Copy` trait

View file

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/invalid-union.rs:40:1
--> $DIR/invalid-union.rs:41:1
|
LL | fn main() {
| ^^^^^^^^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const`
@ -10,7 +10,7 @@ LL | fn main() {
}
error: erroneous constant used
--> $DIR/invalid-union.rs:41:25
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors
@ -24,7 +24,7 @@ error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: erroneous constant used
--> $DIR/invalid-union.rs:41:25
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors

View file

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/invalid-union.rs:40:1
--> $DIR/invalid-union.rs:41:1
|
LL | fn main() {
| ^^^^^^^^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const`
@ -10,7 +10,7 @@ LL | fn main() {
}
error: erroneous constant used
--> $DIR/invalid-union.rs:41:25
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors
@ -24,7 +24,7 @@ error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: erroneous constant used
--> $DIR/invalid-union.rs:41:25
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors

View file

@ -9,8 +9,9 @@
// build-fail
// stderr-per-bitwidth
#![feature(const_mut_refs)]
#![feature(untagged_unions)]
use std::cell::Cell;
use std::mem::ManuallyDrop;
#[repr(C)]
struct S {
@ -25,7 +26,7 @@ enum E {
}
union U {
cell: Cell<u32>,
cell: ManuallyDrop<Cell<u32>>,
}
const C: S = {

View file

@ -1,18 +1,19 @@
// Checks that unions use type based qualification. Regression test for issue #90268.
#![feature(untagged_unions)]
use std::cell::Cell;
use std::mem::ManuallyDrop;
union U { i: u32, c: Cell<u32> }
union U { i: u32, c: ManuallyDrop<Cell<u32>> }
const C1: Cell<u32> = {
unsafe { U { c: Cell::new(0) }.c }
const C1: ManuallyDrop<Cell<u32>> = {
unsafe { U { c: ManuallyDrop::new(Cell::new(0)) }.c }
};
const C2: Cell<u32> = {
const C2: ManuallyDrop<Cell<u32>> = {
unsafe { U { i : 0 }.c }
};
const C3: Cell<u32> = {
const C3: ManuallyDrop<Cell<u32>> = {
let mut u = U { i: 0 };
u.i = 1;
unsafe { u.c }

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/qualif-union.rs:27:26
--> $DIR/qualif-union.rs:28:26
|
LL | let _: &'static _ = &C1;
| ---------- ^^ creates a temporary which is freed while still in use
@ -10,7 +10,7 @@ LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
--> $DIR/qualif-union.rs:28:26
--> $DIR/qualif-union.rs:29:26
|
LL | let _: &'static _ = &C2;
| ---------- ^^ creates a temporary which is freed while still in use
@ -21,7 +21,7 @@ LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
--> $DIR/qualif-union.rs:29:26
--> $DIR/qualif-union.rs:30:26
|
LL | let _: &'static _ = &C3;
| ---------- ^^ creates a temporary which is freed while still in use
@ -32,7 +32,7 @@ LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
--> $DIR/qualif-union.rs:30:26
--> $DIR/qualif-union.rs:31:26
|
LL | let _: &'static _ = &C4;
| ---------- ^^ creates a temporary which is freed while still in use
@ -43,7 +43,7 @@ LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
--> $DIR/qualif-union.rs:31:26
--> $DIR/qualif-union.rs:32:26
|
LL | let _: &'static _ = &C5;
| ---------- ^^ creates a temporary which is freed while still in use

View file

@ -1,7 +1,7 @@
// compile-flags: -Zsave-analysis
// This is also a regression test for #69415 and the above flag is needed.
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
trait Tr1 { type As1: Copy; }
trait Tr2 { type As2: Copy; }
@ -36,9 +36,9 @@ enum _En1<T: Tr1<As1: Tr2>> {
union _Un1<T: Tr1<As1: Tr2>> {
//~^ ERROR associated type bounds are unstable
outest: std::mem::ManuallyDrop<T>,
outer: T::As1,
inner: <T::As1 as Tr2>::As2,
outest: ManuallyDrop<T>,
outer: ManuallyDrop<T::As1>,
inner: ManuallyDrop<<T::As1 as Tr2>::As2>,
}
type _TaWhere1<T> where T: Iterator<Item: Copy> = T;

View file

@ -1,35 +0,0 @@
// ignore-tidy-linelength
union U1 { // OK
a: u8,
}
union U2<T: Copy> { // OK
a: T,
}
union U22<T> { // OK
a: std::mem::ManuallyDrop<T>,
}
union U3 {
a: String, //~ ERROR unions cannot contain fields that may need dropping
}
union U32 { // field that does not drop but is not `Copy`, either -- this is the real feature gate test!
a: std::cell::RefCell<i32>, //~ ERROR unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable
}
union U4<T> {
a: T, //~ ERROR unions cannot contain fields that may need dropping
}
union U5 { // Having a drop impl is OK
a: u8,
}
impl Drop for U5 {
fn drop(&mut self) {}
}
fn main() {}

View file

@ -1,37 +0,0 @@
error[E0658]: unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable
--> $DIR/feature-gate-untagged_unions.rs:20:5
|
LL | a: std::cell::RefCell<i32>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/feature-gate-untagged_unions.rs:16:5
|
LL | a: String,
| ^^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | a: std::mem::ManuallyDrop<String>,
| +++++++++++++++++++++++ +
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/feature-gate-untagged_unions.rs:24:5
|
LL | a: T,
| ^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | a: std::mem::ManuallyDrop<T>,
| +++++++++++++++++++++++ +
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0658, E0740.
For more information about an error, try `rustc --explain E0658`.

View file

@ -1,27 +1,27 @@
// check-pass
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
struct A;
struct B;
union U {
a: A,
b: B,
a: ManuallyDrop<A>,
b: ManuallyDrop<B>,
}
fn main() {
unsafe {
{
let mut u = U { a: A };
let mut u = U { a: ManuallyDrop::new(A) };
let a = u.a;
u.a = A;
u.a = ManuallyDrop::new(A);
let a = u.a; // OK
}
{
let mut u = U { a: A };
let mut u = U { a: ManuallyDrop::new(A) };
let a = u.a;
u.b = B;
u.b = ManuallyDrop::new(B);
let a = u.a; // OK
}
}

View file

@ -1,16 +1,19 @@
#![feature(untagged_unions)]
#![allow(dead_code)]
#[repr(align(16))]
#[derive(Clone, Copy)]
struct SA(i32);
#[derive(Clone, Copy)]
struct SB(SA);
#[repr(align(16))]
#[derive(Clone, Copy)]
union UA {
i: i32
}
#[derive(Clone, Copy)]
union UB {
a: UA
}

View file

@ -1,5 +1,5 @@
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:19:1
--> $DIR/repr-packed-contains-align.rs:22:1
|
LL | struct SC(SA);
| ^^^^^^^^^
@ -11,7 +11,7 @@ LL | struct SA(i32);
| ^^^^^^^^^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:22:1
--> $DIR/repr-packed-contains-align.rs:25:1
|
LL | struct SD(SB);
| ^^^^^^^^^
@ -22,86 +22,86 @@ note: `SA` has a `#[repr(align)]` attribute
LL | struct SA(i32);
| ^^^^^^^^^
note: `SD` contains a field of type `SB`
--> $DIR/repr-packed-contains-align.rs:22:11
--> $DIR/repr-packed-contains-align.rs:25:11
|
LL | struct SD(SB);
| ^^
note: ...which contains a field of type `SA`
--> $DIR/repr-packed-contains-align.rs:7:11
--> $DIR/repr-packed-contains-align.rs:8:11
|
LL | struct SB(SA);
| ^^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:25:1
--> $DIR/repr-packed-contains-align.rs:28:1
|
LL | struct SE(UA);
| ^^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
--> $DIR/repr-packed-contains-align.rs:12:1
|
LL | union UA {
| ^^^^^^^^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:28:1
--> $DIR/repr-packed-contains-align.rs:31:1
|
LL | struct SF(UB);
| ^^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
--> $DIR/repr-packed-contains-align.rs:12:1
|
LL | union UA {
| ^^^^^^^^
note: `SF` contains a field of type `UB`
--> $DIR/repr-packed-contains-align.rs:28:11
--> $DIR/repr-packed-contains-align.rs:31:11
|
LL | struct SF(UB);
| ^^
note: ...which contains a field of type `UA`
--> $DIR/repr-packed-contains-align.rs:15:5
--> $DIR/repr-packed-contains-align.rs:18:5
|
LL | a: UA
| ^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:31:1
--> $DIR/repr-packed-contains-align.rs:34:1
|
LL | union UC {
| ^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
--> $DIR/repr-packed-contains-align.rs:12:1
|
LL | union UA {
| ^^^^^^^^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:36:1
--> $DIR/repr-packed-contains-align.rs:39:1
|
LL | union UD {
| ^^^^^^^^
|
note: `UA` has a `#[repr(align)]` attribute
--> $DIR/repr-packed-contains-align.rs:10:1
--> $DIR/repr-packed-contains-align.rs:12:1
|
LL | union UA {
| ^^^^^^^^
note: `UD` contains a field of type `UB`
--> $DIR/repr-packed-contains-align.rs:37:5
--> $DIR/repr-packed-contains-align.rs:40:5
|
LL | n: UB
| ^
note: ...which contains a field of type `UA`
--> $DIR/repr-packed-contains-align.rs:15:5
--> $DIR/repr-packed-contains-align.rs:18:5
|
LL | a: UA
| ^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:41:1
--> $DIR/repr-packed-contains-align.rs:44:1
|
LL | union UE {
| ^^^^^^^^
@ -113,7 +113,7 @@ LL | struct SA(i32);
| ^^^^^^^^^
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> $DIR/repr-packed-contains-align.rs:46:1
--> $DIR/repr-packed-contains-align.rs:49:1
|
LL | union UF {
| ^^^^^^^^
@ -124,12 +124,12 @@ note: `SA` has a `#[repr(align)]` attribute
LL | struct SA(i32);
| ^^^^^^^^^
note: `UF` contains a field of type `SB`
--> $DIR/repr-packed-contains-align.rs:47:5
--> $DIR/repr-packed-contains-align.rs:50:5
|
LL | n: SB
| ^
note: ...which contains a field of type `SA`
--> $DIR/repr-packed-contains-align.rs:7:11
--> $DIR/repr-packed-contains-align.rs:8:11
|
LL | struct SB(SA);
| ^^

View file

@ -1,11 +1,11 @@
#![feature(rustc_attrs)]
#![feature(untagged_unions)]
#[rustc_outlives]
union Foo<'b, U: Copy> { //~ ERROR rustc_outlives
bar: Bar<'b, U>
}
#[derive(Clone, Copy)]
union Bar<'a, T: Copy> where T: 'a {
x: &'a (),
y: T,

View file

@ -1,5 +1,5 @@
error: rustc_outlives
--> $DIR/explicit-union.rs:5:1
--> $DIR/explicit-union.rs:4:1
|
LL | union Foo<'b, U: Copy> {
| ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,4 @@
#![feature(rustc_attrs)]
#![feature(untagged_unions)]
#[rustc_outlives]
union Foo<'a, T: Copy> { //~ ERROR rustc_outlives
@ -7,6 +6,7 @@ union Foo<'a, T: Copy> { //~ ERROR rustc_outlives
}
// Type U needs to outlive lifetime 'b
#[derive(Clone, Copy)]
union Bar<'b, U: Copy> {
field2: &'b U
}

View file

@ -1,5 +1,5 @@
error: rustc_outlives
--> $DIR/nested-union.rs:5:1
--> $DIR/nested-union.rs:4:1
|
LL | union Foo<'a, T: Copy> {
| ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,65 @@
use std::mem::ManuallyDrop;
union U1 { // OK
a: u8,
}
union U2<T: Copy> { // OK
a: T,
}
union U22<T> { // OK
a: ManuallyDrop<T>,
}
union U23<T> { // OK
a: (ManuallyDrop<T>, i32),
}
union U24<T> { // OK
a: [ManuallyDrop<T>; 2],
}
union U3 {
a: String, //~ ERROR unions cannot contain fields that may need dropping
}
union U32 { // field that does not drop but is not `Copy`, either
a: std::cell::RefCell<i32>, //~ ERROR unions cannot contain fields that may need dropping
}
union U4<T> {
a: T, //~ ERROR unions cannot contain fields that may need dropping
}
union U5 { // Having a drop impl is OK
a: u8,
}
impl Drop for U5 {
fn drop(&mut self) {}
}
union U5Nested { // a nested union that drops is NOT OK
nest: U5, //~ ERROR unions cannot contain fields that may need dropping
}
union U5Nested2 { // for now we don't special-case empty arrays
nest: [U5; 0], //~ ERROR unions cannot contain fields that may need dropping
}
union U6 { // OK
s: &'static i32,
m: &'static mut i32,
}
union U7<T> { // OK
f: (&'static mut i32, ManuallyDrop<T>, i32),
}
union U8<T> { // OK
f1: [(&'static mut i32, i32); 8],
f2: [ManuallyDrop<T>; 2],
}
fn main() {}

View file

@ -0,0 +1,63 @@
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/field_checks.rs:24:5
|
LL | a: String,
| ^^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | a: std::mem::ManuallyDrop<String>,
| +++++++++++++++++++++++ +
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/field_checks.rs:28:5
|
LL | a: std::cell::RefCell<i32>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | a: std::mem::ManuallyDrop<std::cell::RefCell<i32>>,
| +++++++++++++++++++++++ +
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/field_checks.rs:32:5
|
LL | a: T,
| ^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | a: std::mem::ManuallyDrop<T>,
| +++++++++++++++++++++++ +
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/field_checks.rs:44:5
|
LL | nest: U5,
| ^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | nest: std::mem::ManuallyDrop<U5>,
| +++++++++++++++++++++++ +
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/field_checks.rs:48:5
|
LL | nest: [U5; 0],
| ^^^^^^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | nest: std::mem::ManuallyDrop<[U5; 0]>,
| +++++++++++++++++++++++ +
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0740`.

View file

@ -1,5 +1,3 @@
#![feature(untagged_unions)]
union Test {
a: A, //~ ERROR unions cannot contain fields that may need dropping
b: B

View file

@ -1,5 +1,5 @@
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/issue-41073.rs:4:5
--> $DIR/issue-41073.rs:2:5
|
LL | a: A,
| ^^^^

View file

@ -1,49 +1,69 @@
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`)
--> $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 a = &mut (*u.x).0;
| --- mutable borrow occurs here (via `u.x`)
LL | let b = &u.y;
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- 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`
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x`
error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, MockVec<u8>), MockVec<u8>)>`
--> $DIR/union-borrow-move-parent-sibling.rs:62:13
|
LL | let a = u.x.0;
| ^^^^^
| |
| move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
| help: consider borrowing here: `&u.x.0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:63:13
--> $DIR/union-borrow-move-parent-sibling.rs:64:13
|
LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
LL | let u = U { x: ManuallyDrop::new(((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 a = u.x;
| --- 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
error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`)
--> $DIR/union-borrow-move-parent-sibling.rs:70:13
|
LL | let a = &mut (u.x.0).0;
| -------------- mutable borrow occurs here (via `u.x.0.0`)
LL | let a = &mut ((*u.x).0).0;
| --- mutable borrow occurs here (via `u.x`)
LL | let b = &u.y;
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- 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`
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x`
error[E0382]: use of moved value: `u`
error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, MockVec<u8>), MockVec<u8>)>`
--> $DIR/union-borrow-move-parent-sibling.rs:76:13
|
LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
LL | let a = (u.x.0).0;
| ^^^^^^^^^
| |
| move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
| help: consider borrowing here: `&(u.x.0).0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:78:13
|
LL | let u = U { x: ManuallyDrop::new(((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 a = u.x;
| --- 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
--> $DIR/union-borrow-move-parent-sibling.rs:84:13
|
LL | let a = &mut *u.y;
| --- mutable borrow occurs here (via `u.y`)
@ -54,7 +74,7 @@ LL | use_borrow(a);
|
= note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
error: aborting due to 5 previous errors
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0382, E0502.
Some errors have detailed explanations: E0382, E0502, E0507.
For more information about an error, try `rustc --explain E0382`.

View file

@ -1,10 +1,10 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
#![allow(unused)]
use std::ops::{Deref, DerefMut};
use std::mem::ManuallyDrop;
#[derive(Default)]
struct MockBox<T> {
@ -44,47 +44,49 @@ impl<T> DerefMut for MockVec<T> {
union U {
x: ((MockVec<u8>, MockVec<u8>), MockVec<u8>),
y: MockBox<MockVec<u8>>,
x: ManuallyDrop<((MockVec<u8>, MockVec<u8>), MockVec<u8>)>,
y: ManuallyDrop<MockBox<MockVec<u8>>>,
}
fn use_borrow<T>(_: &T) {}
unsafe fn parent_sibling_borrow() {
let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
let a = &mut u.x.0;
let mut u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) };
let a = &mut (*u.x).0;
let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`)
use_borrow(a);
}
unsafe fn parent_sibling_move() {
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
let a = u.x.0;
let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) };
let a = u.x.0; //~ERROR cannot move out of dereference
let a = u.x;
let b = u.y; //~ ERROR use of moved value: `u`
}
unsafe fn grandparent_sibling_borrow() {
let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
let a = &mut (u.x.0).0;
let mut u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) };
let a = &mut ((*u.x).0).0;
let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`)
use_borrow(a);
}
unsafe fn grandparent_sibling_move() {
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
let a = (u.x.0).0;
let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) };
let a = (u.x.0).0; //~ERROR cannot move out of dereference
let a = u.x;
let b = u.y; //~ ERROR use of moved value: `u`
}
unsafe fn deref_sibling_borrow() {
let mut u = U { y: MockBox::default() };
let mut u = U { y: ManuallyDrop::new(MockBox::default()) };
let a = &mut *u.y;
let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
use_borrow(a);
}
unsafe fn deref_sibling_move() {
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) };
// No way to test deref-move without Box in union
// let a = *u.y;
// let b = u.x; ERROR use of moved value: `u`

View file

@ -1,49 +1,69 @@
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`)
--> $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 a = &mut (*u.x).0;
| --- mutable borrow occurs here (via `u.x`)
LL | let b = &u.y;
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- 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`
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x`
error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, MockVec<u8>), MockVec<u8>)>`
--> $DIR/union-borrow-move-parent-sibling.rs:62:13
|
LL | let a = u.x.0;
| ^^^^^
| |
| move occurs because value has type `(MockVec<u8>, MockVec<u8>)`, which does not implement the `Copy` trait
| help: consider borrowing here: `&u.x.0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:63:13
--> $DIR/union-borrow-move-parent-sibling.rs:64:13
|
LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
LL | let u = U { x: ManuallyDrop::new(((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 a = u.x;
| --- 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
error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`)
--> $DIR/union-borrow-move-parent-sibling.rs:70:13
|
LL | let a = &mut (u.x.0).0;
| -------------- mutable borrow occurs here (via `u.x.0.0`)
LL | let a = &mut ((*u.x).0).0;
| --- mutable borrow occurs here (via `u.x`)
LL | let b = &u.y;
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- 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`
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x`
error[E0382]: use of moved value: `u`
error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, MockVec<u8>), MockVec<u8>)>`
--> $DIR/union-borrow-move-parent-sibling.rs:76:13
|
LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
LL | let a = (u.x.0).0;
| ^^^^^^^^^
| |
| move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
| help: consider borrowing here: `&(u.x.0).0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:78:13
|
LL | let u = U { x: ManuallyDrop::new(((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 a = u.x;
| --- 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
--> $DIR/union-borrow-move-parent-sibling.rs:84:13
|
LL | let a = &mut *u.y;
| --- mutable borrow occurs here (via `u.y`)
@ -54,7 +74,7 @@ LL | use_borrow(a);
|
= note: `u.x` is a field of the union `U`, so it overlaps the field `u.y`
error: aborting due to 5 previous errors
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0382, E0502.
Some errors have detailed explanations: E0382, E0502, E0507.
For more information about an error, try `rustc --explain E0382`.

View file

@ -1,19 +0,0 @@
// test for a union with a field that's a union with a manual impl Drop
// Ensures we do not treat all unions as not having any drop glue.
#![feature(untagged_unions)]
union Foo {
bar: Bar, //~ ERROR unions cannot contain fields that may need dropping
}
union Bar {
a: i32,
b: u32,
}
impl Drop for Bar {
fn drop(&mut self) {}
}
fn main() {}

View file

@ -1,15 +0,0 @@
error[E0740]: unions cannot contain fields that may need dropping
--> $DIR/union-custom-drop.rs:7:5
|
LL | bar: Bar,
| ^^^^^^^^
|
= note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type
help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped
|
LL | bar: std::mem::ManuallyDrop<Bar>,
| +++++++++++++++++++++++ +
error: aborting due to previous error
For more information about this error, try `rustc --explain E0740`.

View file

@ -1,5 +1,5 @@
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
--> $DIR/union-deref.rs:17:14
--> $DIR/union-deref.rs:16: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:19:19
--> $DIR/union-deref.rs:18: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:21:14
--> $DIR/union-deref.rs:20: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:25:14
--> $DIR/union-deref.rs:24: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:27:19
--> $DIR/union-deref.rs:26: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:29:14
--> $DIR/union-deref.rs:28:14
|
LL | unsafe { u.f.0.0.push(0) };
| ^^^^^

View file

@ -3,7 +3,6 @@
//! Test the part of RFC 2514 that is about not applying `DerefMut` coercions
//! of union fields.
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;

View file

@ -1,5 +1,5 @@
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
--> $DIR/union-deref.rs:17:14
--> $DIR/union-deref.rs:16: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:19:19
--> $DIR/union-deref.rs:18: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:21:14
--> $DIR/union-deref.rs:20: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:25:14
--> $DIR/union-deref.rs:24: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:27:19
--> $DIR/union-deref.rs:26: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:29:14
--> $DIR/union-deref.rs:28:14
|
LL | unsafe { u.f.0.0.push(0) };
| ^^^^^

View file

@ -27,7 +27,7 @@ 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
| move occurs because `x.f1_nocopy` has type `ManuallyDrop<RefCell<i32>>`, which does not implement the `Copy` trait
error: aborting due to 3 previous errors

View file

@ -3,20 +3,20 @@
//! Test the behavior of moving out of non-`Copy` union fields.
//! Avoid types that `Drop`, we want to focus on moving.
#![feature(untagged_unions)]
use std::cell::RefCell;
use std::mem::ManuallyDrop;
fn move_out<T>(x: T) {}
union U1 {
f1_nocopy: RefCell<i32>,
f2_nocopy: RefCell<i32>,
f1_nocopy: ManuallyDrop<RefCell<i32>>,
f2_nocopy: ManuallyDrop<RefCell<i32>>,
f3_copy: i32,
}
union U2 {
f1_nocopy: RefCell<i32>,
f1_nocopy: ManuallyDrop<RefCell<i32>>,
}
impl Drop for U2 {
fn drop(&mut self) {}

View file

@ -27,7 +27,7 @@ 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
| move occurs because `x.f1_nocopy` has type `ManuallyDrop<RefCell<i32>>`, which does not implement the `Copy` trait
error: aborting due to 3 previous errors

View file

@ -1,8 +1,6 @@
#![feature(untagged_unions)]
union U { //~ ERROR recursive type `U` has infinite size
a: u8,
b: U,
b: std::mem::ManuallyDrop<U>,
}
fn main() {}

View file

@ -1,16 +1,16 @@
error[E0072]: recursive type `U` has infinite size
--> $DIR/union-nonrepresentable.rs:3:1
--> $DIR/union-nonrepresentable.rs:1:1
|
LL | union U {
| ^^^^^^^ recursive type has infinite size
LL | a: u8,
LL | b: U,
| - recursive without indirection
LL | b: std::mem::ManuallyDrop<U>,
| ------------------------- recursive without indirection
|
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable
|
LL | b: Box<U>,
| ++++ +
LL | b: Box<std::mem::ManuallyDrop<U>>,
| ++++ +
error: aborting due to previous error

View file

@ -1,18 +1,18 @@
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
union Foo<T: ?Sized> {
value: T,
value: ManuallyDrop<T>,
//~^ ERROR the size for values of type
}
struct Foo2<T: ?Sized> {
value: T,
value: ManuallyDrop<T>,
//~^ ERROR the size for values of type
t: u32,
}
enum Foo3<T: ?Sized> {
Value(T),
Value(ManuallyDrop<T>),
//~^ ERROR the size for values of type
}

View file

@ -3,9 +3,10 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
|
LL | union Foo<T: ?Sized> {
| - this type parameter needs to be `std::marker::Sized`
LL | value: T,
| ^ doesn't have a size known at compile-time
LL | value: ManuallyDrop<T>,
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: required because it appears within the type `ManuallyDrop<T>`
= 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: consider removing the `?Sized` bound to make the type parameter `Sized`
@ -15,21 +16,22 @@ LL + union Foo<T> {
|
help: borrowed types always have a statically known size
|
LL | value: &T,
LL | value: &ManuallyDrop<T>,
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | value: Box<T>,
| ++++ +
LL | value: Box<ManuallyDrop<T>>,
| ++++ +
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/union-sized-field.rs:9:12
|
LL | struct Foo2<T: ?Sized> {
| - this type parameter needs to be `std::marker::Sized`
LL | value: T,
| ^ doesn't have a size known at compile-time
LL | value: ManuallyDrop<T>,
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: required because it appears within the type `ManuallyDrop<T>`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: consider removing the `?Sized` bound to make the type parameter `Sized`
@ -39,21 +41,22 @@ LL + struct Foo2<T> {
|
help: borrowed types always have a statically known size
|
LL | value: &T,
LL | value: &ManuallyDrop<T>,
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | value: Box<T>,
| ++++ +
LL | value: Box<ManuallyDrop<T>>,
| ++++ +
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/union-sized-field.rs:15:11
|
LL | enum Foo3<T: ?Sized> {
| - this type parameter needs to be `std::marker::Sized`
LL | Value(T),
| ^ doesn't have a size known at compile-time
LL | Value(ManuallyDrop<T>),
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: required because it appears within the type `ManuallyDrop<T>`
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: consider removing the `?Sized` bound to make the type parameter `Sized`
@ -63,12 +66,12 @@ LL + enum Foo3<T> {
|
help: borrowed types always have a statically known size
|
LL | Value(&T),
LL | Value(&ManuallyDrop<T>),
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | Value(Box<T>),
| ++++ +
LL | Value(Box<ManuallyDrop<T>>),
| ++++ +
error: aborting due to 3 previous errors

View file

@ -1,29 +1,13 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:34:5
--> $DIR/union-unsafe.rs:33:5
|
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]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:39:5
|
LL | u.a = (RefCell::new(0), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= 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:40:5
|
LL | u.a.0 = RefCell::new(0);
| ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= 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:47:6
--> $DIR/union-unsafe.rs:46:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
@ -31,7 +15,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:53:6
--> $DIR/union-unsafe.rs:52:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
@ -39,7 +23,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:61:13
--> $DIR/union-unsafe.rs:60:13
|
LL | let a = u1.a;
| ^^^^ access to union field
@ -47,7 +31,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:64:14
--> $DIR/union-unsafe.rs:63:14
|
LL | let U1 { a } = u1;
| ^ access to union field
@ -55,7 +39,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:65:12
--> $DIR/union-unsafe.rs:64:12
|
LL | if let U1 { a: 12 } = u1 {}
| ^^^^^^^^^^^^ access to union field
@ -63,7 +47,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:70:6
--> $DIR/union-unsafe.rs:69:6
|
LL | *u2.a = String::from("new");
| ^^^^ access to union field
@ -71,7 +55,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:74:6
--> $DIR/union-unsafe.rs:73:6
|
LL | *u3.a = 1;
| ^^^^ access to union field
@ -79,13 +63,13 @@ 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:78:6
--> $DIR/union-unsafe.rs:77: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 11 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0133`.

View file

@ -1,7 +1,6 @@
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
use std::mem::ManuallyDrop;
use std::cell::RefCell;
@ -26,7 +25,7 @@ union URef {
}
union URefCell { // field that does not drop but is not `Copy`, either
a: (RefCell<i32>, i32),
a: (ManuallyDrop<RefCell<i32>>, i32),
}
fn deref_union_field(mut u: URef) {
@ -36,8 +35,8 @@ fn deref_union_field(mut u: URef) {
fn assign_noncopy_union_field(mut u: URefCell) {
// FIXME(thir-unsafeck)
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
u.a = (ManuallyDrop::new(RefCell::new(0)), 1); // OK (assignment does not drop)
u.a.0 = ManuallyDrop::new(RefCell::new(0)); // OK (assignment does not drop)
u.a.1 = 1; // OK
}

View file

@ -1,29 +1,13 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:34:6
--> $DIR/union-unsafe.rs:33: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]: assignment to union field that might need dropping is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:39:5
|
LL | u.a = (RefCell::new(0), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= 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:40:5
|
LL | u.a.0 = RefCell::new(0);
| ^^^^^^^^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= 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:47:6
--> $DIR/union-unsafe.rs:46:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
@ -31,7 +15,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:53:6
--> $DIR/union-unsafe.rs:52:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
@ -39,7 +23,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:61:13
--> $DIR/union-unsafe.rs:60:13
|
LL | let a = u1.a;
| ^^^^ access to union field
@ -47,7 +31,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:64:14
--> $DIR/union-unsafe.rs:63:14
|
LL | let U1 { a } = u1;
| ^ access to union field
@ -55,7 +39,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:65:8
--> $DIR/union-unsafe.rs:64:8
|
LL | if let U1 { a: 12 } = u1 {}
| ^^^^^^^^^^^^^^^^^^^^^ access to union field
@ -63,7 +47,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:70:6
--> $DIR/union-unsafe.rs:69:6
|
LL | *u2.a = String::from("new");
| ^^^^ access to union field
@ -71,7 +55,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:74:6
--> $DIR/union-unsafe.rs:73:6
|
LL | *u3.a = 1;
| ^^^^ access to union field
@ -79,13 +63,13 @@ 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:78:6
--> $DIR/union-unsafe.rs:77: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 11 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0133`.

View file

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/union-unsized.rs:7:8
--> $DIR/union-unsized.rs:5: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:15:8
--> $DIR/union-unsized.rs:13:8
|
LL | b: str,
| ^^^ doesn't have a size known at compile-time

View file

@ -1,8 +1,6 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
union U {
a: str,
//~^ ERROR the size for values of type

View file

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/union-unsized.rs:7:8
--> $DIR/union-unsized.rs:5: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:15:8
--> $DIR/union-unsized.rs:13:8
|
LL | b: str,
| ^^^ doesn't have a size known at compile-time

View file

@ -1,5 +1,5 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-assignop.rs:20:5
--> $DIR/union-assignop.rs:19:5
|
LL | foo.a += 5;
| ^^^^^^^^^^ access to union field
@ -7,20 +7,20 @@ LL | foo.a += 5;
= 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-assignop.rs:21:5
--> $DIR/union-assignop.rs:20:6
|
LL | foo.b += Dropping;
| ^^^^^ access to union field
LL | *foo.b += NonCopy;
| ^^^^^ access to union field
|
= 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-assignop.rs:22:5
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-assignop.rs:21:6
|
LL | foo.b = Dropping;
| ^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
LL | *foo.b = NonCopy;
| ^^^^^ access to union field
|
= note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
= 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-assignop.rs:23:5
@ -46,14 +46,6 @@ LL | foo.b = foo.b;
|
= 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-assignop.rs:27:5
|
LL | foo.b = foo.b;
| ^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
error: aborting due to 7 previous errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0133`.

View file

@ -1,30 +1,29 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
use std::ops::AddAssign;
use std::mem::ManuallyDrop;
struct Dropping;
impl AddAssign for Dropping {
struct NonCopy;
impl AddAssign for NonCopy {
fn add_assign(&mut self, _: Self) {}
}
union Foo {
a: u8, // non-dropping
b: Dropping, // treated as dropping
b: ManuallyDrop<NonCopy>,
}
fn main() {
let mut foo = Foo { a: 42 };
foo.a += 5; //~ ERROR access to union field is unsafe
foo.b += Dropping; //~ ERROR access to union field is unsafe
foo.b = Dropping; //~ ERROR assignment to union field that might need dropping is unsafe
*foo.b += NonCopy; //~ ERROR access to union field is unsafe
*foo.b = NonCopy; //~ ERROR access to union field is unsafe
foo.b = ManuallyDrop::new(NonCopy);
foo.a; //~ ERROR access to union field is unsafe
let foo = Foo { a: 42 };
foo.b; //~ ERROR access to union field is unsafe
let mut foo = Foo { a: 42 };
foo.b = foo.b;
//~^ ERROR access to union field is unsafe
//~| ERROR assignment to union field that might need dropping
}

View file

@ -1,5 +1,5 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-assignop.rs:20:5
--> $DIR/union-assignop.rs:19:5
|
LL | foo.a += 5;
| ^^^^^ access to union field
@ -7,20 +7,20 @@ LL | foo.a += 5;
= 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-assignop.rs:21:5
--> $DIR/union-assignop.rs:20:6
|
LL | foo.b += Dropping;
| ^^^^^ access to union field
LL | *foo.b += NonCopy;
| ^^^^^ access to union field
|
= 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-assignop.rs:22:5
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-assignop.rs:21:6
|
LL | foo.b = Dropping;
| ^^^^^^^^^^^^^^^^ assignment to union field that might need dropping
LL | *foo.b = NonCopy;
| ^^^^^ access to union field
|
= note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized
= 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-assignop.rs:23:5
@ -38,14 +38,6 @@ LL | foo.b;
|
= 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-assignop.rs:27:5
|
LL | foo.b = foo.b;
| ^^^^^^^^^^^^^ assignment to union field that might need dropping
|
= 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-assignop.rs:27:13
|
@ -54,6 +46,6 @@ LL | foo.b = foo.b;
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error: aborting due to 7 previous errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0133`.

View file

@ -2,8 +2,6 @@
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
union Foo {
bar: i8,
_blah: isize,

View file

@ -1,19 +1,19 @@
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
#![feature(untagged_unions)]
union Foo {
bar: i8,
zst: (),
pizza: Pizza,
}
#[derive(Clone, Copy)]
struct Pizza {
topping: Option<PizzaTopping>
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
enum PizzaTopping {
Cheese,
Pineapple,

View file

@ -1,7 +1,7 @@
#![feature(untagged_unions)]
#![allow(dead_code)]
#![warn(clippy::expl_impl_clone_on_copy)]
#[derive(Copy)]
struct Qux;

View file

@ -4,7 +4,7 @@
#![allow(path_statements)]
#![allow(clippy::deref_addrof)]
#![allow(clippy::redundant_field_names)]
#![feature(untagged_unions)]
struct Unit;
struct Tuple(i32);