Infinite recursion when extending haskell packages

This simple and naive files gives the infinite recursion error when executing nix-build test.nix:

 { }:

let

  boot = import <nixpkgs> {};

  source = {
    nixpkgs = boot.pkgs.fetchFromGitHub {
      owner = "NixOS";
      repo = "nixpkgs";
      rev = "a381b789984442c1223c1c5b5c6f0aa259eaa4fb";
      sha256 = "1pazqjjmlhg7zbaqi8nygjhy06pq3jz6nnr4ifmk54h403a1hmmp";
    };

    localHaskellPackages = {
      foo = "https://github.com/ip1981/sproxy2";
    };
  };

  inherit (import source.nixpkgs {}) pkgs;
  inherit (pkgs) lib;

  haskellPackages =
    let

      set0 = pkgs.haskell.packages.ghc822;

      set1 = set0.extend (
        self: super:
          lib.mapAttrs' (n: d:
            super.callPackage (
              pkgs.runCommand "cabal2nix-${n}.nix" {} "${super.cabal2nix}/bin/cabal2nix '${d}' > $out"
            ) {}) source.localHaskellPackages);

    in set1;

in haskellPackages.foo

Error:

error: while evaluating anonymous function at /home/pashev/work/cm/app/test.nix:1:1, called from undefined position:
while evaluating ‘extend’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:77:25, called from /home/pashev/work/cm/app/test.nix:28:14:
while evaluating ‘makeExtensibleWithCustomName’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:75:48, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:77:28:
while evaluating ‘fix'’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:25:10, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:76:5:
while evaluating ‘extends’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:44:24, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:25:21:
while evaluating anonymous function at /home/pashev/work/cm/app/test.nix:29:15, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/fixed-points.nix:44:67:
while evaluating ‘mapAttrs'’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/attrsets.nix:211:18, called from /home/pashev/work/cm/app/test.nix:30:11:
while evaluating anonymous function at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/attrsets.nix:212:23, called from undefined position:
while evaluating anonymous function at /home/pashev/work/cm/app/test.nix:30:29, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/attrsets.nix:212:29:
while evaluating ‘callPackage’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:102:22, called from /home/pashev/work/cm/app/test.nix:31:13:
while evaluating ‘callPackageWithScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:75:37, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:102:28:
while evaluating ‘makeOverridable’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/customisation.nix:72:24, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:98:8:
while evaluating ‘drvScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:88:18, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/customisation.nix:74:12:
while evaluating the attribute ‘buildCommand’ of the derivation ‘cabal2nix-foo.nix’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/stdenv/generic/make-derivation.nix:148:11:
while evaluating the attribute ‘cabal2nix’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/configuration-ghc-8.2.x.nix:103:3:
while evaluating the attribute ‘cabal2nix.overrideScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/configuration-common.nix:611:3:
while evaluating the attribute ‘cabal2nix.overrideScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/hackage-packages.nix:41207:3:
while evaluating ‘callPackage’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:102:22, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/hackage-packages.nix:41207:17:
while evaluating ‘callPackageWithScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:75:37, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:102:28:
while evaluating ‘makeOverridable’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/customisation.nix:72:24, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:98:8:
while evaluating ‘drvScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:88:18, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/lib/customisation.nix:74:12:
while evaluating ‘mkScope’ at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:100:13, called from /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:101:18:
infinite recursion encountered, at /nix/store/vcjvhsw3xfyr35kbi81lrz6c217bfqyl-nixpkgs-a381b789984442c1223c1c5b5c6f0aa259eaa4fb-src/pkgs/development/haskell-modules/make-package-set.nix:100:79

The thing is I really want to run cabal2nix (the projects are moving targets). I could use set0.callPackage and set0.cabal2nix, but set0 would obviously miss other packages added via cabal2nix.

What can I do?

Answering myself (made mistakes in nix expressions):

{ }:

let

  boot = import <nixpkgs> {};

  source = {
    nixpkgs = boot.pkgs.fetchFromGitHub {
      owner = "NixOS";
      repo = "nixpkgs";
      rev = "a381b789984442c1223c1c5b5c6f0aa259eaa4fb";
      sha256 = "1pazqjjmlhg7zbaqi8nygjhy06pq3jz6nnr4ifmk54h403a1hmmp";
    };

    localHaskellPackages = {
      fubar123 = ./foobar123;
    };
  };

  inherit (import source.nixpkgs {config = {allowUnfree = true;};}) pkgs;
  inherit (pkgs) lib;

  haskellPackages =
    let

      set0 = pkgs.haskell.packages.ghc822;

      extras =
        lib.mapAttrs (n: d:
          pkgs.runCommand "cabal2nix-${n}.nix" {} "set -x; ${set0.cabal2nix}/bin/cabal2nix '${builtins.toPath d}' > $out"
        ) source.localHaskellPackages;

      set1 = set0.extend (
        self: super: lib.mapAttrs (_: d: super.callPackage d {}) extras
      );

    in set1;

in haskellPackages.fubar123

In my experience, every time there is a fix-point like with haskellPackages this kind of problem tends to happen more easily. It’s tricky to get the code aligned properly. I also find it easier to debug the problem when using overlays once I have learned to use them.

Here I would change a few things:

Split the file in 2, one for the overlays and one for the outputs.

default.nix:

{ }:
let
  fetchNixpkgs = spec: fetchTarball {
    url = "https://github.com/${spec.owner}/${spec.repo}/archive/${spec.rev}.tar.gz";
    sha256 = spec.sha256;
  };
  // This avoids instantiating nixpkgs twice
  nixpkgs = fetchNixpkgs {
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "a381b789984442c1223c1c5b5c6f0aa259eaa4fb";
    sha256 = "1pazqjjmlhg7zbaqi8nygjhy06pq3jz6nnr4ifmk54h403a1hmmp";
  };

  localHaskellPackages = {
    foo = "https://github.com/ip1981/sproxy2";
  };

  overlay = self: pkgs: {
    myHaskellPackages = pkgs.haskell.packages.ghc822.extend (self: super:
      lib.mapAttrs' (n: d:
        super.callPackage (
           pkgs.runCommand "cabal2nix-${n}.nix" {} "${super.cabal2nix}/bin/cabal2nix '${d}' > $out"
            ) {}) localHaskellPackages);
  };
in
  import nixpkgs {
    config = {}; // Set this to avoid user config polluting your package set
    overlays = [ overlay ]; // Same, user overlays could change the build outputs otherwise
  }

And then a release.nix:

let pkgs = import ./. {}; in
{
  inherit (pkgs.myHaskellPackages)
    foo
    ;
}

That way it’s easy in nix repl to load the default.nix and poke around, plus you have access to all the other nixpkgs packages.

1 Like