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 <unknown>
Co-authored-by: SirOlaf <>
(cherry picked from commit 2a8c759df0)
This commit is contained in:
SirOlaf
2023-09-08 06:50:39 +02:00
committed by narimiran
parent 9ac5666271
commit 28cef86a09
3 changed files with 23 additions and 2 deletions

View File

@@ -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:

View File

@@ -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

10
tests/generics/t21742.nim Normal file
View File

@@ -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()