Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: add option parameter for default value priority #296979

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

Atemu
Copy link
Member

@Atemu Atemu commented Mar 18, 2024

It's sometimes the case that your option's default value should be additive such that setting it results in the default value being merged with whatever was set.

Previously, you had to add the default value in the implementation which might be many lines away from the option declaration and is generally an odd pattern.

This is a lot clearer, simpler and doesn't add much complexity.

If this becomes used more widely, it should be rendered in the generated options' manual and nixos-search.

Description of changes

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@Atemu
Copy link
Member Author

Atemu commented Mar 25, 2024

Friendly ping.

Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

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

I've put my thoughts on the design in a comment.

I'll be interested to hear what @infinisil thinks about the design.

When that's agreed, we'll need:

  • tests in lib/tests/modules.sh
  • documentation for the new mkOption arguments in the manual
  • update the docs generation to show the new info
    • nixos/lib/make-options-doc/default.nix
    • pkgs/tools/nix/nixos-render-docs/

lib/modules.nix Outdated Show resolved Hide resolved
@roberth roberth mentioned this pull request Mar 27, 2024
13 tasks
@Atemu
Copy link
Member Author

Atemu commented May 8, 2024

Thank you all for the feedback, I still intend to continue this but it may take a bit.

@Atemu
Copy link
Member Author

Atemu commented Aug 16, 2024

Another thing we may want to think about while fixing this issue is cases where you want to override the default value (i.e. remove an item from a list) but still allow other modules to merge in their values too.

@Atemu
Copy link
Member Author

Atemu commented Oct 13, 2024

I've changed the setting to take a priority value instead of a boolean and exposed the priority values in a sane manner.

Will take a look at docs and tests next.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin and removed 10.rebuild-darwin: 1 10.rebuild-darwin: 1-10 labels Oct 13, 2024
@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: documentation This PR adds or changes documentation labels Nov 1, 2024
@Atemu Atemu changed the title lib: add option parameter to make default additive lib: add option parameter for default value priority Nov 1, 2024
@Atemu
Copy link
Member Author

Atemu commented Nov 1, 2024

I've added documentation but I don't know how to touch nixos-render-docs. I think I'd prefer to not add it for now.

@ofborg ofborg bot added 10.rebuild-darwin: 1-10 10.rebuild-darwin: 1 and removed 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin labels Nov 2, 2024
Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

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

Looks pretty good from a computational perspective, but this does create a problem with the meaning of the word "default" now, ambiguously referring to

  1. certain priorities
  2. a preset value having some declared priority that's not necessarily a "default" priority

We can handle a bit of ambiguity, but the possibility of having "a default that isn't a default" does kind of make it cross out of the grey area.

Ideally we'd rename mkOption { default, defaultText } to something like mkOption { preset, presetText } (and presetPriority). That'd be a huge migration, and canonicalizing the option declarations will have a measurable performance cost during such a migration.
Nonetheless, I do believe most modules are yet to be written...
We've managed the markdown migration pretty well, and this is a simpler syntax change with fewer steps (nothing analogous to remove mdDoc).

It's a heavy decision, but one or two such choices make the difference between devolving into a weird legacy system or something that's actually nice to use.

I think the migration path would be

  1. now
  • add preset and presetText as alternatives
  • add presetPriority
  • set default and defaultText in evalOptionValue for compatibility with code that reads those values
  1. after a release cycle
  • warn when any default* attributes is set, in mkOption
  • warn when default* is used, in evalOptionValue
  1. after another release cycle
  • remove default*.

@Atemu deep apologies for the scope increase.
@infinisil am I going insane?

lib/modules.nix Outdated Show resolved Hide resolved
@Atemu
Copy link
Member Author

Atemu commented Nov 3, 2024

I can see where you're coming from but I think I still prefer default over preset actually; I think it's still a fitting name. It's still the default value if you don't touch it. This only changes what happens to that default value when you set the option and there it still remains the default value, just that it "adds" itself to whatever value is set.

