diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c82caf5fb2..fa6a0868b6 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -362,7 +362,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 af82c839fc..d591ce4f62 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1223,7 +1223,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 83052930a3..655d2f5a8a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1619,7 +1619,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 7122daa209..c9e4291aa5 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 6ab5f3c3f7..b54073b8c9 100644 --- a/lib/system/repr_v2.nim +++ b/lib/system/repr_v2.nim @@ -88,7 +88,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 0000000000..a661b14a15 --- /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()