Skip to content

Commit

Permalink
Introduce marker types for indicating variance and for opting out
Browse files Browse the repository at this point in the history
of builtin bounds.

Fixes #10834.
Fixes #11385.
cc #5922.
  • Loading branch information
nikomatsakis committed Feb 1, 2014
1 parent 83f0f6e commit 81d8328
Show file tree
Hide file tree
Showing 36 changed files with 729 additions and 154 deletions.
4 changes: 3 additions & 1 deletion src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use std::cast;
use std::cell::{Cell, RefCell};
use std::num;
use std::ptr;
use std::kinds::marker;
use std::mem;
use std::rt::global_heap;
use std::uint;
Expand Down Expand Up @@ -71,14 +72,14 @@ struct Chunk {
// different chunks than objects without destructors. This reduces
// overhead when initializing plain-old-data and means we don't need
// to waste time running the destructors of POD.
#[no_freeze]
pub struct Arena {
// The head is separated out from the list as a unbenchmarked
// microoptimization, to avoid needing to case on the list to
// access the head.
priv head: Chunk,
priv pod_head: Chunk,
priv chunks: RefCell<@List<Chunk>>,
priv no_freeze: marker::NoFreeze,
}

impl Arena {
Expand All @@ -91,6 +92,7 @@ impl Arena {
head: chunk(initial_size, false),
pod_head: chunk(initial_size, true),
chunks: RefCell::new(@Nil),
no_freeze: marker::NoFreeze,
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions src/libextra/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use sync;
use sync::{Mutex, RWLock};

use std::cast;
use std::kinds::marker;
use std::sync::arc::UnsafeArc;
use std::task;

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

/// An Arc with mutable data protected by a blocking mutex.
#[no_freeze]
pub struct MutexArc<T> { priv x: UnsafeArc<MutexArcInner<T>> }

pub struct MutexArc<T> {
priv x: UnsafeArc<MutexArcInner<T>>,
priv marker: marker::NoFreeze,
}

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

Expand All @@ -179,7 +182,8 @@ impl<T:Send> MutexArc<T> {
lock: Mutex::new_with_condvars(num_condvars),
failed: false, data: user_data
};
MutexArc { x: UnsafeArc::new(data) }
MutexArc { x: UnsafeArc::new(data),
marker: marker::NoFreeze, }
}

/**
Expand Down Expand Up @@ -318,16 +322,17 @@ struct RWArcInner<T> { lock: RWLock, failed: bool, data: T }
*
* Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
*/
#[no_freeze]
pub struct RWArc<T> {
priv x: UnsafeArc<RWArcInner<T>>,
priv marker: marker::NoFreeze,
}

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

}
Expand All @@ -347,7 +352,8 @@ impl<T:Freeze + Send> RWArc<T> {
lock: RWLock::new_with_condvars(num_condvars),
failed: false, data: user_data
};
RWArc { x: UnsafeArc::new(data), }
RWArc { x: UnsafeArc::new(data),
marker: marker::NoFreeze, }
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,17 @@ lets_do_this! {
37, ManagedHeapLangItem, "managed_heap", managed_heap;
38, ExchangeHeapLangItem, "exchange_heap", exchange_heap;
39, GcLangItem, "gc", gc;

40, CovariantTypeItem, "covariant_type", covariant_type;
41, ContravariantTypeItem, "contravariant_type", contravariant_type;
42, InvariantTypeItem, "invariant_type", invariant_type;

43, CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
44, ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
45, InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;

46, NoFreezeItem, "no_freeze_bound", no_freeze_bound;
47, NoSendItem, "no_send_bound", no_send_bound;
48, NoPodItem, "no_pod_bound", no_pod_bound;
49, ManagedItem, "managed_bound", managed_bound;
}
4 changes: 2 additions & 2 deletions src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,8 +957,8 @@ static other_attrs: &'static [&'static str] = &[
"thread_local", // for statics
"allow", "deny", "forbid", "warn", // lint options
"deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
"crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
"no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", "packed",
"crate_map", "cfg", "doc", "export_name", "link_section",
"no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
"simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
"macro_export", "must_use",

Expand Down
104 changes: 55 additions & 49 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ pub fn at_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef) -> ValueRef {
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
pub fn malloc_raw_dyn<'a>(
bcx: &'a Block,
bcx: &'a Block<'a>,
t: ty::t,
heap: heap,
size: ValueRef)
Expand Down Expand Up @@ -425,7 +425,7 @@ pub fn malloc_general_dyn<'a>(
}
}

pub fn malloc_general<'a>(bcx: &'a Block, t: ty::t, heap: heap)
pub fn malloc_general<'a>(bcx: &'a Block<'a>, t: ty::t, heap: heap)
-> MallocResult<'a> {
let ty = type_of(bcx.ccx(), t);
assert!(heap != heap_exchange);
Expand Down Expand Up @@ -1230,18 +1230,19 @@ pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
//
// Be warned! You must call `init_function` before doing anything with the
// returned function context.
pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
path: ast_map::Path,
llfndecl: ValueRef,
id: ast::NodeId,
has_env: bool,
output_type: ty::t,
param_substs: Option<@param_substs>,
sp: Option<Span>)
-> FunctionContext {
pub fn new_fn_ctxt<'a>(ccx: @CrateContext,
path: ast_map::Path,
llfndecl: ValueRef,
id: ast::NodeId,
has_env: bool,
output_type: ty::t,
param_substs: Option<@param_substs>,
sp: Option<Span>,
block_arena: &'a TypedArena<Block<'a>>)
-> FunctionContext<'a> {
for p in param_substs.iter() { p.validate(); }

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

let mut fcx = FunctionContext {
llfn: llfndecl,
llenv: None,
llretptr: Cell::new(None),
entry_bcx: RefCell::new(None),
alloca_insert_pt: Cell::new(None),
llreturn: Cell::new(None),
personality: Cell::new(None),
caller_expects_out_pointer: uses_outptr,
llargs: RefCell::new(HashMap::new()),
lllocals: RefCell::new(HashMap::new()),
llupvars: RefCell::new(HashMap::new()),
id: id,
param_substs: param_substs,
span: sp,
path: path,
block_arena: TypedArena::new(),
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(~[])
llfn: llfndecl,
llenv: None,
llretptr: Cell::new(None),
entry_bcx: RefCell::new(None),
alloca_insert_pt: Cell::new(None),
llreturn: Cell::new(None),
personality: Cell::new(None),
caller_expects_out_pointer: uses_outptr,
llargs: RefCell::new(HashMap::new()),
lllocals: RefCell::new(HashMap::new()),
llupvars: RefCell::new(HashMap::new()),
id: id,
param_substs: param_substs,
span: sp,
path: path,
block_arena: block_arena,
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(~[])
};

if has_env {
Expand Down Expand Up @@ -1328,18 +1329,6 @@ pub fn init_function<'a>(
}
}

pub fn new_fn_ctxt(ccx: @CrateContext,
path: ast_map::Path,
llfndecl: ValueRef,
has_env: bool,
output_type: ty::t,
sp: Option<Span>)
-> FunctionContext {
// FIXME(#11385): Do not call `init_function` here; it will typecheck
// but segfault.
new_fn_ctxt_detailed(ccx, path, llfndecl, -1, has_env, output_type, None, sp)
}

// NB: must keep 4 fns in sync:
//
// - type_of_fn
Expand Down Expand Up @@ -1411,7 +1400,8 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,

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

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

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

let fcx = new_fn_ctxt_detailed(ccx, path, llfndecl, id, has_env, output_type,
param_substs, Some(body.span));
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx,
path,
llfndecl,
id,
has_env,
output_type,
param_substs,
Some(body.span),
&arena);
init_function(&fcx, false, output_type, param_substs);

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

