Skip to content

Commit

Permalink
Revert "Add the tool "nixos-typecheck" that can check an option decla…
Browse files Browse the repository at this point in the history
…ration to:"

This reverts commit cad8957. It
breaks NixOps, but more importantly, such major changes to the module
system really need to be reviewed.
  • Loading branch information
edolstra committed Mar 1, 2016
1 parent bf4cafd commit f3d94cf
Show file tree
Hide file tree
Showing 24 changed files with 124 additions and 700 deletions.
99 changes: 17 additions & 82 deletions lib/modules.nix
Expand Up @@ -23,6 +23,8 @@ rec {
specialArgs ? {}
, # This would be remove in the future, Prefer _module.args option instead.
args ? {}
, # This would be remove in the future, Prefer _module.check option instead.
check ? true
}:
let
# This internal module declare internal options under the `_module'
Expand All @@ -43,22 +45,9 @@ rec {
_module.check = mkOption {
type = types.bool;
internal = true;
default = true;
default = check;
description = "Whether to check whether all option definitions have matching declarations.";
};

_module.typeInference = mkOption {
type = types.nullOr types.str;
internal = true;
default = null; # TODO: Move away from 'null' after enough testing.
description = ''
Mode of type inferencing. Possible values are:
null = Disable type inferencing completely. Use 'types.unspecified' for every option without type definition.
"silent" = Try to infer type of option without type definition, but do not print anything.
"printUnspecified" = Try to infer type of option without type definition and print options for which no full type could be inferred.
"printAll" = Try to infer type of option without type definition and print all options without type definition.
'';
};
};

