-
-
Notifications
You must be signed in to change notification settings - Fork 18.3k
lib.modules: init types checkAndMerge to allow adding 'valueMeta' #391544
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
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
644527d
lib.modules: init types checkAndMerge to allow adding 'valueMeta' att…
roberth 8fa3300
lib.modules: add tests for option valueMeta
hsjobeki 648dbed
lib/types: add 'checkDefsForError' utility for checking defs with a g…
hsjobeki 70ab11c
lib/modules: add new merge.v2 for 'types.{either,coercedTo}'
hsjobeki 9f787b3
lib/modules: fix test by matching error message more generically
hsjobeki 5d72133
lib/addCheck: add support for new merge
hsjobeki ebafc3e
lib/modules: optimize performance by inlining bindings
hsjobeki 1765370
lib/modules: test revert unentional regression in check
hsjobeki 50bef19
lib/modules: add nested 'headError.message'
hsjobeki cd2e5bd
types/merge: move 'configuration' of submodules into nested attribute…
hsjobeki 45ed757
types/addCheck: add tests for merge v1 and v2
hsjobeki 1fed602
lib/tests: introduce lib cross version checks
hsjobeki 4f802d9
lib/modules: fix typo
hsjobeki bb0bd3d
lib/modules: add _internal to valueMeta of checkedAndMerged
hsjobeki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Motivation unclear,
optionsalready has the merged type 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to avoid double exposing the same data if there is not explicit need for it.
That would only create confusion about the option api. If we want to move type from options into valueMeta that should be a seperate migration, might involve double exposing, but unless there is an explicit benefit, right now i would not do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was supposed to make recursion into the combined type + meta structure easier, and it claims the name
type, so that it isn't used inconsistently. For instance, ifattrsOfwere to add atypeto itsvalueMeta, it has a choice whether to putattrsOf t(itself) or justt(its element type)By forcing it to be
attrsOf t, we ensure that this attribute is consistent regardless of what the type does.In fact,
attrsOf t // { description = "ha"; }can't even put its type anywhere, because its functions are unaware of the//.The
typemay become particularly relevant if we implementattrsWith { type = name: ...; }, in which case the type may be name-dependent. My suggestion addsvalueMeta.attrs.<name>.type(among other.types), so that users who readvalueMetadon't have to reconstruct each item's type again.It's not the only solution to that problem, as
valueMeta.attrTypescould be added, but then users need to traverse both attrsets simultaneously, and make the assumption that the attribute name sets are equal.So in conclusion I believe that by deciding this attribute here, we make
valueMetamore consistent and easier to use.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you be okay with delaying this into a follow-up PR? I'm not sure if its required right now. It might be okay to make this assumption based on the current types that implement merge.v2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roberth I think
valueMetashouldn't be set by the module system internally, but rather be entirely left up to the types to define, with the module system just exposing it.To expose the effective type of an option, the module system always has the option to set other attributes in the
optionsstructure, likeoptions.foo.effectiveType.(discussed with @hsjobeki in a call as well)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer not to because soon after the merge, adding
typewill have to be considered a breaking change.@infinisil I see the problem now. My suggestion isn't just the effective type of an option, because yes, we have a perfectly fine
optionsfor that.Where it matters is when the types are nested and dependent, for example as in this commit.
In such a case,
valueMeta.attrs.<name>.typecan only be provided byattrsWith, where it would interfere with thevalueMeta.attrs.<name>, which is an open attrset where a user-providedtypemay exist.The straightforward solution to this is to change the
valueMetaofattrsWithto havevalueMeta.attrs.<name>.{valueMeta, type}instead ofvalueMeta.attrs.<name> = valueMeta // { type }, orvalueMeta.types.<name>in addition tovalueMeta.attrMetas.<name>, or something like that.But is that really nicer than always having
typeinvalueMeta?User code that traverses more than a single submodule will have to deal in values of
{ type; value; valueMeta; }instead of{ value; valueMeta; }.I think I've made my case. I'll let you decide and support that.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roberth @infinisil I tested both approaches now:
typeviamodules.nixRequires using another let binding and one update operator in the hot path (merging).
The second one should be lazy i think
Did nixos eval, 20 runs with hyperfine, 1 warmup
CPU Time increased, but i also got another run, where noise was bigger than the change.
... other stats omited
This means we need to update every
checkedAndMergedwhich holdsvaluewhich explains the stats.valueMeta.typein types, instead of updating afterwards.Most notably (nixos eval)
0% change, since updating valueMeta is not needed to access the value.
Obvious drawback. Every type is responsible to properly set it, which may make traversal later on brittle, especially on custom / downstream types.
I am not sure if we should add another update operation into the hot path?
On the other hand if we really want to support
attrsWith { getElemType ... }like in the commit you showed i cannot think of a different reasonable way.We could add checking for valueMeta, so every type that defines valueMeta also needs to set
type. This would defer the problem into the time when somebody tries to access malformed valueMeta, which is probably also kind of bad.We cannot really control peoples custom types because we wanted
valueMetato be freeform. It would be a pitty if custom types siltently don't work with this, because we have to many unbespoke conventions.For making this tradeof more future extensible i wouldn't add
typedirectly to valueMeta but maybe reserve_internal = { inherit type; }or similar that we can extend in the future without creating collisions in valueMeta