Skip to content

Commit 5e5e2c7

Browse files
committed
auto merge of #8677 : bblum/rust/scratch, r=alexcrichton
r anybody; there isn't anything complicated here
2 parents 0688bde + 0081961 commit 5e5e2c7

File tree

7 files changed

+110
-54
lines changed

7 files changed

+110
-54
lines changed

src/librustc/middle/resolve.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4814,9 +4814,13 @@ impl Resolver {
48144814
DontAllowCapturingSelf) {
48154815
Some(dl_def(def)) => return Some(def),
48164816
_ => {
4817-
self.session.span_bug(span,
4818-
"self wasn't mapped to a \
4819-
def?!")
4817+
if self.session.has_errors() {
4818+
// May happen inside a nested fn item, cf #6642.
4819+
return None;
4820+
} else {
4821+
self.session.span_bug(span,
4822+
"self wasn't mapped to a def?!")
4823+
}
48204824
}
48214825
}
48224826
}

src/libstd/cell.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ impl<T> Cell<T> {
5050
this.value.take_unwrap()
5151
}
5252

53+
/// Yields the value if the cell is full, or `None` if it is empty.
54+
pub fn take_opt(&self) -> Option<T> {
55+
let this = unsafe { transmute_mut(self) };
56+
this.value.take()
57+
}
58+
5359
/// Returns the value, failing if the cell is full.
5460
pub fn put_back(&self, value: T) {
5561
let this = unsafe { transmute_mut(self) };

src/libstd/macros.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,39 @@ macro_rules! rtabort(
4040
} )
4141
)
4242

43+
macro_rules! assert_once_ever(
44+
($( $msg:expr),+) => ( {
45+
// FIXME(#8472) extra function should not be needed to hide unsafe
46+
fn assert_once_ever() {
47+
unsafe {
48+
static mut already_happened: int = 0;
49+
// Double-check lock to avoid a swap in the common case.
50+
if already_happened != 0 ||
51+
::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
52+
fail!(fmt!("assert_once_ever happened twice: %s", fmt!($($msg),+)));
53+
}
54+
}
55+
}
56+
assert_once_ever();
57+
} )
58+
)
59+
60+
#[cfg(test)]
61+
mod tests {
62+
#[test]
63+
fn test_assert_once_ever_ok() {
64+
assert_once_ever!("help i'm stuck in an");
65+
assert_once_ever!("assertion error message");
66+
}
67+
68+
#[test] #[ignore(cfg(windows))] #[should_fail]
69+
fn test_assert_once_ever_fail() {
70+
use task;
71+
72+
fn f() { assert_once_ever!("if you're seeing this... good!") }
73+
74+
// linked & watched, naturally
75+
task::spawn(f);
76+
task::spawn(f);
77+
}
78+
}

src/libstd/rt/comm.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,14 @@ impl<T> GenericPort<T> for Port<T> {
499499
}
500500

