auto merge of #8677 : bblum/rust/scratch, r=alexcrichton
r anybody; there isn't anything complicated here
This commit is contained in:
commit
5e5e2c71e4
7 changed files with 110 additions and 54 deletions
|
|
@ -4814,9 +4814,13 @@ impl Resolver {
|
|||
DontAllowCapturingSelf) {
|
||||
Some(dl_def(def)) => return Some(def),
|
||||
_ => {
|
||||
self.session.span_bug(span,
|
||||
"self wasn't mapped to a \
|
||||
def?!")
|
||||
if self.session.has_errors() {
|
||||
// May happen inside a nested fn item, cf #6642.
|
||||
return None;
|
||||
} else {
|
||||
self.session.span_bug(span,
|
||||
"self wasn't mapped to a def?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@ impl<T> Cell<T> {
|
|||
this.value.take_unwrap()
|
||||
}
|
||||
|
||||
/// Yields the value if the cell is full, or `None` if it is empty.
|
||||
pub fn take_opt(&self) -> Option<T> {
|
||||
let this = unsafe { transmute_mut(self) };
|
||||
this.value.take()
|
||||
}
|
||||
|
||||
/// Returns the value, failing if the cell is full.
|
||||
pub fn put_back(&self, value: T) {
|
||||
let this = unsafe { transmute_mut(self) };
|
||||
|
|
|
|||
|
|
@ -40,3 +40,39 @@ macro_rules! rtabort(
|
|||
} )
|
||||
)
|
||||
|
||||
macro_rules! assert_once_ever(
|
||||
($( $msg:expr),+) => ( {
|
||||
// FIXME(#8472) extra function should not be needed to hide unsafe
|
||||
fn assert_once_ever() {
|
||||
unsafe {
|
||||
static mut already_happened: int = 0;
|
||||
// Double-check lock to avoid a swap in the common case.
|
||||
if already_happened != 0 ||
|
||||
::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
|
||||
fail!(fmt!("assert_once_ever happened twice: %s", fmt!($($msg),+)));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_once_ever();
|
||||
} )
|
||||
)
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_assert_once_ever_ok() {
|
||||
assert_once_ever!("help i'm stuck in an");
|
||||
assert_once_ever!("assertion error message");
|
||||
}
|
||||
|
||||
#[test] #[ignore(cfg(windows))] #[should_fail]
|
||||
fn test_assert_once_ever_fail() {
|
||||
use task;
|
||||
|
||||
fn f() { assert_once_ever!("if you're seeing this... good!") }
|
||||
|
||||
// linked & watched, naturally
|
||||
task::spawn(f);
|
||||
task::spawn(f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -499,13 +499,14 @@ impl<T> GenericPort<T> for Port<T> {
|
|||
}
|
||||
|
||||
fn try_recv(&self) -> Option<T> {
|
||||
let pone = self.next.take();
|
||||
match pone.try_recv() {
|
||||
Some(StreamPayload { val, next }) => {
|
||||
self.next.put_back(next);
|
||||
Some(val)
|
||||
do self.next.take_opt().map_move_default(None) |pone| {
|
||||
match pone.try_recv() {
|
||||
Some(StreamPayload { val, next }) => {
|
||||
self.next.put_back(next);
|
||||
Some(val)
|
||||
}
|
||||
None => None
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
|
|||
// task tree, shut down the schedulers and set the exit code.
|
||||
let handles = Cell::new(handles);
|
||||
let on_exit: ~fn(bool) = |exit_success| {
|
||||
assert_once_ever!("last task exiting");
|
||||
|
||||
let mut handles = handles.take();
|
||||
for handle in handles.mut_iter() {
|
||||
|
|
|
|||
|
|
@ -446,8 +446,7 @@ fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
|
|||
// Transitionary.
|
||||
struct RuntimeGlue;
|
||||
impl RuntimeGlue {
|
||||
fn kill_task(handle: KillHandle) {
|
||||
let mut handle = handle;
|
||||
fn kill_task(mut handle: KillHandle) {
|
||||
do handle.kill().map_move |killed_task| {
|
||||
let killed_task = Cell::new(killed_task);
|
||||
do Local::borrow::<Scheduler, ()> |sched| {
|
||||
|
|
@ -457,44 +456,38 @@ impl RuntimeGlue {
|
|||
}
|
||||
|
||||
fn with_task_handle_and_failing(blk: &fn(&KillHandle, bool)) {
|
||||
if in_green_task_context() {
|
||||
unsafe {
|
||||
// Can't use safe borrow, because the taskgroup destructor needs to
|
||||
// access the scheduler again to send kill signals to other tasks.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
|
||||
}
|
||||
} else {
|
||||
rtabort!("task dying in bad context")
|
||||
rtassert!(in_green_task_context());
|
||||
unsafe {
|
||||
// Can't use safe borrow, because the taskgroup destructor needs to
|
||||
// access the scheduler again to send kill signals to other tasks.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
|
||||
}
|
||||
}
|
||||
|
||||
fn with_my_taskgroup<U>(blk: &fn(&Taskgroup) -> U) -> U {
|
||||
if in_green_task_context() {
|
||||
unsafe {
|
||||
// Can't use safe borrow, because creating new hashmaps for the
|
||||
// tasksets requires an rng, which needs to borrow the sched.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
blk(match (*me).taskgroup {
|
||||
None => {
|
||||
// First task in its (unlinked/unsupervised) taskgroup.
|
||||
// Lazily initialize.
|
||||
let mut members = TaskSet::new();
|
||||
let my_handle = (*me).death.kill_handle.get_ref().clone();
|
||||
members.insert(my_handle);
|
||||
let tasks = Exclusive::new(Some(TaskGroupData {
|
||||
members: members,
|
||||
descendants: TaskSet::new(),
|
||||
}));
|
||||
let group = Taskgroup(tasks, AncestorList(None), None);
|
||||
(*me).taskgroup = Some(group);
|
||||
(*me).taskgroup.get_ref()
|
||||
}
|
||||
Some(ref group) => group,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
rtabort!("spawning in bad context")
|
||||
rtassert!(in_green_task_context());
|
||||
unsafe {
|
||||
// Can't use safe borrow, because creating new hashmaps for the
|
||||
// tasksets requires an rng, which needs to borrow the sched.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
blk(match (*me).taskgroup {
|
||||
None => {
|
||||
// First task in its (unlinked/unsupervised) taskgroup.
|
||||
// Lazily initialize.
|
||||
let mut members = TaskSet::new();
|
||||
let my_handle = (*me).death.kill_handle.get_ref().clone();
|
||||
members.insert(my_handle);
|
||||
let tasks = Exclusive::new(Some(TaskGroupData {
|
||||
members: members,
|
||||
descendants: TaskSet::new(),
|
||||
}));
|
||||
let group = Taskgroup(tasks, AncestorList(None), None);
|
||||
(*me).taskgroup = Some(group);
|
||||
(*me).taskgroup.get_ref()
|
||||
}
|
||||
Some(ref group) => group,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -567,17 +560,11 @@ fn enlist_many(child: &KillHandle, child_arc: &TaskGroupArc,
|
|||
result
|
||||
}
|
||||
|
||||
pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
|
||||
if in_green_task_context() {
|
||||
spawn_raw_newsched(opts, f)
|
||||
} else {
|
||||
fail!("can't spawn from this context")
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
|
||||
pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
|
||||
use rt::sched::*;
|
||||
|
||||
rtassert!(in_green_task_context());
|
||||
|
||||
let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised));
|
||||
let indestructible = opts.indestructible;
|
||||
|
||||
|
|
|
|||
21
src/test/compile-fail/issue-6642.rs
Normal file
21
src/test/compile-fail/issue-6642.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 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.
|
||||
|
||||
struct A;
|
||||
impl A {
|
||||
fn m(&self) {
|
||||
fn x() {
|
||||
self.m()
|
||||
//~^ ERROR can't capture dynamic environment in a fn item
|
||||
//~^^ ERROR `self` is not allowed in this context
|
||||
}
|
||||
}
|
||||
}
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue