lib: Use Nix's static scope checking, fix error message, optimize

Nix can perform static scope checking, but whenever code is inside
a `with` expression, the analysis breaks down, because it can't
know statically what's in the attribute set whose attributes were
brought into scope. In those cases, Nix has to assume that
everything works out.

Except it doesnt. Removing `with` from lib/ revealed an undefined
variable in an error message.

If that doesn't convince you that we're better off without `with`,
I can tell you that this PR results in a 3% evaluation performance
improvement because Nix can look up local variables by index.
This adds up with applications like the module system.

Furthermore, removing `with` makes the binding site of each
variable obvious, which helps with comprehension.
This commit is contained in:
Robert Hensing
2020-10-20 13:47:24 +02:00
parent 5aa2a98dfa
commit afa6c51f27
9 changed files with 238 additions and 82 deletions

View File

@@ -1,12 +1,55 @@
{ lib }:
with lib.lists;
with lib.strings;
with lib.trivial;
with lib.attrsets;
with lib.options;
with lib.debug;
with lib.types;
let
inherit (lib.attrsets)
mapAttrsRecursiveCond
;
inherit (lib.lists)
any all concatLists concatMap
count filter findFirst foldl foldl'
head imap1 length optional
reverseList sort
;
inherit (lib.options)
isOption
mkOption
showDefs
showFiles
showOption
unknownModule
;
inherit (lib.attrsets)
attrByPath
attrNames
catAttrs
getAttrFromPath
mapAttrs
mapAttrsToList
optionalAttrs
recursiveUpdate
setAttrByPath
toList
;
inherit (lib.types)
types
;
inherit (lib.trivial)
flip
id
isBool
isFunction
isString
min
warn
;
inherit (lib.strings)
optionalString
;
inherit (lib)
elem
isAttrs
;
in
rec {
@@ -616,7 +659,7 @@ rec {
fixupOptionType = loc: opt:
let
options = opt.options or
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
(throw "Option `${showOption loc}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
f = tp:
let optionSetIn = type: (tp.name == type) && (tp.functor.wrapped.name == "optionSet");
in