callPackage with default value error: value is a function while a Boolean was expected

I’ve been playing around with cross compiling rust from my m1 mac to an x86_64-linux machine running Arch. I got things working ( :slight_smile: ) but then refactored the logic a bit and am now getting error: value is a function while a Boolean was expected for unclear reasons; if I don’t explicitly pass a value, the makeStatic boolean that I’m passing in is a lambda whenever I builtins.trace it.

# flake.nix
{
  description = "Example of cross-compiling Rust on aarch64-darwin for x86_64-linux";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
  };

  outputs = {
    self,
    nixpkgs,
    rust-overlay,
  }: let
    system = "aarch64-darwin";
    overlays = [(import rust-overlay)];
    pkgs = import nixpkgs {
      inherit overlays system;
      crossSystem = {
        config = "x86_64-unknown-linux-gnu";
        rustc.config = "x86_64-unknown-linux-gnu";
      };
    };
  in {
    packages.${system} = {
      default = self.outputs.packages.${system}.x86_64-linux;
      x86_64-linux = pkgs.callPackage ./. {};
      x86_64-linux-static = pkgs.callPackage ./. {makeStatic = true;};
    };
  };
}
# default.nix
{
  rustPlatform,
  glibc,
  makeStatic ? false,
}:
rustPlatform.buildRustPackage ({
    name = "rust-cross-test";
    src = ./.;
    cargoLock.lockFile = ./Cargo.lock;
    CARGO_BUILD_TARGET = "x86_64-unknown-linux-gnu";
  }
  // (
    if makeStatic
    then {
      buildInputs = [glibc.static];
      RUSTFLAGS = ["-C" "target-feature=+crt-static"];
    }
    else {
      postBuild = ''
        patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 target/x86_64-unknown-linux-gnu/release/linux-cross-example
      '';
    }
  ))
$ nix build --show-trace
error:
       … while evaluating the attribute 'outputs.packages.aarch64-darwin.x86_64-linux'

       at /nix/store/vf03xql3nkz3am5f6rpdi0j3w7i8x3fi-source/flake.nix:27:7:

           26|       # x86_64-linux = pkgs.callPackage ./. {makeStatic = false;};
           27|       x86_64-linux = pkgs.callPackage ./. {};
             |       ^
           28|       x86_64-linux-static = pkgs.callPackage ./. {makeStatic = true;};

       … while evaluating call site

       at /nix/store/vf03xql3nkz3am5f6rpdi0j3w7i8x3fi-source/flake.nix:27:22:

           26|       # x86_64-linux = pkgs.callPackage ./. {makeStatic = false;};
           27|       x86_64-linux = pkgs.callPackage ./. {};
             |                      ^
           28|       x86_64-linux-static = pkgs.callPackage ./. {makeStatic = true;};

       … while calling 'callPackageWith'

       at /nix/store/jfji1id0l3xxy8mgph757dwyngsjaamr-source/lib/customisation.nix:122:35:

          121|   */
          122|   callPackageWith = autoArgs: fn: args:
             |                                   ^
          123|     let

       … while evaluating call site

       at /nix/store/jfji1id0l3xxy8mgph757dwyngsjaamr-source/lib/customisation.nix:173:34:

          172|
          173|     in if missingArgs == [] then makeOverridable f allArgs else abort error;
             |                                  ^
          174|

       … while calling 'makeOverridable'

       at /nix/store/jfji1id0l3xxy8mgph757dwyngsjaamr-source/lib/customisation.nix:72:24:

           71|   */
           72|   makeOverridable = f: origArgs:
             |                        ^
           73|     let

       … while evaluating call site

       at /nix/store/jfji1id0l3xxy8mgph757dwyngsjaamr-source/lib/customisation.nix:74:16:

           73|     let
           74|       result = f origArgs;
             |                ^
           75|

       … while calling anonymous lambda

       at /nix/store/vf03xql3nkz3am5f6rpdi0j3w7i8x3fi-source/default.nix:1:1:

            1| {
             | ^
            2|   rustPlatform,

       error: value is a function while a Boolean was expected

       at /nix/store/vf03xql3nkz3am5f6rpdi0j3w7i8x3fi-source/default.nix:13:5:

           12|   // (
           13|     if makeStatic
             |     ^
           14|     then {

However, this works fine, but seems essentially identical:

# flake.nix
{
  outputs = {
    self,
    nixpkgs,
  }: let
    system = "aarch64-darwin";
    pkgs = import nixpkgs {inherit system;};
  in {
    packages.${system} = {
      default = self.outputs.packages.${system}.first;
      first = pkgs.callPackage ./. {foo = true;};
      second = pkgs.callPackage ./. {};
    };
  };
}
# default.nix
{
  pkgs,
  foo ? false,
}:
pkgs.stdenv.mkDerivation ({
    name = "test";
    dontUnpack = true;
    patchPhase = ''
      echo yup >> $out
    '';
  }
  // (
    if foo
    then {
      installPhase = ''echo "foo was true!" >> $out'';
    }
    else {
      installPhase = ''echo "foo was false!" >> $out'';
    }
  ))
$ nix build .#first && cat result
yup
foo was true!
$ nix build .#second && cat result
yup
foo was false!

What gives? What makes the second build fine but the first fail?

After lots of cursing, I discovered that changing the attribute name from makeStatic resolved the issue. What a waste of time!

Looks like makeStatic is a function defined in pkgs/stdenv/adapters.nix, so callPackage was using its magic to pull in this function from pkgs (instead of just being a boolean variable like I expected), leading to all sorts of chaos and confusion.