From d35bda6429b0a3a758ddcd899e954043584f1071 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 26 Jan 2021 22:11:12 +0300 Subject: Make always-assert crate reusable --- Cargo.lock | 11 ++++++++ crates/completion/src/item.rs | 4 +-- crates/ide/src/references/rename.rs | 6 ++--- crates/ide_db/src/source_change.rs | 7 ++--- crates/rust-analyzer/Cargo.toml | 2 ++ crates/rust-analyzer/src/bin/main.rs | 9 ------- crates/stdx/Cargo.toml | 1 + crates/stdx/src/lib.rs | 2 +- crates/stdx/src/macros.rs | 51 ------------------------------------ docs/dev/style.md | 2 +- xtask/src/install.rs | 2 +- 11 files changed, 24 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efd1c6d33..45a0211ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", ] diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index eeb952ec3..8ec4ac65e 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs @@ -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>) -> 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()); } } diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index c25bcce50..99a558532 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs @@ -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, local: hir::Local) -> RenameResult { - 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"); } }; diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs index b1f87731b..f76bac151 100644 --- a/crates/ide_db/src/source_change.rs +++ b/crates/ide_db/src/source_change.rs @@ -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); diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 268c00942..82ea76666 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -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"] diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 1d6e5478b..bee2eedbc 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -75,15 +75,6 @@ fn setup_logging(log_file: Option) -> 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(()) } diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml index c47e8d0a8..5866c0a28 100644 --- a/crates/stdx/Cargo.toml +++ b/crates/stdx/Cargo.toml @@ -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] diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index d42817078..d26be4853 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs @@ -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 { diff --git a/crates/stdx/src/macros.rs b/crates/stdx/src/macros.rs index 4f5c6100d..d91fc690c 100644 --- a/crates/stdx/src/macros.rs +++ b/crates/stdx/src/macros.rs @@ -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::(hook) }; - hook(panic::Location::caller(), args) -} diff --git a/docs/dev/style.md b/docs/dev/style.md index 6dc6868c2..0c5e2ad33 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md @@ -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 diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 202c74426..81b9956b8 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs @@ -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 { -- cgit v1.2.3