@@ -61,7 +61,11 @@ let
6161 boolToString
6262 ;
6363
64− inherit (lib.modules) mergeDefinitions;
64+ inherit (lib.modules)
65+ mergeDefinitions
66+ fixupOptionType
67+ mergeOptionDecls
68+ ;
6569 outer_types =
6670rec {
6771 isType = type: x: (x._type or "") == type;
@@ -525,6 +529,31 @@ rec {
525529 modules = toList modules;
526530 };
527531
532+ # The type of a type!
533+ optionType = mkOptionType {
534+ name = "optionType";
535+ description = "optionType";
536+ check = value: value._type or null == "option-type";
537+ merge = loc: defs:
538+ let
539+ # Prepares the type definitions for mergeOptionDecls, which
540+ # annotates submodules types with file locations
541+ optionModules = map ({ value, file }:
542+ {
543+ _file = file;
544+ # There's no way to merge types directly from the module system,
545+ # but we can cheat a bit by just declaring an option with the type
546+ options = lib.mkOption {
547+ type = value;
548+ };
549+ }
550+ ) defs;
551+ # Merges all the types into a single one, including submodule merging.
552+ # This also propagates file information to all submodules
553+ mergedOption = fixupOptionType loc (mergeOptionDecls loc optionModules);
554+ in mergedOption.type;
555+ };
556+
528557 submoduleWith =
529558 { modules
530559 , specialArgs ? {}