let fcx = new_fn_ctxt_detailed(ccx, ~[], llfndecl, ctor_id, false,
result_ty, param_substs, None);
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx,
~[],
llfndecl,
ctor_id,
false,
result_ty,
param_substs,
None,
&arena);
init_function(&fcx, false, result_ty, param_substs);

let arg_tys = ty::ty_fn_args(ctor_ty);
Expand Down
20 changes: 10 additions & 10 deletions src/librustc/middle/trans/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
self.ccx.tcx.sess.bug("No loop scope found");
}

fn normal_exit_block(&self,
fn normal_exit_block(&'a self,
cleanup_scope: ast::NodeId,
exit: uint) -> BasicBlockRef {
/*!
Expand All @@ -226,7 +226,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit))
}

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

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

fn trans_cleanups_to_exit_scope(&self,
fn trans_cleanups_to_exit_scope(&'a self,
label: EarlyExitLabel)
-> BasicBlockRef {
/*!
Expand Down Expand Up @@ -641,7 +641,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
prev_llbb
}

fn get_or_create_landing_pad(&self) -> BasicBlockRef {
fn get_or_create_landing_pad(&'a self) -> BasicBlockRef {
/*!
* Creates a landing pad for the top scope, if one does not
* exist. The landing pad will perform all cleanups necessary
Expand Down Expand Up @@ -903,10 +903,10 @@ pub trait CleanupMethods<'a> {
custom_scope: CustomScopeIndex)
-> &'a Block<'a>;
fn top_loop_scope(&self) -> ast::NodeId;
fn normal_exit_block(&self,
fn normal_exit_block(&'a self,
cleanup_scope: ast::NodeId,
exit: uint) -> BasicBlockRef;
fn return_exit_block(&self) -> BasicBlockRef;
fn return_exit_block(&'a self) -> BasicBlockRef;
fn schedule_drop_mem(&self,
cleanup_scope: ScopeId,
val: ValueRef,
Expand All @@ -929,7 +929,7 @@ pub trait CleanupMethods<'a> {
custom_scope: CustomScopeIndex,
cleanup: ~Cleanup);
fn needs_invoke(&self) -> bool;
fn get_landing_pad(&self) -> BasicBlockRef;
fn get_landing_pad(&'a self) -> BasicBlockRef;
}

trait CleanupHelperMethods<'a> {
Expand All @@ -940,10 +940,10 @@ trait CleanupHelperMethods<'a> {
fn trans_scope_cleanups(&self,
bcx: &'a Block<'a>,
scope: &CleanupScope<'a>) -> &'a Block<'a>;
fn trans_cleanups_to_exit_scope(&self,
fn trans_cleanups_to_exit_scope(&'a self,
label: EarlyExitLabel)
-> BasicBlockRef;
fn get_or_create_landing_pad(&self) -> BasicBlockRef;
fn get_or_create_landing_pad(&'a self) -> BasicBlockRef;
fn scopes_len(&self) -> uint;
fn push_scope(&self, scope: CleanupScope<'a>);
fn pop_scope(&self) -> CleanupScope<'a>;
Expand Down
Loading

5 comments on commit 81d8328

@bors
Copy link
Contributor

@bors bors commented on 81d8328 Feb 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from pnkfelix
at nikomatsakis@81d8328

@bors
Copy link
Contributor

@bors bors commented on 81d8328 Feb 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging nikomatsakis/rust/issue-11385-cell-and-variance = 81d8328 into auto

@bors
Copy link
Contributor

@bors bors commented on 81d8328 Feb 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nikomatsakis/rust/issue-11385-cell-and-variance = 81d8328 merged ok, testing candidate = cc6afe1

@bors
Copy link
Contributor

@bors bors commented on 81d8328 Feb 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 81d8328 Feb 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = cc6afe1

Please sign in to comment.