diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 8c3cb792948..ed5b470849c 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -235,6 +235,11 @@ impl<'a, 'tcx> ty::TyS<'tcx> { }) }); + if def.is_union() { + // unions don't have destructors regardless of the child types + res = res - TC::NeedsDrop; + } + if def.has_dtor() { res = res | TC::OwnsDtor; } diff --git a/src/test/run-pass/union/union-nodrop.rs b/src/test/run-pass/union/union-nodrop.rs new file mode 100644 index 00000000000..22f00be3066 --- /dev/null +++ b/src/test/run-pass/union/union-nodrop.rs @@ -0,0 +1,63 @@ +// Copyright 2016 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(core_intrinsics)] +#![feature(untagged_unions)] + +#![allow(unions_with_drop_fields)] +#![allow(dead_code)] + +use std::intrinsics::needs_drop; + +// drop types in destructors should not require +// drop_types_in_const +static X: Option>> = None; + +// A union that scrubs the drop glue from its inner type +union NoDrop {inner: T} + +// Copy currently can't be implemented on drop-containing unions, +// this may change later +// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289 + +// // We should be able to implement Copy for NoDrop +// impl Copy for NoDrop {} +// impl Clone for NoDrop {fn clone(&self) -> Self { *self }} + +// // We should be able to implement Copy for things using NoDrop +// #[derive(Copy, Clone)] +struct Foo { + x: NoDrop> +} + +struct Baz { + x: NoDrop>, + y: Box, +} + +union ActuallyDrop {inner: T} + +impl Drop for ActuallyDrop { + fn drop(&mut self) {} +} + +fn main() { + unsafe { + // NoDrop should not make needs_drop true + assert!(!needs_drop::()); + assert!(!needs_drop::>()); + assert!(!needs_drop::>>()); + // presence of other drop types should still work + assert!(needs_drop::()); + // drop impl on union itself should work + assert!(needs_drop::>()); + assert!(needs_drop::>>()); + } +}