Skip to content

Conversation

@Ericson2314
Copy link
Member

Motivation

This is an example of "Parse, don't validate" principle.

Before, we had a number of StringSets in DerivationOptions that were not actually allowed to be arbitrary sets of strings. Instead, each set member had to be one of:

  • a store path

  • a CA "downstream placeholder"

  • an output name

Only later, in the code that checks outputs, would these strings be further parsed to match these cases. (Actually, only 2 by that point, because the placeholders must be rewritten away by then.)

Now, we fully parse everything up front, and have an "honest" data type that reflects these invariants:

  • store paths are parsed, stored as (opaque) deriving paths

  • CA "downstream placeholders" are rewritten to the output deriving
    paths they denote

  • output names are the only arbitrary strings left

Since the first two cases both become deriving paths, that leaves us with a std::variant<SingleDerivedPath, String> data type, which we use in our sets instead.

Getting rid of placeholders is especially nice because we are replacing them with something much more internally-structured / transparent.

Context

Progress on #13570

Depends on #14505


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@Ericson2314 Ericson2314 requested a review from edolstra as a code owner November 7, 2025 05:44
@github-actions github-actions bot added new-cli Relating to the "nix" command with-tests Issues related to testing. PRs with tests have some priority labels Nov 7, 2025
@Ericson2314 Ericson2314 force-pushed the derivation-options-parse-paths branch from b126d79 to 00d2bf9 Compare November 7, 2025 05:47
@Ericson2314
Copy link
Member Author

Ah it needs a daemon-version thing for that message.

bool ignoreSelfRefs = false;
std::optional<uint64_t> maxSize, maxClosureSize;

using DrvRef = nix::DrvRef<Input>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already giving me a headache... What is a DrvRef conceptually, and since when do output checks refer to anything other than store paths?

* separately. That would be nice to separate concerns, and not make any
* environment variable names magical.
*/
template<typename Input>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input is a heavily overloaded term. What's the intended meaning of input here?


/**
* A reference is either to a to-be-registered output (by name),
* or to an already-registered store object (by `Input`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't Input be named StorePath then? And why does that need to be a template parameter?

@dpulls
Copy link

dpulls bot commented Nov 10, 2025

🎉 All dependencies have been resolved !

@Ericson2314 Ericson2314 force-pushed the derivation-options-parse-paths branch from 00d2bf9 to 4611d31 Compare November 10, 2025 21:35
This is an example of "Parse, don't validate" principle [1].

Before, we had a number of `StringSet`s in `DerivationOptions` that
were not *actually* allowed to be arbitrary sets of strings. Instead,
each set member had to be one of:

- a store path

- a CA "downstream placeholder"

- an output name

Only later, in the code that checks outputs, would these strings be
further parsed to match these cases. (Actually, only 2 by that point,
because the placeholders must be rewritten away by then.)

Now, we fully parse everything up front, and have an "honest" data type
that reflects these invariants:

- store paths are parsed, stored as (opaque) deriving paths

- CA "downstream placeholders" are rewritten to the output deriving
  paths they denote

- output names are the only arbitrary strings left

Since the first two cases both become deriving paths, that leaves us
with a `std::variant<SingleDerivedPath, String>` data type, which we use
in our sets instead.

Getting rid of placeholders is especially nice because we are replacing
them with something much more internally-structured / transparent.

[1]: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/

Co-authored-by: Sergei Zimmerman <[email protected]>
@Ericson2314 Ericson2314 force-pushed the derivation-options-parse-paths branch from 4611d31 to 81921d7 Compare November 10, 2025 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new-cli Relating to the "nix" command with-tests Issues related to testing. PRs with tests have some priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants