From 535556875ef20d91addeb1b9a0d105bc77edc6d9 Mon Sep 17 00:00:00 2001 From: metagn Date: Sun, 29 Sep 2024 11:23:59 +0300 Subject: [PATCH] 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 b0e6d28782ce8c3d8e0b4a64e01f21d6f900648f) --- compiler/types.nim | 23 +++++++++++----------- tests/distinct/tcomplexaddressableconv.nim | 21 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 tests/distinct/tcomplexaddressableconv.nim diff --git a/compiler/types.nim b/compiler/types.nim index 2c40329723..27ea70f3c9 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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 diff --git a/tests/distinct/tcomplexaddressableconv.nim b/tests/distinct/tcomplexaddressableconv.nim new file mode 100644 index 0000000000..00e96bfeb7 --- /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))