config = {
Expand All @@ -71,7 +60,7 @@ rec {
# Note: the list of modules is reversed to maintain backward
# compatibility with the old module system. Not sure if this is
# the most sensible policy.
options = mergeModules (config._module) prefix (reverseList closed);
options = mergeModules prefix (reverseList closed);

# Traverse options and extract the option values into the final
# config set. At the same time, check whether all option
Expand Down Expand Up @@ -181,11 +170,11 @@ rec {
At the same time, for each option declaration, it will merge the
corresponding option definitions in all machines, returning them
in the ‘value’ attribute of each option. */
mergeModules = _module: prefix: modules:
mergeModules' _module prefix modules
mergeModules = prefix: modules:
mergeModules' prefix modules
(concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules);

mergeModules' = _module: prefix: options: configs:
mergeModules' = prefix: options: configs:
listToAttrs (map (name: {
# We're descending into attribute ‘name’.
inherit name;
Expand All @@ -211,16 +200,16 @@ rec {
(filter (m: m.config ? ${name}) configs);
in
if nrOptions == length decls then
let opt = fixupOptionType _module.typeInference loc (mergeOptionDecls loc decls);
in evalOptionValue _module loc opt defns'
let opt = fixupOptionType loc (mergeOptionDecls loc decls);
in evalOptionValue loc opt defns'
else if nrOptions != 0 then
let
firstOption = findFirst (m: isOption m.options) "" decls;
firstNonOption = findFirst (m: !isOption m.options) "" decls;
in
throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'."
else
mergeModules' _module loc decls defns;
mergeModules' loc decls defns;
}) (concatMap (m: attrNames m.options) options))
// { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; };

Expand Down Expand Up @@ -269,7 +258,7 @@ rec {

/* Merge all the definitions of an option to produce the final
config value. */
evalOptionValue = _module: loc: opt: defs:
evalOptionValue = loc: opt: defs:
let
# Add in the default value for this option, if any.
defs' =
Expand All @@ -281,7 +270,7 @@ rec {
if opt.readOnly or false && length defs' > 1 then
throw "The option `${showOption loc}' is read-only, but it's set multiple times."
else
mergeDefinitions _module loc opt.type defs';
mergeDefinitions loc opt.type defs';

# Check whether the option is defined, and apply the ‘apply’
# function to the merged value. This allows options to yield a
Expand All @@ -302,7 +291,7 @@ rec {
};

# Merge definitions of a value of a given type.
mergeDefinitions = _module: loc: type: defs: rec {
mergeDefinitions = loc: type: defs: rec {
defsFinal =
let
# Process mkMerge and mkIf properties.
Expand All @@ -325,7 +314,7 @@ rec {
mergedValue = foldl' (res: def:
if type.check def.value then res
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.")
(type.merge _module loc defsFinal) defsFinal;
(type.merge loc defsFinal) defsFinal;

isDefined = defsFinal != [];

Expand Down Expand Up @@ -423,7 +412,7 @@ rec {
/* Hack for backward compatibility: convert options of type
optionSet to options of type submodule. FIXME: remove
eventually. */
fixupOptionType = typeInference: loc: opt:
fixupOptionType = loc: opt:
let
options = opt.options or
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
Expand All @@ -435,66 +424,12 @@ rec {
else if tp.name == "list of option sets" then types.listOf (types.submodule options)
else if tp.name == "null or option set" then types.nullOr (types.submodule options)
else tp;

in
if opt.type.getSubModules or null == null
then opt // { type = f (opt.type or (inferType typeInference loc opt)); }
then opt // { type = f (opt.type or types.unspecified); }
else opt // { type = opt.type.substSubModules opt.options; options = []; };


/* Function that tries to infer the type of an option from the default value of the option. */
inferType = mode: loc: opt:
let
doc = x: elemAt x 0;
type = x: elemAt x 1;
containsUnspecified = x: elemAt x 2;
inferType' = def:
if isDerivation def then [ "package" types.package false ]
else if isBool def then [ "bool" types.bool false ]
else if builtins.isString def then [ "str" types.str false ]
else if isInt def then [ "int" types.int false ]
else if isFunction def then [ "functionTo unspecified" (types.functionTo types.unspecified) true ]
else if isList def then
let nestedType = if (length def > 0) && (all (x: (type (inferType' x)) == (type (inferType' (head def)))) def)
then inferType' (head def)
else [ "unspecified" types.unspecified true ];
in [ "listOf ${doc nestedType}" (types.listOf (type nestedType)) (containsUnspecified nestedType) ]
else if isAttrs def then
let list = mapAttrsToList (_: v: v) (removeAttrs def ["_args"]);
nestedType = if (length list > 0) && (all (x: (type (inferType' x)) == (type (inferType' (head list)))) list)
then inferType' (head list)
else [ "unspecified" types.unspecified true ];
in [ "attrsOf ${doc nestedType}" (types.attrsOf (type nestedType)) (containsUnspecified nestedType) ]
else [ "unspecified" types.unspecified true ];

inferDoc = x: ''
Inferring the type of "${showOption loc}" to "${doc x}".
Please verify the inferred type and define the type explicitely in ${showFiles opt.declarations}!
'';

inferredType = printMode:
let inferred = inferType' opt.default;
in if printMode == "silent" then type inferred
else if printMode == "printAll" then builtins.trace (inferDoc inferred) (type inferred)
else if printMode == "printUnspecified" && (containsUnspecified inferred) then builtins.trace (inferDoc inferred) (type inferred)
else type inferred;

noInferDoc = ''
Could not infer a type for "${showOption loc}", using "unspecified" instead.
Please define the type explicitely in ${showFiles opt.declarations}!
'';

hasDefault = (opt ? default) && !(opt ? defaultText);
isExternalVisible = (opt.visible or true) && !(opt.internal or false);
in

if isNull mode || !isExternalVisible
then types.unspecified
else if hasDefault
then inferredType mode /* Set to 'true' to see every type that is being inferred, not just those types that result in 'unspecified'. */
else if mode != "silent" then builtins.trace noInferDoc types.unspecified else types.unspecified;


/* Properties. */

mkIf = condition: content:
Expand Down Expand Up @@ -562,7 +497,7 @@ rec {


/* Compatibility. */
fixMergeModules = modules: args: evalModules { inherit args; modules = (modules ++ [{ _module.check = false; }]); };
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };


/* Return a module that causes a warning to be shown if the
Expand Down

2 comments on commit f3d94cf

@grahamc
Copy link
Member

@grahamc grahamc commented on f3d94cf Mar 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this commit, the nixpkgs no longer evaluates.

<arg>nix-env -f . -qaP --drv-path --show-trace</arg>
</exec>.
13:54:47.964 error: while querying the derivation named ‘iso9660-image’:
13:54:47.965 while evaluating the attribute ‘sources’ of the derivation ‘iso9660-image’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/lib/make-iso9660-image.nix:50:3:
13:54:47.965 while evaluating the attribute ‘src’ of the derivation ‘isolinux.cfg’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/installer/cd-dvd/iso-image.nix:308:13:
13:54:47.965 while evaluating the attribute ‘text’ of the derivation ‘isolinux.cfg-in’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/pkgs/build-support/trivial-builders.nix:10:14:
13:54:47.965 while evaluating the attribute ‘system.build.toplevel’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/activation/top-level.nix:246:5:
13:54:47.966 while evaluating ‘fold’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:20:19, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/activation/top-level.nix:127:12:
13:54:47.966 while evaluating ‘fold'’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:23:15, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:27:8:
13:54:47.966 while evaluating ‘showWarnings’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/activation/top-level.nix:93:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/activation/top-level.nix:100:16:
13:54:47.966 while evaluating ‘fold’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:20:19, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/activation/top-level.nix:93:23:
13:54:47.966 while evaluating ‘fold'’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:23:15, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:27:8:
13:54:47.967 while evaluating the attribute ‘warnings’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:165:44:
13:54:47.967 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:74:45, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:165:52:
13:54:47.967 while evaluating the attribute ‘value’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:287:9:
13:54:47.967 while evaluating the option `warnings':
13:54:47.967 while evaluating the attribute ‘isDefined’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:319:5:
13:54:47.968 while evaluating ‘filterOverrides’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:391:21, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:303:18:
13:54:47.968 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:397:8:
13:54:47.968 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:298:17:
13:54:47.968 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:298:28, called from undefined position:
13:54:47.968 while evaluating ‘dischargeProperties’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:361:25, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:299:62:
13:54:47.969 while evaluating the attribute ‘value’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:199:48:
13:54:47.969 while evaluating the attribute ‘config.warnings’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/boot/systemd.nix:622:5:
13:54:47.969 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:190:10, called from undefined position:
13:54:47.969 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/boot/systemd.nix:622:51, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:190:16:
13:54:47.969 while evaluating ‘optional’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:113:20, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/system/boot/systemd.nix:623:7:
13:54:47.970 while evaluating the attribute ‘serviceConfig.Type’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:165:44:
13:54:47.970 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:74:45, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:165:52:
13:54:47.970 while evaluating the attribute ‘value’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:287:9:
13:54:47.970 while evaluating the option `systemd.services.nixos-manual.serviceConfig':
13:54:47.970 while evaluating the attribute ‘mergedValue’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:314:5:
13:54:47.971 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:314:32, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:314:19:
13:54:47.971 while evaluating ‘merge’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:132:20, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:317:8:
13:54:47.971 while evaluating ‘mapAttrs’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:164:17, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:133:9:
13:54:47.971 while evaluating ‘filterAttrs’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:88:23, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:133:35:
13:54:47.971 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:89:18:
13:54:47.972 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:89:29, called from undefined position:
13:54:47.972 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:133:51, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:89:62:
13:54:47.972 while evaluating the attribute ‘ExecStart’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:275:7:
13:54:47.972 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:133:86, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:275:15:
13:54:47.972 while evaluating the attribute ‘optionalValue’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:321:5:
13:54:47.973 while evaluating ‘filterOverrides’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:391:21, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:303:18:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:397:8:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:298:17:
13:54:47.973 while evaluating anonymous function at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:298:28, called from undefined position:
13:54:47.973 while evaluating ‘dischargeProperties’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:361:25, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:299:62:
13:54:47.973 while evaluating the attribute ‘value’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:138:55:
13:54:47.973 while evaluating the attribute ‘ExecStart’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/services/misc/nixos-manual.nix:124:15:
13:54:47.973 while evaluating the attribute ‘buildCommand’ of the derivation ‘nixos-manual’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/doc/manual/default.nix:99:5:
13:54:47.973 while evaluating the attribute ‘buildCommand’ of the derivation ‘options-db.xml’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/pkgs/build-support/trivial-builders.nix:10:14:
13:54:47.973 while evaluating ‘flip’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/trivial.nix:57:16, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/doc/manual/default.nix:19:18:
13:54:47.973 while evaluating ‘optionAttrSetToDocList'’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/options.nix:85:37, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/doc/manual/default.nix:9:61:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/options.nix:86:5:
13:54:47.973 while evaluating ‘collect’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:140:19, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/options.nix:105:39:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:144:7:
13:54:47.973 while evaluating ‘collect’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:140:19, called from undefined position:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:144:7:
13:54:47.973 while evaluating ‘collect’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:140:19, called from undefined position:
13:54:47.973 while evaluating ‘concatMap’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/lists.nix:62:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:144:7:
13:54:47.973 while evaluating ‘collect’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:140:19, called from undefined position:
13:54:47.974 while evaluating ‘isType’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/types.nix:13:18, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/attrsets.nix:141:8:
13:54:47.974 while evaluating ‘evalOptionValue’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:261:31, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:204:16:
13:54:47.974 while evaluating ‘fixupOptionType’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:415:26, called from /var/lib/gocd-agent/pipelines/nixpkgs-master/lib/modules.nix:203:23:
13:54:47.974 while evaluating the attribute ‘type.getSubModules’ at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/services/misc/octoprint.nix:65:9:
13:54:47.974 attribute ‘functionTo’ missing, at /var/lib/gocd-agent/pipelines/nixpkgs-master/nixos/modules/services/misc/octoprint.nix:65:16
13:54:48.026 [go] Current job status: failed.

@edolstra
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grahamc It's pretty crazy that Nixpkgs depends on NixOS...

Please sign in to comment.