Skip to content

Commit 6a32e79

Browse files
committed
stabilize union with 'ManuallyDrop' fields and 'impl Drop for Union'
1 parent 8e6f69a commit 6a32e79

30 files changed

+97
-148
lines changed

compiler/rustc_passes/src/stability.rs

+29-23
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ use rustc_hir::{Generics, HirId, Item, StructField, TraitRef, Ty, TyKind, Varian
1313
use rustc_middle::hir::map::Map;
1414
use rustc_middle::middle::privacy::AccessLevels;
1515
use rustc_middle::middle::stability::{DeprecationEntry, Index};
16-
use rustc_middle::ty::query::Providers;
17-
use rustc_middle::ty::TyCtxt;
16+
use rustc_middle::ty::{self, query::Providers, TyCtxt};
1817
use rustc_session::lint;
1918
use rustc_session::lint::builtin::INEFFECTIVE_UNSTABLE_TRAIT_IMPL;
2019
use rustc_session::parse::feature_err;
2120
use rustc_session::Session;
2221
use rustc_span::symbol::{sym, Symbol};
23-
use rustc_span::Span;
24-
use rustc_trait_selection::traits::misc::can_type_implement_copy;
22+
use rustc_span::{Span, DUMMY_SP};
2523

2624
use std::cmp::Ordering;
2725
use std::mem::replace;
@@ -711,27 +709,35 @@ impl Visitor<'tcx> for Checker<'tcx> {
711709
// so semi-randomly perform it here in stability.rs
712710
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
713711
let def_id = self.tcx.hir().local_def_id(item.hir_id);
714-
let adt_def = self.tcx.adt_def(def_id);
715712
let ty = self.tcx.type_of(def_id);
713+
let (adt_def, substs) = match ty.kind() {
714+
ty::Adt(adt_def, substs) => (adt_def, substs),
715+
_ => bug!(),
716+
};
716717

717-
if adt_def.has_dtor(self.tcx) {
718-
feature_err(
719-
&self.tcx.sess.parse_sess,
720-
sym::untagged_unions,
721-
item.span,
722-
"unions with `Drop` implementations are unstable",
723-
)
724-
.emit();
725-
} else {
726-
let param_env = self.tcx.param_env(def_id);
727-
if can_type_implement_copy(self.tcx, param_env, ty).is_err() {
728-
feature_err(
729-
&self.tcx.sess.parse_sess,
730-
sym::untagged_unions,
731-
item.span,
732-
"unions with non-`Copy` fields are unstable",
733-
)
734-
.emit();
718+
// Non-`Copy` fields are unstable, except for `ManuallyDrop`.
719+
let param_env = self.tcx.param_env(def_id);
720+
for field in &adt_def.non_enum_variant().fields {
721+
let field_ty = field.ty(self.tcx, substs);
722+
if !field_ty.ty_adt_def().map_or(false, |adt_def| adt_def.is_manually_drop())
723+
&& !field_ty.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
724+
{
725+
if field_ty.needs_drop(self.tcx, param_env) {
726+
// Avoid duplicate error: This will error later anyway because fields
727+
// that need drop are not allowed.
728+
self.tcx.sess.delay_span_bug(
729+
item.span,
730+
"union should have been rejected due to potentially dropping field",
731+
);
732+
} else {
733+
feature_err(
734+
&self.tcx.sess.parse_sess,
735+
sym::untagged_unions,
736+
self.tcx.def_span(field.did),
737+
"unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable",
738+
)
739+
.emit();
740+
}
735741
}
736742
}
737743
}

compiler/rustc_typeck/src/check/check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,7 @@ pub(super) fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
348348
check_packed(tcx, span, def);
349349
}
350350

351-
/// When the `#![feature(untagged_unions)]` gate is active,
352-
/// check that the fields of the `union` does not contain fields that need dropping.
351+
/// Check that the fields of the `union` do not need dropping.
353352
pub(super) fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
354353
let item_type = tcx.type_of(item_def_id);
355354
if let ty::Adt(def, substs) = item_type.kind() {

src/test/ui/did_you_mean/bad-assoc-ty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ enum N<F> where F: Fn() -> _ {
6868

6969
union O<F> where F: Fn() -> _ {
7070
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
71-
//~| ERROR unions with non-`Copy` fields are unstable
7271
foo: F,
7372
}
7473

src/test/ui/did_you_mean/bad-assoc-ty.stderr

+4-17
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,6 @@ LL | type J = ty!(u8);
5757
|
5858
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
5959

60-
error[E0658]: unions with non-`Copy` fields are unstable
61-
--> $DIR/bad-assoc-ty.rs:69:1
62-
|
63-
LL | / union O<F> where F: Fn() -> _ {
64-
LL | |
65-
LL | |
66-
LL | | foo: F,
67-
LL | | }
68-
| |_^
69-
|
70-
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
71-
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
72-
7360
error[E0223]: ambiguous associated type
7461
--> $DIR/bad-assoc-ty.rs:1:10
7562
|
@@ -215,7 +202,7 @@ LL | union O<F, T> where F: Fn() -> T {
215202
| ^^^ ^
216203

217204
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
218-
--> $DIR/bad-assoc-ty.rs:75:29
205+
--> $DIR/bad-assoc-ty.rs:74:29
219206
|
220207
LL | trait P<F> where F: Fn() -> _ {
221208
| ^ not allowed in type signatures
@@ -226,7 +213,7 @@ LL | trait P<F, T> where F: Fn() -> T {
226213
| ^^^ ^
227214

228215
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
229-
--> $DIR/bad-assoc-ty.rs:80:38
216+
--> $DIR/bad-assoc-ty.rs:79:38
230217
|
231218
LL | fn foo<F>(_: F) where F: Fn() -> _ {}
232219
| ^ not allowed in type signatures
@@ -236,7 +223,7 @@ help: use type parameters instead
236223
LL | fn foo<F, T>(_: F) where F: Fn() -> T {}
237224
| ^^^ ^
238225

239-
error: aborting due to 29 previous errors
226+
error: aborting due to 28 previous errors
240227

241-
Some errors have detailed explanations: E0121, E0223, E0658.
228+
Some errors have detailed explanations: E0121, E0223.
242229
For more information about an error, try `rustc --explain E0121`.

src/test/ui/drop/dynamic-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// run-pass
22
// ignore-wasm32-bare compiled with panic=abort by default
33

4-
#![feature(generators, generator_trait, untagged_unions)]
4+
#![feature(generators, generator_trait)]
55
#![feature(bindings_after_at)]
66

77
#![allow(unused_assignments)]

src/test/ui/dropck/dropck-union.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![feature(untagged_unions)]
2-
31
use std::cell::Cell;
42
use std::ops::Deref;
53
use std::mem::ManuallyDrop;

src/test/ui/dropck/dropck-union.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `v` does not live long enough
2-
--> $DIR/dropck-union.rs:39:18
2+
--> $DIR/dropck-union.rs:37:18
33
|
44
LL | v.0.set(Some(&v));
55
| ^^ borrowed value does not live long enough

src/test/ui/feature-gates/feature-gate-untagged_unions.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// ignore-tidy-linelength
2+
13
union U1 { // OK
24
a: u8,
35
}
@@ -6,15 +8,23 @@ union U2<T: Copy> { // OK
68
a: T,
79
}
810

9-
union U3 { //~ ERROR unions with non-`Copy` fields are unstable
11+
union U22<T> { // OK
12+
a: std::mem::ManuallyDrop<T>,
13+
}
14+
15+
union U3 {
1016
a: String, //~ ERROR unions may not contain fields that need dropping
1117
}
1218

13-
union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable
19+
union U32 { // field that does not drop but is not `Copy`, either -- this is the real feature gate test!
20+
a: std::cell::RefCell<i32>, //~ ERROR unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable
21+
}
22+
23+
union U4<T> {
1424
a: T, //~ ERROR unions may not contain fields that need dropping
1525
}
1626

17-
union U5 { //~ ERROR unions with `Drop` implementations are unstable
27+
union U5 { // Having a drop impl is OK
1828
a: u8,
1929
}
2030

Original file line numberDiff line numberDiff line change
@@ -1,61 +1,37 @@
1-
error[E0658]: unions with non-`Copy` fields are unstable
2-
--> $DIR/feature-gate-untagged_unions.rs:9:1
1+
error[E0658]: unions with non-`Copy` fields other than `ManuallyDrop<T>` are unstable
2+
--> $DIR/feature-gate-untagged_unions.rs:20:5
33
|
4-
LL | / union U3 {
5-
LL | | a: String,
6-
LL | | }
7-
| |_^
8-
|
9-
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
10-
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
11-
12-
error[E0658]: unions with non-`Copy` fields are unstable
13-
--> $DIR/feature-gate-untagged_unions.rs:13:1
14-
|
15-
LL | / union U4<T> {
16-
LL | | a: T,
17-
LL | | }
18-
| |_^
19-
|
20-
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
21-
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
22-
23-
error[E0658]: unions with `Drop` implementations are unstable
24-
--> $DIR/feature-gate-untagged_unions.rs:17:1
25-
|
26-
LL | / union U5 {
27-
LL | | a: u8,
28-
LL | | }
29-
| |_^
4+
LL | a: std::cell::RefCell<i32>,
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
306
|
317
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
328
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
339

3410
error[E0740]: unions may not contain fields that need dropping
35-
--> $DIR/feature-gate-untagged_unions.rs:10:5
11+
--> $DIR/feature-gate-untagged_unions.rs:16:5
3612
|
3713
LL | a: String,
3814
| ^^^^^^^^^
3915
|
4016
note: `std::mem::ManuallyDrop` can be used to wrap the type
41-
--> $DIR/feature-gate-untagged_unions.rs:10:5
17+
--> $DIR/feature-gate-untagged_unions.rs:16:5
4218
|
4319
LL | a: String,
4420
| ^^^^^^^^^
4521

4622
error[E0740]: unions may not contain fields that need dropping
47-
--> $DIR/feature-gate-untagged_unions.rs:14:5
23+
--> $DIR/feature-gate-untagged_unions.rs:24:5
4824
|
4925
LL | a: T,
5026
| ^^^^
5127
|
5228
note: `std::mem::ManuallyDrop` can be used to wrap the type
53-
--> $DIR/feature-gate-untagged_unions.rs:14:5
29+
--> $DIR/feature-gate-untagged_unions.rs:24:5
5430
|
5531
LL | a: T,
5632
| ^^^^
5733

58-
error: aborting due to 5 previous errors
34+
error: aborting due to 3 previous errors
5935

6036
Some errors have detailed explanations: E0658, E0740.
6137
For more information about an error, try `rustc --explain E0658`.

src/test/ui/reject-specialized-drops-8142.stderr

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
2-
--> $DIR/reject-specialized-drops-8142.rs:67:21
3-
|
4-
LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
5-
| ^^^^^
6-
|
7-
note: the implementor must specify the same requirement
8-
--> $DIR/reject-specialized-drops-8142.rs:21:1
9-
|
10-
LL | union Union<T: Copy> { f: T }
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12-
131
error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
142
--> $DIR/reject-specialized-drops-8142.rs:23:20
153
|
@@ -145,6 +133,18 @@ note: the implementor must specify the same requirement
145133
LL | struct TupleStruct<T>(T);
146134
| ^^^^^^^^^^^^^^^^^^^^^^^^^
147135

136+
error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
137+
--> $DIR/reject-specialized-drops-8142.rs:67:21
138+
|
139+
LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
140+
| ^^^^^
141+
|
142+
note: the implementor must specify the same requirement
143+
--> $DIR/reject-specialized-drops-8142.rs:21:1
144+
|
145+
LL | union Union<T: Copy> { f: T }
146+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
147+
148148
error: aborting due to 11 previous errors
149149

150150
Some errors have detailed explanations: E0308, E0366, E0367, E0495.

src/test/ui/self/self-in-typedefs.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
// build-pass (FIXME(62277): could be check-pass?)
2-
3-
#![feature(untagged_unions)]
4-
52
#![allow(dead_code)]
63

74
use std::mem::ManuallyDrop;

src/test/ui/transmute/main.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// normalize-stderr-32bit: "`&str` \(64 bits\)" -> "`&str` ($$STR bits)"
22
// normalize-stderr-64bit: "`&str` \(128 bits\)" -> "`&str` ($$STR bits)"
33

4-
5-
6-
#![feature(untagged_unions)]
74
use std::mem::transmute;
85

96
pub trait TypeConstructor<'a> {

src/test/ui/transmute/main.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
2-
--> $DIR/main.rs:16:5
2+
--> $DIR/main.rs:13:5
33
|
44
LL | transmute(x)
55
| ^^^^^^^^^
66
|
77
= note: `<C as TypeConstructor>::T` does not have a fixed size
88

99
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
10-
--> $DIR/main.rs:20:17
10+
--> $DIR/main.rs:17:17
1111
|
1212
LL | let x: u8 = transmute(10u16);
1313
| ^^^^^^^^^
@@ -16,7 +16,7 @@ LL | let x: u8 = transmute(10u16);
1616
= note: target type: `u8` (8 bits)
1717

1818
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
19-
--> $DIR/main.rs:24:17
19+
--> $DIR/main.rs:21:17
2020
|
2121
LL | let x: u8 = transmute("test");
2222
| ^^^^^^^^^
@@ -25,7 +25,7 @@ LL | let x: u8 = transmute("test");
2525
= note: target type: `u8` (8 bits)
2626

2727
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
28-
--> $DIR/main.rs:29:18
28+
--> $DIR/main.rs:26:18
2929
|
3030
LL | let x: Foo = transmute(10);
3131
| ^^^^^^^^^

src/test/ui/union/union-align.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// run-pass
22
#![allow(dead_code)]
33

4-
#![feature(untagged_unions)]
5-
64
use std::mem::{size_of, size_of_val, align_of, align_of_val};
75

86
#[repr(align(16))]
@@ -35,6 +33,7 @@ mod hybrid {
3533
use std::mem::{size_of, align_of};
3634

3735
#[repr(align(16))]
36+
#[derive(Copy, Clone)]
3837
struct S1 {
3938
a: u16,
4039
b: u8,

src/test/ui/union/union-copy.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
#![feature(untagged_unions)]
2-
31
#[derive(Clone)]
42
union U {
53
a: u8
64
}
75

86
#[derive(Clone)]
97
union W {
10-
a: String
8+
a: std::mem::ManuallyDrop<String>
119
}
1210

1311
impl Copy for U {} // OK

src/test/ui/union/union-copy.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0204]: the trait `Copy` may not be implemented for this type
2-
--> $DIR/union-copy.rs:14:6
2+
--> $DIR/union-copy.rs:12:6
33
|
4-
LL | a: String
5-
| --------- this field does not implement `Copy`
4+
LL | a: std::mem::ManuallyDrop<String>
5+
| --------------------------------- this field does not implement `Copy`
66
...
77
LL | impl Copy for W {}
88
| ^^^^

0 commit comments

Comments
 (0)