Introduce types.raw and types.unconditional#132448
Introduce types.raw and types.unconditional#132448infinisil wants to merge 6 commits intoNixOS:masterfrom
types.raw and types.unconditional#132448Conversation
types.raw and types.conditionaltypes.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
There was a problem hiding this comment.
| 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.
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:
emptyValueoftypes.listOf, which should be[]not{}emptyValue, theemptyValueis used instead of throwing an error. Types who have anemptyValue:nullOr:nullattrsOf:{}listOf:[]submodule:{}This means that it's not necessary anymore to define
default = {}forsubmodulesorattrsOfto make it work without any definitions.types.rawas 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.rawfor_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 conditionalmkIfdefinitions 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.attrsandtypes.unspecified.Ping @roberth @nbp @danbst @sphaugh
Things done
emptyValue's being usedtypes.rawtypes.unconditional <elemType>types.rawtypes.unconditional <elemType>