mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Use a thread-local for the symbol interner (1/2)
This commit is contained in:
parent
30769598a4
commit
05d8f5fee7
4 changed files with 33 additions and 17 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1167,7 +1167,6 @@ dependencies = [
|
||||||
"mbe",
|
"mbe",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"object 0.29.0",
|
"object 0.29.0",
|
||||||
"once_cell",
|
|
||||||
"paths",
|
"paths",
|
||||||
"proc-macro-api",
|
"proc-macro-api",
|
||||||
"proc-macro-test",
|
"proc-macro-test",
|
||||||
|
|
|
@ -24,7 +24,6 @@ tt = { path = "../tt", version = "0.0.0" }
|
||||||
mbe = { path = "../mbe", version = "0.0.0" }
|
mbe = { path = "../mbe", version = "0.0.0" }
|
||||||
paths = { path = "../paths", version = "0.0.0" }
|
paths = { path = "../paths", version = "0.0.0" }
|
||||||
proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
|
proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
|
||||||
once_cell = "1.13.0"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
expect-test = "1.4.0"
|
expect-test = "1.4.0"
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl server::FreeFunctions for RustAnalyzer {
|
||||||
s: &str,
|
s: &str,
|
||||||
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
||||||
// FIXME: keep track of LitKind and Suffix
|
// FIXME: keep track of LitKind and Suffix
|
||||||
let symbol = SYMBOL_INTERNER.lock().unwrap().intern(s);
|
let symbol = ThreadLocalSymbolInterner::intern(s);
|
||||||
Ok(bridge::Literal {
|
Ok(bridge::Literal {
|
||||||
kind: bridge::LitKind::Err,
|
kind: bridge::LitKind::Err,
|
||||||
symbol,
|
symbol,
|
||||||
|
@ -124,7 +124,7 @@ impl server::TokenStream for RustAnalyzer {
|
||||||
|
|
||||||
bridge::TokenTree::Ident(ident) => {
|
bridge::TokenTree::Ident(ident) => {
|
||||||
// FIXME: handle raw idents
|
// FIXME: handle raw idents
|
||||||
let text = SYMBOL_INTERNER.lock().unwrap().get(&ident.sym).clone();
|
let text = ThreadLocalSymbolInterner::get_cloned(&ident.sym);
|
||||||
let ident: tt::Ident = tt::Ident { text, id: ident.span };
|
let ident: tt::Ident = tt::Ident { text, id: ident.span };
|
||||||
let leaf = tt::Leaf::from(ident);
|
let leaf = tt::Leaf::from(ident);
|
||||||
let tree = TokenTree::from(leaf);
|
let tree = TokenTree::from(leaf);
|
||||||
|
@ -132,10 +132,11 @@ impl server::TokenStream for RustAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge::TokenTree::Literal(literal) => {
|
bridge::TokenTree::Literal(literal) => {
|
||||||
let symbol = SYMBOL_INTERNER.lock().unwrap().get(&literal.symbol).clone();
|
// FIXME: remove unnecessary clones here
|
||||||
|
let symbol = ThreadLocalSymbolInterner::get_cloned(&literal.symbol);
|
||||||
|
|
||||||
let text: tt::SmolStr = if let Some(suffix) = literal.suffix {
|
let text: tt::SmolStr = if let Some(suffix) = literal.suffix {
|
||||||
let suffix = SYMBOL_INTERNER.lock().unwrap().get(&suffix).clone();
|
let suffix = ThreadLocalSymbolInterner::get_cloned(&suffix);
|
||||||
format!("{symbol}{suffix}").into()
|
format!("{symbol}{suffix}").into()
|
||||||
} else {
|
} else {
|
||||||
symbol
|
symbol
|
||||||
|
@ -203,7 +204,7 @@ impl server::TokenStream for RustAnalyzer {
|
||||||
.map(|tree| match tree {
|
.map(|tree| match tree {
|
||||||
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
|
||||||
bridge::TokenTree::Ident(bridge::Ident {
|
bridge::TokenTree::Ident(bridge::Ident {
|
||||||
sym: SYMBOL_INTERNER.lock().unwrap().intern(&ident.text),
|
sym: ThreadLocalSymbolInterner::intern(&ident.text),
|
||||||
// FIXME: handle raw idents
|
// FIXME: handle raw idents
|
||||||
is_raw: false,
|
is_raw: false,
|
||||||
span: ident.id,
|
span: ident.id,
|
||||||
|
@ -213,7 +214,7 @@ impl server::TokenStream for RustAnalyzer {
|
||||||
bridge::TokenTree::Literal(bridge::Literal {
|
bridge::TokenTree::Literal(bridge::Literal {
|
||||||
// FIXME: handle literal kinds
|
// FIXME: handle literal kinds
|
||||||
kind: bridge::LitKind::Err,
|
kind: bridge::LitKind::Err,
|
||||||
symbol: SYMBOL_INTERNER.lock().unwrap().intern(&lit.text),
|
symbol: ThreadLocalSymbolInterner::intern(&lit.text),
|
||||||
// FIXME: handle suffixes
|
// FIXME: handle suffixes
|
||||||
suffix: None,
|
suffix: None,
|
||||||
span: lit.id,
|
span: lit.id,
|
||||||
|
@ -407,11 +408,11 @@ impl server::Server for RustAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intern_symbol(ident: &str) -> Self::Symbol {
|
fn intern_symbol(ident: &str) -> Self::Symbol {
|
||||||
SYMBOL_INTERNER.lock().unwrap().intern(&tt::SmolStr::from(ident))
|
ThreadLocalSymbolInterner::intern(&tt::SmolStr::from(ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
|
fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
|
||||||
f(SYMBOL_INTERNER.lock().unwrap().get(symbol).as_str())
|
ThreadLocalSymbolInterner::with(symbol, |s| f(s.as_str()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
//! Symbol interner for proc-macro-srv
|
//! Symbol interner for proc-macro-srv
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use std::{cell::RefCell, collections::HashMap};
|
||||||
use std::{collections::HashMap, sync::Mutex};
|
|
||||||
use tt::SmolStr;
|
use tt::SmolStr;
|
||||||
|
|
||||||
pub(super) static SYMBOL_INTERNER: Lazy<Mutex<SymbolInterner>> = Lazy::new(|| Default::default());
|
thread_local! {
|
||||||
|
static SYMBOL_INTERNER: RefCell<SymbolInterner> = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
// ID for an interned symbol.
|
// ID for an interned symbol.
|
||||||
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
|
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
|
||||||
pub struct Symbol(u32);
|
pub struct Symbol(u32);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct SymbolInterner {
|
struct SymbolInterner {
|
||||||
idents: HashMap<SmolStr, u32>,
|
idents: HashMap<SmolStr, u32>,
|
||||||
ident_data: Vec<SmolStr>,
|
ident_data: Vec<SmolStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolInterner {
|
impl SymbolInterner {
|
||||||
pub(super) fn intern(&mut self, data: &str) -> Symbol {
|
fn intern(&mut self, data: &str) -> Symbol {
|
||||||
if let Some(index) = self.idents.get(data) {
|
if let Some(index) = self.idents.get(data) {
|
||||||
return Symbol(*index);
|
return Symbol(*index);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +30,23 @@ impl SymbolInterner {
|
||||||
Symbol(index)
|
Symbol(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get(&self, index: &Symbol) -> &SmolStr {
|
fn get(&self, sym: &Symbol) -> &SmolStr {
|
||||||
&self.ident_data[index.0 as usize]
|
&self.ident_data[sym.0 as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct ThreadLocalSymbolInterner;
|
||||||
|
|
||||||
|
impl ThreadLocalSymbolInterner {
|
||||||
|
pub(super) fn intern(data: &str) -> Symbol {
|
||||||
|
SYMBOL_INTERNER.with(|i| i.borrow_mut().intern(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn with<T>(sym: &Symbol, f: impl FnOnce(&SmolStr) -> T) -> T {
|
||||||
|
SYMBOL_INTERNER.with(|i| f(i.borrow().get(sym)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn get_cloned(sym: &Symbol) -> SmolStr {
|
||||||
|
Self::with(sym, |s| s.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue