Skip to content

Commit 81d8328

Browse files
committed
Introduce marker types for indicating variance and for opting out
of builtin bounds. Fixes #10834. Fixes #11385. cc #5922.
1 parent 83f0f6e commit 81d8328

36 files changed

+729
-154
lines changed

src/libarena/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::cast;
3333
use std::cell::{Cell, RefCell};
3434
use std::num;
3535
use std::ptr;
36+
use std::kinds::marker;
3637
use std::mem;
3738
use std::rt::global_heap;
3839
use std::uint;
@@ -71,14 +72,14 @@ struct Chunk {
7172
// different chunks than objects without destructors. This reduces
7273
// overhead when initializing plain-old-data and means we don't need
7374
// to waste time running the destructors of POD.
74-
#[no_freeze]
7575
pub struct Arena {
7676
// The head is separated out from the list as a unbenchmarked
7777
// microoptimization, to avoid needing to case on the list to
7878
// access the head.
7979
priv head: Chunk,
8080
priv pod_head: Chunk,
8181
priv chunks: RefCell<@List<Chunk>>,
82+
priv no_freeze: marker::NoFreeze,
8283
}
8384

8485
impl Arena {
@@ -91,6 +92,7 @@ impl Arena {
9192
head: chunk(initial_size, false),
9293
pod_head: chunk(initial_size, true),
9394
chunks: RefCell::new(@Nil),
95+
no_freeze: marker::NoFreeze,
9496
}
9597
}
9698
}

src/libextra/arc.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use sync;
4545
use sync::{Mutex, RWLock};
4646

4747
use std::cast;
48+
use std::kinds::marker;
4849
use std::sync::arc::UnsafeArc;
4950
use std::task;
5051

@@ -150,17 +151,19 @@ impl<T:Freeze + Send> Clone for Arc<T> {
150151
struct MutexArcInner<T> { lock: Mutex, failed: bool, data: T }
151152

152153
/// An Arc with mutable data protected by a blocking mutex.
153-
#[no_freeze]
154-
pub struct MutexArc<T> { priv x: UnsafeArc<MutexArcInner<T>> }
155-
154+
pub struct MutexArc<T> {
155+
priv x: UnsafeArc<MutexArcInner<T>>,
156+
priv marker: marker::NoFreeze,
157+
}
156158

157159
impl<T:Send> Clone for MutexArc<T> {
158160
/// Duplicate a mutex-protected Arc. See arc::clone for more details.
159161
#[inline]
160162
fn clone(&self) -> MutexArc<T> {
161163
// NB: Cloning the underlying mutex is not necessary. Its reference
162164
// count would be exactly the same as the shared state's.
163-
MutexArc { x: self.x.clone() }
165+
MutexArc { x: self.x.clone(),
166+
marker: marker::NoFreeze, }
164167
}
165168
}
166169

@@ -179,7 +182,8 @@ impl<T:Send> MutexArc<T> {
179182
lock: Mutex::new_with_condvars(num_condvars),
180183
failed: false, data: user_data
181184
};
182-
MutexArc { x: UnsafeArc::new(data) }
185+
MutexArc { x: UnsafeArc::new(data),
186+
marker: marker::NoFreeze, }
183187
}
184188

185189
/**
@@ -318,16 +322,17 @@ struct RWArcInner<T> { lock: RWLock, failed: bool, data: T }
318322
*
319323
* Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
320324
*/
321-
#[no_freeze]
322325
pub struct RWArc<T> {
323326
priv x: UnsafeArc<RWArcInner<T>>,
327+
priv marker: marker::NoFreeze,
324328
}
325329

326330
impl<T:Freeze + Send> Clone for RWArc<T> {
327331
/// Duplicate a rwlock-protected Arc. See arc::clone for more details.
328332
#[inline]
329333
fn clone(&self) -> RWArc<T> {
330-
RWArc { x: self.x.clone() }
334+
RWArc { x: self.x.clone(),
335+
marker: marker::NoFreeze, }
331336
}
332337

333338
}
@@ -347,7 +352,8 @@ impl<T:Freeze + Send> RWArc<T> {
347352
lock: RWLock::new_with_condvars(num_condvars),
348353
failed: false, data: user_data
349354
};
350-
RWArc { x: UnsafeArc::new(data), }
355+
RWArc { x: UnsafeArc::new(data),
356+
marker: marker::NoFreeze, }
351357
}
352358

