summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-09-29 11:23:59 +0300
committerGitHub <noreply@github.com>2024-09-29 10:23:59 +0200
commitb0e6d28782ce8c3d8e0b4a64e01f21d6f900648f (patch)
treeacc9c48b9b42049f4eba5d8eff1961943f2b8895
parent7974a2208c848440cc5188ee3f38f0432b2ee1db (diff)
downloadNim-b0e6d28782ce8c3d8e0b4a64e01f21d6f900648f.tar.gz
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)`).

#24037 shouldn't be a dependency but the diff follows it.
-rw-r--r--compiler/types.nim27
-rw-r--r--tests/distinct/tcomplexaddressableconv.nim21
2 files changed, 35 insertions, 13 deletions
diff --git a/compiler/types.nim b/compiler/types.nim
index ec310e248..a441b0ea2 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1250,18 +1250,18 @@ 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,
@@ -1269,7 +1269,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 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
diff --git a/tests/distinct/tcomplexaddressableconv.nim b/tests/distinct/tcomplexaddressableconv.nim
new file mode 100644
index 000000000..00e96bfeb
--- /dev/null
+++ b/tests/distinct/tcomplexaddressableconv.nim
@@ -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))