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)`).

#24037 shouldn't be a dependency but the diff follows it.
  • Loading branch information
metagn authored Sep 29, 2024
1 parent 7974a22 commit b0e6d28
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
27 changes: 14 additions & 13 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1250,26 +1250,27 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
b = skipTypes(b.last, aliasSkipSet)
assert(a != nil)
assert(b != nil)
if a.kind != b.kind:
case c.cmp
of dcEq: return false
of dcEqIgnoreDistinct:
let distinctSkipSet = maybeSkipRange({tyDistinct, tyGenericInst})
a = a.skipTypes(distinctSkipSet)
b = b.skipTypes(distinctSkipSet)
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
let distinctSkipSet = maybeSkipRange({tyDistinct, tyGenericInst})
a = a.skipTypes(distinctSkipSet)
if a.kind != b.kind: return false
case c.cmp
of dcEq:
if a.kind != b.kind: return false
of dcEqIgnoreDistinct:
let distinctSkipSet = maybeSkipRange({tyDistinct, tyGenericInst})
a = a.skipTypes(distinctSkipSet)
b = b.skipTypes(distinctSkipSet)
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
let distinctSkipSet = maybeSkipRange({tyDistinct, tyGenericInst})
a = a.skipTypes(distinctSkipSet)
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 x.kind == tyGenericInst and IgnoreTupleFields notin c.flags and tyDistinct != y.kind:
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 b0e6d28

Please sign in to comment.