Skip to content

Commit e2c281a

Browse files
authored
Merge pull request #19219 from Veykril/push-rvosplwpwqqt
Vendor `always-assert` into `stdx`
2 parents b0380db + 9a462b7 commit e2c281a

File tree

5 files changed

+122
-8
lines changed

5 files changed

+122
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rust-analyzer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ syntax-bridge.workspace = true
9494

9595
[features]
9696
jemalloc = ["jemallocator", "profile/jemalloc"]
97-
force-always-assert = ["always-assert/force"]
97+
force-always-assert = ["stdx/force-always-assert"]
9898
sysroot-abi = []
9999
in-rust-tree = [
100100
"sysroot-abi",

crates/stdx/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ doctest = false
1414

1515
[dependencies]
1616
backtrace = { version = "0.3.67", optional = true }
17-
always-assert = { version = "0.2.0", features = ["tracing"] }
1817
jod-thread = "0.1.2"
1918
libc.workspace = true
2019
crossbeam-channel.workspace = true
2120
itertools.workspace = true
21+
tracing.workspace = true
2222
# Think twice before adding anything here
2323

2424
[target.'cfg(windows)'.dependencies]
@@ -28,6 +28,7 @@ windows-sys = { version = "0.59", features = ["Win32_Foundation"] }
2828
[features]
2929
# Uncomment to enable for the whole crate graph
3030
# default = [ "backtrace" ]
31+
force-always-assert = []
3132

3233
[lints]
3334
workspace = true

crates/stdx/src/assert.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Vendored from https://github.com/matklad/always-assert/commit/4cf564eea6fcf18b30c3c3483a611004dc03afbb
2+
//! Recoverable assertions, inspired by [the use of `assert()` in
3+
//! SQLite](https://www.sqlite.org/assert.html).
4+
//!
5+
//! `never!` and `always!` return the actual value of the condition if
6+
//! `debug_assertions` are disabled.
7+
//!
8+
//! Use them when terminating on assertion failure is worse than continuing.
9+
//!
10+
//! One example would be a critical application like a database:
11+
//!
12+
//! ```ignore
13+
//! use stdx::never;
14+
//!
15+
//! fn apply_transaction(&mut self, tx: Transaction) -> Result<(), TransactionAborted> {
16+
//! let delta = self.compute_delta(&tx);
17+
//!
18+
//! if never!(!self.check_internal_invariant(&delta)) {
19+
//! // Ok, something in this transaction messed up our internal state.
20+
//! // This really shouldn't be happening, and this signifies a bug.
21+
//! // Luckily, we can recover by just rejecting the transaction.
22+
//! return abort_transaction(tx);
23+
//! }
24+
//! self.commit(delta);
25+
//! Ok(())
26+
//! }
27+
//! ```
28+
//!
29+
//! Another example is assertions about non-critical functionality in usual apps
30+
//!
31+
//! ```ignore
32+
//! use stdx::never;
33+
//!
34+
//! let english_message = "super app installed!"
35+
//! let mut local_message = localize(english_message);
36+
//! if never!(local_message.is_empty(), "missing localization for {}", english_message) {
37+
//! // We localized all the messages but this one slipper through the cracks?
38+
//! // Better to show the english one then than to fail outright;
39+
//! local_message = english_message;
40+
//! }
41+
//! println!("{}", local_message);
42+
//! ```
43+
44+
/// Asserts that the condition is always true and returns its actual value.
45+
///
46+
/// If the condition is true does nothing and and evaluates to true.
47+
///
48+
/// If the condition is false:
49+
/// * panics if `force` feature or `debug_assertions` are enabled,
50+
/// * logs an error if the `tracing` feature is enabled,
51+
/// * evaluates to false.
52+
///
53+
/// Accepts `format!` style arguments.
54+
#[macro_export]
55+
macro_rules! always {
56+
($cond:expr) => {
57+
$crate::always!($cond, "assertion failed: {}", stringify!($cond))
58+
};
59+
60+
($cond:expr, $fmt:literal $($arg:tt)*) => {{
61+
let cond = $cond;
62+
if cfg!(debug_assertions) || $crate::assert::__FORCE {
63+
assert!(cond, $fmt $($arg)*);
64+
}
65+
if !cond {
66+
$crate::assert::__tracing_error!($fmt $($arg)*);
67+
}
68+
cond
69+
}};
70+
}
71+
72+
/// Asserts that the condition is never true and returns its actual value.
73+
///
74+
/// If the condition is false does nothing and and evaluates to false.
75+
///
76+
/// If the condition is true:
77+
/// * panics if `force` feature or `debug_assertions` are enabled,
78+
/// * logs an error if the `tracing` feature is enabled,
79+
/// * evaluates to true.
80+
///
81+
/// Accepts `format!` style arguments.
82+
///
83+
/// Empty condition is equivalent to false:
84+
///
85+
/// ```ignore
86+
/// never!("oups") ~= unreachable!("oups")
87+
/// ```
88+
#[macro_export]
89+
macro_rules! never {
90+
(true $($tt:tt)*) => { $crate::never!((true) $($tt)*) };
91+
(false $($tt:tt)*) => { $crate::never!((false) $($tt)*) };
92+
() => { $crate::never!("assertion failed: entered unreachable code") };
93+
($fmt:literal $(, $($arg:tt)*)?) => {{
94+
if cfg!(debug_assertions) || $crate::assert::__FORCE {
95+
unreachable!($fmt $(, $($arg)*)?);
96+
}
97+
$crate::assert::__tracing_error!($fmt $(, $($arg)*)?);
98+
}};
99+
100+
($cond:expr) => {{
101+
let cond = !$crate::always!(!$cond);
102+
cond
103+
}};
104+
105+
($cond:expr, $fmt:literal $($arg:tt)*) => {{
106+
let cond = !$crate::always!(!$cond, $fmt $($arg)*);
107+
cond
108+
}};
109+
}
110+
111+
#[doc(hidden)]
112+
pub use tracing::error as __tracing_error;
113+
114+
#[doc(hidden)]
115+
pub const __FORCE: bool = cfg!(feature = "force-always-assert");

crates/stdx/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ use std::io as sio;
44
use std::process::Command;
55
use std::{cmp::Ordering, ops, time::Instant};
66

7-
pub mod anymap;
87
mod macros;
8+
9+
pub mod anymap;
10+
pub mod assert;
911
pub mod non_empty_vec;
1012
pub mod panic_context;
1113
pub mod process;
1214
pub mod rand;
1315
pub mod thin_vec;
1416
pub mod thread;
1517

16-
pub use always_assert::{always, never};
1718
pub use itertools;
1819

1920
#[inline(always)]

0 commit comments

Comments
 (0)