478: WIP: implement cancelation via unwinding r=matklad a=matklad

This uses https://github.com/salsa-rs/salsa/pull/107 to implement cancellation.

Now we can get rid of `Cancelable` wrapper from everywhere except the top-level analyzer library. 



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-01-10 12:51:58 +00:00
commit aef93c918e
8 changed files with 87 additions and 48 deletions

35
Cargo.lock generated
View file

@ -66,11 +66,10 @@ dependencies = [
[[package]]
name = "base64"
version = "0.9.3"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -139,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -661,7 +660,7 @@ dependencies = [
"ra_syntax 0.1.0",
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (git+https://github.com/matklad/salsa?branch=panic-hooks)",
"test_utils 0.1.0",
]
@ -680,7 +679,7 @@ dependencies = [
"ra_syntax 0.1.0",
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (git+https://github.com/matklad/salsa?branch=panic-hooks)",
"test_utils 0.1.0",
]
@ -700,7 +699,7 @@ dependencies = [
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"salsa 0.9.1 (git+https://github.com/matklad/salsa?branch=panic-hooks)",
"test_utils 0.1.0",
"unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -967,10 +966,10 @@ dependencies = [
[[package]]
name = "ron"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1022,15 +1021,10 @@ name = "ryu"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "safemem"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "salsa"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
source = "git+https://github.com/matklad/salsa?branch=panic-hooks#88313c80302c831ebc7601912ab3f11ad37e6bc2"
dependencies = [
"derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1207,7 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1274,7 +1268,7 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.41"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1489,7 +1483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727"
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
@ -1579,15 +1573,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f"
"checksum ron 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d9cb28ade964585205aaca1f3d41a6297f72e1ad097b49c4bbde033ef86b38d7"
"checksum rowan 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9ae7dba5e703f423ceb8646d636c73e6d858a2f8c834808b4565e42ccda9e2"
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
"checksum salsa 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "442ef4acdb48c0e24ddaf4f3b62555af2d1da7047f2f26acd54ae73010aa0c02"
"checksum salsa 0.9.1 (git+https://github.com/matklad/salsa?branch=panic-hooks)" = "<none>"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@ -1612,7 +1605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"

View file

@ -7,3 +7,4 @@ debug = true
[patch.'crates-io']
cargo_metadata = { git = "https://github.com/oli-obk/cargo_metadata.git", rev="f73e27b24e" }
salsa = { git = "https://github.com/matklad/salsa", branch = "panic-hooks" }

View file

@ -27,6 +27,12 @@ impl Canceled {
pub(crate) fn new() -> Canceled {
Canceled { _private: () }
}
pub fn throw() -> ! {
// We use resume and not panic here to avoid running the panic
// hook (that is, to avoid collecting and printing backtrace).
std::panic::resume_unwind(Box::new(Canceled::new()))
}
}
impl std::fmt::Display for Canceled {

View file

@ -5,6 +5,8 @@ mod input;
mod loc2id;
pub mod mock;
use std::panic;
use ra_syntax::{TextUnit, TextRange, SourceFile, TreePtr};
pub use crate::{
@ -18,13 +20,21 @@ pub use crate::{
loc2id::LocationIntener,
};
pub trait BaseDatabase: salsa::Database {
pub trait BaseDatabase: salsa::Database + panic::RefUnwindSafe {
fn check_canceled(&self) -> Cancelable<()> {
if self.salsa_runtime().is_current_revision_canceled() {
Err(Canceled::new())
} else {
Ok(())
}
self.salsa_runtime()
.if_current_revision_is_canceled(Canceled::throw);
Ok(())
}
fn catch_canceled<F: FnOnce(&Self) -> T + panic::UnwindSafe, T>(
&self,
f: F,
) -> Result<T, Canceled> {
panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() {
Ok(canceled) => *canceled,
Err(payload) => panic::resume_unwind(payload),
})
}
}

View file

@ -1,4 +1,4 @@
use std::hash::Hash;
use std::{panic, hash::Hash};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
@ -70,6 +70,15 @@ where
map: Mutex<Loc2IdMap<LOC, ID>>,
}
impl<LOC, ID> panic::RefUnwindSafe for LocationIntener<LOC, ID>
where
ID: ArenaId + Clone,
LOC: Clone + Eq + Hash,
ID: panic::RefUnwindSafe,
LOC: panic::RefUnwindSafe,
{
}
impl<LOC, ID> Default for LocationIntener<LOC, ID>
where
ID: ArenaId + Clone,

View file

@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{sync::Arc, panic};
use parking_lot::Mutex;
use salsa::{self, Database};
@ -18,6 +18,8 @@ pub(crate) struct MockDatabase {
file_counter: u32,
}
impl panic::RefUnwindSafe for MockDatabase {}
impl MockDatabase {
pub(crate) fn with_files(fixture: &str) -> (MockDatabase, SourceRoot) {
let (db, source_root, position) = MockDatabase::from_fixture(fixture);

View file

@ -1,7 +1,7 @@
use std::{fmt, sync::Arc};
use salsa::{self, Database};
use ra_db::{LocationIntener, BaseDatabase, FileId};
use ra_db::{LocationIntener, BaseDatabase, FileId, Canceled};
use crate::{symbol_index, LineIndex};
@ -29,6 +29,9 @@ impl salsa::Database for RootDatabase {
fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
&self.runtime
}
fn on_propagated_panic(&self) -> ! {
Canceled::throw()
}
}
impl Default for RootDatabase {

View file

@ -35,7 +35,7 @@ use std::{fmt, sync::Arc};
use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit};
use ra_text_edit::TextEdit;
use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr};
use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr, BaseDatabase};
use rayon::prelude::*;
use relative_path::RelativePathBuf;
use rustc_hash::FxHashMap;
@ -420,43 +420,47 @@ impl Analysis {
/// Fuzzy searches for a symbol.
pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
let res = symbol_index::world_symbols(&*self.db, query)?
.into_iter()
.map(NavigationTarget::from_symbol)
.collect();
Ok(res)
self.with_db(|db| {
let res = symbol_index::world_symbols(db, query)?
.into_iter()
.map(NavigationTarget::from_symbol)
.collect::<Vec<_>>();
Ok(res)
})?
}
pub fn goto_definition(
&self,
position: FilePosition,
) -> Cancelable<Option<Vec<NavigationTarget>>> {
goto_definition::goto_definition(&*self.db, position)
self.db
.catch_canceled(|db| goto_definition::goto_definition(db, position))?
}
/// Finds all usages of the reference at point.
pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
self.db.find_all_refs(position)
self.with_db(|db| db.find_all_refs(position))?
}
/// Returns a short text descrbing element at position.
pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> {
hover::hover(&*self.db, position)
self.with_db(|db| hover::hover(db, position))?
}
/// Computes parameter information for the given call expression.
pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> {
call_info::call_info(&*self.db, position)
self.db
.catch_canceled(|db| call_info::call_info(db, position))?
}
/// Returns a `mod name;` declaration which created the current module.
pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
self.db.parent_module(position)
self.with_db(|db| db.parent_module(position))?
}
/// Returns crates this file belongs too.
pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
self.db.crate_for(file_id)
self.with_db(|db| db.crate_for(file_id))?
}
/// Returns the root file of the given crate.
@ -466,17 +470,21 @@ impl Analysis {
/// Returns the set of possible targets to run for the current file.
pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
runnables::runnables(&*self.db, file_id)
self.db
.catch_canceled(|db| runnables::runnables(db, file_id))?
}
/// Computes syntax highlighting for the given file.
pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
syntax_highlighting::highlight(&*self.db, file_id)
self.db
.catch_canceled(|db| syntax_highlighting::highlight(db, file_id))?
}
/// Computes completions at the given position.
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
let completions = completion::completions(&self.db, position)?;
let completions = self
.db
.catch_canceled(|db| completion::completions(db, position))??;
Ok(completions.map(|it| it.into()))
}
@ -488,12 +496,12 @@ impl Analysis {
/// Computes the set of diagnostics for the given file.
pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
self.db.diagnostics(file_id)
self.with_db(|db| db.diagnostics(file_id))?
}
/// Computes the type of the expression at the given position.
pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> {
hover::type_of(&*self.db, frange)
self.with_db(|db| hover::type_of(db, frange))?
}
/// Returns the edit required to rename reference at the position to the new
@ -503,7 +511,14 @@ impl Analysis {
position: FilePosition,
new_name: &str,
) -> Cancelable<Vec<SourceFileEdit>> {
self.db.rename(position, new_name)
self.with_db(|db| db.rename(position, new_name))?
}
fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>(
&self,
f: F,
) -> Cancelable<T> {
self.db.catch_canceled(f)
}
}