about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libextra/rl.rs26
-rw-r--r--src/libextra/sort.rs35
-rw-r--r--src/librustc/middle/trans/base.rs41
-rw-r--r--src/librustc/middle/trans/context.rs14
-rw-r--r--src/librusti/program.rs24
-rw-r--r--src/libstd/condition.rs83
-rw-r--r--src/libstd/local_data.rs240
-rw-r--r--src/libstd/os.rs17
-rw-r--r--src/libstd/rand.rs16
-rw-r--r--src/libstd/rt/task.rs14
-rw-r--r--src/libstd/task/local_data_priv.rs7
-rw-r--r--src/libsyntax/ast_util.rs24
-rw-r--r--src/libsyntax/ext/expand.rs12
-rw-r--r--src/libsyntax/parse/token.rs23
-rw-r--r--src/test/compile-fail/core-tls-store-pointer.rs8
15 files changed, 291 insertions, 293 deletions
diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs
index c1eeb5005b2..b7b74694475 100644
--- a/src/libextra/rl.rs
+++ b/src/libextra/rl.rs
@@ -66,24 +66,28 @@ pub unsafe fn read(prompt: &str) -> Option<~str> {
     }
 }
 
-pub type CompletionCb<'self> = @fn(~str, &'self fn(~str));
+pub type CompletionCb = @fn(~str, @fn(~str));
 
-fn complete_key(_v: @CompletionCb) {}
+#[cfg(not(stage0))]
+static complete_key: local_data::Key<@CompletionCb> = &[];
+#[cfg(stage0)]
+fn complete_key(_: @CompletionCb) {}
 
 /// Bind to the main completion callback
 pub unsafe fn complete(cb: CompletionCb) {
-    local_data::set(complete_key, @(cb));
+    local_data::set(complete_key, @cb);
 
     extern fn callback(line: *c_char, completions: *()) {
-        unsafe {
-            let cb = *local_data::get(complete_key, |k| k.map(|&k| *k))
-                .get();
-
-            do cb(str::raw::from_c_str(line)) |suggestion| {
-                do str::as_c_str(suggestion) |buf| {
-                    rustrt::linenoiseAddCompletion(completions, buf);
+        do local_data::get(complete_key) |cb| {
+            let cb = **cb.unwrap();
+
+            unsafe {
+                do cb(str::raw::from_c_str(line)) |suggestion| {
+                    do str::as_c_str(suggestion) |buf| {
+                        rustrt::linenoiseAddCompletion(completions, buf);
+                    }
                 }
-            }
+}
         }
     }
 
diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs
index d4d6162a919..db4ad43e41d 100644
--- a/src/libextra/sort.rs
+++ b/src/libextra/sort.rs
@@ -1195,39 +1195,4 @@ mod big_tests {
             isSorted(arr);
         }
     }
-
-    struct LVal<'self> {
-        val: uint,
-        key: &'self fn:Copy(@uint),
-    }
-
-    #[unsafe_destructor]
-    impl<'self> Drop for LVal<'self> {
-        fn drop(&self) {
-            let x = unsafe { local_data::get(self.key, |k| k.map(|&k| *k)) };
-            match x {
-                Some(@y) => {
-                    unsafe {
-                        local_data::set(self.key, @(y+1));
-                    }
-                }
-                _ => fail!("Expected key to work"),
-            }
-        }
-    }
-
-    impl<'self> Ord for LVal<'self> {
-        fn lt<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val < other.val
-        }
-        fn le<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val <= other.val
-        }
-        fn gt<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val > other.val
-        }
-        fn ge<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val >= other.val
-        }
-    }
 }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 6d3f5d50b4b..bfa325a21ee 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -87,21 +87,20 @@ use syntax::abi::{X86, X86_64, Arm, Mips};
 
 pub use middle::trans::context::task_llcx;
 
