use Void to ensure closure diverges

pull/1/head
John Ericson 2015-08-24 21:42:26 -07:00 committed by edef
parent c83143511e
commit 5411f10460
7 changed files with 22 additions and 6 deletions

View File

@ -7,6 +7,9 @@ build = "build.rs"
[build-dependencies] [build-dependencies]
gcc = "0.3.3" gcc = "0.3.3"
[dependencies]
void = "0.0.5"
[features] [features]
default = ["os", "valgrind"] default = ["os", "valgrind"]
os = ["libc"] os = ["libc"]

View File

@ -15,6 +15,7 @@ fn main() {
let mut ctx = Context::new(stack, move || { let mut ctx = Context::new(stack, move || {
println!("it's alive!"); println!("it's alive!");
(*ctx_slot).swap(); (*ctx_slot).swap();
panic!("Do not come back!")
}); });
ctx_slot = &mut ctx; ctx_slot = &mut ctx;

View File

@ -5,10 +5,13 @@ use core::mem::{size_of, align_of};
use core::cmp::max; use core::cmp::max;
use core::ptr; use core::ptr;
use void::{self, Void};
use super::imp::STACK_ALIGN; use super::imp::STACK_ALIGN;
pub unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) { pub unsafe extern "C" fn rust_trampoline<F>(f: *const F) -> !
ptr::read(f)() where F: FnOnce() -> Void {
void::unreachable(ptr::read(f)())
} }
pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T { pub unsafe fn push<T>(spp: &mut *mut usize, value: T) -> *mut T {

View File

@ -3,6 +3,8 @@
// See the LICENSE file included in this distribution. // See the LICENSE file included in this distribution.
use core::prelude::*; use core::prelude::*;
use void::Void;
use stack::Stack; use stack::Stack;
use super::common::{push, rust_trampoline}; use super::common::{push, rust_trampoline};
@ -16,7 +18,8 @@ pub struct Registers {
impl Registers { impl Registers {
#[inline] #[inline]
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() { pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers
where S: Stack, F: FnOnce() -> Void {
let sp_limit = stack.limit(); let sp_limit = stack.limit();
let mut sp = stack.top() as *mut usize; let mut sp = stack.top() as *mut usize;
let f_ptr = push(&mut sp, f); let f_ptr = push(&mut sp, f);

View File

@ -2,6 +2,7 @@
// Copyright (c) 2015, edef <edef@edef.eu> // Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution. // See the LICENSE file included in this distribution.
use stack::Stack; use stack::Stack;
use void::Void;
use super::common::{push, rust_trampoline}; use super::common::{push, rust_trampoline};
pub const STACK_ALIGN: usize = 16; pub const STACK_ALIGN: usize = 16;
@ -14,7 +15,8 @@ pub struct Registers {
impl Registers { impl Registers {
#[inline] #[inline]
pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() { pub unsafe fn new<S, F>(stack: &mut S, f: F) -> Registers
where S: Stack, F: FnOnce() -> Void {
let sp_limit = stack.limit(); let sp_limit = stack.limit();
let mut sp = stack.top() as *mut usize; let mut sp = stack.top() as *mut usize;
let f_ptr = push(&mut sp, f); let f_ptr = push(&mut sp, f);

View File

@ -2,6 +2,9 @@
// Copyright (c) 2015, edef <edef@edef.eu> // Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution. // See the LICENSE file included in this distribution.
use core::marker::PhantomData; use core::marker::PhantomData;
use void::Void;
use arch::Registers; use arch::Registers;
use stack; use stack;
use debug::StackId; use debug::StackId;
@ -27,10 +30,9 @@ unsafe impl<'a, Stack> Send for Context<'a, Stack>
impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack { impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
/// Create a new Context. When it is swapped into, /// Create a new Context. When it is swapped into,
/// it will call the passed closure. /// it will call the passed closure.
/// The closure shouldn't return - doing that will abort the process.
#[inline] #[inline]
pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack> pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
where F: FnOnce() + Send + 'a { where F: FnOnce() -> Void + Send + 'a {
let stack_id = StackId::register(&mut stack); let stack_id = StackId::register(&mut stack);
let regs = Registers::new(&mut stack, f); let regs = Registers::new(&mut stack, f);
Context { Context {

View File

@ -12,6 +12,8 @@
#[macro_use] #[macro_use]
extern crate std; extern crate std;
extern crate void;
pub use context::Context; pub use context::Context;
pub use stack::Stack; pub use stack::Stack;