Module system improvements#6794
Conversation
This makes the relationship between property types clearer, and more importantly will let option types parameterized by other option types reuse the code for delegated type checking and merging.
This simplifies typechecking and allows properties to be used inside the lists
This simplifes typechecking and allows properties to be used inside of the attribute sets. This fixes the empty synergy-client and synergy-server services previously generated on systems with synergy disabled.
This symplifies typechecking and allows properties to be used inside the function body. It also makes possible checking the type of the result.
This allows for module arguments to be handled modularly, in particular allowing the nixpkgs module to handle the nixpkgs import internally. This creates the __internal option namespace, which should only be added to by the module system itself.
Ideally the module system could be configured pretty much completely by the contents of the modules themselves, so add comments about avoiding complicating it further and possibly removing now-redundant configurability from the existing interface.
With the new evaluation of arguments, pkgs is now defined by the configuration, which implies that option declaration with pkgs.lib will cause an infinite loop.
…he arguments. The current implementation of the ApplyIfFunction is looking at the arguments of a module to decide which arguments should be given to each module. This patch make sure that we do not wrap a submodule function in order to keep functionArgs working as expected.
…dent of each others.
This move idioms which were used in `evalOptionValue` and in the `merge` functions of `listOf` and `attrsOf` types, such that we can use a names such as `isDefined` and `optionalValue` instead or repeating identical comparisons of `defsFinal == []`.
|
👍 |
|
Wow, this looks pretty nice! 👍 |
|
+1 Did i read correctly, that with this patch you can use modules as submodules? Can you please give an example config for that? |
|
@offlinehacker , Indeed I have not tried it yet, but something like the following module will let you embed NixOS modules in something which let you enumerate a set of computer configuration as NixOps does: Even if this is one step in the right direction, this set of patches lacks one feature to make the |
06be675 to
05e8a48
Compare
|
The module system test cases can be tested by using the following command: which prints the following: |
|
I'll try to have a look at this later this week. |
|
@nbp nice, thanks :) |
|
@nbp will you add these changes to the changelog? |
|
I think I already made a branch for adding these to the release notes … I will try to find it again. |
|
Indeed I had a branch, but I might have forgot to merge it: I will open a pull request and cc you. |
|
Thanks (would be awesome if you can do that now, I want to release today) On Wed, Sep 30, 2015 at 9:07 PM, Nicolas B. Pierron <
|
Add pkgs module argument documentation for #6794 incompatible change.
(cherry picked from commit 50146ce) Signed-off-by: Domen Kožar <domen@dev.si>
The latest stable version was failing with infinite recursion due to #6794. I've updated the unstable version to the latest commit to catch recent fixes.
|
This makes Would it be too much of a performance impact to reintroduce the correct checks for |
| listOf = elemType: mkOptionType { | ||
| name = "list of ${elemType.name}s"; | ||
| check = value: isList value && all elemType.check value; | ||
| check = isList; |
There was a problem hiding this comment.
I'm sorry, but why the hell was this done? Please explain otherwise I am going to revert this. (Same for all other changed check functions)
There was a problem hiding this comment.
I think one reason might be that, with this change, we get more localised errors, for example
A definition for option `foo.[definition 1-entry 2]' is not of type `bar'.
instead of
A definition for option `foo' is not of type `list of bar'.
and similarly for attrsOf. I think we want to keep this behaviour.
We should also be careful not to duplicate work, as type checking is currently done by mergeDefinitions.
There was a problem hiding this comment.
So perhaps the solution is to stop using type.check externally, instead call mergeDefinitions with a single definition (maybe make a checkType wrapper around that).
There was a problem hiding this comment.
(And whatever we do, this really needs more documentation, for example the manual doesn't mention that type.check only checks one "layer" of types.)
There was a problem hiding this comment.
Thanks for the input. How about type checking the meta attribute as an entire module system like in NixOS, instead of doing things manually?
attrs = (lib.evalModules {
modules = [ {
options = metaTypes;
config = meta;
} ];
}).config;This allows us to leverage all of the existing infrastructure, and the only thing that needs to change for that is to modify metaTypes to become a "module" instead of just a type declaration.
(Alternatively, how would checkType look like? How do I even use mergeDefinitions?)
There was a problem hiding this comment.
I'm sorry, but why the hell was this done? Please explain otherwise I am going to revert this. (Same for all other changed
checkfunctions)
Previous attempts at fixing this:
- lib/types.nix: listOf.check needs to check the elements #173568
- [RFC] types.listOf: actually validate the contents #168295
I think there are several others.
I think doing the check manually (and correctly) in |
…ange. (cherry picked from commit 50146ce) Signed-off-by: Domen Kožar <domen@dev.si>
This branch change mainly 2 things, the way composite types are processed, and the way internal processing of modules is done.
Property evaluation within composite types: This change is a highly demanded feature, which tend to confuse everybody who used properties with submodules in the past. Composite types such as
types.attrsOf,types.loaOfandtypes.listOfare now able to have properties within their bodies. The most interesting use-case involve submodule, such as jobs or file systems options:This example used to evaluate a submodule with an empty attribute set for unique submodule. With this change to the evaluation of types, which evaluate properties while merging the types, this problem no longer exists as it is equivalent to having no value to be merged. This implies that no submodule would be evaluated, and no empty job would be created.
Argument unification between modules and submodules: This change is a long standing sanity issue which mostly prevented one person to use modules as submodules. Arguments are now processed by an internal option
_module.args, which is given to each module. This implies that any set of modules which can be build in a standalone manner (such as maybe NixUP one day) can also be included as a submodule even if it relies on extra arguments, as long as these arguments are used for the computation of the definitions only.This open the door for a feature which I have not yet heard many people mention, but that I wanted to add for a while, which is to share library functions to build the content of option definitions. For example, the activation script logic can move to the activation script module instead of being part of nixpkgs.
In addition, to this change, the computation of the
pkgsargument of NixOS modules moved from being computed out-side the module system to be computed within the module system. This implies thatnixos/lib/eval-config.nixno longer has to execute the module system twice. The first one with a dummypkgsargument, and the second time with the one computed from the first iteration. This approach is better as it avoid this work-around.Sadly this last change is coming with a few non-backward compatible changes, which are either not well known, or easy to fix:
mkOption, mkIf: These functions are part of the engine of the module system. As the
pkgsargument is no longer a special argument, usingpkgs.lib.mkOptionwill result in an infinite loop during the evaluation. Thus module should be written as{ config, pkgs, lib, ... }:instead of{ config, pkgs, ... }:,pkgscan still be kept for finding packages, but functions should use thelibargument. Thuspkgs.lib.mk…should be replaced bylib.mk…, and identicallywith pkgs.lib;should be replaced bywith lib;.Deprecate the modulePath argument: This attribute is not well known, nor used. It was introduced before the addition of the
NIX_PATHenvironment variable as far as I can recall. From what I can tell, the only purpose of it was to refer to nixos modules which are not included by default within your own the configuration files. This can be done as follow:Explicit argument of modules: Due to the strictness of the deconstruction of attribute set, modules arguments are computed in a way which is similar to the
callPackagefunction. This implies that one cannot write a module which expects any argument custom argument — other thanconfig,libandoptions— which is not explicitly named.This example lead to the fact that
nameis not found on the attribute setargs. On the other hand, if the attribute is made explicit, then it would be visible. This is counter intuitive, but hopefully this is not a common pattern.This work is based on the work made by @shlevy in pull request #2563. Reviewed carefully, rebased, and fixed.