Announcing Lix 2.90 "Vanilla Ice Cream"

We at the Lix team are proud to announce our first release, version 2.90 “Vanilla Ice Cream”. This release focuses on foundations and reliability, but nevertheless contains several small but exciting user-facing features that are exclusive to Lix.

Lix is a Nix implementation focused on reliability, predictability, friendliness, developed by a community of people from around the world. We have long term plans to incrementally evolve Nix to work in more places, to make it more reliable and secure, and to update the language and semantics to correct past mistakes and reduce errors, all the while providing an amazing tooling experience.

Lix forks from CppNix version 2.18, which is the default version of Nix in NixOS 23.11 and 24.05. It includes backports for most bug fixes in later versions of CppNix, as well as various reliability improvements, and many improvements to user experience. Our goal with Lix 2.90 is to create a better Nix 2.18: faster, more user friendly, with fewer bugs, and fully compatible with previously-valid Nix code including flakes.

Some highlights of this release include:

  • :doc in nix repl now works on lambdas, in addition to built-in functions as before, thanks to Lunaphied and jade:

    dev/nixpkgs » nix repl -f .
    Lix 2.90.0-lixpre20240520-992c63f
    Type :? for help.
    Loading installable ''...
    Added 21430 variables.
    nix-repl> :doc lib.forEach
    Synopsis: func = xs: f: ...
    
          |    Apply the function to each element in the list.
          |    Same as `map`, but arguments flipped.
          |
          | Inputs
          |
          |    `xs`
          |
          |    : 1\. Function argument
          |
          |    `f`
          |
          |    : 2\. Function argument
          |
          | Type
          |
          |    ``
          |    forEach :: [a] -> (a -> b) -> [b]
          |    ``
          |
          | Examples
          |    :::{.example}
    
        # lib.lists.forEach usage example
    
          |    ``nix
          |    forEach [ 1 2 ] (x:
          |      toString x
          |    )
          |    => [ "1" "2" ]
          |    ``
          |
          |    :::
    
    /home/jade/dev/nixpkgs/lib/lists.nix:77
    
  • nix repl supports creating shortcuts using the repl-overlays setting, thanks to wiggles. For example, one can create a shortcut to legacyPackages.${currentSystem} with the following repl overlay, configured as a file in the repl-overlays setting in ~/.config/nix/nix.conf:

    { currentSystem, ...}: final: prev: let
      optionalAttrs = predicate: attrs:
        if predicate
        then attrs
        else {};
    in
      optionalAttrs (prev ? legacyPackages && prev.legacyPackages ? ${currentSystem})
      {
        pkgs = prev.legacyPackages.${currentSystem};
      }
    

    Then:

    ~ » nix repl nixpkgs
    Lix 2.90.0-lixpre20240520-992c63f
    Type :? for help.
    Loading installable 'flake:nixpkgs#'...
    Added 5 variables.
    Loading 'repl-overlays'...
    Added 6 variables.
    nix-repl> pkgs.hello
    «derivation /nix/store/w0hjp1fnvyf1z30s29fj4im8c7bxqrql-hello-2.12.1.drv»
    
  • Evaluation is 5-20% faster than 2.18, depending on which benchmark is in use, thanks to eldritch horrors.

  • Various user experience issues have been fixed. For example:

    • Error reporting has been fixed to be more accurate in several cases thanks to wiggles, and errors give more details to diagnose them.

      For instance, type errors now give the actual value that caused the error.

    • nix flake lock --update-input nixpkgs is now the much more reasonable nix flake update nixpkgs.

    • nix build -E is now an alias for nix build --expr, mirroring nix-build -E.

    • Several very silly --debugger bugs that one runs into in normal usage have been fixed thanks to wiggles, so the debugger actually works properly without a mental index of all the bugs in it.

    • The Lix evaluation cache no longer caches failures, so “cached failure” is an error of the past.

    • The REPL value printer now intelligently chooses whether to print on one line or multiple lines, rather than putting everything on one very long line.

    • Various failures that were silent in the past are no longer silent:

      • The Lix daemon warns when it rejects a setting from a client that requires being a trusted user, instead of silently ignoring it.
      • Remote builds failing to connect to a builder now print the error.
      • Crashing the daemon now indicates that is what probably happened.
      • Lix now generally crashes much harder in the case of bugs, such that bugs are easier to find and fix.
    • Various errors have been made more specific, like “path is invalid”.

  • Several hauntings have been exorcised from the codebase:

    • Flake input overrides like foo.inputs.bar.inputs.nixpkgs now work as documented rather than being ignored.
    • Store path names starting with . are now permitted, fixing some home-manager issues.
    • A crash when running patched kernels with non-default schedulers has been fixed.
    • Breakage inside the sandbox when running on systems with unprivileged user namespaces disabled has been fixed.
    • Various format string crashes have been fixed.
    • nix doctor now has correct output of client trustedness.

A lot of internal stability work and development process work has gone into this release. For instance:

  • Lix builds exclusively with the Meson build system. The historical CppNix Make-based build system has been removed altogether. This improves compile times as well as various aspects of the developer experience: the clangd language server just works with no configuration now, for instance.
  • Lix has the beginnings of the infrastructure to do linting of its C++ code and work on modernization with automated tools.
  • Lix enforces various aspects of its styleguide with pre-commit hooks.
  • A lot of onboarding and project planning information has been written down in the Wiki. In general we strive to be transparent with our plans and priorities, and to communicate them clearly.
  • We have completed a release automation project, which should let us release more frequently given that our main is more or less releaseable on any given day.
  • We have built out a lot of infrastructure which we own end-to-end, allowing us to quickly improve on pain points in the project ourselves.
    • We have Single Sign-On permitting us to easily deploy more services that cleanly integrate together.

    • We use Gerrit for reviews, which allows us to focus on providing prompt and high quality patch reviews by making it easy to review changes piece by piece, with CI testing of every commit.

      Gerrit is one of our secret superpowers in shipping correct code, since it, by its structure, enforces good commit history, reviewable code, and incremental changes.

    • We use Forgejo for code hosting and issue tracking, which we have customised to integrate natively with Gerrit and to work natively with Nix flakes for locking tarballs.

    • We have a Wiki with design documents, styleguide, and other project organisational information.

For a more comprehensive list of the changes in this release, see the release notes.

The Lix team as well as several dozen beta testers have been running a development release of Lix 2.90 in production every day for a couple of months, and we do not expect any significant regressions compared to Nix 2.18. However, if you find a bug or suspicious behaviour in Lix, feel free to mention it on Matrix or file a bug on Forgejo. If you would like to participate in beta testing of future Lix versions, we have a guide on the wiki and a Matrix channel for running main.

We would especially like to thank all the following groups for their hard work and trust in contributing to this release:

  • The several dozen Lix beta testers who have been running Lix main in production for over a month, and who have helped us fix the various longstanding CppNix bugs they have had stuck in their craw as well as put up with our work-in-progress infrastructure as we built it out.
  • All the first time contributors who made their first contributions to a Nix implementation in Lix. We are eternally grateful to everyone who helped us out on the numerous important but tedious issues.
  • All the people new to Nix who have trusted us by running experimental versions of Lix and given us feedback.
  • The long time CppNix contributors who came to Lix and helped out with fixing many issues.
  • The CppNix contributors and CppNix team, without whom we would not have this software, and who wrote many of the bug fixes we backported to Lix from CppNix versions > 2.18.
  • Everyone else who has worked with us on starting to make this dream a reality.

We are very proud of what everyone has achieved with this release since we begun in late February 2024, and we are just getting started. We are looking forward to continue working together with everyone to build a better foundation for the future evolution of Nix.