From 5411f1046071b98dcf4ecd97444c87029ed5d643 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 24 Aug 2015 21:42:26 -0700 Subject: [PATCH] use Void to ensure closure diverges --- Cargo.toml | 3 +++ examples/basic.rs | 1 + src/arch/common.rs | 7 +++++-- src/arch/x86/mod.rs | 5 ++++- src/arch/x86_64/mod.rs | 4 +++- src/context.rs | 6 ++++-- src/lib.rs | 2 ++ 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 972243b..73ef430 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,9 @@ build = "build.rs" [build-dependencies] gcc = "0.3.3" +[dependencies] +void = "0.0.5" + [features] default = ["os", "valgrind"] os = ["libc"] diff --git a/examples/basic.rs b/examples/basic.rs index a42e20a..c0de92c 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -15,6 +15,7 @@ fn main() { let mut ctx = Context::new(stack, move || { println!("it's alive!"); (*ctx_slot).swap(); + panic!("Do not come back!") }); ctx_slot = &mut ctx; diff --git a/src/arch/common.rs b/src/arch/common.rs index 48c4f98..465c1ca 100644 --- a/src/arch/common.rs +++ b/src/arch/common.rs @@ -5,10 +5,13 @@ use core::mem::{size_of, align_of}; use core::cmp::max; use core::ptr; +use void::{self, Void}; + use super::imp::STACK_ALIGN; -pub unsafe extern "C" fn rust_trampoline(f: *const F) { - ptr::read(f)() +pub unsafe extern "C" fn rust_trampoline(f: *const F) -> ! + where F: FnOnce() -> Void { + void::unreachable(ptr::read(f)()) } pub unsafe fn push(spp: &mut *mut usize, value: T) -> *mut T { diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs index 7c34191..513bfe0 100644 --- a/src/arch/x86/mod.rs +++ b/src/arch/x86/mod.rs @@ -3,6 +3,8 @@ // See the LICENSE file included in this distribution. use core::prelude::*; +use void::Void; + use stack::Stack; use super::common::{push, rust_trampoline}; @@ -16,7 +18,8 @@ pub struct Registers { impl Registers { #[inline] - pub unsafe fn new(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() { + pub unsafe fn new(stack: &mut S, f: F) -> Registers + where S: Stack, F: FnOnce() -> Void { let sp_limit = stack.limit(); let mut sp = stack.top() as *mut usize; let f_ptr = push(&mut sp, f); diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 3c7e8b5..157b843 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -2,6 +2,7 @@ // Copyright (c) 2015, edef // See the LICENSE file included in this distribution. use stack::Stack; +use void::Void; use super::common::{push, rust_trampoline}; pub const STACK_ALIGN: usize = 16; @@ -14,7 +15,8 @@ pub struct Registers { impl Registers { #[inline] - pub unsafe fn new(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() { + pub unsafe fn new(stack: &mut S, f: F) -> Registers + where S: Stack, F: FnOnce() -> Void { let sp_limit = stack.limit(); let mut sp = stack.top() as *mut usize; let f_ptr = push(&mut sp, f); diff --git a/src/context.rs b/src/context.rs index 955915b..ab65add 100644 --- a/src/context.rs +++ b/src/context.rs @@ -2,6 +2,9 @@ // Copyright (c) 2015, edef // See the LICENSE file included in this distribution. use core::marker::PhantomData; + +use void::Void; + use arch::Registers; use stack; 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 { /// Create a new Context. When it is swapped into, /// it will call the passed closure. - /// The closure shouldn't return - doing that will abort the process. #[inline] pub unsafe fn new(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 regs = Registers::new(&mut stack, f); Context { diff --git a/src/lib.rs b/src/lib.rs index bb1c9f3..a470e25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,8 @@ #[macro_use] extern crate std; +extern crate void; + pub use context::Context; pub use stack::Stack;