Skip to content

Commit 5bf6017

Browse files
committed
remove untagged_union feature gate
1 parent 6dfede3 commit 5bf6017

File tree

57 files changed

+386
-449
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+386
-449
lines changed

compiler/rustc_feature/src/active.rs

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

compiler/rustc_feature/src/removed.rs

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

compiler/rustc_passes/src/stability.rs

+2-66
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ use rustc_hir::{FieldDef, Generics, HirId, Item, ItemKind, TraitRef, Ty, TyKind,
1313
use rustc_middle::hir::nested_filter;
1414
use rustc_middle::middle::privacy::AccessLevels;
1515
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
16-
use rustc_middle::ty::{self, query::Providers, TyCtxt};
16+
use rustc_middle::ty::{query::Providers, TyCtxt};
1717
use rustc_session::lint;
1818
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
19-
use rustc_session::parse::feature_err;
2019
use rustc_session::Session;
2120
use rustc_span::symbol::{sym, Symbol};
22-
use rustc_span::{Span, DUMMY_SP};
21+
use rustc_span::Span;
2322
use rustc_target::spec::abi::Abi;
2423

2524
use std::cmp::Ordering;
@@ -766,69 +765,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
766765
}
767766
}
768767

769-
// There's no good place to insert stability check for non-Copy unions,
770-
// so semi-randomly perform it here in stability.rs
771-
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
772-
let ty = self.tcx.type_of(item.def_id);
773-
let ty::Adt(adt_def, substs) = ty.kind() else { bug!() };
774-
775-
#[allow(rustc::usage_of_qualified_ty)] // `Ty` is `hir::Ty` here, we really want `ty::Ty`.
776-
fn allowed_union_field<'tcx>(
777-
tcx: TyCtxt<'tcx>,
778-
param_env: ty::ParamEnv<'tcx>,
779-
ty: ty::Ty<'tcx>,
780-
) -> bool {
781-
// We don't just accept all !needs_drop fields, due to semver concerns.
782-
match ty.kind() {
783-
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
784-
ty::Tuple(tys) => {
785-
// allow tuples of allowed types
786-
tys.iter().all(|ty| allowed_union_field(tcx, param_env, ty))
787-
}
788-
ty::Array(elem, _len) => {
789-
// Like `Copy`, we do *not* special-case length 0.
790-
allowed_union_field(tcx, param_env, *elem)
791-
}
792-
_ => {
793-
// Fallback case: allow `ManuallyDrop` and things that are `Copy`.
794-
ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
795-
|| ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env)
796-
}
797-
}
798-
}
799-
800-
// `allowed_union_field` determines which fields are allowed on stable.
801-
let param_env = self.tcx.param_env(item.def_id);
802-
for field in &adt_def.non_enum_variant().fields {
803-
let field_ty = field.ty(self.tcx, substs);
804-
if !allowed_union_field(self.tcx, param_env, field_ty) {
805-
if field_ty.needs_drop(self.tcx, param_env) {
806-
// Avoid duplicate error: This will error later anyway because fields
807-
// that need drop are not allowed.
808-
self.tcx.sess.delay_span_bug(
809-
item.span,
810-
"union should have been rejected due to potentially dropping field",
811-
);
812-
} else {
813-
feature_err(
814-
&self.tcx.sess.parse_sess,
815-
sym::untagged_unions,
816-
self.tcx.def_span(field.did),
817-
"unions with non-`Copy` fields other than `ManuallyDrop<T>`, \
818-
references, and tuples of such types are unstable",
819-
)
820-
.emit();
821-
}
822-
} else {
823-
// We allow this field. Make extra sure it does not drop.
824-
assert!(
825-
!field_ty.needs_drop(self.tcx, param_env),
826-
"we should accept no maybe-dropping union fields"
827-
);
828-
}
829-
}
830-
}
831-
832768
_ => (/* pass */),
833769
}
834770
intravisit::walk_item(self, item);

