| 17 Apr 2026 |
| c4lliope changed their profile picture. | 08:41:53 |
| Robin joined the room. | 18:57:51 |
| Robin left the room. | 19:04:02 |
| 18 Apr 2026 |
| Lukas joined the room. | 01:17:12 |
| Sienou Rasmata joined the room. | 15:53:09 |
| Sienou Rasmata left the room. | 15:53:12 |
| 23 Apr 2026 |
| Maxisthespy joined the room. | 21:25:27 |
| 27 Apr 2026 |
| Ninja joined the room. | 14:34:01 |
| 30 Apr 2026 |
| isabel changed their profile picture. | 18:47:35 |
| 1 May 2026 |
| llakala set a profile picture. | 17:12:42 |
| 3 May 2026 |
| isabel changed their profile picture. | 10:39:10 |
| 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 |
| anurag 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 |