diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 117bdad971a20..1fc4d09eb0a1b 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -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` diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 54626caaf53ea..2ddaf9201098e 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -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. diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 620f0380d53b7..6a6ed3dc728d9 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -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 \ diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 8585199faaf5a..54d3b7cdda62c 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -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 \ diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 1f73b7da815c5..ded1f0462cb01 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -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( diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 12050dceb60a6..a06213ca5f442 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -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` are unstable", - ) - .emit(); - } - } - } - } - _ => (/* pass */), } intravisit::walk_item(self, item); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 79edbeab9c72e..dfcd35d2178e7 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -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 { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index dd712fd7ed71d..f98ae46c58730 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -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] diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index e1dc6f8f4b63d..6e464f69510ec 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -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> { //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] @@ -74,36 +74,36 @@ where union UI1> { //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] - f: T, + f: ManuallyDrop, } union UI2> { //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] - f: T, + f: ManuallyDrop, } union UI3> { //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] - f: T, + f: ManuallyDrop, } union UW1 where T: Iterator, //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] { - f: T, + f: ManuallyDrop, } union UW2 where T: Iterator, //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] { - f: T, + f: ManuallyDrop, } union UW3 where T: Iterator, //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] { - f: T, + f: ManuallyDrop, } fn FI1>() {} diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs index 5af057387509d..f26037f070766 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.rs +++ b/src/test/ui/associated-type-bounds/inside-adt.rs @@ -1,5 +1,6 @@ #![feature(associated_type_bounds)] -#![feature(untagged_unions)] + +use std::mem::ManuallyDrop; struct S1 { f: dyn Iterator } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions @@ -17,12 +18,12 @@ enum E3 { V(dyn Iterator) } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions //~| ERROR the size for values of type `(dyn Iterator + 'static)` -union U1 { f: dyn Iterator } +union U1 { f: ManuallyDrop> } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions //~| ERROR the size for values of type `(dyn Iterator + 'static)` -union U2 { f: Box> } +union U2 { f: ManuallyDrop>> } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions -union U3 { f: dyn Iterator } +union U3 { f: ManuallyDrop> } //~^ ERROR associated type bounds are not allowed within structs, enums, or unions //~| ERROR the size for values of type `(dyn Iterator + 'static)` diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr index 0cacd78724732..978390fa71235 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.stderr +++ b/src/test/ui/associated-type-bounds/inside-adt.stderr @@ -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 } | ^^^^^^^^^^ 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> } | ^^^^^^^^^^ 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 } | ^^^^^^^^^^^^^ 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) } | ^^^^^^^^^^ 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>) } | ^^^^^^^^^^ 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) } | ^^^^^^^^^^^^^ 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 } - | ^^^^^^^^^^ +LL | union U1 { f: ManuallyDrop> } + | ^^^^^^^^^^ 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> } - | ^^^^^^^^^^ +LL | union U2 { f: ManuallyDrop>> } + | ^^^^^^^^^^ 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 } - | ^^^^^^^^^^^^^ +LL | union U3 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^ error[E0277]: the size for values of type `(dyn Iterator + '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) } | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -71,7 +71,7 @@ LL | enum E1 { V(Box>) } | ++++ + error[E0277]: the size for values of type `(dyn Iterator + '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) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -89,40 +89,42 @@ LL | enum E3 { V(Box>) } | ++++ + error[E0277]: the size for values of type `(dyn Iterator + '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 } - | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +LL | union U1 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = help: within `ManuallyDrop<(dyn Iterator + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: required because it appears within the type `ManuallyDrop<(dyn Iterator + '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 } +LL | union U1 { f: &ManuallyDrop> } | + help: the `Box` type always has a statically known size and allocates its contents in the heap | -LL | union U1 { f: Box> } - | ++++ + +LL | union U1 { f: Box>> } + | ++++ + error[E0277]: the size for values of type `(dyn Iterator + '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 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +LL | union U3 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = help: within `ManuallyDrop<(dyn Iterator + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: required because it appears within the type `ManuallyDrop<(dyn Iterator + '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 } +LL | union U3 { f: &ManuallyDrop> } | + help: the `Box` type always has a statically known size and allocates its contents in the heap | -LL | union U3 { f: Box> } - | ++++ + +LL | union U3 { f: Box>> } + | ++++ + error: aborting due to 13 previous errors diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs index 97c5acf1f72ca..46e5aef04031a 100644 --- a/src/test/ui/associated-type-bounds/union-bounds.rs +++ b/src/test/ui/associated-type-bounds/union-bounds.rs @@ -1,7 +1,6 @@ // run-pass #![feature(associated_type_bounds)] -#![feature(untagged_unions)] #![allow(unused_assignments)] diff --git a/src/test/ui/binding/issue-53114-safety-checks.rs b/src/test/ui/binding/issue-53114-safety-checks.rs index 5042ad024afff..d0eb28c571411 100644 --- a/src/test/ui/binding/issue-53114-safety-checks.rs +++ b/src/test/ui/binding/issue-53114-safety-checks.rs @@ -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 } diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.rs b/src/test/ui/borrowck/borrowck-union-move-assign.rs index a24f42d2ddf87..4c96ccdb25aaa 100644 --- a/src/test/ui/borrowck/borrowck-union-move-assign.rs +++ b/src/test/ui/borrowck/borrowck-union-move-assign.rs @@ -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, + b: ManuallyDrop, } 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 } } diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.stderr index 0b1714fd75dc0..af6f6fac40870 100644 --- a/src/test/ui/borrowck/borrowck-union-move-assign.stderr +++ b/src/test/ui/borrowck/borrowck-union-move-assign.stderr @@ -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 diff --git a/src/test/ui/borrowck/borrowck-union-move.rs b/src/test/ui/borrowck/borrowck-union-move.rs index d0aa6dff74410..510547ad5bb74 100644 --- a/src/test/ui/borrowck/borrowck-union-move.rs +++ b/src/test/ui/borrowck/borrowck-union-move.rs @@ -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, + n2: ManuallyDrop, } union Ucc { c1: Copy, @@ -14,24 +14,24 @@ union Ucc { } union Ucn { c: Copy, - n: NonCopy, + n: ManuallyDrop, } 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` } diff --git a/src/test/ui/borrowck/borrowck-union-move.stderr b/src/test/ui/borrowck/borrowck-union-move.stderr index abbb0142a9c30..731607fbdd1f7 100644 --- a/src/test/ui/borrowck/borrowck-union-move.stderr +++ b/src/test/ui/borrowck/borrowck-union-move.stderr @@ -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 diff --git a/src/test/ui/borrowck/move-from-union-field-issue-66500.rs b/src/test/ui/borrowck/move-from-union-field-issue-66500.rs index 8fbf120fc1c78..0bd2147f46331 100644 --- a/src/test/ui/borrowck/move-from-union-field-issue-66500.rs +++ b/src/test/ui/borrowck/move-from-union-field-issue-66500.rs @@ -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, diff --git a/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr b/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr index 82c3fe3b12d1c..70078582713c6 100644 --- a/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr +++ b/src/test/ui/borrowck/move-from-union-field-issue-66500.stderr @@ -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 diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr index 7e9abc3ffa7e1..ae5f6b2baee40 100644 --- a/src/test/ui/consts/invalid-union.32bit.stderr +++ b/src/test/ui/consts/invalid-union.32bit.stderr @@ -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 ..y..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 diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index 81c1024424972..d50e74a16ec36 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -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 ..y..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 diff --git a/src/test/ui/consts/invalid-union.rs b/src/test/ui/consts/invalid-union.rs index f3f1af89b2c41..efeddf75cb557 100644 --- a/src/test/ui/consts/invalid-union.rs +++ b/src/test/ui/consts/invalid-union.rs @@ -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, + cell: ManuallyDrop>, } const C: S = { diff --git a/src/test/ui/consts/qualif-union.rs b/src/test/ui/consts/qualif-union.rs index 2054b5b89ed6e..11c019be96432 100644 --- a/src/test/ui/consts/qualif-union.rs +++ b/src/test/ui/consts/qualif-union.rs @@ -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 } +union U { i: u32, c: ManuallyDrop> } -const C1: Cell = { - unsafe { U { c: Cell::new(0) }.c } +const C1: ManuallyDrop> = { + unsafe { U { c: ManuallyDrop::new(Cell::new(0)) }.c } }; -const C2: Cell = { +const C2: ManuallyDrop> = { unsafe { U { i : 0 }.c } }; -const C3: Cell = { +const C3: ManuallyDrop> = { let mut u = U { i: 0 }; u.i = 1; unsafe { u.c } diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr index fda8ad4a3bc81..8ec68ada048a5 100644 --- a/src/test/ui/consts/qualif-union.stderr +++ b/src/test/ui/consts/qualif-union.stderr @@ -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 diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index a93fb7977131d..4e020327447ff 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -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> { union _Un1> { //~^ ERROR associated type bounds are unstable - outest: std::mem::ManuallyDrop, - outer: T::As1, - inner: ::As2, + outest: ManuallyDrop, + outer: ManuallyDrop, + inner: ManuallyDrop<::As2>, } type _TaWhere1 where T: Iterator = T; diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs deleted file mode 100644 index af8d8e92b20bd..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs +++ /dev/null @@ -1,35 +0,0 @@ -// ignore-tidy-linelength - -union U1 { // OK - a: u8, -} - -union U2 { // OK - a: T, -} - -union U22 { // OK - a: std::mem::ManuallyDrop, -} - -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, //~ ERROR unions with non-`Copy` fields other than `ManuallyDrop` are unstable -} - -union U4 { - 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() {} diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr deleted file mode 100644 index 9e4a89f80c852..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0658]: unions with non-`Copy` fields other than `ManuallyDrop` are unstable - --> $DIR/feature-gate-untagged_unions.rs:20:5 - | -LL | a: std::cell::RefCell, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #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, - | +++++++++++++++++++++++ + - -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, - | +++++++++++++++++++++++ + - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0658, E0740. -For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/nll/issue-55651.rs b/src/test/ui/nll/issue-55651.rs index 46255bf74a138..75ba482717460 100644 --- a/src/test/ui/nll/issue-55651.rs +++ b/src/test/ui/nll/issue-55651.rs @@ -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, + b: ManuallyDrop, } 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 } } diff --git a/src/test/ui/repr/repr-packed-contains-align.rs b/src/test/ui/repr/repr-packed-contains-align.rs index 67d87eb5cd520..bef5c7d8c62fc 100644 --- a/src/test/ui/repr/repr-packed-contains-align.rs +++ b/src/test/ui/repr/repr-packed-contains-align.rs @@ -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 } diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr index 531004e8e202b..4c3a960cad2a6 100644 --- a/src/test/ui/repr/repr-packed-contains-align.stderr +++ b/src/test/ui/repr/repr-packed-contains-align.stderr @@ -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); | ^^ diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs index ea8a3c177e9d7..871208b5ba785 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs @@ -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, diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr index 2c6d06aa8c7f5..16b64bdc29dd3 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr @@ -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> { | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs index 0da3cc2ba1b04..27ebd0b54db5d 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs @@ -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 } diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr index 0116a2a68ceb2..a785c63ce3d99 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr @@ -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> { | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/union/field_checks.rs b/src/test/ui/union/field_checks.rs new file mode 100644 index 0000000000000..d5d1e44ac855c --- /dev/null +++ b/src/test/ui/union/field_checks.rs @@ -0,0 +1,65 @@ +use std::mem::ManuallyDrop; + +union U1 { // OK + a: u8, +} + +union U2 { // OK + a: T, +} + +union U22 { // OK + a: ManuallyDrop, +} + +union U23 { // OK + a: (ManuallyDrop, i32), +} + +union U24 { // OK + a: [ManuallyDrop; 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, //~ ERROR unions cannot contain fields that may need dropping +} + +union U4 { + 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 { // OK + f: (&'static mut i32, ManuallyDrop, i32), +} + +union U8 { // OK + f1: [(&'static mut i32, i32); 8], + f2: [ManuallyDrop; 2], +} + +fn main() {} diff --git a/src/test/ui/union/field_checks.stderr b/src/test/ui/union/field_checks.stderr new file mode 100644 index 0000000000000..1f97e97ac6ede --- /dev/null +++ b/src/test/ui/union/field_checks.stderr @@ -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, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:28:5 + | +LL | a: std::cell::RefCell, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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>, + | +++++++++++++++++++++++ + + +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, + | +++++++++++++++++++++++ + + +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, + | +++++++++++++++++++++++ + + +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`. diff --git a/src/test/ui/union/issue-41073.rs b/src/test/ui/union/issue-41073.rs index 80474b807e7f3..4dfdc606bb409 100644 --- a/src/test/ui/union/issue-41073.rs +++ b/src/test/ui/union/issue-41073.rs @@ -1,5 +1,3 @@ -#![feature(untagged_unions)] - union Test { a: A, //~ ERROR unions cannot contain fields that may need dropping b: B diff --git a/src/test/ui/union/issue-41073.stderr b/src/test/ui/union/issue-41073.stderr index 7d4208b10da80..b3887fa0f90be 100644 --- a/src/test/ui/union/issue-41073.stderr +++ b/src/test/ui/union/issue-41073.stderr @@ -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, | ^^^^ diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr index e785a2ee7335d..ca02de4c61bb8 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr @@ -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, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:62:13 + | +LL | let a = u.x.0; + | ^^^^^ + | | + | move occurs because value has type `(MockVec, MockVec)`, 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, MockVec), MockVec)>` --> $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`, 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`. diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index e56d87255dbaf..83781c5e55092 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.rs +++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs @@ -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 { @@ -44,47 +44,49 @@ impl DerefMut for MockVec { union U { - x: ((MockVec, MockVec), MockVec), - y: MockBox>, + x: ManuallyDrop<((MockVec, MockVec), MockVec)>, + y: ManuallyDrop>>, } fn use_borrow(_: &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` diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr index e785a2ee7335d..ca02de4c61bb8 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr @@ -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, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:62:13 + | +LL | let a = u.x.0; + | ^^^^^ + | | + | move occurs because value has type `(MockVec, MockVec)`, 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, MockVec), MockVec)>` --> $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`, 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`. diff --git a/src/test/ui/union/union-custom-drop.rs b/src/test/ui/union/union-custom-drop.rs deleted file mode 100644 index 4b333631ec0f7..0000000000000 --- a/src/test/ui/union/union-custom-drop.rs +++ /dev/null @@ -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() {} diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr deleted file mode 100644 index b5579eeef0977..0000000000000 --- a/src/test/ui/union/union-custom-drop.stderr +++ /dev/null @@ -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, - | +++++++++++++++++++++++ + - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0740`. diff --git a/src/test/ui/union/union-deref.mirunsafeck.stderr b/src/test/ui/union/union-deref.mirunsafeck.stderr index ff37e6fd9177a..be5e60ab88a59 100644 --- a/src/test/ui/union/union-deref.mirunsafeck.stderr +++ b/src/test/ui/union/union-deref.mirunsafeck.stderr @@ -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) }; | ^^^^^ diff --git a/src/test/ui/union/union-deref.rs b/src/test/ui/union/union-deref.rs index 4bf2ba2f1bfce..5aa28d93f96ed 100644 --- a/src/test/ui/union/union-deref.rs +++ b/src/test/ui/union/union-deref.rs @@ -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; diff --git a/src/test/ui/union/union-deref.thirunsafeck.stderr b/src/test/ui/union/union-deref.thirunsafeck.stderr index ff37e6fd9177a..be5e60ab88a59 100644 --- a/src/test/ui/union/union-deref.thirunsafeck.stderr +++ b/src/test/ui/union/union-deref.thirunsafeck.stderr @@ -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) }; | ^^^^^ diff --git a/src/test/ui/union/union-move.mirunsafeck.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr index f55fbea6336e3..53050cf539eaf 100644 --- a/src/test/ui/union/union-move.mirunsafeck.stderr +++ b/src/test/ui/union/union-move.mirunsafeck.stderr @@ -27,7 +27,7 @@ LL | move_out(x.f1_nocopy); | ^^^^^^^^^^^ | | | cannot move out of here - | move occurs because `x.f1_nocopy` has type `RefCell`, which does not implement the `Copy` trait + | move occurs because `x.f1_nocopy` has type `ManuallyDrop>`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs index 8f78c30d67a55..b8b1ac8046a03 100644 --- a/src/test/ui/union/union-move.rs +++ b/src/test/ui/union/union-move.rs @@ -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(x: T) {} union U1 { - f1_nocopy: RefCell, - f2_nocopy: RefCell, + f1_nocopy: ManuallyDrop>, + f2_nocopy: ManuallyDrop>, f3_copy: i32, } union U2 { - f1_nocopy: RefCell, + f1_nocopy: ManuallyDrop>, } impl Drop for U2 { fn drop(&mut self) {} diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr index f55fbea6336e3..53050cf539eaf 100644 --- a/src/test/ui/union/union-move.thirunsafeck.stderr +++ b/src/test/ui/union/union-move.thirunsafeck.stderr @@ -27,7 +27,7 @@ LL | move_out(x.f1_nocopy); | ^^^^^^^^^^^ | | | cannot move out of here - | move occurs because `x.f1_nocopy` has type `RefCell`, which does not implement the `Copy` trait + | move occurs because `x.f1_nocopy` has type `ManuallyDrop>`, which does not implement the `Copy` trait error: aborting due to 3 previous errors diff --git a/src/test/ui/union/union-nonrepresentable.rs b/src/test/ui/union/union-nonrepresentable.rs index 4dbd97ea957ba..4bdf7c6872fa5 100644 --- a/src/test/ui/union/union-nonrepresentable.rs +++ b/src/test/ui/union/union-nonrepresentable.rs @@ -1,8 +1,6 @@ -#![feature(untagged_unions)] - union U { //~ ERROR recursive type `U` has infinite size a: u8, - b: U, + b: std::mem::ManuallyDrop, } fn main() {} diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr index 7da7c870e704b..9804b1418b208 100644 --- a/src/test/ui/union/union-nonrepresentable.stderr +++ b/src/test/ui/union/union-nonrepresentable.stderr @@ -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, + | ------------------------- recursive without indirection | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable | -LL | b: Box, - | ++++ + +LL | b: Box>, + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/union/union-sized-field.rs b/src/test/ui/union/union-sized-field.rs index b84cb3eff56f6..cb852eff0c60a 100644 --- a/src/test/ui/union/union-sized-field.rs +++ b/src/test/ui/union/union-sized-field.rs @@ -1,18 +1,18 @@ -#![feature(untagged_unions)] +use std::mem::ManuallyDrop; union Foo { - value: T, + value: ManuallyDrop, //~^ ERROR the size for values of type } struct Foo2 { - value: T, + value: ManuallyDrop, //~^ ERROR the size for values of type t: u32, } enum Foo3 { - Value(T), + Value(ManuallyDrop), //~^ ERROR the size for values of type } diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index 3fe6e71f3b863..771e8f2619995 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -3,9 +3,10 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim | LL | union Foo { | - this type parameter needs to be `std::marker::Sized` -LL | value: T, - | ^ doesn't have a size known at compile-time +LL | value: ManuallyDrop, + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = note: required because it appears within the type `ManuallyDrop` = 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 { | help: borrowed types always have a statically known size | -LL | value: &T, +LL | value: &ManuallyDrop, | + help: the `Box` type always has a statically known size and allocates its contents in the heap | -LL | value: Box, - | ++++ + +LL | value: Box>, + | ++++ + 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 { | - this type parameter needs to be `std::marker::Sized` -LL | value: T, - | ^ doesn't have a size known at compile-time +LL | value: ManuallyDrop, + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = note: required because it appears within the type `ManuallyDrop` = 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 { | help: borrowed types always have a statically known size | -LL | value: &T, +LL | value: &ManuallyDrop, | + help: the `Box` type always has a statically known size and allocates its contents in the heap | -LL | value: Box, - | ++++ + +LL | value: Box>, + | ++++ + 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 { | - this type parameter needs to be `std::marker::Sized` -LL | Value(T), - | ^ doesn't have a size known at compile-time +LL | Value(ManuallyDrop), + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = note: required because it appears within the type `ManuallyDrop` = 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 { | help: borrowed types always have a statically known size | -LL | Value(&T), +LL | Value(&ManuallyDrop), | + help: the `Box` type always has a statically known size and allocates its contents in the heap | -LL | Value(Box), - | ++++ + +LL | Value(Box>), + | ++++ + error: aborting due to 3 previous errors diff --git a/src/test/ui/union/union-unsafe.mir.stderr b/src/test/ui/union/union-unsafe.mir.stderr index 318b00ddea94e..544213dbc5543 100644 --- a/src/test/ui/union/union-unsafe.mir.stderr +++ b/src/test/ui/union/union-unsafe.mir.stderr @@ -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`. diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index 3cb3a18cb7544..5e1837a901d46 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -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), + a: (ManuallyDrop>, 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 } diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr index a8c3886657f43..f959fe5bdb5c5 100644 --- a/src/test/ui/union/union-unsafe.thir.stderr +++ b/src/test/ui/union/union-unsafe.thir.stderr @@ -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`. diff --git a/src/test/ui/union/union-unsized.mirunsafeck.stderr b/src/test/ui/union/union-unsized.mirunsafeck.stderr index 36e782ac0424d..59ab835fba22d 100644 --- a/src/test/ui/union/union-unsized.mirunsafeck.stderr +++ b/src/test/ui/union/union-unsized.mirunsafeck.stderr @@ -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, | ++++ + 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 diff --git a/src/test/ui/union/union-unsized.rs b/src/test/ui/union/union-unsized.rs index e9792f527dc71..8e897d7d3c6d6 100644 --- a/src/test/ui/union/union-unsized.rs +++ b/src/test/ui/union/union-unsized.rs @@ -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 diff --git a/src/test/ui/union/union-unsized.thirunsafeck.stderr b/src/test/ui/union/union-unsized.thirunsafeck.stderr index 36e782ac0424d..59ab835fba22d 100644 --- a/src/test/ui/union/union-unsized.thirunsafeck.stderr +++ b/src/test/ui/union/union-unsized.thirunsafeck.stderr @@ -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, | ++++ + 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 diff --git a/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr index cd338ac9e3a27..0ecd5203dd9d9 100644 --- a/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr +++ b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr @@ -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`. diff --git a/src/test/ui/unsafe/union-assignop.rs b/src/test/ui/unsafe/union-assignop.rs index c4be20aa567b7..5e667cd10d59f 100644 --- a/src/test/ui/unsafe/union-assignop.rs +++ b/src/test/ui/unsafe/union-assignop.rs @@ -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, } 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 } diff --git a/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr index 71de421a2553e..24b357e762bba 100644 --- a/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr +++ b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr @@ -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`. diff --git a/src/test/ui/unsafe/union-modification.rs b/src/test/ui/unsafe/union-modification.rs index 5c70b78df7c12..9a53ef9085200 100644 --- a/src/test/ui/unsafe/union-modification.rs +++ b/src/test/ui/unsafe/union-modification.rs @@ -2,8 +2,6 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -#![feature(untagged_unions)] - union Foo { bar: i8, _blah: isize, diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs index 5fe09933cfc48..4338d78eabb9d 100644 --- a/src/test/ui/unsafe/union.rs +++ b/src/test/ui/unsafe/union.rs @@ -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 } #[allow(dead_code)] +#[derive(Clone, Copy)] enum PizzaTopping { Cheese, Pineapple, diff --git a/src/tools/clippy/tests/ui/derive.rs b/src/tools/clippy/tests/ui/derive.rs index 4e46bf1399173..b276c384c04ea 100644 --- a/src/tools/clippy/tests/ui/derive.rs +++ b/src/tools/clippy/tests/ui/derive.rs @@ -1,7 +1,7 @@ -#![feature(untagged_unions)] #![allow(dead_code)] #![warn(clippy::expl_impl_clone_on_copy)] + #[derive(Copy)] struct Qux; diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs index 7ece66a1ccb6f..f0c59b4080be3 100644 --- a/src/tools/clippy/tests/ui/no_effect.rs +++ b/src/tools/clippy/tests/ui/no_effect.rs @@ -4,7 +4,7 @@ #![allow(path_statements)] #![allow(clippy::deref_addrof)] #![allow(clippy::redundant_field_names)] -#![feature(untagged_unions)] + struct Unit; struct Tuple(i32);