compiler/rustc_typeck/src/check/check.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,37 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
402402
let item_type = tcx.type_of(item_def_id);
403403
if let ty::Adt(def, substs) = item_type.kind() {
404404
assert!(def.is_union());
405-
let fields = &def.non_enum_variant().fields;
405+
406+
fn allowed_union_field<'tcx>(
407+
ty: Ty<'tcx>,
408+
tcx: TyCtxt<'tcx>,
409+
param_env: ty::ParamEnv<'tcx>,
410+
span: Span,
411+
) -> bool {
412+
// We don't just accept all !needs_drop fields, due to semver concerns.
413+
match ty.kind() {
414+
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
415+
ty::Tuple(tys) => {
416+
// allow tuples of allowed types
417+
tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env, span))
418+
}
419+
ty::Array(elem, _len) => {
420+
// Like `Copy`, we do *not* special-case length 0.
421+
allowed_union_field(*elem, tcx, param_env, span)
422+
}
423+
_ => {
424+
// Fallback case: allow `ManuallyDrop` and things that are `Copy`.
425+
ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
426+
|| ty.is_copy_modulo_regions(tcx.at(span), param_env)
427+
}
428+
}
429+
}
430+
406431
let param_env = tcx.param_env(item_def_id);
407-
for field in fields {
432+
for field in &def.non_enum_variant().fields {
408433
let field_ty = field.ty(tcx, substs);
409-
if field_ty.needs_drop(tcx, param_env) {
434+
435+
if !allowed_union_field(field_ty, tcx, param_env, span) {
410436
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
411437
// We are currently checking the type this field came from, so it must be local.
412438
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
433459
)
434460
.emit();
435461
return false;
462+
} else if field_ty.needs_drop(tcx, param_env) {
463+
// This should never happen. But we can get here e.g. in case of name resolution errors.
464+
tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields");
436465
}
437466
}
438467
} else {

src/test/ui/associated-type-bounds/duplicate.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![feature(associated_type_bounds)]
22
#![feature(type_alias_impl_trait)]
3-
#![feature(untagged_unions)]
43

54
use std::iter;
5+
use std::mem::ManuallyDrop;
66

77
struct SI1<T: Iterator<Item: Copy, Item: Send>> {
88
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
@@ -74,36 +74,36 @@ where
7474

7575
union UI1<T: Iterator<Item: Copy, Item: Send>> {
7676
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
77-
f: T,
77+
f: ManuallyDrop<T>,
7878
}
7979
union UI2<T: Iterator<Item: Copy, Item: Copy>> {
8080
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
81-
f: T,
81+
f: ManuallyDrop<T>,
8282
}
8383
union UI3<T: Iterator<Item: 'static, Item: 'static>> {
8484
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
85-
f: T,
85+
f: ManuallyDrop<T>,
8686
}
8787
union UW1<T>
8888
where
8989
T: Iterator<Item: Copy, Item: Send>,
9090
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
9191
{
92-
f: T,
92+
f: ManuallyDrop<T>,
9393
}
9494
union UW2<T>
9595
where
9696
T: Iterator<Item: Copy, Item: Copy>,
9797
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
9898
{
99-
f: T,
99+
f: ManuallyDrop<T>,
100100
}
101101
union UW3<T>
102102
where
103103
T: Iterator<Item: 'static, Item: 'static>,
104104
//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719]
105105
{
106-
f: T,
106+
f: ManuallyDrop<T>,
107107
}
108108

109109
fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}

src/test/ui/associated-type-bounds/inside-adt.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(associated_type_bounds)]
2-
#![feature(untagged_unions)]
2+
3+
use std::mem::ManuallyDrop;
34

