fix logic for dcEqIgnoreDistinct in sameType (#24197)

fixes #22523

There were 2 problems with the code in `sameType` for
`dcEqIgnoreDistinct`:

1. The code that skipped `{tyDistinct, tyGenericInst}` only ran if the
given types had different kinds. This is fixed by always performing this
skip.
2. The code block below that checks if `tyGenericInst`s have different
values still ran for `dcEqIgnoreDistinct` since it checks if the given
types are generic insts, not the skipped types (and also only the 1st
given type). This is fixed by only invoking this block for `dcEq`;
`dcEqOrDistinctOf` (which is unused) also skips the first given type.
Arguably there is another issue here that `skipGenericAlias` only ever
skips 1 type.

These combined fix the issue (`T` is `GenericInst(V, 1, distinct int)`
and `D[0]` is `GenericInst(D, 0, distinct int)`).

(cherry picked from commit b0e6d28782)
This commit is contained in:
metagn
2024-09-29 11:23:59 +03:00
committed by narimiran
parent 95fa7f0f12
commit 535556875e
2 changed files with 33 additions and 11 deletions

View File

@@ -1226,16 +1226,16 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
b = skipTypes(b[^1], {tyAlias})
assert(a != nil)
assert(b != nil)
if a.kind != b.kind:
case c.cmp
of dcEq: return false
of dcEqIgnoreDistinct:
a = a.skipTypes({tyDistinct, tyGenericInst})
b = b.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
a = a.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
case c.cmp
of dcEq:
if a.kind != b.kind: return false
of dcEqIgnoreDistinct:
a = a.skipTypes({tyDistinct, tyGenericInst})
b = b.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
a = a.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
#[
The following code should not run in the case either side is an generic alias,
@@ -1243,7 +1243,8 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
objects ie `type A[T] = SomeObject`
]#
# this is required by tunique_type but makes no sense really:
if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
if c.cmp == dcEq and x.kind == tyGenericInst and
IgnoreTupleFields notin c.flags and tyDistinct != y.kind:
let
lhs = x.skipGenericAlias
rhs = y.skipGenericAlias

View File

@@ -0,0 +1,21 @@
# issue #22523
from std/typetraits import distinctBase
type
V[p: static int] = distinct int
D[p: static int] = distinct int
T = V[1]
proc f(y: var T) = discard
var a: D[0]
static:
doAssert distinctBase(T) is distinctBase(D[0])
doAssert distinctBase(T) is int
doAssert distinctBase(D[0]) is int
doAssert T(a) is T
f(cast[ptr T](addr a)[])
f(T(a))