353359
/**

src/librustc/middle/lang_items.rs

+13
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,17 @@ lets_do_this! {
273273
37, ManagedHeapLangItem, "managed_heap", managed_heap;
274274
38, ExchangeHeapLangItem, "exchange_heap", exchange_heap;
275275
39, GcLangItem, "gc", gc;
276+
277+
40, CovariantTypeItem, "covariant_type", covariant_type;
278+
41, ContravariantTypeItem, "contravariant_type", contravariant_type;
279+
42, InvariantTypeItem, "invariant_type", invariant_type;
280+
281+
43, CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
282+
44, ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
283+
45, InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
284+
285+
46, NoFreezeItem, "no_freeze_bound", no_freeze_bound;
286+
47, NoSendItem, "no_send_bound", no_send_bound;
287+
48, NoPodItem, "no_pod_bound", no_pod_bound;
288+
49, ManagedItem, "managed_bound", managed_bound;
276289
}

src/librustc/middle/lint.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,8 @@ static other_attrs: &'static [&'static str] = &[
957957
"thread_local", // for statics
958958
"allow", "deny", "forbid", "warn", // lint options
959959
"deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
960-
"crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
961-
"no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", "packed",
960+
"crate_map", "cfg", "doc", "export_name", "link_section",
961+
"no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
962962
"simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
963963
"macro_export", "must_use",
964964

src/librustc/middle/trans/base.rs

+55-49
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ pub fn at_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef) -> ValueRef {
328328
// malloc_raw_dyn: allocates a box to contain a given type, but with a
329329
// potentially dynamic size.
330330
pub fn malloc_raw_dyn<'a>(
331-
bcx: &'a Block,
331+
bcx: &'a Block<'a>,
332332
t: ty::t,
333333
heap: heap,
334334
size: ValueRef)
@@ -425,7 +425,7 @@ pub fn malloc_general_dyn<'a>(
425425
}
426426
}
427427

428-
pub fn malloc_general<'a>(bcx: &'a Block, t: ty::t, heap: heap)
428+
pub fn malloc_general<'a>(bcx: &'a Block<'a>, t: ty::t, heap: heap)
429429
-> MallocResult<'a> {
430430
let ty = type_of(bcx.ccx(), t);
431431
assert!(heap != heap_exchange);
@@ -1230,18 +1230,19 @@ pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
12301230
//
12311231
// Be warned! You must call `init_function` before doing anything with the
12321232
// returned function context.
1233-
pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
1234-
path: ast_map::Path,
1235-
llfndecl: ValueRef,
1236-
id: ast::NodeId,
1237-
has_env: bool,
1238-
output_type: ty::t,
1239-
param_substs: Option<@param_substs>,
1240-
sp: Option<Span>)
1241-
-> FunctionContext {
1233+
pub fn new_fn_ctxt<'a>(ccx: @CrateContext,
1234+
path: ast_map::Path,
1235+
llfndecl: ValueRef,
1236+
id: ast::NodeId,
1237+
has_env: bool,
1238+
output_type: ty::t,
1239+
param_substs: Option<@param_substs>,
1240+
sp: Option<Span>,
1241+
block_arena: &'a TypedArena<Block<'a>>)
1242+
-> FunctionContext<'a> {
12421243
for p in param_substs.iter() { p.validate(); }
12431244

1244-
debug!("new_fn_ctxt_detailed(path={},
1245+
debug!("new_fn_ctxt(path={},
12451246
id={:?}, \
12461247
param_substs={})",
12471248
path_str(ccx.sess, path),
@@ -1258,25 +1259,25 @@ pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
12581259
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
12591260

12601261
let mut fcx = FunctionContext {
1261-
llfn: llfndecl,
1262-
llenv: None,
1263-
llretptr: Cell::new(None),
1264-
entry_bcx: RefCell::new(None),
1265-
alloca_insert_pt: Cell::new(None),
1266-
llreturn: Cell::new(None),
1267-
personality: Cell::new(None),
1268-
caller_expects_out_pointer: uses_outptr,
1269-
llargs: RefCell::new(HashMap::new()),
1270-
lllocals: RefCell::new(HashMap::new()),
1271-
llupvars: RefCell::new(HashMap::new()),
1272-
id: id,
1273-
param_substs: param_substs,
1274-
span: sp,
1275-
path: path,
1276-
block_arena: TypedArena::new(),
1277-
ccx: ccx,
1278-
debug_context: debug_context,
1279-
scopes: RefCell::new(~[])
1262+
llfn: llfndecl,
1263+
llenv: None,
1264+
llretptr: Cell::new(None),
1265+
entry_bcx: RefCell::new(None),
1266+
alloca_insert_pt: Cell::new(None),
1267+
llreturn: Cell::new(None),
1268+
personality: Cell::new(None),
1269+
caller_expects_out_pointer: uses_outptr,
1270+
llargs: RefCell::new(HashMap::new()),
1271+
lllocals: RefCell::new(HashMap::new()),
1272+
llupvars: RefCell::new(HashMap::new()),
1273+
id: id,
1274+
param_substs: param_substs,
1275+
span: sp,
1276+
path: path,
1277+
block_arena: block_arena,
1278+
ccx: ccx,
1279+
debug_context: debug_context,
1280+
scopes: RefCell::new(~[])
12801281
};
12811282

12821283
if has_env {
@@ -1328,18 +1329,6 @@ pub fn init_function<'a>(
13281329
}
13291330
}
13301331

1331-
pub fn new_fn_ctxt(ccx: @CrateContext,
1332-
path: ast_map::Path,
1333-
llfndecl: ValueRef,
1334-
has_env: bool,
1335-
output_type: ty::t,
1336-
sp: Option<Span>)
1337-
-> FunctionContext {
1338-
// FIXME(#11385): Do not call `init_function` here; it will typecheck
1339-
// but segfault.
1340-
new_fn_ctxt_detailed(ccx, path, llfndecl, -1, has_env, output_type, None, sp)
1341-
}
1342-
13431332
// NB: must keep 4 fns in sync:
13441333
//
13451334
// - type_of_fn
@@ -1411,7 +1400,8 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
14111400

14121401
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
14131402
// and builds the return block.
1414-
pub fn finish_fn(fcx: &FunctionContext, last_bcx: &Block) {
1403+
pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
1404+
last_bcx: &'a Block<'a>) {
14151405
let _icx = push_ctxt("finish_fn");
14161406

14171407
let ret_cx = match fcx.llreturn.get() {
@@ -1469,7 +1459,7 @@ pub fn trans_closure<'a>(ccx: @CrateContext,
14691459
id: ast::NodeId,
14701460
_attributes: &[ast::Attribute],
14711461
output_type: ty::t,
1472-
maybe_load_env: |&'a Block<'a>| -> &'a Block<'a>) {
1462+
maybe_load_env: <'b> |&'b Block<'b>| -> &'b Block<'b>) {
14731463
ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
14741464

14751465
let _icx = push_ctxt("trans_closure");
@@ -1483,8 +1473,16 @@ pub fn trans_closure<'a>(ccx: @CrateContext,
14831473
_ => false
14841474
};
14851475

1486-
let fcx = new_fn_ctxt_detailed(ccx, path, llfndecl, id, has_env, output_type,
1487-
param_substs, Some(body.span));
1476+
let arena = TypedArena::new();
1477+
let fcx = new_fn_ctxt(ccx,
1478+
path,
1479+
llfndecl,
1480+
id,
1481+
has_env,
1482+
output_type,
1483+
param_substs,
1484+
Some(body.span),
1485+
&arena);
14881486
init_function(&fcx, false, output_type, param_substs);
14891487

14901488
// cleanup scope for the incoming arguments
@@ -1626,8 +1624,16 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
16261624
ty_to_str(ccx.tcx, ctor_ty)))
16271625
};
16281626

1629-
let fcx = new_fn_ctxt_detailed(ccx, ~[], llfndecl, ctor_id, false,
1630-
result_ty, param_substs, None);
1627+
let arena = TypedArena::new();
1628+
let fcx = new_fn_ctxt(ccx,
1629+
~[],
1630+
llfndecl,
1631+
ctor_id,
1632+
false,
1633+
result_ty,
1634+
param_substs,
1635+
None,
1636+
&arena);
16311637
init_function(&fcx, false, result_ty, param_substs);
16321638

16331639
let arg_tys = ty::ty_fn_args(ctor_ty);

src/librustc/middle/trans/cleanup.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
214214
self.ccx.tcx.sess.bug("No loop scope found");
215215
}
216216

217-
fn normal_exit_block(&self,
217+
fn normal_exit_block(&'a self,
218218
cleanup_scope: ast::NodeId,
219219
exit: uint) -> BasicBlockRef {
220220
/*!
@@ -226,7 +226,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
226226
self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit))
227227
}
228228

229-
fn return_exit_block(&self) -> BasicBlockRef {
229+
fn return_exit_block(&'a self) -> BasicBlockRef {
230230
/*!
231231
* Returns a block to branch to which will perform all pending
232232
* cleanups and then return from this function
@@ -371,7 +371,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
371371
scopes.get().iter().rev().any(|s| s.needs_invoke())
372372
}
373373

374-
fn get_landing_pad(&self) -> BasicBlockRef {
374+
fn get_landing_pad(&'a self) -> BasicBlockRef {
375375
/*!
376376
* Returns a basic block to branch to in the event of a failure.
377377
* This block will run the failure cleanups and eventually
@@ -481,7 +481,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
481481
f(scopes.get().last().unwrap())
482482
}
483483

484-
fn trans_cleanups_to_exit_scope(&self,
484+
fn trans_cleanups_to_exit_scope(&'a self,
485485
label: EarlyExitLabel)
486486
-> BasicBlockRef {
487487
/*!
@@ -641,7 +641,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
641641
prev_llbb
642642
}
643643

644-
fn get_or_create_landing_pad(&self) -> BasicBlockRef {
644+
fn get_or_create_landing_pad(&'a self) -> BasicBlockRef {
645645
/*!
646646
* Creates a landing pad for the top scope, if one does not
647647
* exist. The landing pad will perform all cleanups necessary
@@ -903,10 +903,10 @@ pub trait CleanupMethods<'a> {
903903
custom_scope: CustomScopeIndex)
904904
-> &'a Block<'a>;
905905
fn top_loop_scope(&self) -> ast::NodeId;
906-
fn normal_exit_block(&self,
906+
fn normal_exit_block(&'a self,
907907
cleanup_scope: ast::NodeId,
908908
exit: uint) -> BasicBlockRef;
909-
fn return_exit_block(&self) -> BasicBlockRef;
909+
fn return_exit_block(&'a self) -> BasicBlockRef;
910910
fn schedule_drop_mem(&self,
911911
cleanup_scope: ScopeId,
912912
val: ValueRef,
@@ -929,7 +929,7 @@ pub trait CleanupMethods<'a> {
929929
custom_scope: CustomScopeIndex,
930930
cleanup: ~Cleanup);
931931
fn needs_invoke(&self) -> bool;
932-
fn get_landing_pad(&self) -> BasicBlockRef;
932+
fn get_landing_pad(&'a self) -> BasicBlockRef;
933933
}
934934

935935
trait CleanupHelperMethods<'a> {
@@ -940,10 +940,10 @@ trait CleanupHelperMethods<'a> {
940940
fn trans_scope_cleanups(&self,
941941
bcx: &'a Block<'a>,
942942
scope: &CleanupScope<'a>) -> &'a Block<'a>;
943-
fn trans_cleanups_to_exit_scope(&self,
943+
fn trans_cleanups_to_exit_scope(&'a self,
944944
label: EarlyExitLabel)
945945
-> BasicBlockRef;
946-
fn get_or_create_landing_pad(&self) -> BasicBlockRef;
946+
fn get_or_create_landing_pad(&'a self) -> BasicBlockRef;
947947
fn scopes_len(&self) -> uint;
948948
fn push_scope(&self, scope: CleanupScope<'a>);
949949
fn pop_scope(&self) -> CleanupScope<'a>;

0 commit comments

Comments
 (0)