45
struct S1 { f: dyn Iterator<Item: Copy> }
56
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
@@ -17,12 +18,12 @@ enum E3 { V(dyn Iterator<Item: 'static>) }
1718
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
1819
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
1920

20-
union U1 { f: dyn Iterator<Item: Copy> }
21+
union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
2122
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
2223
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
23-
union U2 { f: Box<dyn Iterator<Item: Copy>> }
24+
union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
2425
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
25-
union U3 { f: dyn Iterator<Item: 'static> }
26+
union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
2627
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
2728
//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)`
2829

src/test/ui/associated-type-bounds/inside-adt.stderr

+33-31
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,59 @@
11
error: associated type bounds are not allowed within structs, enums, or unions
2-
--> $DIR/inside-adt.rs:4:29
2+
--> $DIR/inside-adt.rs:5:29
33
|
44
LL | struct S1 { f: dyn Iterator<Item: Copy> }
55
| ^^^^^^^^^^
66

77
error: associated type bounds are not allowed within structs, enums, or unions
8-
--> $DIR/inside-adt.rs:6:33
8+
--> $DIR/inside-adt.rs:7:33
99
|
1010
LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
1111
| ^^^^^^^^^^
1212

1313
error: associated type bounds are not allowed within structs, enums, or unions
14-
--> $DIR/inside-adt.rs:8:29
14+
--> $DIR/inside-adt.rs:9:29
1515
|
1616
LL | struct S3 { f: dyn Iterator<Item: 'static> }
1717
| ^^^^^^^^^^^^^
1818

1919
error: associated type bounds are not allowed within structs, enums, or unions
20-
--> $DIR/inside-adt.rs:11:26
20+
--> $DIR/inside-adt.rs:12:26
2121
|
2222
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
2323
| ^^^^^^^^^^
2424

2525
error: associated type bounds are not allowed within structs, enums, or unions
26-
--> $DIR/inside-adt.rs:14:30
26+
--> $DIR/inside-adt.rs:15:30
2727
|
2828
LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
2929
| ^^^^^^^^^^
3030

3131
error: associated type bounds are not allowed within structs, enums, or unions
32-
--> $DIR/inside-adt.rs:16:26
32+
--> $DIR/inside-adt.rs:17:26
3333
|
3434
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
3535
| ^^^^^^^^^^^^^
3636

3737
error: associated type bounds are not allowed within structs, enums, or unions
38-
--> $DIR/inside-adt.rs:20:28
38+
--> $DIR/inside-adt.rs:21:41
3939
|
40-
LL | union U1 { f: dyn Iterator<Item: Copy> }
41-
| ^^^^^^^^^^
40+
LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
41+
| ^^^^^^^^^^
4242

4343
error: associated type bounds are not allowed within structs, enums, or unions
44-
--> $DIR/inside-adt.rs:23:32
44+
--> $DIR/inside-adt.rs:24:45
4545
|
46-
LL | union U2 { f: Box<dyn Iterator<Item: Copy>> }
47-
| ^^^^^^^^^^
46+
LL | union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
47+
| ^^^^^^^^^^
4848

4949
error: associated type bounds are not allowed within structs, enums, or unions
50-
--> $DIR/inside-adt.rs:25:28
50+
--> $DIR/inside-adt.rs:26:41
5151
|
52-
LL | union U3 { f: dyn Iterator<Item: 'static> }
53-
| ^^^^^^^^^^^^^
52+
LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
53+
| ^^^^^^^^^^^^^
5454

5555
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
56-
--> $DIR/inside-adt.rs:11:13
56+
--> $DIR/inside-adt.rs:12:13
5757
|
5858
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -71,7 +71,7 @@ LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
7171
| ++++ +
7272

7373
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
74-
--> $DIR/inside-adt.rs:16:13
74+
--> $DIR/inside-adt.rs:17:13
7575
|
7676
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
7777
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -89,40 +89,42 @@ LL | enum E3 { V(Box<dyn Iterator<Item: 'static>>) }
8989
| ++++ +
9090

9191
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
92-
--> $DIR/inside-adt.rs:20:15
92+
--> $DIR/inside-adt.rs:21:15
9393
|
94-
LL | union U1 { f: dyn Iterator<Item: Copy> }
95-
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
94+
LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
9696
|
97-
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
97+
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
98+
= note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`
9899
= note: no field of a union may have a dynamically sized type
99100
= help: change the field's type to have a statically known size
100101
help: borrowed types always have a statically known size
101102
|
102-
LL | union U1 { f: &dyn Iterator<Item: Copy> }
103+
LL | union U1 { f: &ManuallyDrop<dyn Iterator<Item: Copy>> }
103104
| +
104105
help: the `Box` type always has a statically known size and allocates its contents in the heap
105106
|
106-
LL | union U1 { f: Box<dyn Iterator<Item: Copy>> }
107-
| ++++ +
107+
LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
108+
| ++++ +
108109

109110
error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
110-
--> $DIR/inside-adt.rs:25:15
111+
--> $DIR/inside-adt.rs:26:15
111112
|
112-
LL | union U3 { f: dyn Iterator<Item: 'static> }
113-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
113+
LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
114+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
114115
|
115-
= help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
116+
= help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
117+
= note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`
116118
= note: no field of a union may have a dynamically sized type
117119
= help: change the field's type to have a statically known size
118120
help: borrowed types always have a statically known size
119121
|
120-
LL | union U3 { f: &dyn Iterator<Item: 'static> }
122+
LL | union U3 { f: &ManuallyDrop<dyn Iterator<Item: 'static>> }
121123
| +
122124
help: the `Box` type always has a statically known size and allocates its contents in the heap
123125
|
124-
LL | union U3 { f: Box<dyn Iterator<Item: 'static>> }
125-
| ++++ +
126+
LL | union U3 { f: Box<ManuallyDrop<dyn Iterator<Item: 'static>>> }
127+
| ++++ +
126128

127129
error: aborting due to 13 previous errors
128130

src/test/ui/associated-type-bounds/union-bounds.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// run-pass
22

33
#![feature(associated_type_bounds)]
4-
#![feature(untagged_unions)]
54

65
#![allow(unused_assignments)]
76

src/test/ui/binding/issue-53114-safety-checks.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// captures the behavior of how `_` bindings are handled with respect to how we
44
// flag expressions that are meant to request unsafe blocks.
55

6-
#![feature(untagged_unions)]
7-
6+
#[derive(Copy, Clone)]
87
struct I(i64);
8+
#[derive(Copy, Clone)]
99
struct F(f64);
1010

1111
union U { a: I, b: F }

0 commit comments

Comments
 (0)