With keyword real cases encountered issues

Hello,

Currently writing a blog post about Nix with construction, I’m looking for real use cases exemples.
In this post, I speak about possible issues with Nix with. I already have an idea of the theoretically possible issues, but would like to have real config exemples where you had some of them. Also, if you think it’s the case, why in practice it’s not an issue.

I listed below 3 possible causes of issues. Don’t hesitate to share if you have others in mind.

  • Statically defined variables in outer blocks are not shadowed by with. Is it really an issue? At least it let the interpreter resolve what it can statically. But may it cause confusion for the user; in big files for instance.
  • When we are in a with block, it’s impossible to know the variables in scope. Nix will try to resolve dynamically all unbounded variables (look for them in the record passed to with). It may cause difficulty to debug code inside these blocks right? Also, I never tried any LSP for Nix but how could it manage this?
  • When in nested with blocks, the inner one has priority. But it mean if it is updated with a new field and the user don’t know it (with some_lib; an external library), It can easily break the code.

All above are only suppositions. I’m far to be a Nix specialist :wink: so if anyone can share deeper info and experience with it, thanks in advance.
I mainly need, real life exemples where you had these types of issues, or why you think they actually are not issues in practice.

After [RFC 0110] Add "inherit-as-list" syntax construct to the Nix language by r-burns · Pull Request #110 · NixOS/rfcs · GitHub we could probably start deprecating with, at least in nixpkgs

2 Likes

In my experience, the with construct is used only in very limited circumstances, so it’s just not that likely to cause problems. Things like with some_lib; just isn’t that useful.

I have a previous blog post on the topic of with: The with construct in nix-lang -- dramforever

Sadly that’s your perception.

I see a lot of code in the wild that roughly does this:

{ pkgs, lib, config, ...}:

with pkgs;
with lib;

{
  # module definition
}

More often than not, the actually use neither lib nor pkgs

2 Likes

And lots of newcomers just repeat it because they don’t really know what the with keyword does yet. How would they, it has no obvious effect, except that suddenly things don’t work anymore when you remove them.

I think it and rec are the most confusing (and harmful) bits of nix syntax, and definitely the ones used redundantly most frequently, which is probably something worth pointing out in a blog post.

1 Like

The answer is not really. You could probably in theory evaluate the code that results in the attrset with is being used on, but that would be slow. Neither rnix-lsp nor oxalica’s nil have support for scopes filled by with.

With both, the “undefined name” check gets basically disabled within the withs “effect” area.

1 Like

Instead of this pattern I like to use:

{ pkgs, lib, config, ...}:

let
  inherit (pkgs) coreutils gcc bash;
  inherit (lib) mapAttrs concatStringsSep;
in {
  # module definition
}

And the same idea for rec

let
  package1 = mkDerivation { ... };
  package2 = mkDerivation { buildInputs = [ package1 ]; };
in {
  inherit package1 package2;
}

Maybe someone will find this useful :slight_smile:

2 Likes