Unnamed repository; edit this file 'description' to name the repository.
Vendor always-assert
Lukas Wirth 2025-02-24
parent 6d68c47 · commit 9a462b7
-rw-r--r--Cargo.lock5
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/stdx/Cargo.toml3
-rw-r--r--crates/stdx/src/assert.rs115
-rw-r--r--crates/stdx/src/lib.rs5
5 files changed, 122 insertions, 8 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fc3680ce27..b4e97261d7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -22,9 +22,6 @@ name = "always-assert"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1078fa1ce1e34b1872d8611ad921196d76bdd7027e949fbe31231abde201892"
-dependencies = [
- "tracing",
-]
[[package]]
name = "anyhow"
@@ -1922,13 +1919,13 @@ dependencies = [
name = "stdx"
version = "0.0.0"
dependencies = [
- "always-assert",
"backtrace",
"crossbeam-channel",
"itertools",
"jod-thread",
"libc",
"miow",
+ "tracing",
"windows-sys 0.59.0",
]
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index b8ce2b7430..64c8afdc1f 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -94,7 +94,7 @@ syntax-bridge.workspace = true
[features]
jemalloc = ["jemallocator", "profile/jemalloc"]
-force-always-assert = ["always-assert/force"]
+force-always-assert = ["stdx/force-always-assert"]
sysroot-abi = []
in-rust-tree = [
"sysroot-abi",
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml
index 1ebb48c577..62c32d68e6 100644
--- a/crates/stdx/Cargo.toml
+++ b/crates/stdx/Cargo.toml
@@ -14,11 +14,11 @@ doctest = false
[dependencies]
backtrace = { version = "0.3.67", optional = true }
-always-assert = { version = "0.2.0", features = ["tracing"] }
jod-thread = "0.1.2"
libc.workspace = true
crossbeam-channel.workspace = true
itertools.workspace = true
+tracing.workspace = true
# Think twice before adding anything here
[target.'cfg(windows)'.dependencies]
@@ -28,6 +28,7 @@ windows-sys = { version = "0.59", features = ["Win32_Foundation"] }
[features]
# Uncomment to enable for the whole crate graph
# default = [ "backtrace" ]
+force-always-assert = []
[lints]
workspace = true
diff --git a/crates/stdx/src/assert.rs b/crates/stdx/src/assert.rs
new file mode 100644
index 0000000000..91c279798c
--- /dev/null
+++ b/crates/stdx/src/assert.rs
@@ -0,0 +1,115 @@
+// Vendored from https://github.com/matklad/always-assert/commit/4cf564eea6fcf18b30c3c3483a611004dc03afbb
+//! Recoverable assertions, inspired by [the use of `assert()` in
+//! SQLite](https://www.sqlite.org/assert.html).
+//!
+//! `never!` and `always!` return the actual value of the condition if
+//! `debug_assertions` are disabled.
+//!
+//! Use them when terminating on assertion failure is worse than continuing.
+//!
+//! One example would be a critical application like a database:
+//!
+//! ```ignore
+//! use stdx::never;
+//!
+//! fn apply_transaction(&mut self, tx: Transaction) -> Result<(), TransactionAborted> {
+//! let delta = self.compute_delta(&tx);
+//!
+//! if never!(!self.check_internal_invariant(&delta)) {
+//! // Ok, something in this transaction messed up our internal state.
+//! // This really shouldn't be happening, and this signifies a bug.
+//! // Luckily, we can recover by just rejecting the transaction.
+//! return abort_transaction(tx);
+//! }
+//! self.commit(delta);
+//! Ok(())
+//! }
+//! ```
+//!
+//! Another example is assertions about non-critical functionality in usual apps
+//!
+//! ```ignore
+//! use stdx::never;
+//!
+//! let english_message = "super app installed!"
+//! let mut local_message = localize(english_message);
+//! if never!(local_message.is_empty(), "missing localization for {}", english_message) {
+//! // We localized all the messages but this one slipper through the cracks?
+//! // Better to show the english one then than to fail outright;
+//! local_message = english_message;
+//! }
+//! println!("{}", local_message);
+//! ```
+
+/// Asserts that the condition is always true and returns its actual value.
+///
+/// If the condition is true does nothing and and evaluates to true.
+///
+/// If the condition is false:
+/// * panics if `force` feature or `debug_assertions` are enabled,
+/// * logs an error if the `tracing` feature is enabled,
+/// * evaluates to false.
+///
+/// Accepts `format!` style arguments.
+#[macro_export]
+macro_rules! always {
+ ($cond:expr) => {
+ $crate::always!($cond, "assertion failed: {}", stringify!($cond))
+ };
+
+ ($cond:expr, $fmt:literal $($arg:tt)*) => {{
+ let cond = $cond;
+ if cfg!(debug_assertions) || $crate::assert::__FORCE {
+ assert!(cond, $fmt $($arg)*);
+ }
+ if !cond {
+ $crate::assert::__tracing_error!($fmt $($arg)*);
+ }
+ cond
+ }};
+}
+
+/// Asserts that the condition is never true and returns its actual value.
+///
+/// If the condition is false does nothing and and evaluates to false.
+///
+/// If the condition is true:
+/// * panics if `force` feature or `debug_assertions` are enabled,
+/// * logs an error if the `tracing` feature is enabled,
+/// * evaluates to true.
+///
+/// Accepts `format!` style arguments.
+///
+/// Empty condition is equivalent to false:
+///
+/// ```ignore
+/// never!("oups") ~= unreachable!("oups")
+/// ```
+#[macro_export]
+macro_rules! never {
+ (true $($tt:tt)*) => { $crate::never!((true) $($tt)*) };
+ (false $($tt:tt)*) => { $crate::never!((false) $($tt)*) };
+ () => { $crate::never!("assertion failed: entered unreachable code") };
+ ($fmt:literal $(, $($arg:tt)*)?) => {{
+ if cfg!(debug_assertions) || $crate::assert::__FORCE {
+ unreachable!($fmt $(, $($arg)*)?);
+ }
+ $crate::assert::__tracing_error!($fmt $(, $($arg)*)?);
+ }};
+
+ ($cond:expr) => {{
+ let cond = !$crate::always!(!$cond);
+ cond
+ }};
+
+ ($cond:expr, $fmt:literal $($arg:tt)*) => {{
+ let cond = !$crate::always!(!$cond, $fmt $($arg)*);
+ cond
+ }};
+}
+
+#[doc(hidden)]
+pub use tracing::error as __tracing_error;
+
+#[doc(hidden)]
+pub const __FORCE: bool = cfg!(feature = "force-always-assert");
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 04c2153abf..8313e1871f 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -4,8 +4,10 @@ use std::io as sio;
use std::process::Command;
use std::{cmp::Ordering, ops, time::Instant};
-pub mod anymap;
mod macros;
+
+pub mod anymap;
+pub mod assert;
pub mod non_empty_vec;
pub mod panic_context;
pub mod process;
@@ -13,7 +15,6 @@ pub mod rand;
pub mod thin_vec;
pub mod thread;
-pub use always_assert::{always, never};
pub use itertools;
#[inline(always)]