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:
commit
cbb07c27a4
66 changed files with 507 additions and 529 deletions
|
@ -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`
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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>>() {}
|
||||
|
|
|
@ -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)`
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// run-pass
|
||||
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
| ^^
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
65
src/test/ui/union/field_checks.rs
Normal file
65
src/test/ui/union/field_checks.rs
Normal 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() {}
|
63
src/test/ui/union/field_checks.stderr
Normal file
63
src/test/ui/union/field_checks.stderr
Normal 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`.
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(untagged_unions)]
|
||||
|
||||
union Test {
|
||||
a: A, //~ ERROR unions cannot contain fields that may need dropping
|
||||
b: B
|
||||
|
|
|
@ -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,
|
||||
| ^^^^
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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) };
|
||||
| ^^^^^
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) };
|
||||
| ^^^^^
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// revisions: mir thir
|
||||
// [thir]compile-flags: -Z thir-unsafeck
|
||||
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
union Foo {
|
||||
bar: i8,
|
||||
_blah: isize,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#![feature(untagged_unions)]
|
||||
#![allow(dead_code)]
|
||||
#![warn(clippy::expl_impl_clone_on_copy)]
|
||||
|
||||
|
||||
#[derive(Copy)]
|
||||
struct Qux;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#![allow(path_statements)]
|
||||
#![allow(clippy::deref_addrof)]
|
||||
#![allow(clippy::redundant_field_names)]
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
|
||||
struct Unit;
|
||||
struct Tuple(i32);
|
||||
|
|
Loading…
Add table
Reference in a new issue