about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libextra/rl.rs2
-rw-r--r--src/librustc/back/link.rs8
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/librustc/middle/trans/context.rs2
-rw-r--r--src/librusti/program.rs10
-rw-r--r--src/libstd/local_data.rs80
-rw-r--r--src/libstd/os.rs2
-rw-r--r--src/libstd/rand.rs2
-rw-r--r--src/libstd/rt/task.rs4
-rw-r--r--src/libstd/std.rs1
-rw-r--r--src/libstd/task/local_data_priv.rs3
-rw-r--r--src/libstd/task/spawn.rs19
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/expand.rs8
-rw-r--r--src/libsyntax/parse/token.rs3
-rw-r--r--src/test/compile-fail/core-tls-store-pointer.rs3
16 files changed, 81 insertions, 70 deletions
diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs
index b7b74694475..59801c945b6 100644
--- a/src/libextra/rl.rs
+++ b/src/libextra/rl.rs
@@ -69,7 +69,7 @@ pub unsafe fn read(prompt: &str) -> Option<~str> {
 pub type CompletionCb = @fn(~str, @fn(~str));
 
 #[cfg(not(stage0))]
-static complete_key: local_data::Key<@CompletionCb> = &[];
+static complete_key: local_data::Key<@CompletionCb> = &local_data::Key;
 #[cfg(stage0)]
 fn complete_key(_: @CompletionCb) {}
 
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 593a1ed535d..aeed2d842c1 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -105,6 +105,7 @@ pub mod jit {
     use metadata::cstore;
 
     use std::cast;
+    #[cfg(not(stage0))]
     use std::local_data;
     use std::unstable::intrinsics;
 
@@ -202,18 +203,19 @@ pub mod jit {
 
     // The stage1 compiler won't work, but that doesn't really matter. TLS
     // changed only very recently to allow storage of owned values.
-    fn engine_key(_: ~Engine) {}
+    #[cfg(not(stage0))]
+    static engine_key: local_data::Key<~Engine> = &local_data::Key;
 
     #[cfg(not(stage0))]
     fn set_engine(engine: ~Engine) {
-        unsafe { local_data::set(engine_key, engine) }
+        local_data::set(engine_key, engine)
     }
     #[cfg(stage0)]
     fn set_engine(_: ~Engine) {}
 
     #[cfg(not(stage0))]
     pub fn consume_engine() -> Option<~Engine> {
-        unsafe { local_data::pop(engine_key) }
+        local_data::pop(engine_key)
     }
     #[cfg(stage0)]
     pub fn consume_engine() -> Option<~Engine> { None }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index bfa325a21ee..7182f7ff8b7 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -88,7 +88,7 @@ use syntax::abi::{X86, X86_64, Arm, Mips};
 pub use middle::trans::context::task_llcx;
 
 #[cfg(not(stage0))]
-static task_local_insn_key: local_data::Key<@~[&'static str]> = &[];
+static task_local_insn_key: local_data::Key<@~[&'static str]> = &local_data::Key;
 #[cfg(stage0)]
 fn task_local_insn_key(_: @~[&'static str]) {}
 
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index a2f0fd480e1..ffebb87d5cf 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -239,7 +239,7 @@ impl Drop for CrateContext {
 #[cfg(stage0)]
 fn task_local_llcx_key(_v: @ContextRef) {}
 #[cfg(not(stage0))]
-static task_local_llcx_key: local_data::Key<@ContextRef> = &[];
+static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
 
 pub fn task_llcx() -> ContextRef {
     let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
diff --git a/src/librusti/program.rs b/src/librusti/program.rs
index d1d5b47ff57..9031a001eca 100644
--- a/src/librusti/program.rs
+++ b/src/librusti/program.rs
@@ -8,9 +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::vec;
 
 use syntax::ast;
 use syntax::parse::token;
@@ -57,7 +57,7 @@ struct LocalVariable {
 }
 
 type LocalCache = @mut HashMap<~str, @~[u8]>;
-static tls_key: local_data::Key<LocalCache> = &[];
+static tls_key: local_data::Key<LocalCache> = &local_data::Key;
 
 impl Program {
     pub fn new() -> Program {
@@ -130,16 +130,14 @@ impl Program {
             fn main() {
         ");
 
-        let key: *LocalCache = vec::raw::to_ptr(tls_key);
+        let key: uint= unsafe { cast::transmute(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::vec::raw::SliceRepr{ data: %? as *u8,
-                                                      len: 0 };
-                let key = ::std::cast::transmute(key);
+                let key = ::std::cast::transmute(%u);
                 ::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap()
             };\n", key as uint));
 
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
index 640bcc757b3..be170cce07e 100644
--- a/src/libstd/local_data.rs
+++ b/src/libstd/local_data.rs
@@ -13,18 +13,19 @@
 Task local data management
 
 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.
+anywhere within a task, keyed by a global pointer parameterized over the type of
+the TLS slot.  Useful for dynamic variables, singletons, and interfacing with
+foreign code with bad callback interfaces.
 
-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.
+To use, declare a static variable of the type you wish to store. The
+initialization should be `&local_data::Key`. This is then the key to what you
+wish to store.
 
 ~~~{.rust}
 use std::local_data;
 
-static key_int: local_data::Key<int> = &[];
-static key_vector: local_data::Key<~[int]> = &[];
+static key_int: local_data::Key<int> = &local_data::Key;
+static key_vector: local_data::Key<~[int]> = &local_data::Key;
 
 local_data::set(key_int, 3);
 local_data::get(key_int, |opt| assert_eq!(opt, Some(&3)));
@@ -45,24 +46,23 @@ use task::local_data_priv::{local_get, local_pop, local_set, Handle};
 #[cfg(test)] use task;
 
 /**
- * Indexes a task-local data slot. The function's code pointer is used for
- * comparison. Recommended use is to write an empty function for each desired
- * task-local data slot (and use class destructors, not code inside the
- * function, if specific teardown is needed). DO NOT use multiple
- * instantiations of a single polymorphic function to index data of different
- * types; arbitrary type coercion is possible this way.
+ * Indexes a task-local data slot. This pointer is used for comparison to
+ * differentiate keys from one another. The actual type `T` is not used anywhere
+ * as a member of this type, except that it is parameterized with it to define
+ * the type of each key's value.
  *
- * One other exception is that this global state can be used in a destructor
- * context to create a circular @-box reference, which will crash during task
- * failure (see issue #3039).
- *
- * These two cases aside, the interface is safe.
+ * The value of each Key is of the singleton enum KeyValue. These also have the
+ * same name as `Key` and their purpose is to take up space in the programs data
+ * sections to ensure that each value of the `Key` type points to a unique
+ * location.
  */
 #[cfg(not(stage0))]
-pub type Key<T> = &'static [T];
+pub type Key<T> = &'static KeyValue<T>;
 #[cfg(stage0)]
 pub type Key<'self,T> = &'self fn:Copy(v: T);
 
+pub enum KeyValue<T> { Key }
+
 /**
  * Remove a task-local data value from the table, returning the
  * reference that was originally created to insert it.
@@ -136,7 +136,7 @@ pub fn modify<T: 'static>(key: Key<T>, f: &fn(Option<T>) -> Option<T>) {
 
 #[test]
 fn test_tls_multitask() {
-    static my_key: Key<@~str> = &[];
+    static my_key: Key<@~str> = &Key;
     set(my_key, @~"parent data");
     do task::spawn {
         // TLS shouldn't carry over.
@@ -154,7 +154,7 @@ fn test_tls_multitask() {
 
 #[test]
 fn test_tls_overwrite() {
-    static my_key: Key<@~str> = &[];
+    static my_key: Key<@~str> = &Key;
     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");
@@ -162,7 +162,7 @@ fn test_tls_overwrite() {
 
 #[test]
 fn test_tls_pop() {
-    static my_key: Key<@~str> = &[];
+    static my_key: Key<@~str> = &Key;
     set(my_key, @~"weasel");
     assert!(*(pop(my_key).get()) == ~"weasel");
     // Pop must remove the data from the map.
@@ -171,7 +171,7 @@ fn test_tls_pop() {
 
 #[test]
 fn test_tls_modify() {
-    static my_key: Key<@~str> = &[];
+    static my_key: Key<@~str> = &Key;
     modify(my_key, |data| {
         match data {
             Some(@ref val) => fail!("unwelcome value: %s", *val),
@@ -196,7 +196,7 @@ 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.
-    static my_key: Key<@~str> = &[];
+    static my_key: Key<@~str> = &Key;
     do task::spawn {
         set(my_key, @~"hax");
     }
@@ -204,9 +204,9 @@ fn test_tls_crust_automorestack_memorial_bug() {
 
 #[test]
 fn test_tls_multiple_types() {
-    static str_key: Key<@~str> = &[];
-    static box_key: Key<@@()> = &[];
-    static int_key: Key<@int> = &[];
+    static str_key: Key<@~str> = &Key;
+    static box_key: Key<@@()> = &Key;
+    static int_key: Key<@int> = &Key;
     do task::spawn {
         set(str_key, @~"string data");
         set(box_key, @@());
@@ -216,9 +216,9 @@ fn test_tls_multiple_types() {
 
 #[test]
 fn test_tls_overwrite_multiple_types() {
-    static str_key: Key<@~str> = &[];
-    static box_key: Key<@@()> = &[];
-    static int_key: Key<@int> = &[];
+    static str_key: Key<@~str> = &Key;
+    static box_key: Key<@@()> = &Key;
+    static int_key: Key<@int> = &Key;
     do task::spawn {
         set(str_key, @~"string data");
         set(int_key, @42);
@@ -233,9 +233,9 @@ fn test_tls_overwrite_multiple_types() {
 #[should_fail]
 #[ignore(cfg(windows))]
 fn test_tls_cleanup_on_failure() {
-    static str_key: Key<@~str> = &[];
-    static box_key: Key<@@()> = &[];
-    static int_key: Key<@int> = &[];
+    static str_key: Key<@~str> = &Key;
+    static box_key: Key<@@()> = &Key;
+    static int_key: Key<@int> = &Key;
     set(str_key, @~"parent data");
     set(box_key, @@());
     do task::spawn {
@@ -252,7 +252,7 @@ fn test_tls_cleanup_on_failure() {
 
 #[test]
 fn test_static_pointer() {
-    static key: Key<@&'static int> = &[];
+    static key: Key<@&'static int> = &Key;
     static VALUE: int = 0;
     let v: @&'static int = @&VALUE;
     set(key, v);
@@ -260,17 +260,17 @@ fn test_static_pointer() {
 
 #[test]
 fn test_owned() {
-    static key: Key<~int> = &[];
+    static key: Key<~int> = &Key;
     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> = &[];
+    static key1: Key<int> = &Key;
+    static key2: Key<int> = &Key;
+    static key3: Key<int> = &Key;
+    static key4: Key<int> = &Key;
+    static key5: Key<int> = &Key;
     set(key1, 1);
     set(key2, 2);
     set(key3, 3);
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index cbd1e4e7663..58175db1241 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -1242,7 +1242,7 @@ struct OverriddenArgs {
 #[cfg(stage0)]
 fn overridden_arg_key(_v: @OverriddenArgs) {}
 #[cfg(not(stage0))]
-static overridden_arg_key: local_data::Key<@OverriddenArgs> = &[];
+static overridden_arg_key: local_data::Key<@OverriddenArgs> = &local_data::Key;
 
 /// Returns the arguments which this program was started with (normally passed
 /// via the command line).
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
index 8551012d6d7..6f89e7ffb07 100644
--- a/src/libstd/rand.rs
+++ b/src/libstd/rand.rs
@@ -854,7 +854,7 @@ pub fn seed() -> ~[u8] {
 #[cfg(stage0)]
 fn tls_rng_state(_v: @@mut IsaacRng) {}
 #[cfg(not(stage0))]
-static tls_rng_state: local_data::Key<@@mut IsaacRng> = &[];
+static tls_rng_state: local_data::Key<@@mut IsaacRng> = &local_data::Key;
 
 /**
  * Gives back a lazily initialized task-local random number generator,
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 0fd8c5c03d3..17d0d59660f 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -348,10 +348,10 @@ mod test {
     fn tls() {
         use local_data;
         do run_in_newsched_task() {
-            static key: local_data::Key<@~str> = &[];
+            static key: local_data::Key<@~str> = &local_data::Key;
             local_data::set(key, @~"data");
             assert!(*local_data::get(key, |k| k.map(|&k| *k)).get() == ~"data");
-            static key2: local_data::Key<@~str> = &[];
+            static key2: local_data::Key<@~str> = &local_data::Key;
             local_data::set(key2, @~"data");
             assert!(*local_data::get(key2, |k| k.map(|&k| *k)).get() == ~"data");
         }
diff --git a/src/libstd/std.rs b/src/libstd/std.rs
index 8f86216d240..03b895b3860 100644
--- a/src/libstd/std.rs
+++ b/src/libstd/std.rs
@@ -222,6 +222,7 @@ mod std {
     pub use condition;
     pub use option;
     pub use kinds;
+    pub use local_data;
     pub use sys;
     pub use pipes;
     pub use unstable;
diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs
index 1a2141e996a..d46e5707f14 100644
--- a/src/libstd/task/local_data_priv.rs
+++ b/src/libstd/task/local_data_priv.rs
@@ -17,7 +17,6 @@ use prelude::*;
 use ptr;
 use task::rt;
 use util;
-use vec;
 
 use super::rt::rust_task;
 use rt::task::{Task, LocalStorage};
@@ -143,7 +142,7 @@ unsafe fn get_local_map(handle: Handle) -> &mut TaskLocalMap {
 }
 
 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;
+    unsafe { cast::transmute(key) }
 }
 
 pub unsafe fn local_pop<T: 'static>(handle: Handle,
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 27cb1c2c100..206d19e175f 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -80,6 +80,7 @@ use cell::Cell;
 use container::MutableMap;
 use comm::{Chan, GenericChan};
 use hashmap::HashSet;
+use local_data;
 use task::local_data_priv::{local_get, local_set, OldHandle};
 use task::rt::rust_task;
 use task::rt;
@@ -465,10 +466,14 @@ fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
 
 // FIXME (#2912): Work around core-vs-coretest function duplication. Can't use
 // a proper closure because the #[test]s won't understand. Have to fake it.
-macro_rules! taskgroup_key (
-    // Use a "code pointer" value that will never be a real code pointer.
-    () => (cast::transmute((-2 as uint, 0u)))
-)
+#[cfg(not(stage0))]
+fn taskgroup_key() -> local_data::Key<@@mut TCB> {
+    unsafe { cast::transmute(-2) }
+}
+#[cfg(stage0)]
+fn taskgroup_key() -> local_data::Key<@@mut TCB> {
+    unsafe { cast::transmute((-2, 0)) }
+}
 
 fn gen_child_taskgroup(linked: bool, supervised: bool)
     -> (TaskGroupArc, AncestorList, bool) {
@@ -478,7 +483,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
          * Step 1. Get spawner's taskgroup info.
          *##################################################################*/
         let spawner_group: @@mut TCB =
-            do local_get(OldHandle(spawner), taskgroup_key!()) |group| {
+            do local_get(OldHandle(spawner), taskgroup_key()) |group| {
                 match group {
                     None => {
                         // Main task, doing first spawn ever. Lazily initialise
@@ -495,7 +500,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
                                               AncestorList(None),
                                               true,
                                               None);
-                        local_set(OldHandle(spawner), taskgroup_key!(), group);
+                        local_set(OldHandle(spawner), taskgroup_key(), group);
                         group
                     }
                     Some(&group) => group
@@ -688,7 +693,7 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
                                       is_main,
                                       notifier);
                 unsafe {
-                    local_set(OldHandle(child), taskgroup_key!(), group);
+                    local_set(OldHandle(child), taskgroup_key(), group);
                 }
 
                 // Run the child's body.
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 0b876bf1f81..a1d209d19ac 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -695,7 +695,7 @@ 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 {
     #[cfg(not(stage0))]
-    static sctable_key: local_data::Key<@@mut SCTable> = &[];
+    static sctable_key: local_data::Key<@@mut SCTable> = &local_data::Key;
     #[cfg(stage0)]
     fn sctable_key(_: @@mut SCTable) {}
     match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 4fbc3862848..b45cde6a8e3 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -580,7 +580,9 @@ pub fn core_macros() -> @str {
 
             pub mod $c {
                 #[allow(non_uppercase_statics)];
-                static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
+                static key: ::std::local_data::Key<
+                    @::std::condition::Handler<$in, $out>> =
+                    &::std::local_data::Key;
 
                 pub static cond :
                     ::std::condition::Condition<$in,$out> =
@@ -596,7 +598,9 @@ pub fn core_macros() -> @str {
             // FIXME (#6009): remove mod's `pub` below once variant above lands.
             pub mod $c {
                 #[allow(non_uppercase_statics)];
-                static key: &'static [@::std::condition::Handler<$in, $out>] = &[];
+                static key: ::std::local_data::Key<
+                    @::std::condition::Handler<$in, $out>> =
+                    &::std::local_data::Key;
 
                 pub static cond :
                     ::std::condition::Condition<$in,$out> =
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 8737e571399..01860c3ae99 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -485,7 +485,8 @@ fn mk_fresh_ident_interner() -> @ident_interner {
 // fresh one.
 pub fn get_ident_interner() -> @ident_interner {
     #[cfg(not(stage0))]
-    static key: local_data::Key<@@::parse::token::ident_interner> = &[];
+    static key: local_data::Key<@@::parse::token::ident_interner> =
+        &local_data::Key;
     #[cfg(stage0)]
     fn key(_: @@::parse::token::ident_interner) {}
     match local_data::get(key, |k| k.map(|&k| *k)) {
diff --git a/src/test/compile-fail/core-tls-store-pointer.rs b/src/test/compile-fail/core-tls-store-pointer.rs
index f5b7f34b365..576b1c452a5 100644
--- a/src/test/compile-fail/core-tls-store-pointer.rs
+++ b/src/test/compile-fail/core-tls-store-pointer.rs
@@ -12,6 +12,7 @@
 
 use std::local_data;
 
-static key: local_data::Key<@&int> = &[]; //~ ERROR only 'static is allowed
+static key: local_data::Key<@&int> = &local_data::Key;
+//~^ ERROR only 'static is allowed
 
 fn main() {}