Skip to content

vm: coerce the path builtin's path argument like Nix's coerceToPath - #10

Closed
dan-v wants to merge 1 commit into
psyclyx:mainfrom
dan-v:pr/path-builtin-coerce
Closed

vm: coerce the path builtin's path argument like Nix's coerceToPath#10
dan-v wants to merge 1 commit into
psyclyx:mainfrom
dan-v:pr/path-builtin-coerce

Conversation

@dan-v

@dan-v dan-v commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Problem

builtins.path rejects an attrset path argument with a type error. Nix's prim_path routes it through coerceToPath: paths and strings directly, __toString recursively, anything else through the non-copying string coercion (an attrset via outPath), then requires an absolute result. Passing a flake input or derivation-like value as path is a common idiom.

$ nix-instantiate --eval --impure -E 'builtins.path { path = { outPath = ./tree; }; name = "t"; }'
"/nix/store/<hash>-t"
$ fix eval --impure -E 'builtins.path { path = { outPath = ./tree; }; name = "t"; }'
error: type error

Fix

Route the path attribute through the existing non-copying string coercion (stringLikeValue, whose __toString-before-outPath ordering matches coerceToPath). The absolute-path requirement and the other attributes are unchanged.

Verification

  • outPath-as-path, outPath-as-string, __toString, and a non-canonical /x/../. argument all produce the store path Nix produces, byte-identical.
  • A unit test pins the four vectors against the plain-string argument.
  • Lix (357) and snix (114) conformance corpora pass; a nixpkgs universe chunk of 9,732 attrs has zero drvPath mismatches.

builtins.path rejected an attrset path argument with a type error;
Nix's prim_path routes it through coerceToPath, which takes paths and
strings directly and coerces anything else without store copies (an
attrset via outPath or __toString), then requires an absolute result.
Passing a flake input or derivation-like value as path is a common
idiom.

Route the path attribute through the existing non-copying string
coercion; the absolute-path requirement and the other attributes are
unchanged. Verified against nix-instantiate: outPath-as-path,
outPath-as-string, and __toString arguments all produce the identical
store path Nix produces. A unit test pins the three vectors against
the plain-string argument.
@psyclyx

psyclyx commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Merged as c5913653, preserving the PR's original author attribution. Verified against nix-instantiate: the outPath-as-path, outPath-as-string, and __toString arguments all produce the identical store path, and __toString correctly wins over outPath.

Three follow-up commits on top. stringBytes only borrows, and for a heap string the slice dies at the next GC safepoint, so routing the path attribute through the string coercion (a __toString result is a fresh heap string) left it dangling across the later attr forces and the user filter calls in recursiveIngest; the coerced bytes are now interned, which covers store_name too. The name and sha256 attrs had the same defect already and got the same treatment.

The third one is the crash you would have hit next: a cyclic { outPath = r; } reaching the coercion recursed on the native stack until the fiber faulted. Nested coercion levels now count against max-call-depth, as Nix's coerceToString does via addCallDepth, with the same native backstop forceThunkImpl uses. The depth is fiber state beside tryeval_depth, so every clone of the walk shares one budget. Cyclic outPath, __toString, nested-list, and builtins.path shapes all report stack overflow; max-call-depth exceeded now instead of segfaulting, and finite chains are unchanged.

The derivation-specific coercion clones still recurse unguarded; #8 covers those and can adopt coercionEnter/coercionExit. Thank you!

@psyclyx psyclyx closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants