Skip to content

Introduce marker types #11768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 1, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Member

Choose a reason for hiding this comment

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

you removed the above warning about init_function causing segfaults. Is your plan to later put in code to call init_function from within new_fn_ctxt, but you didn't want to remove this comment here about init_function until doing that?

Or does your code cause a hypothetical addition of init_function to no longer type-check, which is my more recent inference from reading your comment here? (Which would mean that this comment should indeed stay while the other comment should not stay, at least not in its current form.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't believe there is any danger. I didn't merge the two functions simply because that would have added yet more parameters to new_fn_ctxt, but maybe I should do so. It's not like one more parameter will hurt.

// 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