about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-13 23:42:05 +0000
committerbors <bors@rust-lang.org>2022-07-13 23:42:05 +0000
commitcbb07c27a4d78f95557a6b9cdcc32f98d67a0c22 (patch)
treec6ca234d183a8002b09848b116cd547ff2d01b14
parent87588a2afd9ca903366f0deaf84d805f34469384 (diff)
parent07fe9882cc6e03682fcfa7b18c8f5b998219bdd2 (diff)
downloadrust-cbb07c27a4d78f95557a6b9cdcc32f98d67a0c22.tar.gz
rust-cbb07c27a4d78f95557a6b9cdcc32f98d67a0c22.zip
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
-rw-r--r--compiler/rustc_feature/src/active.rs7
-rw-r--r--compiler/rustc_feature/src/removed.rs3
-rw-r--r--compiler/rustc_middle/src/mir/query.rs6
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs20
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs23
-rw-r--r--compiler/rustc_passes/src/stability.rs38
-rw-r--r--compiler/rustc_typeck/src/check/check.rs35
-rw-r--r--compiler/rustc_typeck/src/lib.rs1
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.rs14
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.rs9
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.stderr64
-rw-r--r--src/test/ui/associated-type-bounds/union-bounds.rs1
-rw-r--r--src/test/ui/binding/issue-53114-safety-checks.rs4
-rw-r--r--src/test/ui/borrowck/borrowck-union-move-assign.rs16
-rw-r--r--src/test/ui/borrowck/borrowck-union-move-assign.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-union-move.rs14
-rw-r--r--src/test/ui/borrowck/borrowck-union-move.stderr6
-rw-r--r--src/test/ui/borrowck/move-from-union-field-issue-66500.rs2
-rw-r--r--src/test/ui/borrowck/move-from-union-field-issue-66500.stderr8
-rw-r--r--src/test/ui/consts/invalid-union.32bit.stderr6
-rw-r--r--src/test/ui/consts/invalid-union.64bit.stderr6
-rw-r--r--src/test/ui/consts/invalid-union.rs5
-rw-r--r--src/test/ui/consts/qualif-union.rs13
-rw-r--r--src/test/ui/consts/qualif-union.stderr10
-rw-r--r--src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs8
-rw-r--r--src/test/ui/feature-gates/feature-gate-untagged_unions.rs35
-rw-r--r--src/test/ui/feature-gates/feature-gate-untagged_unions.stderr37
-rw-r--r--src/test/ui/nll/issue-55651.rs14
-rw-r--r--src/test/ui/repr/repr-packed-contains-align.rs5
-rw-r--r--src/test/ui/repr/repr-packed-contains-align.stderr40
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-union.rs2
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr2
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/nested-union.rs2
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/nested-union.stderr2
-rw-r--r--src/test/ui/union/field_checks.rs65
-rw-r--r--src/test/ui/union/field_checks.stderr63
-rw-r--r--src/test/ui/union/issue-41073.rs2
-rw-r--r--src/test/ui/union/issue-41073.stderr2
-rw-r--r--src/test/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr60
-rw-r--r--src/test/ui/union/union-borrow-move-parent-sibling.rs28
-rw-r--r--src/test/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr60
-rw-r--r--src/test/ui/union/union-custom-drop.rs19
-rw-r--r--src/test/ui/union/union-custom-drop.stderr15
-rw-r--r--src/test/ui/union/union-deref.mirunsafeck.stderr12
-rw-r--r--src/test/ui/union/union-deref.rs1
-rw-r--r--src/test/ui/union/union-deref.thirunsafeck.stderr12
-rw-r--r--src/test/ui/union/union-move.mirunsafeck.stderr2
-rw-r--r--src/test/ui/union/union-move.rs8
-rw-r--r--src/test/ui/union/union-move.thirunsafeck.stderr2
-rw-r--r--src/test/ui/union/union-nonrepresentable.rs4
-rw-r--r--src/test/ui/union/union-nonrepresentable.stderr10
-rw-r--r--src/test/ui/union/union-sized-field.rs8
-rw-r--r--src/test/ui/union/union-sized-field.stderr33
-rw-r--r--src/test/ui/union/union-unsafe.mir.stderr36
-rw-r--r--src/test/ui/union/union-unsafe.rs7
-rw-r--r--src/test/ui/union/union-unsafe.thir.stderr36
-rw-r--r--src/test/ui/union/union-unsized.mirunsafeck.stderr4
-rw-r--r--src/test/ui/union/union-unsized.rs2
-rw-r--r--src/test/ui/union/union-unsized.thirunsafeck.stderr4
-rw-r--r--src/test/ui/unsafe/union-assignop.mirunsafeck.stderr28
-rw-r--r--src/test/ui/unsafe/union-assignop.rs15
-rw-r--r--src/test/ui/unsafe/union-assignop.thirunsafeck.stderr28
-rw-r--r--src/test/ui/unsafe/union-modification.rs2
-rw-r--r--src/test/ui/unsafe/union.rs4
-rw-r--r--src/tools/clippy/tests/ui/derive.rs2
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs2
66 files changed, 507 insertions, 529 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 117bdad971a..1fc4d09eb0a 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 54626caaf53..2ddaf920109 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 620f0380d53..6a6ed3dc728 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 8585199faaf..54d3b7cdda6 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 1f73b7da815..ded1f0462cb 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 12050dceb60..a06213ca5f4 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<T>` 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 79edbeab9c7..dfcd35d2178 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 dd712fd7ed7..f98ae46c587 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 e1dc6f8f4b6..6e464f69510 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<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>>() {}
diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs
index 5af05738750..f26037f0707 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<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)`
 
diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr
index 0cacd787247..978390fa712 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<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
 
diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs
index 97c5acf1f72..46e5aef0403 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 5042ad024af..d0eb28c5714 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 a24f42d2ddf..4c96ccdb25a 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<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
         }
     }
diff --git a/src/test/ui/borrowck/borrowck-union-move-assign.stderr b/src/test/ui/borrowck/borrowck-union-move-assign.stderr
index 0b1714fd75d..af6f6fac408 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 d0aa6dff744..510547ad5bb 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<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`
         }
diff --git a/src/test/ui/borrowck/borrowck-union-move.stderr b/src/test/ui/borrowck/borrowck-union-move.stderr
index abbb0142a9c..731607fbdd1 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 8fbf120fc1c..0bd2147f463 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 82c3fe3b12d..70078582713 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 7e9abc3ffa7..ae5f6b2baee 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 .<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
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 81c10244249..d50e74a16ec 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 .<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
diff --git a/src/test/ui/consts/invalid-union.rs b/src/test/ui/consts/invalid-union.rs
index f3f1af89b2c..efeddf75cb5 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<u32>,
+    cell: ManuallyDrop<Cell<u32>>,
 }
 
 const C: S = {
diff --git a/src/test/ui/consts/qualif-union.rs b/src/test/ui/consts/qualif-union.rs
index 2054b5b89ed..11c019be964 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<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 }
diff --git a/src/test/ui/consts/qualif-union.stderr b/src/test/ui/consts/qualif-union.stderr
index fda8ad4a3bc..8ec68ada048 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 a93fb797713..4e020327447 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<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;
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 af8d8e92b20..00000000000
--- 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<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() {}
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 9e4a89f80c8..00000000000
--- 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<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`.
diff --git a/src/test/ui/nll/issue-55651.rs b/src/test/ui/nll/issue-55651.rs
index 46255bf74a1..75ba4827174 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<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
         }
     }
diff --git a/src/test/ui/repr/repr-packed-contains-align.rs b/src/test/ui/repr/repr-packed-contains-align.rs
index 67d87eb5cd5..bef5c7d8c62 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 531004e8e20..4c3a960cad2 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 ea8a3c177e9..871208b5ba7 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 2c6d06aa8c7..16b64bdc29d 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 0da3cc2ba1b..27ebd0b54db 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 0116a2a68ce..a785c63ce3d 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 00000000000..d5d1e44ac85
--- /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<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() {}
diff --git a/src/test/ui/union/field_checks.stderr b/src/test/ui/union/field_checks.stderr
new file mode 100644
index 00000000000..1f97e97ac6e
--- /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<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`.
diff --git a/src/test/ui/union/issue-41073.rs b/src/test/ui/union/issue-41073.rs
index 80474b807e7..4dfdc606bb4 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 7d4208b10da..b3887fa0f90 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 e785a2ee733..ca02de4c61b 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<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`.
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 e56d87255db..83781c5e550 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<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`
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 e785a2ee733..ca02de4c61b 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<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`.
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 4b333631ec0..00000000000
--- 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 b5579eeef09..00000000000
--- 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<Bar>,
-   |          +++++++++++++++++++++++   +
-
-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 ff37e6fd917..be5e60ab88a 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 4bf2ba2f1bf..5aa28d93f96 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 ff37e6fd917..be5e60ab88a 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 f55fbea6336..53050cf539e 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<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
 
diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs
index 8f78c30d67a..b8b1ac8046a 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<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) {}
diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr
index f55fbea6336..53050cf539e 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<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
 
diff --git a/src/test/ui/union/union-nonrepresentable.rs b/src/test/ui/union/union-nonrepresentable.rs
index 4dbd97ea957..4bdf7c6872f 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<U>,
 }
 
 fn main() {}
diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr
index 7da7c870e70..9804b1418b2 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<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
 
diff --git a/src/test/ui/union/union-sized-field.rs b/src/test/ui/union/union-sized-field.rs
index b84cb3eff56..cb852eff0c6 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<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
 }
 
diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr
index 3fe6e71f3b8..771e8f26199 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<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
 
diff --git a/src/test/ui/union/union-unsafe.mir.stderr b/src/test/ui/union/union-unsafe.mir.stderr
index 318b00ddea9..544213dbc55 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 3cb3a18cb75..5e1837a901d 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>, 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
 }
 
diff --git a/src/test/ui/union/union-unsafe.thir.stderr b/src/test/ui/union/union-unsafe.thir.stderr
index a8c3886657f..f959fe5bdb5 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 36e782ac042..59ab835fba2 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<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
diff --git a/src/test/ui/union/union-unsized.rs b/src/test/ui/union/union-unsized.rs
index e9792f527dc..8e897d7d3c6 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 36e782ac042..59ab835fba2 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<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
diff --git a/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr
index cd338ac9e3a..0ecd5203dd9 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 c4be20aa567..5e667cd10d5 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<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
 }
diff --git a/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr
index 71de421a255..24b357e762b 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 5c70b78df7c..9a53ef90852 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 5fe09933cfc..4338d78eabb 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<PizzaTopping>
 }
 
 #[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 4e46bf13991..b276c384c04 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 7ece66a1ccb..f0c59b4080b 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);