Convert libs to a fixed-point

This does break the API of being able to import any lib file and get
its libs, however I'm not sure people did this.

I made this while exploring being able to swap out docFn with a stub
in #2305, to avoid functor performance problems. I don't know if that
is going to move forward (or if it is a problem or not,) but after
doing all this work figured I'd put it up anyway :)

Two notable advantages to this approach:

1. when a lib inherits another lib's functions, it doesn't
automatically get put in to the scope of lib
2. when a lib implements a new obscure functions, it doesn't
automatically get put in to the scope of lib

Using the test script (later in this commit) I got the following diff
on the API:

+ diff master fixed-lib
11764a11765,11766
> .types.defaultFunctor
> .types.defaultTypeMerge
11774a11777,11778
> .types.isOptionType
> .types.isType
11781a11786
> .types.mkOptionType
11788a11794
> .types.setType
11795a11802
> .types.types

This means that this commit _adds_ to the API, however I can't find a
way to fix these last remaining discrepancies. At least none are
_removed_.

Test script (run with nix-repl in the PATH):

#!/bin/sh

set -eux

repl() {
suff=${1:-}
echo "(import ./lib)$suff" \
| nix-repl 2>&1
}

attrs_to_check() {
repl "${1:-}" \
| tr ';' $'\n' \
| grep "\.\.\." \
| cut -d' ' -f2 \
| sed -e "s/^/${1:-}./" \
| sort
}

summ() {
repl "${1:-}" \
| tr ' ' $'\n' \
| sort \
| uniq
}

deep_summ() {
suff="${1:-}"
depth="${2:-4}"
depth=$((depth - 1))
summ "$suff"

for attr in $(attrs_to_check "$suff" | grep -v "types.types"); do
if [ $depth -eq 0 ]; then
summ "$attr" | sed -e "s/^/$attr./"
else
deep_summ "$attr" "$depth" | sed -e "s/^/$attr./"
fi
done
}

(
cd nixpkgs

#git add .
#git commit -m "Auto-commit, sorry" || true
git checkout fixed-lib
deep_summ > ../fixed-lib
git checkout master
deep_summ > ../master
)

if diff master fixed-lib; then
echo "SHALLOW MATCH!"
fi

(
cd nixpkgs
git checkout fixed-lib
repl .types
)

+4 -4
lib/attrsets.nix
···
+
{ lib }:
# Operations on attribute sets.
let
inherit (builtins) head tail length;
-
inherit (import ./trivial.nix) and or;
-
inherit (import ./default.nix) fold;
-
inherit (import ./strings.nix) concatStringsSep;
-
inherit (import ./lists.nix) concatMap concatLists all deepSeqList;
+
inherit (lib.trivial) and or;
+
inherit (lib.strings) concatStringsSep;
+
inherit (lib.lists) fold concatMap concatLists all deepSeqList;
in
rec {
+1 -1
lib/customisation.nix
···
+
{ lib }:
let
-
lib = import ./default.nix;
inherit (builtins) attrNames isFunction;
in
+3 -1
lib/debug.nix
···
-
let lib = import ./default.nix;
+
{ lib }:
+
+
let
inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt
isString isBool head substring attrNames;
+113 -44
lib/default.nix
···
*/
let
-
# often used, or depending on very little
-
trivial = import ./trivial.nix;
-
fixedPoints = import ./fixed-points.nix;
+
callLibs = file: import file { inherit lib; };
-
# datatypes
-
attrsets = import ./attrsets.nix;
-
lists = import ./lists.nix;
-
strings = import ./strings.nix;
-
stringsWithDeps = import ./strings-with-deps.nix;
+
lib = rec {
-
# packaging
-
customisation = import ./customisation.nix;
-
maintainers = import ./maintainers.nix;
-
meta = import ./meta.nix;
-
sources = import ./sources.nix;
+
# often used, or depending on very little
+
trivial = callLibs ./trivial.nix;
+
fixedPoints = callLibs ./fixed-points.nix;
-
# module system
-
modules = import ./modules.nix;
-
options = import ./options.nix;
-
types = import ./types.nix;
+
# datatypes
+
attrsets = callLibs ./attrsets.nix;
+
lists = callLibs ./lists.nix;
+
strings = callLibs ./strings.nix;
+
stringsWithDeps = callLibs ./strings-with-deps.nix;
-
# constants
-
licenses = import ./licenses.nix;
-
systems = import ./systems;
+
# packaging
+
customisation = callLibs ./customisation.nix;
+
maintainers = callLibs ./maintainers.nix;
+
meta = callLibs ./meta.nix;
+
sources = callLibs ./sources.nix;
+
+
+
# module system
+
modules = callLibs ./modules.nix;
+
options = callLibs ./options.nix;
+
types = callLibs ./types.nix;
-
# misc
-
debug = import ./debug.nix;
-
generators = import ./generators.nix;
-
misc = import ./deprecated.nix;
+
# constants
+
licenses = callLibs ./licenses.nix;
+
systems = callLibs ./systems;
-
# domain-specific
-
sandbox = import ./sandbox.nix;
-
fetchers = import ./fetchers.nix;
+
# misc
+
debug = callLibs ./debug.nix;
-
# Eval-time filesystem handling
-
filesystem = import ./filesystem.nix;
+
generators = callLibs ./generators.nix;
+
misc = callLibs ./deprecated.nix;
+
# domain-specific
+
sandbox = callLibs ./sandbox.nix;
+
fetchers = callLibs ./fetchers.nix;
-
in
-
{ inherit trivial fixedPoints
-
attrsets lists strings stringsWithDeps
-
customisation maintainers meta sources
-
modules options types
-
licenses systems
-
debug generators misc
-
sandbox fetchers filesystem;
+
# Eval-time filesystem handling
+
filesystem = callLibs ./filesystem.nix;
# back-compat aliases
platforms = systems.doubles;
-
}
-
# !!! don't include everything at top-level; perhaps only the most
-
# commonly used functions.
-
// trivial // fixedPoints
-
// lists // strings // stringsWithDeps // attrsets // sources
-
// options // types // meta // debug // misc // modules
-
// customisation
+
+
inherit (builtins) add addErrorContext attrNames
+
concatLists deepSeq elem elemAt filter genericClosure genList
+
getAttr hasAttr head isAttrs isBool isFunction isInt isList
+
isString length lessThan listToAttrs pathExists readFile
+
replaceStrings seq stringLength sub substring tail;
+
inherit (trivial) id const concat or and boolToString mergeAttrs
+
flip mapNullable inNixShell min max importJSON warn info
+
nixpkgsVersion mod;
+
+
inherit (fixedPoints) fix fix' extends composeExtensions
+
makeExtensible makeExtensibleWithCustomName;
+
inherit (attrsets) attrByPath hasAttrByPath setAttrByPath
+
getAttrFromPath attrVals attrValues catAttrs filterAttrs
+
filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
+
mapAttrs' mapAttrsToList mapAttrsRecursive mapAttrsRecursiveCond
+
genAttrs isDerivation toDerivation optionalAttrs
+
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
+
recursiveUpdate matchAttrs overrideExisting getOutput getBin
+
getLib getDev chooseDevOutputs zipWithNames zip;
+
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
+
concatMap flatten remove findSingle findFirst any all count
+
optional optionals toList range partition zipListsWith zipLists
+
reverseList listDfs toposort sort take drop sublist last init
+
crossLists unique intersectLists subtractLists
+
mutuallyExclusive;
+
inherit (strings) concatStrings concatMapStrings concatImapStrings
+
intersperse concatStringsSep concatMapStringsSep
+
concatImapStringsSep makeSearchPath makeSearchPathOutput
+
makeLibraryPath makeBinPath makePerlPath optionalString
+
hasPrefix hasSuffix stringToCharacters stringAsChars escape
+
escapeShellArg escapeShellArgs replaceChars lowerChars upperChars
+
toLower toUpper addContextFrom splitString removePrefix
+
removeSuffix versionOlder versionAtLeast getVersion nameFromURL
+
enableFeature fixedWidthString fixedWidthNumber isStorePath
+
toInt readPathsFromFile fileContents;
+
inherit (stringsWithDeps) textClosureList textClosureMap
+
noDepEntry fullDepEntry packEntry stringAfter;
+
inherit (customisation) overrideDerivation makeOverridable
+
callPackageWith callPackagesWith addPassthru hydraJob makeScope;
+
inherit (meta) addMetaAttrs dontDistribute setName updateName
+
appendToName mapDerivationAttrset lowPrio lowPrioSet hiPrio
+
hiPrioSet;
+
inherit (sources) pathType pathIsDirectory cleanSourceFilter
+
cleanSource sourceByRegex sourceFilesBySuffices
+
commitIdFromGitRepo;
+
inherit (modules) evalModules closeModules unifyModuleSyntax
+
applyIfFunction unpackSubmodule packSubmodule mergeModules
+
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
+
pushDownProperties dischargeProperties filterOverrides
+
sortProperties fixupOptionType mkIf mkAssert mkMerge mkOverride
+
mkOptionDefault mkDefault mkForce mkVMOverride mkStrict
+
mkFixStrictness mkOrder mkBefore mkAfter mkAliasDefinitions
+
mkAliasAndWrapDefinitions fixMergeModules mkRemovedOptionModule
+
mkRenamedOptionModule mkMergedOptionModule mkChangedOptionModule
+
mkAliasOptionModule doRename filterModules;
+
inherit (options) isOption mkEnableOption mkSinkUndeclaredOptions
+
mergeDefaultOption mergeOneOption mergeEqualOption getValues
+
getFiles optionAttrSetToDocList optionAttrSetToDocList'
+
scrubOptionValue literalExample showOption showFiles
+
unknownModule mkOption;
+
inherit (types) isType setType defaultTypeMerge defaultFunctor
+
isOptionType mkOptionType;
+
inherit (debug) addErrorContextToAttrs traceIf traceVal
+
traceXMLVal traceXMLValMarked traceSeq traceSeqN traceValSeq
+
traceValSeqN traceShowVal traceShowValMarked
+
showVal traceCall traceCall2 traceCall3 traceValIfNot runTests
+
testAllTrue strict traceCallXml attrNamesToStr;
+
inherit (misc) maybeEnv defaultMergeArg defaultMerge foldArgs
+
defaultOverridableDelayableArgs composedArgsAndFun
+
maybeAttrNullable maybeAttr ifEnable checkFlag getValue
+
checkReqs uniqList uniqListExt condConcat lazyGenericClosure
+
innerModifySumArgs modifySumArgs innerClosePropagation
+
closePropagation mapAttrsFlatten nvs setAttr setAttrMerge
+
mergeAttrsWithFunc mergeAttrsConcatenateValues
+
mergeAttrsNoOverride mergeAttrByFunc mergeAttrsByFuncDefaults
+
mergeAttrsByFuncDefaultsClean mergeAttrBy
+
prepareDerivationArgs nixType imap overridableDelayableArgs;
+
};
+
in lib
+5 -4
lib/deprecated.nix
···
-
let lib = import ./default.nix;
+
{ lib }:
+
let
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
in
-
with import ./lists.nix;
-
with import ./attrsets.nix;
-
with import ./strings.nix;
+
with lib.lists;
+
with lib.attrsets;
+
with lib.strings;
rec {
+1
lib/fetchers.nix
···
# snippets that can be shared by multiple fetchers (pkgs/build-support)
+
{ lib }:
{
proxyImpureEnvVars = [
+1
lib/filesystem.nix
···
+
{ lib }:
{ # haskellPathsInDir : Path -> Map String Path
# A map of all haskell packages defined in the given path,
# identified by having a cabal file with the same name as the
+1
lib/fixed-points.nix
···
+
{ ... }:
rec {
# Compute the fixed point of the given function `f`, which is usually an
# attribute set that expects its final, non-recursive representation as an
+4 -3
lib/generators.nix
···
* Tests can be found in ./tests.nix
* Documentation in the manual, #sec-generators
*/
-
with import ./trivial.nix;
+
{ lib }:
+
with (lib).trivial;
let
-
libStr = import ./strings.nix;
-
libAttr = import ./attrsets.nix;
+
libStr = lib.strings;
+
libAttr = lib.attrsets;
flipMapAttrs = flip libAttr.mapAttrs;
in
+2 -3
lib/licenses.nix
···
+
{ lib }:
let
-
-
lib = import ./default.nix;
spdx = lic: lic // {
url = "http://spdx.org/licenses/${lic.spdxId}";
···
url = "https://raw.githubusercontent.com/raboof/notion/master/LICENSE";
fullName = "Notion modified LGPL";
};
-
+
ofl = spdx {
spdxId = "OFL-1.1";
fullName = "SIL Open Font License 1.1";
+2 -2
lib/lists.nix
···
# General list operations.
-
-
with import ./trivial.nix;
+
{ lib }:
+
with lib.trivial;
rec {
+1
lib/maintainers.nix
···
+
{ ...}:
/* List of NixOS maintainers. The format is:
handle = "Real Name <address@example.org>";
+1 -2
lib/meta.nix
···
/* Some functions for manipulating meta attributes, as well as the
name attribute. */
-
let lib = import ./default.nix;
-
in
+
{ lib }:
rec {
+9 -7
lib/modules.nix
···
-
with import ./lists.nix;
-
with import ./strings.nix;
-
with import ./trivial.nix;
-
with import ./attrsets.nix;
-
with import ./options.nix;
-
with import ./debug.nix;
-
with import ./types.nix;
+
{ lib }:
+
+
with lib.lists;
+
with lib.strings;
+
with lib.trivial;
+
with lib.attrsets;
+
with lib.options;
+
with lib.debug;
+
with lib.types;
rec {
+5 -6
lib/options.nix
···
# Nixpkgs/NixOS option handling.
+
{ lib }:
-
let lib = import ./default.nix; in
-
-
with import ./trivial.nix;
-
with import ./lists.nix;
-
with import ./attrsets.nix;
-
with import ./strings.nix;
+
with lib.trivial;
+
with lib.lists;
+
with lib.attrsets;
+
with lib.strings;
rec {
+2 -1
lib/sandbox.nix
···
-
with import ./strings.nix;
+
{ lib }:
+
with lib.strings;
/* Helpers for creating lisp S-exprs for the Apple sandbox
+1 -2
lib/sources.nix
···
# Functions for copying sources to the Nix store.
-
-
let lib = import ./default.nix; in
+
{ lib }:
rec {
+4 -3
lib/strings-with-deps.nix
···
+
{ lib }:
/*
Usage:
···
[1] maybe this behaviour should be removed to keep things simple (?)
*/
-
with import ./lists.nix;
-
with import ./attrsets.nix;
-
with import ./strings.nix;
+
with lib.lists;
+
with lib.attrsets;
+
with lib.strings;
rec {
+2 -2
lib/strings.nix
···
/* String manipulation functions. */
-
-
let lib = import ./default.nix;
+
{ lib }:
+
let
inherit (builtins) length;
+7 -6
lib/systems/default.nix
···
-
let inherit (import ../attrsets.nix) mapAttrs; in
+
{ lib }:
+
let inherit (lib.attrsets) mapAttrs; in
rec {
-
doubles = import ./doubles.nix;
-
parse = import ./parse.nix;
-
inspect = import ./inspect.nix;
-
platforms = import ./platforms.nix;
-
examples = import ./examples.nix;
+
doubles = import ./doubles.nix { inherit lib; };
+
parse = import ./parse.nix { inherit lib; };
+
inspect = import ./inspect.nix { inherit lib; };
+
platforms = import ./platforms.nix { inherit lib; };
+
examples = import ./examples.nix { inherit lib; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary.
+5 -4
lib/systems/doubles.nix
···
+
{ lib }:
let
-
lists = import ../lists.nix;
-
parse = import ./parse.nix;
-
inherit (import ./inspect.nix) predicates;
-
inherit (import ../attrsets.nix) matchAttrs;
+
inherit (lib) lists;
+
parse = import ./parse.nix { inherit lib; };
+
inherit (import ./inspect.nix { inherit lib; }) predicates;
+
inherit (lib.attrsets) matchAttrs;
all = [
"aarch64-linux"
+2 -2
lib/systems/examples.nix
···
# These can be passed to nixpkgs as either the `localSystem` or
# `crossSystem`. They are put here for user convenience, but also used by cross
# tests and linux cross stdenv building, so handle with care!
-
-
let platforms = import ./platforms.nix; in
+
{ lib }:
+
let platforms = import ./platforms.nix { inherit lib; }; in
rec {
#
+4 -3
lib/systems/inspect.nix
···
-
with import ./parse.nix;
-
with import ../attrsets.nix;
-
with import ../lists.nix;
+
{ lib }:
+
with import ./parse.nix { inherit lib; };
+
with lib.attrsets;
+
with lib.lists;
rec {
patterns = rec {
+5 -6
lib/systems/parse.nix
···
# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially
# Triple::normalize. Parsing should essentially act as a more conservative
# version of that last function.
-
-
with import ../lists.nix;
-
with import ../types.nix;
-
with import ../attrsets.nix;
-
with (import ./inspect.nix).predicates;
+
{ lib }:
+
with lib.lists;
+
with lib.types;
+
with lib.attrsets;
+
with (import ./inspect.nix { inherit lib; }).predicates;
let
-
lib = import ../default.nix;
setTypesAssert = type: pred:
mapAttrs (name: value:
assert pred value;
+1
lib/systems/platforms.nix
···
+
{ lib }:
rec {
pcBase = {
name = "pc";
+2 -1
lib/trivial.nix
···
+
{ lib }:
rec {
/* The identity function
···
isInt add sub lessThan
seq deepSeq genericClosure;
-
inherit (import ./strings.nix) fileContents;
+
inherit (lib.strings) fileContents;
# Return the Nixpkgs version number.
nixpkgsVersion =
+12 -11
lib/types.nix
···
# Definitions related to run-time type checking. Used in particular
# to type-check NixOS configurations.
+
{ lib }:
+
with lib.lists;
+
with lib.attrsets;
+
with lib.options;
+
with lib.trivial;
+
with lib.strings;
+
let
-
with import ./lists.nix;
-
with import ./attrsets.nix;
-
with import ./options.nix;
-
with import ./trivial.nix;
-
with import ./strings.nix;
-
let inherit (import ./modules.nix) mergeDefinitions filterOverrides; in
-
+
inherit (lib.modules) mergeDefinitions filterOverrides;
+
outer_types =
rec {
-
isType = type: x: (x._type or "") == type;
setType = typeName: value: value // {
···
# When adding new types don't forget to document them in
# nixos/doc/manual/development/option-types.xml!
types = rec {
-
unspecified = mkOptionType {
name = "unspecified";
};
···
submodule = opts:
let
opts' = toList opts;
-
inherit (import ./modules.nix) evalModules;
+
inherit (lib.modules) evalModules;
in
mkOptionType rec {
name = "submodule";
···
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
};
+
};
-
}
+
in outer_types // outer_types.types