Multiple builtins.trace in let/in

tl;dr
How can I have multiple trace’ in in

let ...
in
  builtins.map (value: builtins.trace value.pkgs.hello.opt1 { }) [set1 set2]
  builtins.map (value: builtins.trace value.pkgs.hello.opt1 { }) [set3 set4]

long

I’m trying to learn something about overriding derivations, so I made a test file

let
  pkgs = import <nixpkgs> { };

  testHelloPkg = ({ stdenv, opt1 ? false }:
    stdenv.mkDerivation {
      pname = "hello";
      passthru = { inherit opt1;};
    });

  testPythonPkg = ({ buildPythonPackage, opt1 ? false }:
    buildPythonPackage {
      pname = "hello";
      version = "1";
      passthru = { inherit opt1;};
    });

  ## python
  # First override, original python package set
  python3_1 = pkgs.python3.override {
    packageOverrides = self: super: {
      hello = super.pkgs.callPackage testPythonPkg {
        inherit (super) buildPythonPackage;
      };
    };
  };

  # Second override. XXX: fails! python.override does not compose!
  # https://github.com/NixOS/nixpkgs/issues/44426
  python3_2 = python3_1.override {
    packageOverrides = self: super: {
      hello = super.hello.override { opt1 = true; };
    };
  };

  # third override
  python3_3 = pkgs.python3.override {
    packageOverrides = self: super: {
      hello = super.pkgs.callPackage testPythonPkg {
        inherit (super) buildPythonPackage;
        opt1 = true;
      };
    };
  };

  ## mkDerivation
  # https://nixos.org/manual/nixpkgs/stable/#sec-overlays-argument
  hello1 = pkgs.extend
    (self: super: { hello = super.callPackage testHelloPkg { }; });

  hello2 = hello1.appendOverlays
    [ (self: super: { hello = super.hello.override { opt1 = true; }; }) ];

in
# builtins.map (value: builtins.trace value.pkgs.hello.opt1 { }) [
#   python3_1
#   # python3_2  # XXX: fails
#   python3_3
# ]

builtins.map (value: builtins.trace value.pkgs.hello.opt1 { }) [
  hello1
  hello2
]

run with nix-build --no-out-link test_overlay.nix.

How can I have both trace’ uncommented in the in clause?

you can use assert

assert builtins.all (value: builtins.trace value.pkgs.hello.opt1 true) [
  python3_1
  # python3_2  # XXX: fails
  python3_3
];
trace: false
trace: true
trace: false
trace: true

You can have as many traces as you want. The problem here is not related to the traces, but the fact that you are calling builtins.map with 5 arguments (under the assumption you have no cimments in the in part):

  • (value: builtins.trace value.pkgs.hello.opt1 { })
  • [
      python3_1
      # python3_2  # XXX: fails
      python3_3
    ]
    
  • builtins.map
  • (value: builtins.trace value.pkgs.hello.opt1 { })
  • [
      hello1
      hello2
    ]
    

So this is not really different from doing map (x: x) [ ] map (x: x) [ ] which becomes [ ] map (x: x) [ ]. which tries to call a list…

@figsoda thanks!

@NobbZ ok, thanks for the explanation. Is there any other way to have multiple traces, except for using assert as figsoda suggest(and I use it now)

As said, you can have as many traces you’d like. You just need to make sure that you produce a proper value for which endresult all the traced values are evaluated.