From 2a8c759df0e8a952f7cbea8539e3fb7aa234795a Mon Sep 17 00:00:00 2001 From: SirOlaf <34164198+SirOlaf@users.noreply.github.com> Date: Fri, 8 Sep 2023 06:50:39 +0200 Subject: [PATCH] Fix #21742: Check generic alias depth before skip (#22443) Close #21742 Checking if there's any side-effects and if just changing typeRel is adequate for this issue before trying to look into related ones. `skipBoth` is also not that great, it can lead to code that works sometimes but fails when the proc is instantiated with branching aliases. This is mostly an issue with error clarity though. --------- Co-authored-by: SirOlaf Co-authored-by: SirOlaf <> --- compiler/sigmatch.nim | 8 ++++++-- compiler/types.nim | 7 +++++++ tests/generics/t21742.nim | 10 ++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/generics/t21742.nim diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index bb99463b64..1cf29dcfd4 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1456,8 +1456,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, let origF = f var f = if prev == nil: f else: prev - let roota = a.skipGenericAlias - let rootf = f.skipGenericAlias + let deptha = a.genericAliasDepth() + let depthf = f.genericAliasDepth() + let skipBoth = deptha == depthf and (a.len > 0 and f.len > 0 and a.base != f.base) + + let roota = if skipBoth or deptha > depthf: a.skipGenericAlias else: a + let rootf = if skipBoth or depthf > deptha: f.skipGenericAlias else: f if a.kind == tyGenericInst: if roota.base == rootf.base: diff --git a/compiler/types.nim b/compiler/types.nim index 4dc9d36f5f..f5e965df98 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1175,6 +1175,13 @@ proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool = proc isGenericAlias*(t: PType): bool = return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst +proc genericAliasDepth*(t: PType): int = + result = 0 + var it = t + while it.isGenericAlias: + it = it.lastSon + inc result + proc skipGenericAlias*(t: PType): PType = return if t.isGenericAlias: t.lastSon else: t diff --git a/tests/generics/t21742.nim b/tests/generics/t21742.nim new file mode 100644 index 0000000000..c49c8ee97c --- /dev/null +++ b/tests/generics/t21742.nim @@ -0,0 +1,10 @@ +type + Foo[T] = object + x:T + Bar[T,R] = Foo[T] + Baz = Bar[int,float] + +proc qux[T,R](x: Bar[T,R]) = discard + +var b:Baz +b.qux() \ No newline at end of file