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:
bors[bot] 2021-01-26 19:14:16 +00:00 committed by GitHub
commit 8775bc4be1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 24 additions and 73 deletions

11
Cargo.lock generated
View file

@ -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",
]

View file

@ -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());
}
}

View file

@ -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");
}
};

View file

@ -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);

View file

@ -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"]

View file

@ -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(())
}

View file

@ -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]

View file

@ -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 {

View file

@ -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)
}

View file

@ -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

View file

@ -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 {