Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions lib/modules.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ let
elem
filter
findFirst
flip
foldl
foldl'
getAttrFromPath
head
Expand Down Expand Up @@ -403,7 +401,7 @@ rec {
[{ inherit (module) file; inherit value; }]
) configs;

resultsByName = flip mapAttrs declsByName (name: decls:
resultsByName = mapAttrs (name: decls:
# We're descending into attribute ‘name’.
let
loc = prefix ++ [name];
Expand All @@ -424,7 +422,7 @@ rec {
in
throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
else
mergeModules' loc decls defns);
mergeModules' loc decls defns) declsByName;

matchedOptions = mapAttrs (n: v: v.matchedOptions) resultsByName;

Expand All @@ -438,12 +436,19 @@ rec {
inherit matchedOptions;

# Transforms unmatchedDefnsByName into a list of definitions
unmatchedDefns = concatLists (mapAttrsToList (name: defs:
map (def: def // {
# Set this so we know when the definition first left unmatched territory
prefix = [name] ++ (def.prefix or []);
}) defs
) unmatchedDefnsByName);
unmatchedDefns =
if configs == []
then
# When no config values exist, there can be no unmatched config, so
# we short circuit and avoid evaluating more _options_ than necessary.
[]
else
concatLists (mapAttrsToList (name: defs:
map (def: def // {
# Set this so we know when the definition first left unmatched territory
prefix = [name] ++ (def.prefix or []);
}) defs
) unmatchedDefnsByName);
};

/* Merge multiple option declarations into a single declaration. In
Expand Down Expand Up @@ -857,7 +862,7 @@ rec {
mkMergedOptionModule = from: to: mergeFn:
{ config, options, ... }:
{
options = foldl recursiveUpdate {} (map (path: setAttrByPath path (mkOption {
options = foldl' recursiveUpdate {} (map (path: setAttrByPath path (mkOption {
visible = false;
# To use the value in mergeFn without triggering errors
default = "_mkMergedOptionModule";
Expand Down Expand Up @@ -941,7 +946,7 @@ rec {

/* Use this function to import a JSON file as NixOS configuration.

importJSON -> path -> attrs
modules.importJSON :: path -> attrs
*/
importJSON = file: {
_file = file;
Expand All @@ -950,7 +955,7 @@ rec {

/* Use this function to import a TOML file as NixOS configuration.

importTOML -> path -> attrs
modules.importTOML :: path -> attrs
*/
importTOML = file: {
_file = file;
Expand Down
9 changes: 8 additions & 1 deletion lib/tests/modules/declare-attrsOf.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{ lib, ... }: {
{ lib, ... }:
let
deathtrapArgs = lib.mapAttrs
(k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.")
(lib.functionArgs lib.mkOption);
in
{
options.value = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = {};
};
options.testing-laziness-so-don't-read-me = lib.mkOption deathtrapArgs;
}
9 changes: 8 additions & 1 deletion lib/tests/modules/freeform-nested.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{ lib, ... }: {
{ lib, ... }:
let
deathtrapArgs = lib.mapAttrs
(k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.")
(lib.functionArgs lib.mkOption);
in
{
options.nest.foo = lib.mkOption {
type = lib.types.bool;
default = false;
};
options.nest.unused = lib.mkOption deathtrapArgs;
config.nest.bar = "bar";
}