Skip to content

Commit 05d0045

Browse files
committed
fix Option<~ZeroSizeType>
1778b63 provided the guarantee of no `exchange_free` calls for ~ZeroSizeType, so a sentinel can now be used without overhead. Closes #11998
1 parent 3786b55 commit 05d0045

File tree

3 files changed

+44
-9
lines changed

3 files changed

+44
-9
lines changed

src/librustc/middle/trans/expr.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use middle::typeck::MethodCall;
6767
use util::common::indenter;
6868
use util::ppaux::Repr;
6969
use util::nodemap::NodeMap;
70-
use middle::trans::machine::llsize_of;
70+
use middle::trans::machine::{llsize_of, llsize_of_alloc};
7171
use middle::trans::type_::Type;
7272

7373
use std::slice;
@@ -1200,12 +1200,19 @@ fn trans_boxed_expr<'a>(bcx: &'a Block<'a>,
12001200
let size = llsize_of(bcx.ccx(), llty);
12011201
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
12021202
heap_exchange, size);
1203-
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
1204-
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
1205-
val, heap_exchange);
1206-
let bcx = trans_into(bcx, contents, SaveIn(val));
1207-
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
1208-
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
1203+
// Unique boxes do not allocate for zero-size types. The standard library may assume
1204+
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
1205+
if llsize_of_alloc(bcx.ccx(), llty) == 0 {
1206+
let bcx = trans_into(bcx, contents, SaveIn(val));
1207+
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
1208+
} else {
1209+
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
1210+
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
1211+
val, heap_exchange);
1212+
let bcx = trans_into(bcx, contents, SaveIn(val));
1213+
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
1214+
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
1215+
}
12091216
} else {
12101217
let base::MallocResult { bcx, smart_ptr: bx, body } =
12111218
base::malloc_general(bcx, contents_ty, heap);

src/libstd/rt/global_heap.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,21 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
6464
}
6565
}
6666

67+
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
68+
// allocations can point to this `static`. It would be incorrect to use a null
69+
// pointer, due to enums assuming types like unique pointers are never null.
70+
static EMPTY: () = ();
71+
6772
/// The allocator for unique pointers without contained managed pointers.
6873
#[cfg(not(test))]
6974
#[lang="exchange_malloc"]
7075
#[inline]
71-
pub unsafe fn exchange_malloc(size: uint) -> *u8 {
72-
malloc_raw(size) as *u8
76+
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
77+
if size == 0 {
78+
&EMPTY as *() as *mut u8
79+
} else {
80+
malloc_raw(size)
81+
}
7382
}
7483

7584
// FIXME: #7496
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub fn main() {
12+
assert!(Some(~()).is_some());
13+
14+
struct Foo;
15+
assert!(Some(~Foo).is_some());
16+
17+
let xs: ~[()] = ~[];
18+
assert!(Some(xs).is_some());
19+
}

0 commit comments

Comments
 (0)