1{ lib }:
2# Simple internal type checks for meta.
3# This file is not a stable interface and may be changed arbitrarily.
4#
5# TODO: add a method to the module system types
6# see https://github.com/NixOS/nixpkgs/pull/273935#issuecomment-1854173100
7let
8 inherit (builtins)
9 isString
10 isInt
11 isAttrs
12 isList
13 all
14 any
15 attrValues
16 isFunction
17 isBool
18 concatStringsSep
19 isFloat
20 ;
21 isTypeDef = t: isAttrs t && t ? name && isString t.name && t ? verify && isFunction t.verify;
22
23in
24lib.fix (self: {
25 string = {
26 name = "string";
27 verify = isString;
28 };
29 str = self.string; # Type alias
30
31 any = {
32 name = "any";
33 verify = _: true;
34 };
35
36 int = {
37 name = "int";
38 verify = isInt;
39 };
40
41 float = {
42 name = "float";
43 verify = isFloat;
44 };
45
46 bool = {
47 name = "bool";
48 verify = isBool;
49 };
50
51 attrs = {
52 name = "attrs";
53 verify = isAttrs;
54 };
55
56 list = {
57 name = "list";
58 verify = isList;
59 };
60
61 attrsOf =
62 t:
63 assert isTypeDef t;
64 let
65 inherit (t) verify;
66 in
67 {
68 name = "attrsOf<${t.name}>";
69 verify =
70 # attrsOf<any> can be optimised to just isAttrs
71 if t == self.any then isAttrs else attrs: isAttrs attrs && all verify (attrValues attrs);
72 };
73
74 listOf =
75 t:
76 assert isTypeDef t;
77 let
78 inherit (t) verify;
79 in
80 {
81 name = "listOf<${t.name}>";
82 verify =
83 # listOf<any> can be optimised to just isList
84 if t == self.any then isList else v: isList v && all verify v;
85 };
86
87 union =
88 types:
89 assert all isTypeDef types;
90 let
91 # Store a list of functions so we don't have to pay the cost of attrset lookups at runtime.
92 funcs = map (t: t.verify) types;
93 in
94 {
95 name = "union<${concatStringsSep "," (map (t: t.name) types)}>";
96 verify = v: any (func: func v) funcs;
97 };
98})