commit e067eb1f6da7994150f10854e5fd635ca8bd0e92 Author: traxys Date: Sun Jan 14 17:54:55 2024 +0100 lib.types: Include the suboptions of both types for either This allows to correctly gather the sub options for types of the form `either (submodule {...})`. This requires adding two new types: `eitherRecursive` and `oneOfRecursive` that avoid infinite recursions for types like configuration types that are often of the form `oneOf [atom (listOf configType)]` diff --git a/lib/types.nix b/lib/types.nix index cea63c598321..d26982db6cc0 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -906,10 +906,16 @@ rec { then functor.type mt1 mt2 else null; functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; }; + getSubOptions = prefix: (t1.getSubOptions prefix) // (t2.getSubOptions prefix); nestedTypes.left = t1; nestedTypes.right = t2; }; + # Handle recursive leaf types, avoiding an infinite recursion + eitherRecursive = t1: t2: (either t1 t2) // { + getSubOptions = _: {}; + }; + # Any of the types in the given list oneOf = ts: let @@ -917,6 +923,13 @@ rec { tail' = tail ts; in foldl' either head' tail'; + # Handle recursive leaf types, avoiding an infinite recursion + oneOfRecursive = ts: + let + head' = if ts == [] then throw "types.oneOfRecursive needs to get at least one type in its argument" else head ts; + tail' = tail ts; + in foldl' eitherRecursive head' tail'; + # Either value of type `coercedType` or `finalType`, the former is # converted to `finalType` using `coerceFunc`. coercedTo = coercedType: coerceFunc: finalType: