From 8007e31a5b59838d3ef48893c5b5cadca4078564 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 13 May 2016 03:09:21 +0300 Subject: [PATCH] Ban #[unsafe_no_drop_flag] on zero-sized types. --- src/librustc/ty/layout.rs | 16 ++++++++-- src/librustc/ty/mod.rs | 2 +- src/librustc_trans/type_of.rs | 5 ++++ .../zero-size-type-destructors.rs | 6 ++-- src/test/run-pass/auxiliary/issue-10028.rs | 22 -------------- src/test/run-pass/issue-10028.rs | 29 ------------------- 6 files changed, 22 insertions(+), 58 deletions(-) rename src/test/{run-pass => compile-fail}/zero-size-type-destructors.rs (80%) delete mode 100644 src/test/run-pass/auxiliary/issue-10028.rs delete mode 100644 src/test/run-pass/issue-10028.rs diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 82a3b0b8db284..d46e3c519093b 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -882,13 +882,19 @@ impl<'a, 'gcx, 'tcx> Layout { // won't actually be in the location we say it is because it'll be after // the unsized field. Several other pieces of code assume that the unsized // field is definitely the last one. - if def.dtor_kind().has_drop_flag() && + let dtor_kind = def.dtor_kind(); + if dtor_kind.has_drop_flag() && ty.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) { st.extend(dl, Some(Ok(&Scalar { value: Int(I8), non_zero: false })).into_iter(), ty)?; } + if dtor_kind == ty::TraitDtor(false) && st.min_size().bytes() == 0 { + let span = tcx.map.def_id_span(def.did, DUMMY_SP); + tcx.sess.span_fatal(span, &format!( + "cannot have a destructor for zero-sized type `{}`", ty)); + } Univariant { variant: st, non_zero: Some(def.did) == tcx.lang_items.non_zero() @@ -898,7 +904,8 @@ impl<'a, 'gcx, 'tcx> Layout { let hint = *tcx.lookup_repr_hints(def.did).get(0) .unwrap_or(&attr::ReprAny); - let dtor = def.dtor_kind().has_drop_flag(); + let dtor_kind = def.dtor_kind(); + let dtor = dtor_kind.has_drop_flag(); let drop_flag = if dtor { Some(Scalar { value: Int(I8), non_zero: false }) } else { @@ -953,6 +960,11 @@ impl<'a, 'gcx, 'tcx> Layout { }); let mut st = Struct::new(dl, false); st.extend(dl, fields.chain(drop_flag.iter().map(Ok)), ty)?; + if dtor_kind == ty::TraitDtor(false) && st.min_size().bytes() == 0 { + let span = tcx.map.def_id_span(def.did, DUMMY_SP); + tcx.sess.span_fatal(span, &format!( + "cannot have a destructor for zero-sized type `{}`", ty)); + } return Ok(Univariant { variant: st, non_zero: false }); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 005d83da38dbf..b66d85e98f24a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -117,7 +117,7 @@ pub struct CrateAnalysis<'a> { pub glob_map: Option, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum DtorKind { NoDtor, TraitDtor(bool) diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 98ec87ebbcf6f..ac7072da44a21 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -231,6 +231,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> return llty; } + // FIXME(eddyb) use the layout to actually compute the LLVM type. + let _layout = cx.tcx().normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| { + t.layout(&infcx) + }); + let mut llty = match t.sty { ty::TyBool => Type::bool(cx), ty::TyChar => Type::char(cx), diff --git a/src/test/run-pass/zero-size-type-destructors.rs b/src/test/compile-fail/zero-size-type-destructors.rs similarity index 80% rename from src/test/run-pass/zero-size-type-destructors.rs rename to src/test/compile-fail/zero-size-type-destructors.rs index a663ae650c087..bb438ffa12622 100644 --- a/src/test/run-pass/zero-size-type-destructors.rs +++ b/src/test/compile-fail/zero-size-type-destructors.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_attrs, unsafe_no_drop_flag)] - -// ignore-pretty : (#23623) problems when ending with // comments +#![feature(unsafe_no_drop_flag)] static mut destructions : isize = 3; -#[rustc_no_mir] // FIXME #29855 MIR doesn't handle all drops correctly. pub fn foo() { #[unsafe_no_drop_flag] struct Foo; + //~^ ERROR cannot have a destructor for zero-sized type `foo::Foo` impl Drop for Foo { fn drop(&mut self) { diff --git a/src/test/run-pass/auxiliary/issue-10028.rs b/src/test/run-pass/auxiliary/issue-10028.rs deleted file mode 100644 index a21deb44fcc83..0000000000000 --- a/src/test/run-pass/auxiliary/issue-10028.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 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(unsafe_no_drop_flag)] - -#[unsafe_no_drop_flag] -pub struct ZeroLengthThingWithDestructor; -impl Drop for ZeroLengthThingWithDestructor { - fn drop(&mut self) {} -} -impl ZeroLengthThingWithDestructor { - pub fn new() -> ZeroLengthThingWithDestructor { - ZeroLengthThingWithDestructor - } -} diff --git a/src/test/run-pass/issue-10028.rs b/src/test/run-pass/issue-10028.rs deleted file mode 100644 index 53d6f67f119ee..0000000000000 --- a/src/test/run-pass/issue-10028.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2014 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. - -// aux-build:issue-10028.rs - -// pretty-expanded FIXME #23616 - -extern crate issue_10028 as issue10028; - -use issue10028::ZeroLengthThingWithDestructor; - -struct Foo { - zero_length_thing: ZeroLengthThingWithDestructor -} - -fn make_foo() -> Foo { - Foo { zero_length_thing: ZeroLengthThingWithDestructor::new() } -} - -fn main() { - let _f:Foo = make_foo(); -}