diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 916cedab6a0e3..e2b20765300a9 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2929,7 +2929,10 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType # hasEmpty/nil check is to not break existing code like # `const foo = [(1, {}), (2, {false})]`, # `const foo = if true: (0, nil) else: (1, new(int))` - n[i][1] = fitNode(c, expectedElemType, n[i][1], n[i][1].info) + let conversion = indexTypesMatch(c, expectedElemType, n[i][1].typ, n[i][1]) + # ignore matching error, full tuple will be matched later which may call converter, see #24609 + if conversion != nil: + n[i][1] = conversion if n[i][1].typ.kind == tyTypeDesc: localError(c.config, n[i][1].info, "typedesc not allowed as tuple field.") diff --git a/tests/tuples/ttupleconverter.nim b/tests/tuples/ttupleconverter.nim new file mode 100644 index 0000000000000..2f615dc91e0b8 --- /dev/null +++ b/tests/tuples/ttupleconverter.nim @@ -0,0 +1,18 @@ +# issue #24609 + +import std/options + +type + Config* = object + bits*: tuple[r, g, b, a: Option[int32]] + +# works on 2.0.8 +# +# results in error on 2.2.0 +# type mismatch: got 'int literal(8)' for '8' but expected 'Option[system.int32]' +# +converter toInt32Tuple*(t: tuple[r,g,b,a: int]): tuple[r,g,b,a: Option[int32]] = + (some(t.r.int32), some(t.g.int32), some(t.b.int32), some(t.a.int32)) + +var cfg: Config +cfg.bits = (r: 8, g: 8, b: 8, a: 16)