diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index b290faec78..c7ff437e7c 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -563,6 +563,26 @@ proc eraseVoidParams*(t: PType) = setLen t.n.sons, pos break +proc eraseTupleVoidFields*(t: PType) = + ## Remove void fields from a named tuple type, compacting both `t.n` + ## (the field symbol nodes) and `t.sonsImpl` (the child types). + if t.n == nil: return # anonymous tuple, nothing to compact + for i in 0..= t.n.len or t.n[j].kind != nkRecList): + t.n[pos] = t.n[j] + t[pos] = t[j] + if t.n[pos].kind == nkSym: + t.n[pos].sym.position = pos + inc pos + # else: skip void entries + setLen t.n.sons, pos + t.setSonsLen pos + break + proc skipIntLiteralParams*(t: PType; idgen: IdGenerator) = for i, p in t.ikids: if p == nil: continue @@ -768,6 +788,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false): propagateFieldFlags(result, result.n) if result.kind == tyObject and cl.c.computeRequiresInit(cl.c, result): result.incl tfRequiresInit + if result.kind == tyTuple: + eraseTupleVoidFields(result) of tyProc: eraseVoidParams(result) diff --git a/tests/tuples/ttuples_issues.nim b/tests/tuples/ttuples_issues.nim index 70defdfce9..0a640bfb76 100644 --- a/tests/tuples/ttuples_issues.nim +++ b/tests/tuples/ttuples_issues.nim @@ -131,3 +131,47 @@ static: main() mainProc() + + +block: + type + Tuple[N] = tuple + a: int + b: N + + TupleVoid = Tuple[void] + + var x: TupleVoid = (a: 1, ) + doAssert x.a == 1 + +block: + type W[N] = seq[tuple[b: N]] + var _: W[void] + +block: + type Tuple2[N] = tuple + a: int + b: N + c: int + + var y: Tuple2[void] = (a: 10, c: 20) + doAssert y.a == 10 + doAssert y.c == 20 + +block: + type Outer[N] = tuple + inner: tuple[x: int, y: N] + + var o: Outer[void] = (inner: (x: 3, )) + doAssert o.inner.x == 3 + +block: + type Tup[T] = tuple + a: int + b: T + + proc f[T](t: Tup[T]): int = + result = t.a + + var z: Tup[void] = (a: 7, ) + doAssert f(z) == 7