mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #7455
7455: Make always-assert crate reusable r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
8775bc4be1
11 changed files with 24 additions and 73 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -15,6 +15,15 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
|
||||
[[package]]
|
||||
name = "always-assert"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "727786f78c5bc0cda8011831616589f72084cb16b7df4213a997b78749b55a60"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
|
@ -1415,6 +1424,7 @@ dependencies = [
|
|||
name = "rust-analyzer"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"always-assert",
|
||||
"anyhow",
|
||||
"cfg",
|
||||
"crossbeam-channel 0.5.0",
|
||||
|
@ -1658,6 +1668,7 @@ dependencies = [
|
|||
name = "stdx"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"always-assert",
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use ide_db::{
|
|||
},
|
||||
SymbolKind,
|
||||
};
|
||||
use stdx::{assert_never, impl_from};
|
||||
use stdx::{impl_from, never};
|
||||
use syntax::{algo, TextRange};
|
||||
use text_edit::TextEdit;
|
||||
|
||||
|
@ -404,7 +404,7 @@ impl Builder {
|
|||
pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder {
|
||||
self.detail = detail.map(Into::into);
|
||||
if let Some(detail) = &self.detail {
|
||||
if assert_never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
|
||||
if never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
|
||||
self.detail = Some(detail.splitn(2, '\n').next().unwrap().to_string());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use ide_db::{
|
|||
search::FileReference,
|
||||
RootDatabase,
|
||||
};
|
||||
use stdx::assert_never;
|
||||
use stdx::never;
|
||||
use syntax::{
|
||||
ast::{self, NameOwner},
|
||||
lex_single_syntax_kind, AstNode, SyntaxKind, SyntaxNode, T,
|
||||
|
@ -285,7 +285,7 @@ fn rename_mod(
|
|||
}
|
||||
|
||||
fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> {
|
||||
if assert_never!(local.is_self(sema.db)) {
|
||||
if never!(local.is_self(sema.db)) {
|
||||
bail!("rename_to_self invoked on self");
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ fn rename_self_to_param(
|
|||
let (file_id, self_param) = match local.source(sema.db) {
|
||||
InFile { file_id, value: Either::Right(self_param) } => (file_id, self_param),
|
||||
_ => {
|
||||
assert_never!(true, "rename_self_to_param invoked on a non-self local");
|
||||
never!(true, "rename_self_to_param invoked on a non-self local");
|
||||
bail!("rename_self_to_param invoked on a non-self local");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::{
|
|||
|
||||
use base_db::{AnchoredPathBuf, FileId};
|
||||
use rustc_hash::FxHashMap;
|
||||
use stdx::assert_never;
|
||||
use stdx::never;
|
||||
use text_edit::TextEdit;
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
|
@ -40,10 +40,7 @@ impl SourceChange {
|
|||
pub fn insert_source_edit(&mut self, file_id: FileId, edit: TextEdit) {
|
||||
match self.source_file_edits.entry(file_id) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
assert_never!(
|
||||
entry.get_mut().union(edit).is_err(),
|
||||
"overlapping edits for same file"
|
||||
);
|
||||
never!(entry.get_mut().union(edit).is_err(), "overlapping edits for same file");
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(edit);
|
||||
|
|
|
@ -37,6 +37,7 @@ lsp-server = "0.5.0"
|
|||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
|
||||
tracing-tree = { version = "0.1.4" }
|
||||
always-assert = "0.1"
|
||||
|
||||
stdx = { path = "../stdx", version = "0.0.0" }
|
||||
flycheck = { path = "../flycheck", version = "0.0.0" }
|
||||
|
@ -72,3 +73,4 @@ tt = { path = "../tt" }
|
|||
|
||||
[features]
|
||||
jemalloc = ["jemallocator", "profile/jemalloc"]
|
||||
force-always-assert = ["always-assert/force"]
|
||||
|
|
|
@ -75,15 +75,6 @@ fn setup_logging(log_file: Option<PathBuf>) -> Result<()> {
|
|||
|
||||
profile::init();
|
||||
|
||||
if !cfg!(debug_assertions) {
|
||||
stdx::set_assert_hook(|loc, args| {
|
||||
if env::var("RA_PROFILE").is_ok() {
|
||||
panic!("assertion failed at {}: {}", loc, args)
|
||||
}
|
||||
log::error!("assertion failed at {}: {}", loc, args)
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ doctest = false
|
|||
|
||||
[dependencies]
|
||||
backtrace = { version = "0.3.44", optional = true }
|
||||
always-assert = { version = "0.1.1", features = ["log"] }
|
||||
# Think twice before adding anything here
|
||||
|
||||
[features]
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{cmp::Ordering, ops, process, time::Instant};
|
|||
mod macros;
|
||||
pub mod panic_context;
|
||||
|
||||
pub use crate::macros::{on_assert_failure, set_assert_hook};
|
||||
pub use always_assert::{always, never};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_ci() -> bool {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
//! Convenience macros.
|
||||
|
||||
use std::{
|
||||
fmt, mem, panic,
|
||||
sync::atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
};
|
||||
#[macro_export]
|
||||
macro_rules! eprintln {
|
||||
($($tt:tt)*) => {{
|
||||
|
@ -49,50 +45,3 @@ macro_rules! impl_from {
|
|||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of `assert!` macro which allows to handle an assertion failure.
|
||||
///
|
||||
/// In release mode, it returns the condition and logs an error.
|
||||
///
|
||||
/// ```
|
||||
/// if assert_never!(impossible) {
|
||||
/// // Heh, this shouldn't have happened, but lets try to soldier on...
|
||||
/// return None;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Rust analyzer is a long-running process, and crashing really isn't an option.
|
||||
///
|
||||
/// Shamelessly stolen from: https://www.sqlite.org/assert.html
|
||||
#[macro_export]
|
||||
macro_rules! assert_never {
|
||||
($cond:expr) => { $crate::assert_never!($cond, "") };
|
||||
($cond:expr, $($fmt:tt)*) => {{
|
||||
let value = $cond;
|
||||
if value {
|
||||
$crate::on_assert_failure(
|
||||
format_args!($($fmt)*)
|
||||
);
|
||||
}
|
||||
value
|
||||
}};
|
||||
}
|
||||
|
||||
type AssertHook = fn(&panic::Location<'_>, fmt::Arguments<'_>);
|
||||
static HOOK: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub fn set_assert_hook(hook: AssertHook) {
|
||||
HOOK.store(hook as usize, SeqCst);
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
pub fn on_assert_failure(args: fmt::Arguments) {
|
||||
let hook: usize = HOOK.load(SeqCst);
|
||||
if hook == 0 {
|
||||
panic!("\n assertion failed: {}\n", args);
|
||||
}
|
||||
|
||||
let hook: AssertHook = unsafe { mem::transmute::<usize, AssertHook>(hook) };
|
||||
hook(panic::Location::caller(), args)
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ if idx >= len {
|
|||
## Assertions
|
||||
|
||||
Assert liberally.
|
||||
Prefer `stdx::assert_never!` to standard `assert!`.
|
||||
Prefer `stdx::never!` to standard `assert!`.
|
||||
|
||||
## Getters & Setters
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ fn install_server(opts: ServerOpt) -> Result<()> {
|
|||
Malloc::Jemalloc => &["--features", "jemalloc"],
|
||||
};
|
||||
|
||||
let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force {features...}");
|
||||
let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force --features force-always-assert {features...}");
|
||||
let res = cmd.run();
|
||||
|
||||
if res.is_err() && old_rust {
|
||||
|
|
Loading…
Reference in a new issue