-fn task_local_insn_key(_v: @~[&'static str]) {}
+#[cfg(not(stage0))]
+static task_local_insn_key: local_data::Key<@~[&'static str]> = &[];
+#[cfg(stage0)]
+fn task_local_insn_key(_: @~[&'static str]) {}
 
 pub fn with_insn_ctxt(blk: &fn(&[&'static str])) {
-    unsafe {
-        let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
-        if opt.is_some() {
-            blk(*opt.unwrap());
-        }
+    let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
+    if opt.is_some() {
+        blk(*opt.unwrap());
     }
 }
 
 pub fn init_insn_ctxt() {
-    unsafe {
-        local_data::set(task_local_insn_key, @~[]);
-    }
+    local_data::set(task_local_insn_key, @~[]);
 }
 
 pub struct _InsnCtxt { _x: () }
@@ -109,13 +108,11 @@ pub struct _InsnCtxt { _x: () }
 #[unsafe_destructor]
 impl Drop for _InsnCtxt {
     fn drop(&self) {
-        unsafe {
-            do local_data::modify(task_local_insn_key) |c| {
-                do c.map_consume |ctx| {
-                    let mut ctx = copy *ctx;
-                    ctx.pop();
-                    @ctx
-                }
+        do local_data::modify(task_local_insn_key) |c| {
+            do c.map_consume |ctx| {
+                let mut ctx = copy *ctx;
+                ctx.pop();
+                @ctx
             }
         }
     }
@@ -123,13 +120,11 @@ impl Drop for _InsnCtxt {
 
 pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
     debug!("new InsnCtxt: %s", s);
-    unsafe {
-        do local_data::modify(task_local_insn_key) |c| {
-            do c.map_consume |ctx| {
-                let mut ctx = copy *ctx;
-                ctx.push(s);
-                @ctx
-            }
+    do local_data::modify(task_local_insn_key) |c| {
+        do c.map_consume |ctx| {
+            let mut ctx = copy *ctx;
+            ctx.push(s);
+            @ctx
         }
     }
     _InsnCtxt { _x: () }
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index 1557916658d..a2f0fd480e1 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -232,22 +232,24 @@ impl CrateContext {
 #[unsafe_destructor]
 impl Drop for CrateContext {
     fn drop(&self) {
-        unsafe {
-            unset_task_llcx();
-        }
+        unset_task_llcx();
     }
 }
 
+#[cfg(stage0)]
 fn task_local_llcx_key(_v: @ContextRef) {}
+#[cfg(not(stage0))]
+static task_local_llcx_key: local_data::Key<@ContextRef> = &[];
+
 pub fn task_llcx() -> ContextRef {
-    let opt = unsafe { local_data::get(task_local_llcx_key, |k| k.map(|&k| *k)) };
+    let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
     *opt.expect("task-local LLVMContextRef wasn't ever set!")
 }
 
-unsafe fn set_task_llcx(c: ContextRef) {
+fn set_task_llcx(c: ContextRef) {
     local_data::set(task_local_llcx_key, @c);
 }
 
-unsafe fn unset_task_llcx() {
+fn unset_task_llcx() {
     local_data::pop(task_local_llcx_key);
 }
diff --git a/src/librusti/program.rs b/src/librusti/program.rs
index 716c7a2481e..d1d5b47ff57 100644
--- a/src/librusti/program.rs
+++ b/src/librusti/program.rs
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cast;
 use std::hashmap::HashMap;
 use std::local_data;
-use std::sys;
+use std::vec;
 
 use syntax::ast;
 use syntax::parse::token;
@@ -58,7 +57,7 @@ struct LocalVariable {
 }
 
 type LocalCache = @mut HashMap<~str, @~[u8]>;
-fn tls_key(_k: LocalCache) {}
+static tls_key: local_data::Key<LocalCache> = &[];
 
 impl Program {
     pub fn new() -> Program {
@@ -131,21 +130,18 @@ impl Program {
             fn main() {
         ");
 
-        let key: sys::Closure = unsafe {
-            let tls_key: &'static fn(LocalCache) = tls_key;
-            cast::transmute(tls_key)
-        };
+        let key: *LocalCache = vec::raw::to_ptr(tls_key);
         // First, get a handle to the tls map which stores all the local
         // variables. This works by totally legitimately using the 'code'
         // pointer of the 'tls_key' function as a uint, and then casting it back
         // up to a function
         code.push_str(fmt!("
             let __tls_map: @mut ::std::hashmap::HashMap<~str, @~[u8]> = unsafe {
-                let key = ::std::sys::Closure{ code: %? as *(),
-                                               env: ::std::ptr::null() };
+                let key = ::std::vec::raw::SliceRepr{ data: %? as *u8,
+                                                      len: 0 };
                 let key = ::std::cast::transmute(key);
                 ::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap()
-            };\n", key.code as uint));
+            };\n", key as uint));
 
         // Using this __tls_map handle, deserialize each variable binding that
         // we know about
@@ -226,18 +222,14 @@ impl Program {
         for self.local_vars.iter().advance |(name, value)| {
             map.insert(copy *name, @copy value.data);
         }
-        unsafe {
-            local_data::set(tls_key, map);
-        }
+        local_data::set(tls_key, map);
     }
 
     /// Once the program has finished running, this function will consume the
     /// task-local cache of local variables. After the program finishes running,
     /// it updates this cache with the new values of each local variable.
     pub fn consume_cache(&mut self) {
-        let map = unsafe {
-            local_data::pop(tls_key).expect("tls is empty")
-        };
+        let map = local_data::pop(tls_key).expect("tls is empty");
         do map.consume |name, value| {
             match self.local_vars.find_mut(&name) {
                 Some(v) => { v.data = copy *value; }
diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs
index d6d09527f83..3a5be12b3c5 100644
--- a/src/libstd/condition.rs
+++ b/src/libstd/condition.rs
@@ -23,13 +23,59 @@ pub struct Handler<T, U> {
     prev: Option<@Handler<T, U>>,
 }
 
+#[cfg(stage0)]
 pub struct Condition<'self, T, U> {
     name: &'static str,
     key: local_data::Key<'self, @Handler<T, U>>
 }
+#[cfg(not(stage0))]
+pub struct Condition<T, U> {
+    name: &'static str,
+    key: local_data::Key<@Handler<T, U>>
+}
+
+#[cfg(not(stage0))]
+impl<T, U> Condition<T, U> {
+    pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
+        unsafe {
+            let p : *RustClosure = ::cast::transmute(&h);
+            let prev = local_data::get(self.key, |k| k.map(|&x| *x));
+            let h = @Handler { handle: *p, prev: prev };
+            Trap { cond: self, handler: h }
+        }
+    }
+
+    pub fn raise(&self, t: T) -> U {
+        let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
+        self.raise_default(t, || fail!(copy msg))
+    }
 
+    pub fn raise_default(&self, t: T, default: &fn() -> U) -> U {
+        unsafe {
+            match local_data::pop(self.key) {
+                None => {
+                    debug!("Condition.raise: found no handler");
+                    default()
+                }
+                Some(handler) => {
+                    debug!("Condition.raise: found handler");
+                    match handler.prev {
+                        None => {}
+                        Some(hp) => local_data::set(self.key, hp)
+                    }
+                    let handle : &fn(T) -> U =
+                        ::cast::transmute(handler.handle);
+                    let u = handle(t);
+                    local_data::set(self.key, handler);
+                    u
+                }
+            }
+        }
+    }
+}
+#[cfg(stage0)]
 impl<'self, T, U> Condition<'self, T, U> {
-    pub fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
+    pub fn trap<'a>(&'a self, h: &'a fn(T) -> U) -> Trap<'a, T, U> {
         unsafe {
             let p : *RustClosure = ::cast::transmute(&h);
             let prev = local_data::get(self.key, |k| k.map(|&x| *x));
@@ -67,38 +113,45 @@ impl<'self, T, U> Condition<'self, T, U> {
     }
 }
 
+#[cfg(stage0)]
 struct Trap<'self, T, U> {
     cond: &'self Condition<'self, T, U>,
     handler: @Handler<T, U>
 }
+#[cfg(not(stage0))]
+struct Trap<'self, T, U> {
+    cond: &'self Condition<T, U>,
+    handler: @Handler<T, U>
+}
 
 impl<'self, T, U> Trap<'self, T, U> {
     pub fn in<V>(&self, inner: &'self fn() -> V) -> V {
-        unsafe {
-            let _g = Guard { cond: self.cond };
-            debug!("Trap: pushing handler to TLS");
-            local_data::set(self.cond.key, self.handler);
-            inner()
-        }
+        let _g = Guard { cond: self.cond };
+        debug!("Trap: pushing handler to TLS");
+        local_data::set(self.cond.key, self.handler);
+        inner()
     }
 }
 
+#[cfg(stage0)]
 struct Guard<'self, T, U> {
     cond: &'self Condition<'self, T, U>
 }
+#[cfg(not(stage0))]
+struct Guard<'self, T, U> {
+    cond: &'self Condition<T, U>
+}
 
 #[unsafe_destructor]
 impl<'self, T, U> Drop for Guard<'self, T, U> {
     fn drop(&self) {
-        unsafe {
-            debug!("Guard: popping handler from TLS");
-            let curr = local_data::pop(self.cond.key);
-            match curr {
+        debug!("Guard: popping handler from TLS");
+        let curr = local_data::pop(self.cond.key);
+        match curr {
+            None => {}
+            Some(h) => match h.prev {
                 None => {}
-                Some(h) => match h.prev {
-                    None => {}
-                    Some(hp) => local_data::set(self.cond.key, hp)
-                }
+                Some(hp) => local_data::set(self.cond.key, hp)
             }
         }
     }
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
index b241de88700..640bcc757b3 100644
--- a/src/libstd/local_data.rs
+++ b/src/libstd/local_data.rs
@@ -12,27 +12,25 @@
 
 Task local data management
 
-Allows storing boxes with arbitrary types inside, to be accessed anywhere within
-a task, keyed by a pointer to a global finaliser function. Useful for dynamic
-variables, singletons, and interfacing with foreign code with bad callback
-interfaces.
+Allows storing arbitrary types inside task-local-storage (TLS), to be accessed
+anywhere within a task, keyed by a global slice of the appropriate type.
+Useful for dynamic variables, singletons, and interfacing with foreign code
+with bad callback interfaces.
 
-To use, declare a monomorphic (no type parameters) global function at the type
-to store, and use it as the 'key' when accessing.
+To use, declare a static slice of the type you wish to store. The initialization
+should be `&[]`. This is then the key to what you wish to store.
 
 ~~~{.rust}
 use std::local_data;
 
-fn key_int(_: @int) {}
-fn key_vector(_: @~[int]) {}
+static key_int: local_data::Key<int> = &[];
+static key_vector: local_data::Key<~[int]> = &[];
 
-unsafe {
-    local_data::set(key_int, @3);
-    assert!(local_data::get(key_int) == Some(@3));
+local_data::set(key_int, 3);
+local_data::get(key_int, |opt| assert_eq!(opt, Some(&3)));
 
-    local_data::set(key_vector, @~[3]);
-    assert!(local_data::get(key_vector).unwrap()[0] == 3);
-}
+local_data::set(key_vector, ~[4]);
+local_data::get(key_int, |opt| assert_eq!(opt, Some(&~[4])));
 ~~~
 
 Casting 'Arcane Sight' reveals an overwhelming aura of Transmutation
@@ -60,6 +58,9 @@ use task::local_data_priv::{local_get, local_pop, local_set, Handle};
  *
  * These two cases aside, the interface is safe.
  */
+#[cfg(not(stage0))]
+pub type Key<T> = &'static [T];
+#[cfg(stage0)]
 pub type Key<'self,T> = &'self fn:Copy(v: T);
 
 /**
@@ -67,56 +68,55 @@ pub type Key<'self,T> = &'self fn:Copy(v: T);
  * reference that was originally created to insert it.
  */
 #[cfg(stage0)]
-pub unsafe fn pop<T: 'static>(key: Key<@T>) -> Option<@T> {
-    local_pop(Handle::new(), key)
+pub fn pop<T: 'static>(key: Key<@T>) -> Option<@T> {
+    unsafe { local_pop(Handle::new(), key) }
 }
 /**
  * Remove a task-local data value from the table, returning the
  * reference that was originally created to insert it.
  */
 #[cfg(not(stage0))]
-pub unsafe fn pop<T: 'static>(key: Key<T>) -> Option<T> {
-    local_pop(Handle::new(), key)
+pub fn pop<T: 'static>(key: Key<T>) -> Option<T> {
+    unsafe { local_pop(Handle::new(), key) }
 }
 /**
  * Retrieve a task-local data value. It will also be kept alive in the
  * table until explicitly removed.
  */
 #[cfg(stage0)]
-pub unsafe fn get<T: 'static, U>(key: Key<@T>, f: &fn(Option<&@T>) -> U) -> U {
-    local_get(Handle::new(), key, f)
+pub fn get<T: 'static, U>(key: Key<@T>, f: &fn(Option<&@T>) -> U) -> U {
+    unsafe { local_get(Handle::new(), key, f) }
 }
 /**
  * Retrieve a task-local data value. It will also be kept alive in the
  * table until explicitly removed.
  */
 #[cfg(not(stage0))]
-pub unsafe fn get<T: 'static, U>(key: Key<T>, f: &fn(Option<&T>) -> U) -> U {
-    local_get(Handle::new(), key, f)
+pub fn get<T: 'static, U>(key: Key<T>, f: &fn(Option<&T>) -> U) -> U {
+    unsafe { local_get(Handle::new(), key, f) }
 }
 /**
  * Store a value in task-local data. If this key already has a value,
  * that value is overwritten (and its destructor is run).
  */
 #[cfg(stage0)]
-pub unsafe fn set<T: 'static>(key: Key<@T>, data: @T) {
-    local_set(Handle::new(), key, data)
+pub fn set<T: 'static>(key: Key<@T>, data: @T) {
+    unsafe { local_set(Handle::new(), key, data) }
 }
 /**
  * Store a value in task-local data. If this key already has a value,
  * that value is overwritten (and its destructor is run).
  */
 #[cfg(not(stage0))]
-pub unsafe fn set<T: 'static>(key: Key<T>, data: T) {
-    local_set(Handle::new(), key, data)
+pub fn set<T: 'static>(key: Key<T>, data: T) {
+    unsafe { local_set(Handle::new(), key, data) }
 }
 /**
  * Modify a task-local data value. If the function returns 'None', the
  * data is removed (and its reference dropped).
  */
 #[cfg(stage0)]
-pub unsafe fn modify<T: 'static>(key: Key<@T>,
-                                 f: &fn(Option<@T>) -> Option<@T>) {
+pub fn modify<T: 'static>(key: Key<@T>, f: &fn(Option<@T>) -> Option<@T>) {
     match f(pop(key)) {
         Some(next) => { set(key, next); }
         None => {}
@@ -127,8 +127,7 @@ pub unsafe fn modify<T: 'static>(key: Key<@T>,
  * data is removed (and its reference dropped).
  */
 #[cfg(not(stage0))]
-pub unsafe fn modify<T: 'static>(key: Key<T>,
-                                 f: &fn(Option<T>) -> Option<T>) {
+pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) {
     match f(pop(key)) {
         Some(next) => { set(key, next); }
         None => {}
@@ -137,64 +136,56 @@ pub unsafe fn modify<T: 'static>(key: Key<T>,
 
 #[test]
 fn test_tls_multitask() {
-    unsafe {
-        fn my_key(_x: @~str) { }
-        set(my_key, @~"parent data");
-        do task::spawn {
-            // TLS shouldn't carry over.
-            assert!(get(my_key, |k| k.map(|&k| *k)).is_none());
-            set(my_key, @~"child data");
-            assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) ==
-                    ~"child data");
-            // should be cleaned up for us
-        }
-        // Must work multiple times
-        assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
-        assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
-        assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
+    static my_key: Key<@~str> = &[];
+    set(my_key, @~"parent data");
+    do task::spawn {
+        // TLS shouldn't carry over.
+        assert!(get(my_key, |k| k.map(|&k| *k)).is_none());
+        set(my_key, @~"child data");
+        assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) ==
+                ~"child data");
+        // should be cleaned up for us
     }
+    // Must work multiple times
+    assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
+    assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
+    assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"parent data");
 }
 
 #[test]
 fn test_tls_overwrite() {
-    unsafe {
-        fn my_key(_x: @~str) { }
-        set(my_key, @~"first data");
-        set(my_key, @~"next data"); // Shouldn't leak.
-        assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"next data");
-    }
+    static my_key: Key<@~str> = &[];
+    set(my_key, @~"first data");
+    set(my_key, @~"next data"); // Shouldn't leak.
+    assert!(*(get(my_key, |k| k.map(|&k| *k)).get()) == ~"next data");
 }
 
 #[test]
 fn test_tls_pop() {
-    unsafe {
-        fn my_key(_x: @~str) { }
-        set(my_key, @~"weasel");
-        assert!(*(pop(my_key).get()) == ~"weasel");
-        // Pop must remove the data from the map.
-        assert!(pop(my_key).is_none());
-    }
+    static my_key: Key<@~str> = &[];
+    set(my_key, @~"weasel");
+    assert!(*(pop(my_key).get()) == ~"weasel");
+    // Pop must remove the data from the map.
+    assert!(pop(my_key).is_none());
 }
 
 #[test]
 fn test_tls_modify() {
-    unsafe {
-        fn my_key(_x: @~str) { }
-        modify(my_key, |data| {
-            match data {
-                Some(@ref val) => fail!("unwelcome value: %s", *val),
-                None           => Some(@~"first data")
-            }
-        });
-        modify(my_key, |data| {
-            match data {
-                Some(@~"first data") => Some(@~"next data"),
-                Some(@ref val)       => fail!("wrong value: %s", *val),
-                None                 => fail!("missing value")
-            }
-        });
-        assert!(*(pop(my_key).get()) == ~"next data");
-    }
+    static my_key: Key<@~str> = &[];
+    modify(my_key, |data| {
+        match data {
+            Some(@ref val) => fail!("unwelcome value: %s", *val),
+            None           => Some(@~"first data")
+        }
+    });
+    modify(my_key, |data| {
+        match data {
+            Some(@~"first data") => Some(@~"next data"),
+            Some(@ref val)       => fail!("wrong value: %s", *val),
+            None                 => fail!("missing value")
+        }
+    });
+    assert!(*(pop(my_key).get()) == ~"next data");
 }
 
 #[test]
@@ -205,40 +196,36 @@ fn test_tls_crust_automorestack_memorial_bug() {
     // to get recorded as something within a rust stack segment. Then a
     // subsequent upcall (esp. for logging, think vsnprintf) would run on
     // a stack smaller than 1 MB.
-    fn my_key(_x: @~str) { }
+    static my_key: Key<@~str> = &[];
     do task::spawn {
-        unsafe { set(my_key, @~"hax"); }
+        set(my_key, @~"hax");
     }
 }
 
 #[test]
 fn test_tls_multiple_types() {
-    fn str_key(_x: @~str) { }
-    fn box_key(_x: @@()) { }
-    fn int_key(_x: @int) { }
+    static str_key: Key<@~str> = &[];
+    static box_key: Key<@@()> = &[];
+    static int_key: Key<@int> = &[];
     do task::spawn {
-        unsafe {
-            set(str_key, @~"string data");
-            set(box_key, @@());
-            set(int_key, @42);
-        }
+        set(str_key, @~"string data");
+        set(box_key, @@());
+        set(int_key, @42);
     }
 }
 
 #[test]
 fn test_tls_overwrite_multiple_types() {
-    fn str_key(_x: @~str) { }
-    fn box_key(_x: @@()) { }
-    fn int_key(_x: @int) { }
+    static str_key: Key<@~str> = &[];
+    static box_key: Key<@@()> = &[];
+    static int_key: Key<@int> = &[];
     do task::spawn {
-        unsafe {
-            set(str_key, @~"string data");
-            set(int_key, @42);
-            // This could cause a segfault if overwriting-destruction is done
-            // with the crazy polymorphic transmute rather than the provided
-            // finaliser.
-            set(int_key, @31337);
-        }
+        set(str_key, @~"string data");
+        set(int_key, @42);
+        // This could cause a segfault if overwriting-destruction is done
+        // with the crazy polymorphic transmute rather than the provided
+        // finaliser.
+        set(int_key, @31337);
     }
 }
 
@@ -246,38 +233,53 @@ fn test_tls_overwrite_multiple_types() {
 #[should_fail]
 #[ignore(cfg(windows))]
 fn test_tls_cleanup_on_failure() {
-    unsafe {
-        fn str_key(_x: @~str) { }
-        fn box_key(_x: @@()) { }
-        fn int_key(_x: @int) { }
-        set(str_key, @~"parent data");
+    static str_key: Key<@~str> = &[];
+    static box_key: Key<@@()> = &[];
+    static int_key: Key<@int> = &[];
+    set(str_key, @~"parent data");
+    set(box_key, @@());
+    do task::spawn {
+        // spawn_linked
+        set(str_key, @~"string data");
         set(box_key, @@());
-        do task::spawn {
-            // spawn_linked
-            set(str_key, @~"string data");
-            set(box_key, @@());
-            set(int_key, @42);
-            fail!();
-        }
-        // Not quite nondeterministic.
-        set(int_key, @31337);
+        set(int_key, @42);
         fail!();
     }
+    // Not quite nondeterministic.
+    set(int_key, @31337);
+    fail!();
 }
 
 #[test]
 fn test_static_pointer() {
-    unsafe {
-        fn key(_x: @&'static int) { }
-        static VALUE: int = 0;
-        set(key, @&VALUE);
-    }
+    static key: Key<@&'static int> = &[];
+    static VALUE: int = 0;
+    let v: @&'static int = @&VALUE;
+    set(key, v);
 }
 
 #[test]
 fn test_owned() {
-    unsafe {
-        fn key(_x: ~int) { }
-        set(key, ~1);
-    }
+    static key: Key<~int> = &[];
+    set(key, ~1);
+}
+
+#[test]
+fn test_same_key_type() {
+    static key1: Key<int> = &[];
+    static key2: Key<int> = &[];
+    static key3: Key<int> = &[];
+    static key4: Key<int> = &[];
+    static key5: Key<int> = &[];
+    set(key1, 1);
+    set(key2, 2);
+    set(key3, 3);
+    set(key4, 4);
+    set(key5, 5);
+
+    get(key1, |x| assert_eq!(*x.unwrap(), 1));
+    get(key2, |x| assert_eq!(*x.unwrap(), 2));
+    get(key3, |x| assert_eq!(*x.unwrap(), 3));
+    get(key4, |x| assert_eq!(*x.unwrap(), 4));
+    get(key5, |x| assert_eq!(*x.unwrap(), 5));
 }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 8d70732641d..cbd1e4e7663 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -1239,7 +1239,10 @@ struct OverriddenArgs {
     val: ~[~str]
 }
 
+#[cfg(stage0)]
 fn overridden_arg_key(_v: @OverriddenArgs) {}
+#[cfg(not(stage0))]
+static overridden_arg_key: local_data::Key<@OverriddenArgs> = &[];
 
 /// Returns the arguments which this program was started with (normally passed
 /// via the command line).
@@ -1247,11 +1250,9 @@ fn overridden_arg_key(_v: @OverriddenArgs) {}
 /// The return value of the function can be changed by invoking the
 /// `os::set_args` function.
 pub fn args() -> ~[~str] {
-    unsafe {
-        match local_data::get(overridden_arg_key, |k| k.map(|&k| *k)) {
-            None => real_args(),
-            Some(args) => copy args.val
-        }
+    match local_data::get(overridden_arg_key, |k| k.map(|&k| *k)) {
+        None => real_args(),
+        Some(args) => copy args.val
     }
 }
 
@@ -1259,10 +1260,8 @@ pub fn args() -> ~[~str] {
 /// program had when it started. These new arguments are only available to the
 /// current task via the `os::args` method.
 pub fn set_args(new_args: ~[~str]) {
-    unsafe {
-        let overridden_args = @OverriddenArgs { val: copy new_args };
-        local_data::set(overridden_arg_key, overridden_args);
-    }
+    let overridden_args = @OverriddenArgs { val: copy new_args };
+    local_data::set(overridden_arg_key, overridden_args);
 }
 
 // FIXME #6100 we should really use an internal implementation of this - using
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
index 2cf45ba70ec..8551012d6d7 100644
--- a/src/libstd/rand.rs
+++ b/src/libstd/rand.rs
@@ -851,7 +851,10 @@ pub fn seed() -> ~[u8] {
 }
 
 // used to make space in TLS for a random number generator
+#[cfg(stage0)]
 fn tls_rng_state(_v: @@mut IsaacRng) {}
+#[cfg(not(stage0))]
+static tls_rng_state: local_data::Key<@@mut IsaacRng> = &[];
 
 /**
  * Gives back a lazily initialized task-local random number generator,
@@ -860,17 +863,12 @@ fn tls_rng_state(_v: @@mut IsaacRng) {}
  */
 #[inline]
 pub fn task_rng() -> @mut IsaacRng {
-    let r : Option<@@mut IsaacRng>;
-    unsafe {
-        r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
-    }
+    let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
     match r {
         None => {
-            unsafe {
-                let rng = @@mut IsaacRng::new_seeded(seed());
-                local_data::set(tls_rng_state, rng);
-                *rng
-            }
+            let rng = @@mut IsaacRng::new_seeded(seed());
+            local_data::set(tls_rng_state, rng);
+            *rng
         }
         Some(rng) => *rng
     }
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index c5961be40ec..0fd8c5c03d3 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -348,14 +348,12 @@ mod test {
     fn tls() {
         use local_data;
         do run_in_newsched_task() {
-            unsafe {
-                fn key(_x: @~str) { }
-                local_data::set(key, @~"data");
-                assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data");
-                fn key2(_x: @~str) { }
-                local_data::set(key2, @~"data");
-                assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data");
-            }
+            static key: local_data::Key<@~str> = &[];
+            local_data::set(key, @~"data");
+            assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data");
+            static key2: local_data::Key<@~str> = &[];
+            local_data::set(key2, @~"data");
+            assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data");
         }
     }
 
diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs
index 42cfcbc16db..1a2141e996a 100644
--- a/src/libstd/task/local_data_priv.rs
+++ b/src/libstd/task/local_data_priv.rs
@@ -15,9 +15,9 @@ use libc;
 use local_data;
 use prelude::*;
 use ptr;
-use sys;
 use task::rt;
 use util;
+use vec;
 
 use super::rt::rust_task;
 use rt::task::{Task, LocalStorage};
@@ -142,9 +142,8 @@ unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap {
     }
 }
 
-unsafe fn key_to_key_value<T: 'static>(key: local_data::Key<T>) -> *libc::c_void {
-    let pair: sys::Closure = cast::transmute(key);
-    return pair.code as *libc::c_void;
+fn key_to_key_value<T: 'static>(key: local_data::Key<T>) -> *libc::c_void {
+    return vec::raw::to_ptr(key) as *libc::c_void;
 }
 
 pub unsafe fn local_pop<T: 'static>(handle: Handle,
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 7567dc0000b..0b876bf1f81 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -20,7 +20,6 @@ use std::hashmap::HashMap;
 use std::int;
 use std::num;
 use std::option;
-use std::cast;
 use std::local_data;
 
 pub fn path_name_i(idents: &[ident]) -> ~str {
@@ -695,18 +694,17 @@ pub fn new_sctable_internal() -> SCTable {
 
 // fetch the SCTable from TLS, create one if it doesn't yet exist.
 pub fn get_sctable() -> @mut SCTable {
-    unsafe {
-        let sctable_key = (cast::transmute::<(uint, uint),
-                           &fn:Copy(v: @@mut SCTable)>(
-                               (-4 as uint, 0u)));
-        match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
-            None => {
-                let new_table = @@mut new_sctable_internal();
-                local_data::set(sctable_key,new_table);
-                *new_table
-            },
-            Some(intr) => *intr
-        }
+    #[cfg(not(stage0))]
+    static sctable_key: local_data::Key<@@mut SCTable> = &[];
+    #[cfg(stage0)]
+    fn sctable_key(_: @@mut SCTable) {}
+    match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
+        None => {
+            let new_table = @@mut new_sctable_internal();
+            local_data::set(sctable_key,new_table);
+            *new_table
+        },
+        Some(intr) => *intr
     }
 }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 2c3f42cca9a..4fbc3862848 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -579,11 +579,11 @@ pub fn core_macros() -> @str {
         { pub $c:ident: $in:ty -> $out:ty; } => {
 
             pub mod $c {
-                fn key(_x: @::std::condition::Handler<$in,$out>) { }
+                #[allow(non_uppercase_statics)];
+                static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
 
-                #[allow(non_uppercase_statics)]
                 pub static cond :
-                    ::std::condition::Condition<'static,$in,$out> =
+                    ::std::condition::Condition<$in,$out> =
                     ::std::condition::Condition {
                         name: stringify!($c),
                         key: key
@@ -595,11 +595,11 @@ pub fn core_macros() -> @str {
 
             // FIXME (#6009): remove mod's `pub` below once variant above lands.
             pub mod $c {
-                fn key(_x: @::std::condition::Handler<$in,$out>) { }
+                #[allow(non_uppercase_statics)];
+                static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
 
-                #[allow(non_uppercase_statics)]
                 pub static cond :
-                    ::std::condition::Condition<'static,$in,$out> =
+                    ::std::condition::Condition<$in,$out> =
                     ::std::condition::Condition {
                         name: stringify!($c),
                         key: key
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 46e0ef32321..8737e571399 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -15,7 +15,6 @@ use parse::token;
 use util::interner::StrInterner;
 use util::interner;
 
-use std::cast;
 use std::cmp::Equiv;
 use std::local_data;
 use std::rand;
@@ -485,18 +484,16 @@ fn mk_fresh_ident_interner() -> @ident_interner {
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
 pub fn get_ident_interner() -> @ident_interner {
-    unsafe {
-        let key =
-            (cast::transmute::<(uint, uint),
-             &fn:Copy(v: @@::parse::token::ident_interner)>(
-                 (-3 as uint, 0u)));
-        match local_data::get(key, |k| k.map(|&k| *k)) {
-            Some(interner) => *interner,
-            None => {
-                let interner = mk_fresh_ident_interner();
-                local_data::set(key, @interner);
-                interner
-            }
+    #[cfg(not(stage0))]
+    static key: local_data::Key<@@::parse::token::ident_interner> = &[];
+    #[cfg(stage0)]
+    fn key(_: @@::parse::token::ident_interner) {}
+    match local_data::get(key, |k| k.map(|&k| *k)) {
+        Some(interner) => *interner,
+        None => {
+            let interner = mk_fresh_ident_interner();
+            local_data::set(key, @interner);
+            interner
         }
     }
 }
diff --git a/src/test/compile-fail/core-tls-store-pointer.rs b/src/test/compile-fail/core-tls-store-pointer.rs
index 13c99669228..f5b7f34b365 100644
--- a/src/test/compile-fail/core-tls-store-pointer.rs
+++ b/src/test/compile-fail/core-tls-store-pointer.rs
@@ -12,10 +12,6 @@
 
 use std::local_data;
 
-fn key(_x: @&int) { }
+static key: local_data::Key<@&int> = &[]; //~ ERROR only 'static is allowed
 
-fn main() {
-    unsafe {
-        local_data::set(key, @&0); //~ ERROR does not fulfill `'static`
-    }
-}
+fn main() {}