Single-threaded LSP server?

I've to contain single-threaded (!Send + !Sync) fields in my Backend structure for tower-lsp. LanguageServer forces my Backend to implement these, so I am wondering whether there is anyway to make my single-threaded code to work. Perhaps I can use a thread_local! or a lazy_static!?

Or maybe there is some alternative crate?

are you implmeneting interior mutability somewhere, i.e. UnsafeCell internally? any reason you don't use the thread safe wrapper type Arc<Mutex<...>>?

1 Like

It happens that I have compiler_results: RefCell<Vec<(DepSeq, Rc<Database>)>>, inside Backend, and Rc<Database> is used widely many times in my codebase. DepSeq itself contains some Rc as well, so it can't implement Send + Sync.

Interior mutability definitely exists in my semantic model (using the smodel crate).

the tower_lsp::LanguageServer trait uses Send + Sync as super trait, so your backend must be thread safe. replace Rc<RefCell<T>> with its thread safe counter part Arc<Mutex<T>> (or Arc<RwLock<T>>, if you need to distinguish shared borrow and exclusive borrow).

But I think it just won't work, as I'd have to change my entire codebase to use Arc/RwLock/Mutex instead of Rc/RefCell/Cell. I guess I'll explore to see if there are single-threaded crates instead of tower-lsp :confused:

I have found async-lsp: LanguageServer in async_lsp - Rust

Only the error has to implement Send, apparently.

1 Like

looking at the documentation of async_lsp::LanguageServer, it doesn't require Send. I can only guess the Send is required because you use tokio::spawn(). try use spawn_local(). this will force the task to be run on a single thread.

1 Like