-
-
Notifications
You must be signed in to change notification settings - Fork 15k
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
Introduce types.raw
and types.unconditional
#132448
Conversation
types.raw
and types.conditional
types.raw
and types.unconditional
However, I don't think The crux of it is that "attrsets and lists can be big" is not a good intuition. Let me explain. The thing is, you can always insert a minimal check. For an option to make sense it must be used in some way. The minimal way of using a thunk is to evaluate it to weak head normal form (whnf)*. This means that we always have the opportunity to put a check in front of the config's thunk, so that the check evaluates it to whnf and shallowly checks the type before returning it to whatever needed the value. The overhead of this is absolutely tiny compared to the rest of the module system and does not increase with value size, no more of the value is evaluated than would be without the check. Of course this is only possible because of the fact that definitions are only checked when used. That doesn't usually feel like a relevant property and there's something unpleasant about it, but it works out rather well. Another thing to note is that whnf doesn't always give you a lot of information, but discerning between types like int, list, attrset, string, bool is possible and useful. I guess another way to put it is that checking whnf only doesn't increase strictness and is therefore of constant time (and small, because what can you really do). * I don't think whnf has been defined anywhere for Nix, but the concept applies. It's essentially |
@roberth Good point. But doing such an extra check can be done by However, after thinking about it, I think you're right, we don't need The only place we could therefore use such a Or maybe we should still just have |
I guess there's one potential use case of a |
b261241
to
29e016f
Compare
I changed |
de783e0
to
7129dfc
Compare
9679e9d
to
91cc1ca
Compare
Wrote tests and docs for everything now |
7d40615
to
bba62b1
Compare
element type in `types.attrsOf` and `types.listOf`, the attribute keys and | ||
the list length respectively can be known without evaluating each | ||
individual attribute/list value strictly, making these structures lazy. |
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.
element type in `types.attrsOf` and `types.listOf`, the attribute keys and | |
the list length respectively can be known without evaluating each | |
individual attribute/list value strictly, making these structures lazy. | |
element type in `types.attrsOf` and `types.listOf`, the attribute keys and | |
the list length respectively can be known without evaluating each | |
individual attribute/list value, keeping these structures lazy. | |
For instance, this prevents a case of infinite recursion by allowing elements | |
in an attribute set to reference other elements of the same attribute set | |
via the `config` module argument. |
strictly -> no evaluation at all.
making lazy -> keeping lazy
add example use case
I decided not to define spine laziness here, although that could be a useful term.
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.
Applied!
bba62b1
to
8e50891
Compare
An empty list is [], not {}! Also, non-empty lists shouldn't have a default of an empty list!
This patch makes it so that if an option has no definitions, but its type specifies an `emptyValue`, that is used instead of throwing an error. This means that for e.g. `attrsOf`, there's no need to specify a default of `default = {}` anymore. Other types that have such a default are `nullOr` (default `null`), `submodule` (default `{}`) and `listOf` (default `[]`).
8e50891
to
194e6d2
Compare
Updated to resolve merge conflicts after #148315 |
Allows replacing `types.lazyAttrsOf elemType` with `types.attrsOf (types.unconditional elemType)`. Also works with lists: `types.listOf (types.unconditional elemType)`.
Fixes NixOS#53458, as types.raw doesn't allow setting multiple values
194e6d2
to
8e483d6
Compare
This PR is a bit too convoluted with too many separate changes. I split off the I also thought about it some more: Making options default to the |
Regarding |
Finally, the |
Motivation for this change
This PR contains a number of changes which are related or weakly dependent on each other:
emptyValue
oftypes.listOf
, which should be[]
not{}
emptyValue
, theemptyValue
is used instead of throwing an error. Types who have anemptyValue
:nullOr
:null
attrsOf
:{}
listOf
:[]
submodule
:{}
This means that it's not necessary anymore to define
default = {}
forsubmodules
orattrsOf
to make it work without any definitions.types.raw
as a type that doesn't do any nested processing formkIf
,mkForce
, etc. on its values. This is useful when this processing would throw errors or where it would be too expensive (such as with package sets like nixpkgs).types.raw
for_module.args
's type. This finally fixes _module.args.name gets merged on assignment #53458types.unconditional <elemType>
as a type, which when used as e.g.attrsOf (unconditional str)
can replacelazyAttrsOf str
. This type ensures that conditionalmkIf
definitions can't influence whether the option is defined or not, and therefore make the attribute set values be evaluated lazily. This notably also works withlistOf (unconditional str)
, making the list elements evaluated lazily, which was not possible before.This is probably the last piece needed before we can finally deprecate
types.attrs
andtypes.unspecified
.Ping @roberth @nbp @danbst @sphaugh
Things done
emptyValue
's being usedtypes.raw
types.unconditional <elemType>
types.raw
types.unconditional <elemType>