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
@ -67,7 +67,7 @@ use middle::typeck::MethodCall;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::Repr;
|
||||
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 std::slice;
|
||||
@ -1200,12 +1200,19 @@ fn trans_boxed_expr<'a>(bcx: &'a Block<'a>,
|
||||
let size = llsize_of(bcx.ccx(), llty);
|
||||
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
||||
heap_exchange, size);
|
||||
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()
|
||||
// Unique boxes do not allocate for zero-size types. The standard library may assume
|
||||
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
|
||||
if llsize_of_alloc(bcx.ccx(), llty) == 0 {
|
||||
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||
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 {
|
||||
let base::MallocResult { bcx, smart_ptr: bx, body } =
|
||||
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.
|
||||
#[cfg(not(test))]
|
||||
#[lang="exchange_malloc"]
|
||||
#[inline]
|
||||
pub unsafe fn exchange_malloc(size: uint) -> *u8 {
|
||||
malloc_raw(size) as *u8
|
||||
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
|
||||
if size == 0 {
|
||||
&EMPTY as *() as *mut u8
|
||||
} else {
|
||||
malloc_raw(size)
|
||||
}
|
||||
}
|
||||
|
||||
// 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…
Reference in New Issue
Block a user