Skip to content

Commit 8dad6be

Browse files
committed
Auto merge of #53288 - RalfJung:dropck, r=nikomatsakis
unions are not always trivially dropable Fixes #52786 r? @nikomatsakis
2 parents 8b923a1 + d8f5790 commit 8dad6be

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

src/librustc/traits/query/dropck_outlives.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -242,16 +242,14 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
242242
.all(|t| trivial_dropck_outlives(tcx, t)),
243243

244244
ty::TyAdt(def, _) => {
245-
if def.is_union() {
246-
// Unions never have a dtor.
247-
true
248-
} else if Some(def.did) == tcx.lang_items().manually_drop() {
245+
if Some(def.did) == tcx.lang_items().manually_drop() {
249246
// `ManuallyDrop` never has a dtor.
250247
true
251248
} else {
252249
// Other types might. Moreover, PhantomData doesn't
253250
// have a dtor, but it is considered to own its
254-
// content, so it is non-trivial.
251+
// content, so it is non-trivial. Unions can have `impl Drop`,
252+
// and hence are non-trivial as well.
255253
false
256254
}
257255
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0597]: `v` does not live long enough
2+
--> $DIR/dropck-union.rs:49:18
3+
|
4+
LL | v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
5+
| ^^ borrowed value does not live long enough
6+
LL | }
7+
| -
8+
| |
9+
| `v` dropped here while still borrowed
10+
| borrow later used here, when `v` is dropped
11+
|
12+
= note: values in a scope are dropped in the opposite order they are defined
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0597`.

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

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(untagged_unions)]
12+
13+
use std::cell::Cell;
14+
use std::ops::Deref;
15+
use std::mem::ManuallyDrop;
16+
17+
union Wrap<T> { x: ManuallyDrop<T> }
18+
19+
impl<T> Drop for Wrap<T> {
20+
fn drop(&mut self) {
21+
unsafe { std::ptr::drop_in_place(&mut *self.x as *mut T); }
22+
}
23+
}
24+
25+
impl<T> Wrap<T> {
26+
fn new(x: T) -> Self {
27+
Wrap { x: ManuallyDrop::new(x) }
28+
}
29+
}
30+
31+
impl<T> Deref for Wrap<T> {
32+
type Target = T;
33+
#[inline]
34+
fn deref(&self) -> &Self::Target {
35+
unsafe {
36+
&self.x
37+
}
38+
}
39+
}
40+
41+
struct C<'a>(Cell<Option<&'a C<'a>>>);
42+
43+
impl<'a> Drop for C<'a> {
44+
fn drop(&mut self) {}
45+
}
46+
47+
fn main() {
48+
let v : Wrap<C> = Wrap::new(C(Cell::new(None)));
49+
v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
50+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0597]: `v` does not live long enough
2+
--> $DIR/dropck-union.rs:49:19
3+
|
4+
LL | v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
5+
| ^ borrowed value does not live long enough
6+
LL | }
7+
| - `v` dropped here while still borrowed
8+
|
9+
= note: values in a scope are dropped in the opposite order they are created
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)