Auto-caller calls invalid functors #1057

Open
opened 2025-12-01 09:42:13 +00:00 by nrabulinski · 2 comments
Member

Describe the bug

A valid1 functor is an attrset with a __functor attribute, which is a function of type AttrSet -> Any -> Any. However, in a case where someone writes an invalid one, where it’s a function that returns anything but a function, auto-caller will still call it, and resolve the value. Despite it being impossible in regular nix code.

Steps To Reproduce

Given file:

# foo.nix
{
  foo = "hi from outside";
  __functor = _: {
    foo = "hi from inside";
  };
}

We can observe:

$ nix-instantiate --eval foo.nix
{ __functor = <CODE>; foo = "hi from outside"; }
$ nix-instantiate --eval foo.nix -A foo
"hi from inside"

Expected behavior

Either an error saying attrset is not a function, or auto-caller not being engaged and returning hi from outside.

nix --version output

nix (Lix, like Nix) 2.94.0-pre20251115-dev_243836e (still occurs on latest main)

Additional context

Discussed on matrix. cc @piegames @raito


  1. valid is defined by semantics of callFunction, as seen in

    Value args2[] = {vCur, args[0]};

    ↩︎

## Describe the bug A valid[^1] functor is an attrset with a `__functor` attribute, which is a function of type `AttrSet -> Any -> Any`. However, in a case where someone writes an invalid one, where it’s a function that returns anything but a function, auto-caller will still call it, and resolve the value. Despite it being impossible in regular nix code. ## Steps To Reproduce Given file: ```nix # foo.nix { foo = "hi from outside"; __functor = _: { foo = "hi from inside"; }; } ``` We can observe: ``` $ nix-instantiate --eval foo.nix { __functor = <CODE>; foo = "hi from outside"; } $ nix-instantiate --eval foo.nix -A foo "hi from inside" ``` ## Expected behavior Either an error saying attrset is not a function, or auto-caller not being engaged and returning `hi from outside`. ## `nix --version` output `nix (Lix, like Nix) 2.94.0-pre20251115-dev_243836e` (still occurs on latest main) ## Additional context Discussed on matrix. cc @piegames @raito [^1]: valid is defined by semantics of callFunction, as seen in https://git.lix.systems/lix-project/lix/src/commit/3981458d8c498ea88e2107e704b4e859203c72f2/lix/libexpr/eval.cc#L1762
Owner

On the other hand, it doesn't autocall correct functors. What the fuck.

On the other hand, it *doesn't* autocall correct functors. What the fuck.
Owner

auto-calls should be removed entirely. there are multiple issues about how fundamentally broken this feature is, and even apart from that it is completely useless and counterproductive except for the { pkgs ? import <nixpkgs> {} }: header commonly seen in shell.nix files, which is better served by allowing functions with defaults for all structured args to be called exactly one level deep.

auto-calls should be removed entirely. there are multiple issues about how fundamentally broken this feature is, and even apart from that it is completely useless *and counterproductive* except for the `{ pkgs ? import <nixpkgs> {} }:` header commonly seen in shell.nix files, which is better served by allowing functions with defaults for all structured args to be called *exactly one level deep*.
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lix-project/lix#1057
No description provided.