about summary refs log tree commit diff
path: root/src/libsyntax_pos
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-05-12 18:45:00 +0000
committerbors <bors@rust-lang.org>2018-05-12 18:45:00 +0000
commitff2ac35db93a80b2de5daa4f280bf1503d62c164 (patch)
treed267bc43ba84346d4592ed77f5d2a7084d299304 /src/libsyntax_pos
parentc0cea750a0a10a0ed5a101839e37968d87f8ef9d (diff)
parentda79ff3cc2265514483d2a5e1f4238c85baa70e9 (diff)
Auto merge of #50686 - Mark-Simulacrum:rollup, r=Mark-Simulacrum
Rollup of 13 pull requests

Successful merges:

 - #50544 (Cleanup some dependencies)
 - #50545 (Made some functions in time module const)
 - #50550 (use fmt::Result where applicable)
 - #50558 (Remove all reference to DepGraph::work_products)
 - #50602 (Update canonicalize docs)
 - #50607 (Allocate Symbol strings from an arena)
 - #50613 (Migrate the toolstate update bot to rust-highfive)
 - #50624 (fs::write: Add example writing a &str)
 - #50634 (Do not silently truncate offsets for `read_at`/`write_at` on emscripten)
 - #50644 (AppVeyor: Read back trace from crash dump on failure.)
 - #50661 (Ignore non .rs files for tidy libcoretest)
 - #50663 (rustc: Allow an edition's feature on that edition)
 - #50667 (rustc: Only suggest deleting `extern crate` if it works)

Failed merges:
Diffstat (limited to 'src/libsyntax_pos')
-rw-r--r--src/libsyntax_pos/Cargo.toml1
-rw-r--r--src/libsyntax_pos/lib.rs1
-rw-r--r--src/libsyntax_pos/symbol.rs40
3 files changed, 34 insertions, 8 deletions
diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml
index b9637b1855e..a9147b394f7 100644
--- a/src/libsyntax_pos/Cargo.toml
+++ b/src/libsyntax_pos/Cargo.toml
@@ -11,5 +11,6 @@ crate-type = ["dylib"]
 [dependencies]
 serialize = { path = "../libserialize" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+arena = { path = "../libarena" }
 scoped-tls = { version = "0.1.1", features = ["nightly"] }
 unicode-width = "0.1.4"
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 8b4a3ea26a1..d30d3d78ca5 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -35,6 +35,7 @@ use std::path::PathBuf;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{Lrc, Lock};
 
+extern crate arena;
 extern crate rustc_data_structures;
 
 #[macro_use]
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 4a8b1e8b1c1..b84ff5697a4 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -16,8 +16,10 @@ use hygiene::SyntaxContext;
 use {Span, DUMMY_SP, GLOBALS};
 
 use rustc_data_structures::fx::FxHashMap;
+use arena::DroplessArena;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use std::str;
 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::hash::{Hash, Hasher};
 
@@ -198,22 +200,35 @@ impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
     }
 }
 
-#[derive(Default)]
+// The &'static strs in this type actually point into the arena
 pub struct Interner {
-    names: FxHashMap<Box<str>, Symbol>,
-    strings: Vec<Box<str>>,
+    arena: DroplessArena,
+    names: FxHashMap<&'static str, Symbol>,
+    strings: Vec<&'static str>,
     gensyms: Vec<Symbol>,
 }
 
 impl Interner {
     pub fn new() -> Self {
-        Interner::default()
+        Interner {
+            arena: DroplessArena::new(),
+            names: Default::default(),
+            strings: Default::default(),
+            gensyms: Default::default(),
+        }
     }
 
     fn prefill(init: &[&str]) -> Self {
         let mut this = Interner::new();
         for &string in init {
-            this.intern(string);
+            if string == "" {
+                // We can't allocate empty strings in the arena, so handle this here
+                let name = Symbol(this.strings.len() as u32);
+                this.names.insert("", name);
+                this.strings.push("");
+            } else {
+                this.intern(string);
+            }
         }
         this
     }
@@ -224,8 +239,17 @@ impl Interner {
         }
 
         let name = Symbol(self.strings.len() as u32);
-        let string = string.to_string().into_boxed_str();
-        self.strings.push(string.clone());
+
+        // from_utf8_unchecked is safe since we just allocated a &str which is known to be utf8
+        let string: &str = unsafe {
+            str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes()))
+        };
+        // It is safe to extend the arena allocation to 'static because we only access
+        // these while the arena is still alive
+        let string: &'static str =  unsafe {
+            &*(string as *const str)
+        };
+        self.strings.push(string);
         self.names.insert(string, name);
         name
     }
@@ -254,7 +278,7 @@ impl Interner {
 
     pub fn get(&self, symbol: Symbol) -> &str {
         match self.strings.get(symbol.0 as usize) {
-            Some(ref string) => string,
+            Some(string) => string,
             None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
         }
     }