aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2024-12-23 14:15:59 +0900
committerYawning Angel <yawning@schwanenlied.me>2024-12-25 00:08:09 +0900
commit3a5440e4eddea3735b26689e576ba4e1102a6a3a (patch)
treef26f390da293a6f1d0c9388357678fdc5b7fe7d0
parentad99d20d292ab4708996c935315c36aef58796a8 (diff)
base/runtime: Add `ensure` and `ensure_contextless`
This provides an equivalent to `assert` and `assert_contextless` that are always evaluated, ignoring `ODIN_DISABLE_ASSERT`, which is useful for enforcing API contracts or "asserting" on conditionals with side-effects.
-rw-r--r--base/runtime/core_builtin.odin29
1 files changed, 29 insertions, 0 deletions
diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin
index d28dadd02..f06dcb478 100644
--- a/base/runtime/core_builtin.odin
+++ b/base/runtime/core_builtin.odin
@@ -964,6 +964,24 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
}
}
+// Evaluates the condition and aborts the program iff the condition is
+// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
+// execute.
+@builtin
+ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
+ if !condition {
+ @(cold)
+ internal :: proc(message: string, loc: Source_Code_Location) {
+ p := context.assertion_failure_proc
+ if p == nil {
+ p = default_assertion_failure_proc
+ }
+ p("unsatisfied ensure", message, loc)
+ }
+ internal(message, loc)
+ }
+}
+
@builtin
panic :: proc(message: string, loc := #caller_location) -> ! {
p := context.assertion_failure_proc
@@ -1000,6 +1018,17 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
}
@builtin
+ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
+ if !condition {
+ @(cold)
+ internal :: proc "contextless" (message: string, loc: Source_Code_Location) {
+ default_assertion_contextless_failure_proc("unsatisfied ensure", message, loc)
+ }
+ internal(message, loc)
+ }
+}
+
+@builtin
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
default_assertion_contextless_failure_proc("panic", message, loc)
}