about summary refs log tree commit diff
diff options
context:
space:
mode:
authorsternenseemann <sternenseemann@systemli.org>2022-01-17 19:12:54 +0100
committersterni <sternenseemann@systemli.org>2022-01-19 00:50:06 +0100
commit48965506a1ac5b0a08a0224551e8604c323691d1 (patch)
treed957fc79688fb02a7c06249e2bbe343ae8faa6da
parent6733a4dffa4341cd714e97b403f77367d1abf977 (diff)
lib/asserts: use throw to display message for assertMsg
`assert` has the annoying property that it dumps a lot of code at the
user without the built in capability to display a nicer message. We have
worked around this using `assertMsg` which would *additionally* display
a nice message. We can do even better: By using `throw` we can make
evaluation fail before assert draws its conclusions and prevent it from
displaying the code making up the assert condition, so we get the nicer
message of `throw` and the syntactical convenience of `assert`.

Before:

    nix-repl> python.override { reproducibleBuild = true; stripBytecode = false; }
    trace: Deterministic builds require stripping bytecode.
    error: assertion (((lib).assertMsg  (reproducibleBuild -> stripBytecode))  "Deterministic builds require stripping bytecode.") failed at /home/lukas/src/nix/nixpkgs/pkgs/development/interpreters/python/cpython/2.7/default.nix:45:1

After:

    nix-repl> python.override { reproducibleBuild = true; stripBytecode = false; }
    error: Deterministic builds require stripping bytecode.
-rw-r--r--lib/asserts.nix22
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml12
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md2
3 files changed, 24 insertions, 12 deletions
diff --git a/lib/asserts.nix b/lib/asserts.nix
index 8a5f1fb3feb76..9ae357cbc935e 100644
--- a/lib/asserts.nix
+++ b/lib/asserts.nix
@@ -2,35 +2,33 @@
 
 rec {
 
-  /* Print a trace message if pred is false.
+  /* Throw if pred is false, else return pred.
      Intended to be used to augment asserts with helpful error messages.
 
      Example:
        assertMsg false "nope"
-       => false
-       stderr> trace: nope
+       stderr> error: nope
 
-       assert (assertMsg ("foo" == "bar") "foo is not bar, silly"); ""
-       stderr> trace: foo is not bar, silly
-       stderr> assert failed at …
+       assert assertMsg ("foo" == "bar") "foo is not bar, silly"; ""
+       stderr> error: foo is not bar, silly
 
      Type:
        assertMsg :: Bool -> String -> Bool
   */
   # TODO(Profpatsch): add tests that check stderr
   assertMsg = pred: msg:
-    if pred
-    then true
-    else builtins.trace msg false;
+    pred || builtins.throw msg;
 
   /* Specialized `assertMsg` for checking if val is one of the elements
      of a list. Useful for checking enums.
 
      Example:
-       let sslLibrary = "libressl"
+       let sslLibrary = "libressl";
        in assertOneOf "sslLibrary" sslLibrary [ "openssl" "bearssl" ]
-       => false
-       stderr> trace: sslLibrary must be one of "openssl", "bearssl", but is: "libressl"
+       stderr> error: sslLibrary must be one of [
+       stderr>   "openssl"
+       stderr>   "bearssl"
+       stderr> ], but is: "libressl"
 
      Type:
        assertOneOf :: String -> ComparableVal -> List ComparableVal -> Bool
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index 34e31b6e505e4..ce45b0d797756 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -408,6 +408,18 @@
           configuration.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          <literal>lib.assertMsg</literal> and
+          <literal>lib.assertOneOf</literal> no longer return
+          <literal>false</literal> if the passed condition is
+          <literal>false</literal>, <literal>throw</literal>ing the
+          given error message instead (which makes the resulting error
+          message less cluttered). This will not impact the behaviour of
+          code using these functions as intended, namely as top-level
+          wrapper for <literal>assert</literal> conditions.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
   <section xml:id="sec-release-22.05-notable-changes">
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index feac58f05e8b2..25b3ada2c5630 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -132,6 +132,8 @@ In addition to numerous new and upgraded packages, this release has the followin
   [settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md)
   configuration.
 
+- `lib.assertMsg` and `lib.assertOneOf` no longer return `false` if the passed condition is `false`, `throw`ing the given error message instead (which makes the resulting error message less cluttered). This will not impact the behaviour of code using these functions as intended, namely as top-level wrapper for `assert` conditions.
+
 <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
 
 ## Other Notable Changes {#sec-release-22.05-notable-changes}