Skip to content

Commit

Permalink
fix logic for dcEqIgnoreDistinct in sameType (#24197)
Browse files Browse the repository at this point in the history
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 b0e6d28)
  • Loading branch information
metagn authored and narimiran committed Dec 20, 2024
1 parent 95fa7f0 commit 5355568
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
23 changes: 12 additions & 11 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1226,24 +1226,25 @@ 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,
but it's not presently possible to distinguish the genericinsts from aliases of
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
Expand Down
21 changes: 21 additions & 0 deletions tests/distinct/tcomplexaddressableconv.nim
Original file line number Diff line number Diff line change
@@ -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))

0 comments on commit 5355568

Please sign in to comment.