Auto merge of #53288 - RalfJung:dropck, r=nikomatsakis

unions are not always trivially dropable

Fixes #52786

r? @nikomatsakis
This commit is contained in:
bors 2018-08-17 14:16:54 +00:00
commit 8dad6be9ad
4 changed files with 82 additions and 5 deletions

View File

@ -242,16 +242,14 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
.all(|t| trivial_dropck_outlives(tcx, t)), .all(|t| trivial_dropck_outlives(tcx, t)),
ty::TyAdt(def, _) => { ty::TyAdt(def, _) => {
if def.is_union() { if Some(def.did) == tcx.lang_items().manually_drop() {
// Unions never have a dtor.
true
} else if Some(def.did) == tcx.lang_items().manually_drop() {
// `ManuallyDrop` never has a dtor. // `ManuallyDrop` never has a dtor.
true true
} else { } else {
// Other types might. Moreover, PhantomData doesn't // Other types might. Moreover, PhantomData doesn't
// have a dtor, but it is considered to own its // have a dtor, but it is considered to own its
// content, so it is non-trivial. // content, so it is non-trivial. Unions can have `impl Drop`,
// and hence are non-trivial as well.
false false
} }
} }

View File

@ -0,0 +1,16 @@
error[E0597]: `v` does not live long enough
--> $DIR/dropck-union.rs:49:18
|
LL | v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
| ^^ borrowed value does not live long enough
LL | }
| -
| |
| `v` dropped here while still borrowed
| borrow later used here, when `v` is dropped
|
= note: values in a scope are dropped in the opposite order they are defined
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.

View File

@ -0,0 +1,50 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(untagged_unions)]
use std::cell::Cell;
use std::ops::Deref;
use std::mem::ManuallyDrop;
union Wrap<T> { x: ManuallyDrop<T> }
impl<T> Drop for Wrap<T> {
fn drop(&mut self) {
unsafe { std::ptr::drop_in_place(&mut *self.x as *mut T); }
}
}
impl<T> Wrap<T> {
fn new(x: T) -> Self {
Wrap { x: ManuallyDrop::new(x) }
}
}
impl<T> Deref for Wrap<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
&self.x
}
}
}
struct C<'a>(Cell<Option<&'a C<'a>>>);
impl<'a> Drop for C<'a> {
fn drop(&mut self) {}
}
fn main() {
let v : Wrap<C> = Wrap::new(C(Cell::new(None)));
v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
}

View File

@ -0,0 +1,13 @@
error[E0597]: `v` does not live long enough
--> $DIR/dropck-union.rs:49:19
|
LL | v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough
| ^ borrowed value does not live long enough
LL | }
| - `v` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.