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.types: init mergeTypes #364620

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

hsjobeki
Copy link
Contributor

Expose a utility for merging types together manually

Related: #363565

Sometimes downstream projects want to extend an enum and it is quite complicated to understand which attributes of a type are meant to be internal.

catppuccin/nix#400

This PR help to reduce downstream reliance on type attributes by adding this function as abstraction.

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/)
  • 25.05 Release Notes (or backporting 24.11 and 25.05 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.

@hsjobeki
Copy link
Contributor Author

hsjobeki commented Jan 7, 2025

@infinisil What do you think about this function? It abstracts the need to use attributes of a type which i think is good. Because it decouples them and allows changes without breaking.

Copy link
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

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

I think I like it!

lib/types.nix Outdated
Merges two option types together.

:::{.note}
Uses the merge function of the first type, to merge it with the second type.
Copy link
Member

Choose a reason for hiding this comment

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

This seems like an implementation detail

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Uses the merge function of the first type, to merge it with the second type.
Uses the type merge function of the first type, to merge it with the second type.

This is relevant for solving the "expression problem". Interactions between extensions don't have a natural home. This says that interactions are the responsibility of the first type. Concretely: if the types can be merged, you can only fix it if you control the first.
If you have to deal with a partially applied mergeTypes, you are subject to the provided type's merging support, with no way to extend its merging behavior.
If you control the first argument, you can add as much merge support as you like.

Copy link
Contributor Author

@hsjobeki hsjobeki Jan 9, 2025

Choose a reason for hiding this comment

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

I had similar thoughts as roberth. If you want to change some of the merge behavior its important to know that merging is not commutative. In most cases it might be, but thats only true when both types are the same anyways.

lib/types.nix Outdated
Comment on lines 1127 to 1128
- The merged option type.
- `null` if the types can't be merged.
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit worried that this API isn't very future proof, because null doesn't allow for better error messages. How about we change it to return a string instead, for now just always "Cannot merge types"

Copy link
Contributor Author

@hsjobeki hsjobeki Jan 8, 2025

Choose a reason for hiding this comment

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

How about a set { error = "..."; } representing the empty type? Since a "type" is also an attribute set internally this means it is somewhat homomorphic. You can check for the success by checking result ? error .

We could extend that set in the future to contain more error related information

Copy link
Contributor Author

@hsjobeki hsjobeki Jan 9, 2025

Choose a reason for hiding this comment

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

I made this an attribute set { error = ... ; } for now.
I think this is the best compromise that is extensible in the future.

Error case alternatives:

  • string: Some Error: Not extensible in the future. (Cannot hold other attributes)
  • null: null: Leaks an implementation detail. Cannot hold any helpful information about the actual problem.
  • Throw "error": Downstream projects cannot handle error cases. (downstream wrapping with TryEval not a good idea either, since the error is not made accessible)

lib/types.nix Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: lib The Nixpkgs function library 6.topic: module system About "NixOS" module system internals 10.rebuild-darwin: 1-10 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants