fix Option<~ZeroSizeType>
1778b63616
provided the guarantee of no
`exchange_free` calls for ~ZeroSizeType, so a sentinel can now be used
without overhead.
Closes #11998
This commit is contained in:
parent
1ac8b34ccd
commit
898669c4e2
3 changed files with 44 additions and 9 deletions
|
@ -67,7 +67,7 @@ use middle::typeck::MethodCall;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
use util::nodemap::NodeMap;
|
use util::nodemap::NodeMap;
|
||||||
use middle::trans::machine::llsize_of;
|
use middle::trans::machine::{llsize_of, llsize_of_alloc};
|
||||||
use middle::trans::type_::Type;
|
use middle::trans::type_::Type;
|
||||||
|
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -1200,12 +1200,19 @@ fn trans_boxed_expr<'a>(bcx: &'a Block<'a>,
|
||||||
let size = llsize_of(bcx.ccx(), llty);
|
let size = llsize_of(bcx.ccx(), llty);
|
||||||
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
||||||
heap_exchange, size);
|
heap_exchange, size);
|
||||||
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
|
// Unique boxes do not allocate for zero-size types. The standard library may assume
|
||||||
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
|
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
|
||||||
val, heap_exchange);
|
if llsize_of_alloc(bcx.ccx(), llty) == 0 {
|
||||||
let bcx = trans_into(bcx, contents, SaveIn(val));
|
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||||
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
|
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
|
||||||
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
|
} else {
|
||||||
|
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
|
||||||
|
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
|
||||||
|
val, heap_exchange);
|
||||||
|
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||||
|
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
|
||||||
|
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let base::MallocResult { bcx, smart_ptr: bx, body } =
|
let base::MallocResult { bcx, smart_ptr: bx, body } =
|
||||||
base::malloc_general(bcx, contents_ty, heap);
|
base::malloc_general(bcx, contents_ty, heap);
|
||||||
|
|
|
@ -64,12 +64,21 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
|
||||||
|
// allocations can point to this `static`. It would be incorrect to use a null
|
||||||
|
// pointer, due to enums assuming types like unique pointers are never null.
|
||||||
|
static EMPTY: () = ();
|
||||||
|
|
||||||
/// The allocator for unique pointers without contained managed pointers.
|
/// The allocator for unique pointers without contained managed pointers.
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang="exchange_malloc"]
|
#[lang="exchange_malloc"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn exchange_malloc(size: uint) -> *u8 {
|
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
|
||||||
malloc_raw(size) as *u8
|
if size == 0 {
|
||||||
|
&EMPTY as *() as *mut u8
|
||||||
|
} else {
|
||||||
|
malloc_raw(size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: #7496
|
// FIXME: #7496
|
||||||
|
|
19
src/test/run-pass/empty-allocation-non-null.rs
Normal file
19
src/test/run-pass/empty-allocation-non-null.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// 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 <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.
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
assert!(Some(~()).is_some());
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
assert!(Some(~Foo).is_some());
|
||||||
|
|
||||||
|
let xs: ~[()] = ~[];
|
||||||
|
assert!(Some(xs).is_some());
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue