From 28cef86a0911ab0addd0cc30edd5df2d1148894c 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 <> (cherry picked from commit 2a8c759df0e8a952f7cbea8539e3fb7aa234795a) --- 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 53ef54431e..2dd86d7694 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1453,8 +1453,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 41fd18bfe7..3d620b1f6f 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1184,6 +1184,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