librustc: Redo the unsafe checker and make unsafe methods not callable from safe code
This commit is contained in:
@@ -198,6 +198,7 @@ pub impl<T:Owned> MutexARC<T> {
|
|||||||
*/
|
*/
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn access<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
|
unsafe fn access<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
|
||||||
|
unsafe {
|
||||||
let state = self.x.get();
|
let state = self.x.get();
|
||||||
// Borrowck would complain about this if the function were
|
// Borrowck would complain about this if the function were
|
||||||
// not already unsafe. See borrow_rwlock, far below.
|
// not already unsafe. See borrow_rwlock, far below.
|
||||||
@@ -207,6 +208,7 @@ pub impl<T:Owned> MutexARC<T> {
|
|||||||
blk(&mut (*state).data)
|
blk(&mut (*state).data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// As access(), but with a condvar, as sync::mutex.lock_cond().
|
/// As access(), but with a condvar, as sync::mutex.lock_cond().
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -356,8 +358,8 @@ pub impl<T:Const + Owned> RWARC<T> {
|
|||||||
* access modes, this will not poison the ARC.
|
* access modes, this will not poison the ARC.
|
||||||
*/
|
*/
|
||||||
fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
|
fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
|
||||||
let state = self.x.get();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let state = self.x.get();
|
||||||
do (*state).lock.read {
|
do (*state).lock.read {
|
||||||
check_poison(false, (*state).failed);
|
check_poison(false, (*state).failed);
|
||||||
blk(&(*state).data)
|
blk(&(*state).data)
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ fn new_sem_and_signal(count: int, num_condvars: uint)
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub impl<Q:Owned> Sem<Q> {
|
pub impl<Q:Owned> Sem<Q> {
|
||||||
fn acquire(&self) {
|
fn acquire(&self) {
|
||||||
|
unsafe {
|
||||||
let mut waiter_nobe = None;
|
let mut waiter_nobe = None;
|
||||||
do (**self).with |state| {
|
do (**self).with |state| {
|
||||||
state.count -= 1;
|
state.count -= 1;
|
||||||
@@ -119,7 +120,9 @@ pub impl<Q:Owned> Sem<Q> {
|
|||||||
let _ = comm::recv_one(waiter_nobe.unwrap());
|
let _ = comm::recv_one(waiter_nobe.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn release(&self) {
|
fn release(&self) {
|
||||||
|
unsafe {
|
||||||
do (**self).with |state| {
|
do (**self).with |state| {
|
||||||
state.count += 1;
|
state.count += 1;
|
||||||
if state.count <= 0 {
|
if state.count <= 0 {
|
||||||
@@ -127,6 +130,7 @@ pub impl<Q:Owned> Sem<Q> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// FIXME(#3154) move both copies of this into Sem<Q>, and unify the 2 structs
|
// FIXME(#3154) move both copies of this into Sem<Q>, and unify the 2 structs
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -283,6 +287,7 @@ pub impl<'self> Condvar<'self> {
|
|||||||
|
|
||||||
/// As signal, but with a specified condvar_id. See wait_on.
|
/// As signal, but with a specified condvar_id. See wait_on.
|
||||||
fn signal_on(&self, condvar_id: uint) -> bool {
|
fn signal_on(&self, condvar_id: uint) -> bool {
|
||||||
|
unsafe {
|
||||||
let mut out_of_bounds = None;
|
let mut out_of_bounds = None;
|
||||||
let mut result = false;
|
let mut result = false;
|
||||||
do (**self.sem).with |state| {
|
do (**self.sem).with |state| {
|
||||||
@@ -296,6 +301,7 @@ pub impl<'self> Condvar<'self> {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Wake up all blocked tasks. Returns the number of tasks woken.
|
/// Wake up all blocked tasks. Returns the number of tasks woken.
|
||||||
fn broadcast(&self) -> uint { self.broadcast_on(0) }
|
fn broadcast(&self) -> uint { self.broadcast_on(0) }
|
||||||
@@ -304,6 +310,7 @@ pub impl<'self> Condvar<'self> {
|
|||||||
fn broadcast_on(&self, condvar_id: uint) -> uint {
|
fn broadcast_on(&self, condvar_id: uint) -> uint {
|
||||||
let mut out_of_bounds = None;
|
let mut out_of_bounds = None;
|
||||||
let mut queue = None;
|
let mut queue = None;
|
||||||
|
unsafe {
|
||||||
do (**self.sem).with |state| {
|
do (**self.sem).with |state| {
|
||||||
if condvar_id < state.blocked.len() {
|
if condvar_id < state.blocked.len() {
|
||||||
// To avoid :broadcast_heavy, we make a new waitqueue,
|
// To avoid :broadcast_heavy, we make a new waitqueue,
|
||||||
@@ -320,6 +327,7 @@ pub impl<'self> Condvar<'self> {
|
|||||||
broadcast_waitqueue(&queue)
|
broadcast_waitqueue(&queue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks whether a condvar ID was out of bounds, and fails if so, or does
|
// Checks whether a condvar ID was out of bounds, and fails if so, or does
|
||||||
|
|||||||
@@ -262,6 +262,9 @@ pub fn compile_rest(sess: Session,
|
|||||||
time(time_passes, ~"privacy checking", ||
|
time(time_passes, ~"privacy checking", ||
|
||||||
middle::privacy::check_crate(ty_cx, &method_map, crate));
|
middle::privacy::check_crate(ty_cx, &method_map, crate));
|
||||||
|
|
||||||
|
time(time_passes, ~"effect checking", ||
|
||||||
|
middle::effect::check_crate(ty_cx, method_map, crate));
|
||||||
|
|
||||||
time(time_passes, ~"loop checking", ||
|
time(time_passes, ~"loop checking", ||
|
||||||
middle::check_loop::check_crate(ty_cx, crate));
|
middle::check_loop::check_crate(ty_cx, crate));
|
||||||
|
|
||||||
|
|||||||
154
src/librustc/middle/effect.rs
Normal file
154
src/librustc/middle/effect.rs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// Copyright 2012-2013 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.
|
||||||
|
|
||||||
|
//! Enforces the Rust effect system. Currently there is just one effect,
|
||||||
|
/// `unsafe`.
|
||||||
|
|
||||||
|
use middle::ty::{ty_bare_fn, ty_closure, ty_ptr};
|
||||||
|
use middle::ty;
|
||||||
|
use middle::typeck::method_map;
|
||||||
|
use util::ppaux;
|
||||||
|
|
||||||
|
use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call};
|
||||||
|
use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn};
|
||||||
|
use syntax::ast;
|
||||||
|
use syntax::codemap::span;
|
||||||
|
use syntax::visit::{fk_item_fn, fk_method};
|
||||||
|
use syntax::visit;
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
enum UnsafeContext {
|
||||||
|
SafeContext,
|
||||||
|
UnsafeFn,
|
||||||
|
UnsafeBlock(node_id),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
/// The method map.
|
||||||
|
method_map: method_map,
|
||||||
|
/// Whether we're in an unsafe context.
|
||||||
|
unsafe_context: UnsafeContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_is_unsafe_function(ty: ty::t) -> bool {
|
||||||
|
match ty::get(ty).sty {
|
||||||
|
ty_bare_fn(ref f) => f.purity == unsafe_fn,
|
||||||
|
ty_closure(ref f) => f.purity == unsafe_fn,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_crate(tcx: ty::ctxt,
|
||||||
|
method_map: method_map,
|
||||||
|
crate: @ast::crate) {
|
||||||
|
let context = @mut Context {
|
||||||
|
method_map: method_map,
|
||||||
|
unsafe_context: SafeContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
let require_unsafe: @fn(span: span,
|
||||||
|
description: &str) = |span, description| {
|
||||||
|
match context.unsafe_context {
|
||||||
|
SafeContext => {
|
||||||
|
// Report an error.
|
||||||
|
tcx.sess.span_err(span,
|
||||||
|
fmt!("%s requires unsafe function or block",
|
||||||
|
description))
|
||||||
|
}
|
||||||
|
UnsafeBlock(block_id) => {
|
||||||
|
// OK, but record this.
|
||||||
|
debug!("effect: recording unsafe block as used: %?", block_id);
|
||||||
|
let _ = tcx.used_unsafe.insert(block_id);
|
||||||
|
}
|
||||||
|
UnsafeFn => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let visitor = visit::mk_vt(@visit::Visitor {
|
||||||
|
visit_fn: |fn_kind, fn_decl, block, span, node_id, _, visitor| {
|
||||||
|
let is_unsafe_fn = match *fn_kind {
|
||||||
|
fk_item_fn(_, _, purity, _) => purity == unsafe_fn,
|
||||||
|
fk_method(_, _, method) => method.purity == unsafe_fn,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let old_unsafe_context = context.unsafe_context;
|
||||||
|
if is_unsafe_fn {
|
||||||
|
context.unsafe_context = UnsafeFn
|
||||||
|
}
|
||||||
|
|
||||||
|
visit::visit_fn(fn_kind,
|
||||||
|
fn_decl,
|
||||||
|
block,
|
||||||
|
span,
|
||||||
|
node_id,
|
||||||
|
(),
|
||||||
|
visitor);
|
||||||
|
|
||||||
|
context.unsafe_context = old_unsafe_context
|
||||||
|
},
|
||||||
|
|
||||||
|
visit_block: |block, _, visitor| {
|
||||||
|
let old_unsafe_context = context.unsafe_context;
|
||||||
|
if block.node.rules == unsafe_blk {
|
||||||
|
context.unsafe_context = UnsafeBlock(block.node.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
visit::visit_block(block, (), visitor);
|
||||||
|
|
||||||
|
context.unsafe_context = old_unsafe_context
|
||||||
|
},
|
||||||
|
|
||||||
|
visit_expr: |expr, _, visitor| {
|
||||||
|
match expr.node {
|
||||||
|
expr_method_call(*) => {
|
||||||
|
let base_type = ty::node_id_to_type(tcx, expr.callee_id);
|
||||||
|
debug!("effect: method call case, base type is %s",
|
||||||
|
ppaux::ty_to_str(tcx, base_type));
|
||||||
|
if type_is_unsafe_function(base_type) {
|
||||||
|
require_unsafe(expr.span,
|
||||||
|
"invocation of unsafe method")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr_call(base, _, _) => {
|
||||||
|
let base_type = ty::node_id_to_type(tcx, base.id);
|
||||||
|
debug!("effect: call case, base type is %s",
|
||||||
|
ppaux::ty_to_str(tcx, base_type));
|
||||||
|
if type_is_unsafe_function(base_type) {
|
||||||
|
require_unsafe(expr.span, "call to unsafe function")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr_unary(deref, base) => {
|
||||||
|
let base_type = ty::node_id_to_type(tcx, base.id);
|
||||||
|
debug!("effect: unary case, base type is %s",
|
||||||
|
ppaux::ty_to_str(tcx, base_type));
|
||||||
|
match ty::get(base_type).sty {
|
||||||
|
ty_ptr(_) => {
|
||||||
|
require_unsafe(expr.span,
|
||||||
|
"dereference of unsafe pointer")
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr_inline_asm(*) => {
|
||||||
|
require_unsafe(expr.span, "use of inline assembly")
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit::visit_expr(expr, (), visitor)
|
||||||
|
},
|
||||||
|
|
||||||
|
.. *visit::default_visitor()
|
||||||
|
});
|
||||||
|
|
||||||
|
visit::visit_crate(crate, (), visitor)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -891,21 +891,6 @@ pub impl FnCtxt {
|
|||||||
infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup)
|
infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn require_unsafe(&self, sp: span, op: ~str) {
|
|
||||||
match self.ps.purity {
|
|
||||||
ast::unsafe_fn => {
|
|
||||||
// ok, but flag that we used the source of unsafeness
|
|
||||||
debug!("flagging %? as a used unsafe source", self.ps);
|
|
||||||
self.tcx().used_unsafe.insert(self.ps.def);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.ccx.tcx.sess.span_err(
|
|
||||||
sp,
|
|
||||||
fmt!("%s requires unsafe function or block", op));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_region_lb<R>(@mut self, lb: ast::node_id, f: &fn() -> R) -> R {
|
fn with_region_lb<R>(@mut self, lb: ast::node_id, f: &fn() -> R) -> R {
|
||||||
let old_region_lb = self.region_lb;
|
let old_region_lb = self.region_lb;
|
||||||
self.region_lb = lb;
|
self.region_lb = lb;
|
||||||
@@ -2285,16 +2270,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||||||
}
|
}
|
||||||
ast::deref => {
|
ast::deref => {
|
||||||
let sty = structure_of(fcx, expr.span, oprnd_t);
|
let sty = structure_of(fcx, expr.span, oprnd_t);
|
||||||
match sty {
|
|
||||||
// deref'ing an unsafe pointer requires that we be in
|
|
||||||
// an unsafe context
|
|
||||||
ty::ty_ptr(*) => {
|
|
||||||
fcx.require_unsafe(
|
|
||||||
expr.span,
|
|
||||||
~"dereference of unsafe pointer");
|
|
||||||
}
|
|
||||||
_ => { /*ok*/ }
|
|
||||||
}
|
|
||||||
let operand_ty = ty::deref_sty(tcx, &sty, true);
|
let operand_ty = ty::deref_sty(tcx, &sty, true);
|
||||||
match operand_ty {
|
match operand_ty {
|
||||||
Some(mt) => {
|
Some(mt) => {
|
||||||
@@ -2392,8 +2367,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||||||
fcx.write_ty(id, ty_param_bounds_and_ty.ty);
|
fcx.write_ty(id, ty_param_bounds_and_ty.ty);
|
||||||
}
|
}
|
||||||
ast::expr_inline_asm(ref ia) => {
|
ast::expr_inline_asm(ref ia) => {
|
||||||
fcx.require_unsafe(expr.span, ~"use of inline assembly");
|
|
||||||
|
|
||||||
for ia.inputs.each |&(_, in)| {
|
for ia.inputs.each |&(_, in)| {
|
||||||
check_expr(fcx, in);
|
check_expr(fcx, in);
|
||||||
}
|
}
|
||||||
@@ -3223,13 +3196,6 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::def_fn(id, ast::unsafe_fn) |
|
|
||||||
ast::def_static_method(id, _, ast::unsafe_fn) => {
|
|
||||||
// Unsafe functions can only be touched in an unsafe context
|
|
||||||
fcx.require_unsafe(sp, ~"access to unsafe function");
|
|
||||||
return ty::lookup_item_type(fcx.ccx.tcx, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::def_fn(id, _) | ast::def_static_method(id, _, _) |
|
ast::def_fn(id, _) | ast::def_static_method(id, _, _) |
|
||||||
ast::def_const(id) | ast::def_variant(_, id) |
|
ast::def_const(id) | ast::def_variant(_, id) |
|
||||||
ast::def_struct(id) => {
|
ast::def_struct(id) => {
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ pub mod middle {
|
|||||||
pub mod privacy;
|
pub mod privacy;
|
||||||
pub mod moves;
|
pub mod moves;
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
pub mod effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod front {
|
pub mod front {
|
||||||
|
|||||||
@@ -236,22 +236,26 @@ impl<T: Owned> SharedChan<T> {
|
|||||||
|
|
||||||
impl<T: Owned> GenericChan<T> for SharedChan<T> {
|
impl<T: Owned> GenericChan<T> for SharedChan<T> {
|
||||||
fn send(&self, x: T) {
|
fn send(&self, x: T) {
|
||||||
|
unsafe {
|
||||||
let mut xx = Some(x);
|
let mut xx = Some(x);
|
||||||
do self.ch.with_imm |chan| {
|
do self.ch.with_imm |chan| {
|
||||||
let x = replace(&mut xx, None);
|
let x = replace(&mut xx, None);
|
||||||
chan.send(x.unwrap())
|
chan.send(x.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
|
impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
|
||||||
fn try_send(&self, x: T) -> bool {
|
fn try_send(&self, x: T) -> bool {
|
||||||
|
unsafe {
|
||||||
let mut xx = Some(x);
|
let mut xx = Some(x);
|
||||||
do self.ch.with_imm |chan| {
|
do self.ch.with_imm |chan| {
|
||||||
let x = replace(&mut xx, None);
|
let x = replace(&mut xx, None);
|
||||||
chan.try_send(x.unwrap())
|
chan.try_send(x.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Owned> ::clone::Clone for SharedChan<T> {
|
impl<T: Owned> ::clone::Clone for SharedChan<T> {
|
||||||
|
|||||||
@@ -861,11 +861,8 @@ pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
|
|||||||
|
|
||||||
fn key(_: Exclusive<()>) { }
|
fn key(_: Exclusive<()>) { }
|
||||||
|
|
||||||
let result = unsafe {
|
unsafe {
|
||||||
global_data_clone_create(key, || {
|
let result = global_data_clone_create(key, || { ~exclusive(()) });
|
||||||
~exclusive(())
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
do result.with_imm() |_| {
|
do result.with_imm() |_| {
|
||||||
let old_dir = os::getcwd();
|
let old_dir = os::getcwd();
|
||||||
@@ -877,6 +874,7 @@ pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies a file from one location to another
|
/// Copies a file from one location to another
|
||||||
|
|||||||
@@ -29,11 +29,14 @@ impl<T: Owned> MessageQueue<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, value: T) {
|
pub fn push(&mut self, value: T) {
|
||||||
|
unsafe {
|
||||||
let value = Cell(value);
|
let value = Cell(value);
|
||||||
self.queue.with(|q| q.push(value.take()) );
|
self.queue.with(|q| q.push(value.take()) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
|
unsafe {
|
||||||
do self.queue.with |q| {
|
do self.queue.with |q| {
|
||||||
if !q.is_empty() {
|
if !q.is_empty() {
|
||||||
Some(q.shift())
|
Some(q.shift())
|
||||||
@@ -42,6 +45,7 @@ impl<T: Owned> MessageQueue<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for MessageQueue<T> {
|
impl<T> Clone for MessageQueue<T> {
|
||||||
|
|||||||
@@ -29,11 +29,14 @@ pub impl<T: Owned> WorkQueue<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, value: T) {
|
fn push(&mut self, value: T) {
|
||||||
|
unsafe {
|
||||||
let value = Cell(value);
|
let value = Cell(value);
|
||||||
self.queue.with(|q| q.unshift(value.take()) );
|
self.queue.with(|q| q.unshift(value.take()) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> Option<T> {
|
fn pop(&mut self) -> Option<T> {
|
||||||
|
unsafe {
|
||||||
do self.queue.with |q| {
|
do self.queue.with |q| {
|
||||||
if !q.is_empty() {
|
if !q.is_empty() {
|
||||||
Some(q.shift())
|
Some(q.shift())
|
||||||
@@ -42,8 +45,10 @@ pub impl<T: Owned> WorkQueue<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn steal(&mut self) -> Option<T> {
|
fn steal(&mut self) -> Option<T> {
|
||||||
|
unsafe {
|
||||||
do self.queue.with |q| {
|
do self.queue.with |q| {
|
||||||
if !q.is_empty() {
|
if !q.is_empty() {
|
||||||
Some(q.pop())
|
Some(q.pop())
|
||||||
@@ -52,10 +57,13 @@ pub impl<T: Owned> WorkQueue<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
self.queue.with_imm(|q| q.is_empty() )
|
self.queue.with_imm(|q| q.is_empty() )
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for WorkQueue<T> {
|
impl<T> Clone for WorkQueue<T> {
|
||||||
|
|||||||
@@ -159,13 +159,17 @@ struct AncestorList(Option<Exclusive<AncestorNode>>);
|
|||||||
// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
|
// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U {
|
fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U {
|
||||||
|
unsafe {
|
||||||
x.with(blk)
|
x.with(blk)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn access_ancestors<U>(x: &Exclusive<AncestorNode>,
|
fn access_ancestors<U>(x: &Exclusive<AncestorNode>,
|
||||||
blk: &fn(x: &mut AncestorNode) -> U) -> U {
|
blk: &fn(x: &mut AncestorNode) -> U) -> U {
|
||||||
|
unsafe {
|
||||||
x.with(blk)
|
x.with(blk)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterates over an ancestor list.
|
// Iterates over an ancestor list.
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ mod test {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
test::free();
|
test::free();
|
||||||
//~^ ERROR access to unsafe function requires unsafe function or block
|
//~^ ERROR call to unsafe function requires unsafe function or block
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ mod test {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = test::free;
|
let x = test::free;
|
||||||
//~^ ERROR access to unsafe function requires unsafe function or block
|
//~^ ERROR call to unsafe function requires unsafe function or block
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ use std::unstable::intrinsics::{init, forget};
|
|||||||
|
|
||||||
// Test that the `forget` and `init` intrinsics are really unsafe
|
// Test that the `forget` and `init` intrinsics are really unsafe
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let stuff = init::<int>(); //~ ERROR access to unsafe function requires unsafe
|
let stuff = init::<int>(); //~ ERROR call to unsafe function requires unsafe
|
||||||
forget(stuff); //~ ERROR access to unsafe function requires unsafe
|
forget(stuff); //~ ERROR call to unsafe function requires unsafe
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
unsafe fn f() { return; }
|
unsafe fn f() { return; }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
f(); //~ ERROR access to unsafe function requires unsafe function or block
|
f(); //~ ERROR call to unsafe function requires unsafe function or block
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
unsafe fn f() { return; }
|
unsafe fn f() { return; }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = f; //~ ERROR access to unsafe function requires unsafe function or block
|
let x = f;
|
||||||
x();
|
x(); //~ ERROR call to unsafe function requires unsafe function or block
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user