mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Use a thread-local for the symbol interner (1/2)
This commit is contained in:
		
							parent
							
								
									30769598a4
								
							
						
					
					
						commit
						05d8f5fee7
					
				
							
								
								
									
										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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user