statix icon indicating copy to clipboard operation
statix copied to clipboard

Warn when inheriting attributes from a function call

Open ilkecan opened this issue 3 years ago • 1 comments

It is possible to inherit attributes from another set^1. For example:

let
  x = { a = 1; b = 2; }
  y = { inherit (x) a b; }
in
y # evaluates to `{ a = 1; b = 2; }`

But since Nix does not have maximal laziness, inheriting from the result of a function call will evaluate the function for each inherited attribute. That is, evaluating the expression below:

let
  f = x:
    builtins.trace "evaluated" {
      a = x + 1;
      b = x + 2;
    };
  inherit (f 0) a b;
in
[ a b ]

will evaluate f 0 2 times (which can be checked with trace). This can be avoided with:

let
  f = x:
    builtins.trace "evaluated" {
      a = x + 1;
      b = x + 2;
    };
  set = f 0;
  inherit (set) a b;
in
[ a b ]

In this case f 0 will be evaluated only once because the result is saved in a variable.


An exception to this is import. While the manual notes that import is a regular function, result of import <path> seems to be cached internally, so:

let
  inherit (import <path>) f g;            # this is OK
  inherit (import <path> <some-args>) f g # this is not OK 
in

ilkecan avatar Sep 24 '22 03:09 ilkecan

aha, this is a very nice lint idea, thanks!

oppiliappan avatar Jan 08 '23 13:01 oppiliappan