I think it's perfectly expectable for configuration system's default values to remain in effect when an option is set, so I don't think this violates the principle of least surprise. I'd even argue it's more of a quirk of the NixOS module system that this wasn't possible before. We're used to only overrides of course but I don't think an outsider would consider it odd if both overriding and merging a default value was possible.

I don't see a dependency between PR and potentially renaming default though; it's entirely independent. We can just change the naming for defaultPriority later together with all the other default* parameter names if/when we decide to do it. If such a change was already cut and dried, I'd wait of course but this appears to be the first time you bring it up and it's very much still up to debate whether it actually needs to happen.

I'd prefer to keep the name for default out of scope for this PR.

lib/modules.nix Outdated Show resolved Hide resolved
lib/modules.nix Outdated Show resolved Hide resolved
@github-actions github-actions bot added 8.has: module (update) This PR changes an existing module in `nixos/` 6.topic: testing Tooling for automated testing of packages and modules labels Nov 4, 2024
@Atemu
Copy link
Member Author

Atemu commented Nov 9, 2024

Another point that just came to mind is that most of what this is useful for is already possible without this PR (as described in the commit message), it just isn't as nice to implement. It's actually already in use in a few places.

@Atemu Atemu requested a review from roberth November 14, 2024 22:21
@wegank wegank added the 2.status: merge conflict This PR has merge conflicts with the target branch label Dec 10, 2024
Atemu added 10 commits January 3, 2025 21:13
I needed to expose the baseline priority (and ideally the other priorities too)
for external use.

While I was at it, I gave mkDefault and defaultOverridePriority (not the same
thing in any way, confused yet?) better names.
When you define an option's default value, the expectation is that whenever the
option is set somewhere, the default value will be overridden by that setting
rather than merged.

It's sometimes the case however that your option's default value should be
merged with what is being set rather than overwritten by it; only allowing
explicit overrides via `mkForce`. Creating such an option was not possible
previously as all options' default values were forcefully clamped via
mkOptionDefault.

There were some workarounds such as creating additional options ("things" +
"extraThings") which you'd then have to explain to users and generally aren't
ergonomical to use.

Another workaround was to explicitly set options value to the default value in
the implementation but those two lines of code might be many lines apart from
another and it's generally an odd pattern. Example:

    {
      options.foo = lib.mkOption {
        default = [ "foo" ];
      };

      # Many more lines of code

      config.foo = options.foo.default;
    }

It is now possible to control this behaviour at option declaration which is much
clearer in the code and is introspect-able.

    {
      options.foo = lib.mkOption {
        default = [ "foo" ];
        defaultPriority = lib.modules.priorities.baseline;
      };

      # Many more lines of code
    }

The implementation is trivial.

If this becomes used more widely, it should be rendered in the generated options
manual and nixos-search.
It's a bit unfortunate to have to change things again but hopefully this
iteration will last for longer.
I don't expect this to be used much but it should exist for completeness' sake.
This makes the wording clearer with more examples and usage of the new names for
functions and priority values.
@Atemu Atemu force-pushed the options-additive branch from d5d0fbd to 75ca593 Compare January 3, 2025 20:29
erikarvstedt added a commit to erikarvstedt/nixpkgs that referenced this pull request Jan 5, 2025
`v.default` always fails because v is the (boolean) attrvalue of the
default settings.

`lib.mkOptionDefault v` would work fine.
But let's just plainly set the default option value.
This way, we can later convert the `settings` option to use
@Atemu's `defaultPriority` (NixOS#296979)
without forcing users to update their config.
erikarvstedt added a commit to erikarvstedt/nixpkgs that referenced this pull request Jan 5, 2025
`v.default` always fails because v is the (boolean) attrvalue of the
default settings.

`lib.mkOptionDefault v` would work fine.
But let's just plainly set the default option value.
This way, we can later convert the `settings` option to use
@Atemu's `defaultPriority` (NixOS#296979)
without forcing users to update their config.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.status: merge conflict This PR has merge conflicts with the target branch 6.topic: lib The Nixpkgs function library 6.topic: module system About "NixOS" module system internals 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 6.topic: testing Tooling for automated testing of packages and modules 8.has: documentation This PR adds or changes documentation 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 1-10 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants