lol

lib/types: Add emptyValue attribute to types

Co-Authored-By: Robert Hensing <roberth@users.noreply.github.com>

+18 -2
+18 -2
lib/types.nix
··· 65 65 # definition values and locations (e.g. [ { file = "/foo.nix"; 66 66 # value = 1; } { file = "/bar.nix"; value = 2 } ]). 67 67 merge ? mergeDefaultOption 68 + , # Whether this type has a value representing nothingness. If it does, 69 + # this should be a value of the form { value = <the nothing value>; } 70 + # If it doesn't, this should be {} 71 + # This may be used when a value is required for `mkIf false`. This allows the extra laziness in e.g. `lazyAttrsOf`. 72 + emptyValue ? {} 68 73 , # Return a flat list of sub-options. Used to generate 69 74 # documentation. 70 75 getSubOptions ? prefix: {} ··· 88 93 functor ? defaultFunctor name 89 94 }: 90 95 { _type = "option-type"; 91 - inherit name check merge getSubOptions getSubModules substSubModules typeMerge functor; 96 + inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor; 92 97 description = if description == null then name else description; 93 98 }; 94 99 ··· 225 230 description = "attribute set"; 226 231 check = isAttrs; 227 232 merge = loc: foldl' (res: def: mergeAttrs res def.value) {}; 233 + emptyValue = { value = {}; }; 228 234 }; 229 235 230 236 # derivation is a reserved keyword. ··· 265 271 ) def.value 266 272 else 267 273 throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs))); 274 + emptyValue = { value = {}; }; 268 275 getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); 269 276 getSubModules = elemType.getSubModules; 270 277 substSubModules = m: listOf (elemType.substSubModules m); ··· 273 280 274 281 nonEmptyListOf = elemType: 275 282 let list = addCheck (types.listOf elemType) (l: l != []); 276 - in list // { description = "non-empty " + list.description; }; 283 + in list // { 284 + description = "non-empty " + list.description; 285 + # Note: emptyValue is left as is, because another module may define an element. 286 + }; 277 287 278 288 attrsOf = elemType: mkOptionType rec { 279 289 name = "attrsOf"; ··· 285 295 ) 286 296 # Push down position info. 287 297 (map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs))); 298 + emptyValue = { value = {}; }; 288 299 getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]); 289 300 getSubModules = elemType.getSubModules; 290 301 substSubModules = m: attrsOf (elemType.substSubModules m); ··· 339 350 description = "list or attribute set of ${elemType.description}s"; 340 351 check = x: isList x || isAttrs x; 341 352 merge = loc: defs: attrOnly.merge loc (convertAllLists loc defs); 353 + emptyValue = { value = {}; }; 342 354 getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]); 343 355 getSubModules = elemType.getSubModules; 344 356 substSubModules = m: loaOf (elemType.substSubModules m); ··· 350 362 name = "uniq"; 351 363 inherit (elemType) description check; 352 364 merge = mergeOneOption; 365 + emptyValue = elemType.emptyValue; 353 366 getSubOptions = elemType.getSubOptions; 354 367 getSubModules = elemType.getSubModules; 355 368 substSubModules = m: uniq (elemType.substSubModules m); ··· 367 380 else if nrNulls != 0 then 368 381 throw "The option `${showOption loc}` is defined both null and not null, in ${showFiles (getFiles defs)}." 369 382 else elemType.merge loc defs; 383 + emptyValue = { value = null; }; 370 384 getSubOptions = elemType.getSubOptions; 371 385 getSubModules = elemType.getSubModules; 372 386 substSubModules = m: nullOr (elemType.substSubModules m); ··· 407 421 args.name = last loc; 408 422 prefix = loc; 409 423 }).config; 424 + emptyValue = { value = {}; }; 410 425 getSubOptions = prefix: (evalModules 411 426 { inherit modules prefix specialArgs; 412 427 # This is a work-around due to the fact that some sub-modules, ··· 515 530 if finalType.check val then val 516 531 else coerceFunc val; 517 532 in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs); 533 + emptyValue = finalType.emptyValue; 518 534 getSubOptions = finalType.getSubOptions; 519 535 getSubModules = finalType.getSubModules; 520 536 substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);