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"
name = "rust-analyzer"
version = "0.0.0"
dependencies = [
+ "always-assert",
"anyhow",
"cfg",
"crossbeam-channel 0.5.0",
name = "stdx"
version = "0.0.0"
dependencies = [
+ "always-assert",
"backtrace",
]
},
SymbolKind,
};
-use stdx::{assert_never, impl_from};
+use stdx::{impl_from, never};
use syntax::{algo, TextRange};
use text_edit::TextEdit;
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());
}
}
search::FileReference,
RootDatabase,
};
-use stdx::assert_never;
+use stdx::never;
use syntax::{
ast::{self, NameOwner},
lex_single_syntax_kind, AstNode, SyntaxKind, SyntaxNode, T,
}
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");
}
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");
}
};
use base_db::{AnchoredPathBuf, FileId};
use rustc_hash::FxHashMap;
-use stdx::assert_never;
+use stdx::never;
use text_edit::TextEdit;
#[derive(Default, Debug, Clone)]
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);
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" }
[features]
jemalloc = ["jemallocator", "profile/jemalloc"]
+force-always-assert = ["always-assert/force"]
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(())
}
[dependencies]
backtrace = { version = "0.3.44", optional = true }
+always-assert = { version = "0.1.1", features = ["log"] }
# Think twice before adding anything here
[features]
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 {
//! Convenience macros.
-use std::{
- fmt, mem, panic,
- sync::atomic::{AtomicUsize, Ordering::SeqCst},
-};
#[macro_export]
macro_rules! eprintln {
($($tt:tt)*) => {{
)*
}
}
-
-/// 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)
-}
## Assertions
Assert liberally.
-Prefer `stdx::assert_never!` to standard `assert!`.
+Prefer `stdx::never!` to standard `assert!`.
## Getters & Setters
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 {