summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-04-23 12:43:59 +0300
committerGitHub <noreply@github.com>2023-04-23 17:43:59 +0800
commit380dafcc32abed83148f5da78a2aaef608831f8a (patch)
treec39cb15fa3eb4533e6d6a2a5c140ec7ae2292dc9
parent265a340e807a44c63c31ba7ffda1f68f6f887624 (diff)
downloadNim-380dafcc32abed83148f5da78a2aaef608831f8a.tar.gz
fix iterator equality + add test for proc equality + fix sameType (#21707)
* fix iterator equality + add test also for procs

fixes #21706

* all targets

* and isNil and repr

* separate overloads, fix sameType

* more restricted sameType?

* merge overloads again??

* remove sametype change for now

* fix sameType anyway (CI failure was not related)

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
-rw-r--r--compiler/sigmatch.nim2
-rw-r--r--compiler/types.nim6
-rw-r--r--lib/system.nim2
-rw-r--r--lib/system/comparisons.nim2
-rw-r--r--lib/system/repr_v2.nim2
-rw-r--r--tests/system/tcomparisons.nim51
-rw-r--r--tests/typerel/tproctypeclass.nim13
7 files changed, 73 insertions, 5 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index ad88ed7b2..19fa0b599 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -372,7 +372,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
   of tyOwned:
     # bug #11257: the comparison system.`==`[T: proc](x, y: T) works
     # better without the 'owned' type:
-    if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass}).kind == tyProc:
+    if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass, tyOr}).kind == tyProc:
       result = t.lastSon
     else:
       result = t
diff --git a/compiler/types.nim b/compiler/types.nim
index 387429567..d2517127a 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1235,7 +1235,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     assert a[0].len == 0
     assert b.len == 1
     assert b[0].len == 0
-    result = a[0].kind == b[0].kind
+    result = a[0].kind == b[0].kind and sameFlags(a[0], b[0])
+    if result and a[0].kind == tyProc and IgnoreCC notin c.flags:
+      let ecc = a[0].flags * {tfExplicitCallConv}
+      result = ecc == b[0].flags * {tfExplicitCallConv} and
+               (ecc == {} or a[0].callConv == b[0].callConv)
   of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef,
      tyPtr, tyVar, tyLent, tySink, tyUncheckedArray, tyArray, tyProc, tyVarargs,
      tyOrdinal, tyCompositeTypeClass, tyUserTypeClass, tyUserTypeClassInst,
diff --git a/lib/system.nim b/lib/system.nim
index dcf09d604..f23242315 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1405,7 +1405,7 @@ proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
-proc isNil*[T: proc](x: T): bool {.noSideEffect, magic: "IsNil".}
+proc isNil*[T: proc | iterator {.closure.}](x: T): bool {.noSideEffect, magic: "IsNil".}
   ## Fast check whether `x` is nil. This is sometimes more efficient than
   ## `== nil`.
 
diff --git a/lib/system/comparisons.nim b/lib/system/comparisons.nim
index 36d4d06a8..9759c3c99 100644
--- a/lib/system/comparisons.nim
+++ b/lib/system/comparisons.nim
@@ -35,7 +35,7 @@ proc `==`*[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
   ## Checks that two `ref` variables refer to the same item.
 proc `==`*[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
   ## Checks that two `ptr` variables refer to the same item.
-proc `==`*[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
+proc `==`*[T: proc | iterator](x, y: T): bool {.magic: "EqProc", noSideEffect.}
   ## Checks that two `proc` variables refer to the same procedure.
 
 proc `<=`*[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}
diff --git a/lib/system/repr_v2.nim b/lib/system/repr_v2.nim
index 206b5c5f5..e9a6596fd 100644
--- a/lib/system/repr_v2.nim
+++ b/lib/system/repr_v2.nim
@@ -94,7 +94,7 @@ proc repr*(p: pointer): string =
         result[j] = HexChars[n and 0xF]
         n = n shr 4
 
-proc repr*(p: proc): string =
+proc repr*(p: proc | iterator {.closure.}): string =
   ## repr of a proc as its address
   repr(cast[ptr pointer](unsafeAddr p)[])
 
diff --git a/tests/system/tcomparisons.nim b/tests/system/tcomparisons.nim
new file mode 100644
index 000000000..a661b14a1
--- /dev/null
+++ b/tests/system/tcomparisons.nim
@@ -0,0 +1,51 @@
+discard """
+  targets: "c cpp js"
+"""
+
+template main =
+  block: # proc equality
+    var prc: proc(): int {.closure.}
+    prc = nil
+    doAssert prc == nil
+    doAssert prc.isNil
+    prc = proc(): int =
+      result = 123
+    doAssert prc != nil
+    doAssert not prc.isNil
+    doAssert prc == prc
+    let prc2 = prc
+    doAssert prc == prc2
+    doAssert prc2 != nil
+    doAssert not prc2.isNil
+    doAssert not prc.isNil
+    prc = proc(): int =
+      result = 456
+    doAssert prc != nil
+    doAssert not prc.isNil
+    doAssert prc != prc2
+  block: # iterator equality
+    when nimvm: discard # vm does not support closure iterators
+    else:
+      when not defined(js): # js also does not support closure iterators
+        var iter: iterator(): int {.closure.}
+        iter = nil
+        doAssert iter == nil
+        doAssert iter.isNil
+        iter = iterator(): int =
+          yield 123
+        doAssert iter != nil
+        doAssert not iter.isNil
+        doAssert iter == iter
+        let iter2 = iter
+        doAssert iter == iter2
+        doAssert iter2 != nil
+        doAssert not iter2.isNil
+        doAssert not iter.isNil
+        iter = iterator(): int =
+          yield 456
+        doAssert iter != nil
+        doAssert not iter.isNil
+        doAssert iter != iter2
+
+static: main()
+main()
diff --git a/tests/typerel/tproctypeclass.nim b/tests/typerel/tproctypeclass.nim
index 4df9c558b..e8fab9780 100644
--- a/tests/typerel/tproctypeclass.nim
+++ b/tests/typerel/tproctypeclass.nim
@@ -73,4 +73,17 @@ proc main =
   doAssert closureProc is proc
   takesAnyProc(closureProc)
 
+  block: # supposed to test that sameType works 
+    template ensureNotRedefine(Ty): untyped =
+      proc foo[T: Ty](x: T) = discard
+      doAssert not (compiles do:
+        proc bar[T: Ty](x: T) = discard
+        proc bar[T: Ty](x: T) = discard)
+    ensureNotRedefine proc
+    ensureNotRedefine iterator
+    ensureNotRedefine proc {.nimcall.}
+    ensureNotRedefine iterator {.nimcall.}
+    ensureNotRedefine proc {.closure.}
+    ensureNotRedefine iterator {.closure.}
+
 main()