| 8 May 2026 |
| jopejoe1 changed their display name from jopejoe1 (4094@epvpn) to jopejoe1. | 08:46:19 |
| 9 May 2026 |
| linj joined the room. | 05:02:21 |
| 11 May 2026 |
| Maëlys joined the room. | 20:40:21 |
| 12 May 2026 |
| Richard Tichý joined the room. | 11:19:41 |
| Michal Koutenský joined the room. | 18:16:59 |
| 14 May 2026 |
| tuhana joined the room. | 15:12:49 |
| 19 May 2026 |
| @snow101:matrix.org left the room. | 08:37:05 |
| amadaluzia changed their profile picture. | 20:58:55 |
| 22 May 2026 |
| polykernel joined the room. | 16:40:58 |
polykernel | What is the best way to propagate checks added by addCheck in the type merge process? I tried overriding functor in the extended type but the functor attached to the type after merging options declarations is not the one I overwrote. | 17:00:24 |
polykernel | Here is a MWE:
{
pkgs ? import <nixpkgs> { },
lib ? pkgs.lib,
}:
let
testSubmodule =
{ config, ... }:
{
freeformType = lib.types.lazyAttrsOf lib.types.raw;
options.a = lib.mkOption {
type = lib.types.int;
default = 0;
};
};
isSubmoduleFn =
m:
let
args = builtins.functionArgs m;
in
args ? lib || args ? config || args ? options;
staticInnerType =
let
baseType = lib.types.addCheck (lib.types.submodule testSubmodule) (
v: builtins.isAttrs v || isSubmoduleFn v
);
in
baseType
// rec {
functor = baseType.functor // {
type =
attrs:
let
mergedType = lib.types.addCheck (lib.types.submoduleWith attrs) (
v: builtins.isAttrs v || isSubmoduleFn v
);
in
mergedType
// {
inherit substSubModules;
functor = mergedType.functor // {
inherit (functor) type;
};
};
};
substSubModules =
m:
lib.types.addCheck (lib.types.submodule m) (v: builtins.isAttrs v || isSubmoduleFn v)
// {
inherit substSubModules;
};
};
dynamicInnerType = lib.types.functionTo staticInnerType;
innerType = lib.types.either staticInnerType dynamicInnerType // rec {
substSubModules =
m:
(lib.types.either (staticInnerType.substSubModules m) (dynamicInnerType.substSubModules m))
// {
inherit substSubModules;
};
};
testType = lib.types.lazyAttrsOf innerType;
optionModule1 = {
options.test = lib.mkOption {
type = testType;
};
};
optionModule2 = {
options.test = lib.mkOption {
type = testType.substSubModules [
{
options.b = lib.mkOption {
type = lib.types.bool;
};
}
];
};
};
staticConfig = {
config.test.random2 = {
b = false;
};
};
dynamicConfig = {
config.test.random1 =
{ arg1 }:
{
a = 1;
};
};
result = lib.evalModules {
modules = [
optionModule1
optionModule2
staticConfig
dynamicConfig
];
};
in
result
| 17:01:39 |
polykernel | The check on staticInnerType gets dropped after the type merge. | 17:02:19 |
polykernel | * What is the best way to propagate checks added by addCheck in the type merge process? I tried overriding functor in the extended type but the functor attached to the type after merging options declarations is not one supplied in my override (I am not sure why this is the case?). | 17:06:14 |
| Jon Hermansen changed their display name from jonhermansen to Jon Hermansen. | 19:18:49 |
polykernel | After some reading, I realized I needed to override typeMerge as overriding functor after mkOptionType has materialized does not change the typeMerge field. I ended up making a function that builds a custom submodule type instead of shallowing attributes. Here is the updated example that works in case it helps anyone in the future:
{
pkgs ? import /home/sheaf/projects/github/nixpkgs { },
lib ? pkgs.lib,
}:
let
testSubmodule =
{ config, ... }:
{
freeformType = lib.types.lazyAttrsOf lib.types.raw;
options.a = lib.mkOption {
type = lib.types.int;
default = 0;
};
};
isSubmoduleFn =
m:
let
args = builtins.functionArgs m;
in
args ? lib || args ? config || args ? options;
customSubmoduleWith =
attrs:
let
t = lib.types.addCheck (lib.types.submoduleWith attrs) (v: builtins.isAttrs v || isSubmoduleFn v);
in
t
// rec {
substSubmodules = m: customSubmoduleWith (attrs // { modules = m; });
functor = t.functor // {
type = customSubmoduleWith;
};
typeMerge = lib.types.defaultTypeMerge functor;
};
customSubmodule =
module:
customSubmoduleWith {
shorthandOnlyDefinesConfig = true;
modules = [ module ];
};
staticInnerType = customSubmodule testSubmodule;
dynamicInnerType = lib.types.functionTo staticInnerType;
innerType = lib.types.either staticInnerType dynamicInnerType;
testType = lib.types.lazyAttrsOf innerType;
optionModule1 = {
options.test = lib.mkOption {
type = testType;
};
};
optionModule2 = {
options.test = lib.mkOption {
type =
let
t = customSubmodule {
options.b = lib.mkOption {
type = lib.types.bool;
};
};
in
lib.types.lazyAttrsOf (lib.types.either t (lib.types.functionTo t));
};
};
staticConfig = {
config.test.random2 = {
b = false;
};
};
dynamicConfig = {
config.test.random1 =
{ arg1 }:
{
a = 1;
};
};
result = lib.evalModules {
modules = [
optionModule1
optionModule2
staticConfig
dynamicConfig
];
};
in
result
| 21:50:44 |
polykernel | Redacted or Malformed Event | 21:50:54 |
polykernel | I found where my error is. I need to override typeMerge as well since shallowing functor after the mkOptionType call won't affect the typeMerge field. | 21:53:07 |
polykernel | Here is the updated working example in case it helps anyone in the future:
{
pkgs ? import <nixpkgs> { },
lib ? pkgs.lib,
}:
let
testSubmodule =
{ config, ... }:
{
freeformType = lib.types.lazyAttrsOf lib.types.raw;
options.a = lib.mkOption {
type = lib.types.int;
default = 0;
};
};
isSubmoduleFn =
m:
let
args = builtins.functionArgs m;
in
args ? lib || args ? config || args ? options;
customSubmoduleWith =
attrs:
let
t = lib.types.addCheck (lib.types.submoduleWith attrs) (v: builtins.isAttrs v || isSubmoduleFn v);
in
t
// rec {
substSubmodules = m: customSubmoduleWith (attrs // { modules = m; });
functor = t.functor // {
type = customSubmoduleWith;
};
typeMerge = lib.types.defaultTypeMerge functor;
};
customSubmodule =
module:
customSubmoduleWith {
shorthandOnlyDefinesConfig = true;
modules = [ module ];
};
staticInnerType = customSubmodule testSubmodule;
dynamicInnerType = lib.types.functionTo staticInnerType;
innerType = lib.types.either staticInnerType dynamicInnerType;
testType = lib.types.lazyAttrsOf innerType;
optionModule1 = {
options.test = lib.mkOption {
type = testType;
};
};
optionModule2 = {
options.test = lib.mkOption {
type =
let
t = customSubmodule {
options.b = lib.mkOption {
type = lib.types.bool;
};
};
in
lib.types.lazyAttrsOf (lib.types.either t (lib.types.functionTo t));
};
};
staticConfig = {
config.test.random2 = {
b = false;
};
};
dynamicConfig = {
config.test.random1 =
{ arg1 }:
{
a = 1;
};
};
result = lib.evalModules {
modules = [
optionModule1
optionModule2
staticConfig
dynamicConfig
];
};
in
result
| 21:54:16 |
hsjobeki | https://github.com/NixOS/nixpkgs/issues/396021
This limitation of addCheck is known.
Fyi the more "idiomatic" way is to use mkOptionType to create a custom type such as it is done in lib/types.nix itself. | 22:06:04 |
polykernel | Ah, for some reason I skipped over the link to that issue in the comment when reading. Thanks for the pointer. | 22:16:22 |
polykernel | I haven't done a lot of thinking on this but is it possible to overcome this limitation by using some fixpoint mechanism like overlays? The problem seems to be that the type functor only has access to the type when it is defined (at the mkOptionType call site), not the type that is actually materalized (after all // updates). If the materialized type is accessible to the type functor, I think we can create a replica of the type. | 22:31:18 |
| 23 May 2026 |
Matt Sturgeon |
using some fixpoint mechanism like overlays?
Maybe mkOptionType could apply mkExtensible, which adds the .extend attribute? addCheck could then apply an overlay to <type>.extend 🤔
| 20:30:14 |
| 24 May 2026 |
| maurice joined the room. | 18:17:10 |
| 26 May 2026 |
| ·☽•Nameless☆•777 · ± changed their profile picture. | 05:42:37 |
| phanirithvij changed their display name from loudgolem to phanirithvij. | 11:41:58 |
| 27 May 2026 |
| isabel changed their profile picture. | 21:17:16 |
| 28 May 2026 |
| define9293 joined the room. | 02:06:27 |
| 29 May 2026 |
| Necoro joined the room. | 09:16:41 |
| Louis2747 joined the room. | 09:52:55 |
| toonn joined the room. | 10:16:32 |