From 376a6b2663528b7174472e475a3f4e80ed54e122 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 12 Aug 2018 18:58:08 +0200 Subject: [PATCH 1/2] unions are not always trivially dropable Fixes #52786 --- src/librustc/traits/query/dropck_outlives.rs | 8 ++-- src/test/ui/dropck/dropck-union.nll.stderr | 16 ++++++++ src/test/ui/dropck/dropck-union.rs | 40 ++++++++++++++++++++ src/test/ui/dropck/dropck-union.stderr | 13 +++++++ 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/dropck/dropck-union.nll.stderr create mode 100644 src/test/ui/dropck/dropck-union.rs create mode 100644 src/test/ui/dropck/dropck-union.stderr diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index a48d24bb97a..e41ed0824b4 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -242,16 +242,14 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> .all(|t| trivial_dropck_outlives(tcx, t)), ty::TyAdt(def, _) => { - if def.is_union() { - // Unions never have a dtor. - true - } else if Some(def.did) == tcx.lang_items().manually_drop() { + if Some(def.did) == tcx.lang_items().manually_drop() { // `ManuallyDrop` never has a dtor. true } else { // Other types might. Moreover, PhantomData doesn't // 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 } } diff --git a/src/test/ui/dropck/dropck-union.nll.stderr b/src/test/ui/dropck/dropck-union.nll.stderr new file mode 100644 index 00000000000..375ae35af60 --- /dev/null +++ b/src/test/ui/dropck/dropck-union.nll.stderr @@ -0,0 +1,16 @@ +error[E0597]: `v` does not live long enough + --> $DIR/dropck-union.rs:39: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`. diff --git a/src/test/ui/dropck/dropck-union.rs b/src/test/ui/dropck/dropck-union.rs new file mode 100644 index 00000000000..ef4d1b360b8 --- /dev/null +++ b/src/test/ui/dropck/dropck-union.rs @@ -0,0 +1,40 @@ +#![feature(untagged_unions)] + +use std::cell::Cell; +use std::ops::Deref; +use std::mem::ManuallyDrop; + +union Wrap { x: ManuallyDrop } + +impl Drop for Wrap { + fn drop(&mut self) { + unsafe { std::ptr::drop_in_place(&mut *self.x as *mut T); } + } +} + +impl Wrap { + fn new(x: T) -> Self { + Wrap { x: ManuallyDrop::new(x) } + } +} + +impl Deref for Wrap { + type Target = T; + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { + &self.x + } + } +} + +struct C<'a>(Cell>>); + +impl<'a> Drop for C<'a> { + fn drop(&mut self) {} +} + +fn main() { + let v : Wrap = Wrap::new(C(Cell::new(None))); + v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough +} diff --git a/src/test/ui/dropck/dropck-union.stderr b/src/test/ui/dropck/dropck-union.stderr new file mode 100644 index 00000000000..6cb3c139132 --- /dev/null +++ b/src/test/ui/dropck/dropck-union.stderr @@ -0,0 +1,13 @@ +error[E0597]: `v` does not live long enough + --> $DIR/dropck-union.rs:39: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`. From d8f5790262fe17b5ff2a8e6ba00b890046f8f59b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 16 Aug 2018 20:36:34 +0200 Subject: [PATCH 2/2] fix license --- src/test/ui/dropck/dropck-union.nll.stderr | 2 +- src/test/ui/dropck/dropck-union.rs | 10 ++++++++++ src/test/ui/dropck/dropck-union.stderr | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/test/ui/dropck/dropck-union.nll.stderr b/src/test/ui/dropck/dropck-union.nll.stderr index 375ae35af60..35d7ffc7879 100644 --- a/src/test/ui/dropck/dropck-union.nll.stderr +++ b/src/test/ui/dropck/dropck-union.nll.stderr @@ -1,5 +1,5 @@ error[E0597]: `v` does not live long enough - --> $DIR/dropck-union.rs:39:18 + --> $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 diff --git a/src/test/ui/dropck/dropck-union.rs b/src/test/ui/dropck/dropck-union.rs index ef4d1b360b8..f16d761fdab 100644 --- a/src/test/ui/dropck/dropck-union.rs +++ b/src/test/ui/dropck/dropck-union.rs @@ -1,3 +1,13 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![feature(untagged_unions)] use std::cell::Cell; diff --git a/src/test/ui/dropck/dropck-union.stderr b/src/test/ui/dropck/dropck-union.stderr index 6cb3c139132..a383ca5d390 100644 --- a/src/test/ui/dropck/dropck-union.stderr +++ b/src/test/ui/dropck/dropck-union.stderr @@ -1,5 +1,5 @@ error[E0597]: `v` does not live long enough - --> $DIR/dropck-union.rs:39:19 + --> $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