mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 21:43:33 +00:00
skip tyAlias in generic alias checks [backport:2.0] (#24417)
fixes #24415 Since #23978 (which is in 2.0), all generic types that alias to another type now insert a `tyAlias` layer in their value. However the `skipGenericAlias` etc code which `sigmatch` uses is not updated for this, so `tyAlias` is now skipped in these. The relevant code in sigmatch is:67ad1ae159/compiler/sigmatch.nim (L1668-L1673)This behavior is also suspicious IMO, not skipping a structural `tyGenericInst` alias can be useful for code like #10220, but this is currently arbitrarily decided based on "depth" and whether the alias is to another `tyGenericInst` type or not. Maybe in the future we could enforce the use of a nominal type. (cherry picked from commit45b8434c7d)
This commit is contained in:
@@ -1201,17 +1201,19 @@ proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
|
||||
if not result: return
|
||||
|
||||
proc isGenericAlias*(t: PType): bool =
|
||||
return t.kind == tyGenericInst and t.skipModifier.kind == tyGenericInst
|
||||
return t.kind == tyGenericInst and t.skipModifier.skipTypes({tyAlias}).kind == tyGenericInst
|
||||
|
||||
proc genericAliasDepth*(t: PType): int =
|
||||
result = 0
|
||||
var it = t
|
||||
var it = t.skipTypes({tyAlias})
|
||||
while it.isGenericAlias:
|
||||
it = it.skipModifier
|
||||
it = it.skipModifier.skipTypes({tyAlias})
|
||||
inc result
|
||||
|
||||
proc skipGenericAlias*(t: PType): PType =
|
||||
return if t.isGenericAlias: t.skipModifier else: t
|
||||
result = t.skipTypes({tyAlias})
|
||||
if result.isGenericAlias:
|
||||
result = result.skipModifier.skipTypes({tyAlias})
|
||||
|
||||
proc sameFlags*(a, b: PType): bool {.inline.} =
|
||||
result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
|
||||
|
||||
@@ -11,3 +11,12 @@ block: # issue #13799
|
||||
proc works2(): Y[int] = t(X[int, int])
|
||||
proc works3(): Y[int] = t(Y[int])
|
||||
proc broken(): Y[int] = s(Y[int])
|
||||
|
||||
block: # issue #24415
|
||||
type GVec2[T] = object
|
||||
x, y: T
|
||||
type Uniform[T] = T
|
||||
proc foo(v: Uniform[GVec2[float32]]): float32 =
|
||||
result = v.x
|
||||
let f = GVec2[float32](x: 1.0f, y: 2.0f)
|
||||
doAssert foo(f) == 1.0f
|
||||
|
||||
Reference in New Issue
Block a user