501501
fn try_recv(&self) -> Option<T> {
502-
let pone = self.next.take();
503-
match pone.try_recv() {
504-
Some(StreamPayload { val, next }) => {
505-
self.next.put_back(next);
506-
Some(val)
502+
do self.next.take_opt().map_move_default(None) |pone| {
503+
match pone.try_recv() {
504+
Some(StreamPayload { val, next }) => {
505+
self.next.put_back(next);
506+
Some(val)
507+
}
508+
None => None
507509
}
508-
None => None
509510
}
510511
}
511512
}

src/libstd/rt/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
323323
// task tree, shut down the schedulers and set the exit code.
324324
let handles = Cell::new(handles);
325325
let on_exit: ~fn(bool) = |exit_success| {
326+
assert_once_ever!("last task exiting");
326327

327328
let mut handles = handles.take();
328329
for handle in handles.mut_iter() {

src/libstd/task/spawn.rs

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,7 @@ fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
446446
// Transitionary.
447447
struct RuntimeGlue;
448448
impl RuntimeGlue {
449-
fn kill_task(handle: KillHandle) {
450-
let mut handle = handle;
449+
fn kill_task(mut handle: KillHandle) {
451450
do handle.kill().map_move |killed_task| {
452451
let killed_task = Cell::new(killed_task);
453452
do Local::borrow::<Scheduler, ()> |sched| {
@@ -457,44 +456,38 @@ impl RuntimeGlue {
457456
}
458457

459458
fn with_task_handle_and_failing(blk: &fn(&KillHandle, bool)) {
460-
if in_green_task_context() {
461-
unsafe {
462-
// Can't use safe borrow, because the taskgroup destructor needs to
463-
// access the scheduler again to send kill signals to other tasks.
464-
let me = Local::unsafe_borrow::<Task>();
465-
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
466-
}
467-
} else {
468-
rtabort!("task dying in bad context")
459+
rtassert!(in_green_task_context());
460+
unsafe {
461+
// Can't use safe borrow, because the taskgroup destructor needs to
462+
// access the scheduler again to send kill signals to other tasks.
463+
let me = Local::unsafe_borrow::<Task>();
464+
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
469465
}
470466
}
471467

472468
fn with_my_taskgroup<U>(blk: &fn(&Taskgroup) -> U) -> U {
473-
if in_green_task_context() {
474-
unsafe {
475-
// Can't use safe borrow, because creating new hashmaps for the
476-
// tasksets requires an rng, which needs to borrow the sched.
477-
let me = Local::unsafe_borrow::<Task>();
478-
blk(match (*me).taskgroup {
479-
None => {
480-
// First task in its (unlinked/unsupervised) taskgroup.
481-
// Lazily initialize.
482-
let mut members = TaskSet::new();
483-
let my_handle = (*me).death.kill_handle.get_ref().clone();
484-
members.insert(my_handle);
485-
let tasks = Exclusive::new(Some(TaskGroupData {
486-
members: members,
487-
descendants: TaskSet::new(),
488-
}));
489-
let group = Taskgroup(tasks, AncestorList(None), None);
490-
(*me).taskgroup = Some(group);
491-
(*me).taskgroup.get_ref()
492-
}
493-
Some(ref group) => group,
494-
})
495-
}
496-
} else {
497-
rtabort!("spawning in bad context")
469+
rtassert!(in_green_task_context());
470+
unsafe {
471+
// Can't use safe borrow, because creating new hashmaps for the
472+
// tasksets requires an rng, which needs to borrow the sched.
473+
let me = Local::unsafe_borrow::<Task>();
474+
blk(match (*me).taskgroup {
475+
None => {
476+
// First task in its (unlinked/unsupervised) taskgroup.
477+
// Lazily initialize.
478+
let mut members = TaskSet::new();
479+
let my_handle = (*me).death.kill_handle.get_ref().clone();
480+
members.insert(my_handle);
481+
let tasks = Exclusive::new(Some(TaskGroupData {
482+
members: members,
483+
descendants: TaskSet::new(),
484+
}));
485+
let group = Taskgroup(tasks, AncestorList(None), None);
486+
(*me).taskgroup = Some(group);
487+
(*me).taskgroup.get_ref()
488+
}
489+
Some(ref group) => group,
490+
})
498491
}
499492
}
500493
}
@@ -567,17 +560,11 @@ fn enlist_many(child: &KillHandle, child_arc: &TaskGroupArc,
567560
result
568561
}
569562

570-
pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
571-
if in_green_task_context() {
572-
spawn_raw_newsched(opts, f)
573-
} else {
574-
fail!("can't spawn from this context")
575-
}
576-
}
577-
578-
fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
563+
pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
579564
use rt::sched::*;
580565

566+
rtassert!(in_green_task_context());
567+
581568
let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised));
582569
let indestructible = opts.indestructible;
583570

src/test/compile-fail/issue-6642.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct A;
12+
impl A {
13+
fn m(&self) {
14+
fn x() {
15+
self.m()
16+
//~^ ERROR can't capture dynamic environment in a fn item
17+
//~^^ ERROR `self` is not allowed in this context
18+
}
19+
}
20+
}
21+
fn main() {}

0 commit comments

Comments
 (0)