summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/types.nim51
-rw-r--r--tests/effects/teffects1.nim7
-rw-r--r--tests/errmsgs/t2614.nim21
-rw-r--r--tests/errmsgs/tproc_mismatch.nim21
4 files changed, 69 insertions, 31 deletions
diff --git a/compiler/types.nim b/compiler/types.nim
index cd7d11b94..0d98becda 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1572,6 +1572,7 @@ proc getProcConvMismatch*(c: ConfigRef, f, a: PType, rel = isNone): (set[ProcCon
       of isInferred: result[1] = isInferredConvertible
       of isBothMetaConvertible: result[1] = isBothMetaConvertible
       elif result[1] != isNone: result[1] = isConvertible
+      else: result[0].incl pcmDifferentCallConv
     else:
       result[1] = isNone
       result[0].incl pcmDifferentCallConv
@@ -1607,6 +1608,25 @@ proc addPragmaAndCallConvMismatch*(message: var string, formal, actual: PType, c
     expectedPragmas.setLen(max(0, expectedPragmas.len - 2)) # Remove ", "
     message.add "\n  Pragma mismatch: got '{.$1.}', but expected '{.$2.}'." % [gotPragmas, expectedPragmas]
 
+proc processPragmaAndCallConvMismatch(msg: var string, formal, actual: PType, conf: ConfigRef) =
+  if formal.kind == tyProc and actual.kind == tyProc:
+    msg.addPragmaAndCallConvMismatch(formal, actual, conf)
+    case compatibleEffects(formal, actual)
+    of efCompat: discard
+    of efRaisesDiffer:
+      msg.add "\n.raise effects differ"
+    of efRaisesUnknown:
+      msg.add "\n.raise effect is 'can raise any'"
+    of efTagsDiffer:
+      msg.add "\n.tag effects differ"
+    of efTagsUnknown:
+      msg.add "\n.tag effect is 'any tag allowed'"
+    of efLockLevelsDiffer:
+      msg.add "\nlock levels differ"
+    of efEffectsDelayed:
+      msg.add "\n.effectsOf annotations differ"
+    of efTagsIllegal:
+      msg.add "\n.notTag catched an illegal effect"
 
 proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType, n: PNode) =
   if formal.kind != tyError and actual.kind != tyError:
@@ -1626,25 +1646,18 @@ proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType, n: P
       msg.add "\n"
     msg.add " but expected '$1'" % x
     if verbose: msg.addDeclaredLoc(conf, formal)
-
-    if formal.kind == tyProc and actual.kind == tyProc:
-      msg.addPragmaAndCallConvMismatch(formal, actual, conf)
-      case compatibleEffects(formal, actual)
-      of efCompat: discard
-      of efRaisesDiffer:
-        msg.add "\n.raise effects differ"
-      of efRaisesUnknown:
-        msg.add "\n.raise effect is 'can raise any'"
-      of efTagsDiffer:
-        msg.add "\n.tag effects differ"
-      of efTagsUnknown:
-        msg.add "\n.tag effect is 'any tag allowed'"
-      of efLockLevelsDiffer:
-        msg.add "\nlock levels differ"
-      of efEffectsDelayed:
-        msg.add "\n.effectsOf annotations differ"
-      of efTagsIllegal:
-        msg.add "\n.notTag catched an illegal effect"
+    var a = formal
+    var b = actual
+    if formal.kind == tyArray and actual.kind == tyArray:
+      a = formal[1]
+      b = actual[1]
+      processPragmaAndCallConvMismatch(msg, a, b, conf)
+    elif formal.kind == tySequence and actual.kind == tySequence:
+      a = formal[0]
+      b = actual[0]
+      processPragmaAndCallConvMismatch(msg, a, b, conf)
+    else:
+      processPragmaAndCallConvMismatch(msg, a, b, conf)
     localError(conf, info, msg)
 
 proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool =
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index 3978d8cc2..ca9021999 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim check $file"
+  cmd: "nim check --hint:Conf:off --hint:XDeclaredButNotUsed:off $file"
   nimout: '''
 teffects1.nim(17, 28) template/generic instantiation from here
 '''
@@ -27,14 +27,15 @@ proc forw: int =
 type
   MyProcType* = proc(x: int): string #{.raises: [ValueError, Defect].}
 
-proc foo(x: int): string {.raises: [ValueError].} =
+proc foo(x: int): string {.nimcall, raises: [ValueError].} =
   if x > 9:
     raise newException(ValueError, "Use single digit")
   $x
 
 var p: MyProcType = foo #[tt.Error
                     ^
-type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
+type mismatch: got <proc (x: int): string{.nimcall, noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
 .raise effects differ
 ]#
 {.pop.}
diff --git a/tests/errmsgs/t2614.nim b/tests/errmsgs/t2614.nim
new file mode 100644
index 000000000..4034249e7
--- /dev/null
+++ b/tests/errmsgs/t2614.nim
@@ -0,0 +1,21 @@
+discard """
+  cmd: "nim check $options --hints:off $file"
+  errormsg: ""
+  nimout: '''
+t2614.nim(19, 27) Error: type mismatch: got <array[0..1, proc (){.locks: <unknown>.}]> but expected 'array[0..1, proc (){.closure.}]'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
+t2614.nim(21, 22) Error: type mismatch: got <seq[proc (){.locks: <unknown>.}]> but expected 'seq[proc (){.closure.}]'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
+'''
+"""
+
+proc g
+proc f =
+  if false: g()
+proc g =
+  if false: f()
+
+var a = [f, g] # This works
+var b: array[2, proc()] = [f, g] # Error
+
+var c: seq[proc()] = @[f, g] 
\ No newline at end of file
diff --git a/tests/errmsgs/tproc_mismatch.nim b/tests/errmsgs/tproc_mismatch.nim
index 4ddc7635e..f92589d96 100644
--- a/tests/errmsgs/tproc_mismatch.nim
+++ b/tests/errmsgs/tproc_mismatch.nim
@@ -3,9 +3,9 @@ discard """
   cmd: '''nim check --hints:off $options $file'''
   nimoutFull: true
   nimout: '''
-tproc_mismatch.nim(35, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}'
+tproc_mismatch.nim(38, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}'
   Calling convention mismatch: got '{.cdecl.}', but expected '{.closure.}'.
-tproc_mismatch.nim(39, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}>
+tproc_mismatch.nim(42, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}>
 but expected one of:
 proc bar(a: proc ())
   first type mismatch at position: 1
@@ -14,18 +14,21 @@ proc bar(a: proc ())
   Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'.
 
 expression: bar(fn1)
-tproc_mismatch.nim(43, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (){.closure.}'
+tproc_mismatch.nim(46, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (){.closure.}'
   Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'.
-tproc_mismatch.nim(48, 8) Error: type mismatch: got <proc (){.locks: 0.}> but expected 'proc (){.closure, noSideEffect.}'
+tproc_mismatch.nim(51, 8) Error: type mismatch: got <proc (){.locks: 0.}> but expected 'proc (){.closure, noSideEffect.}'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
   Pragma mismatch: got '{..}', but expected '{.noSideEffect.}'.
-tproc_mismatch.nim(52, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: float){.closure.}'
-tproc_mismatch.nim(61, 9) Error: type mismatch: got <proc (a: int){.locks: 0.}> but expected 'proc (a: int){.closure, gcsafe.}'
+tproc_mismatch.nim(55, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: float){.closure.}'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
+tproc_mismatch.nim(64, 9) Error: type mismatch: got <proc (a: int){.locks: 0.}> but expected 'proc (a: int){.closure, gcsafe.}'
+  Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'.
   Pragma mismatch: got '{..}', but expected '{.gcsafe.}'.
-tproc_mismatch.nim(69, 9) Error: type mismatch: got <proc (a: int): int{.nimcall.}> but expected 'proc (a: int): int{.cdecl.}'
+tproc_mismatch.nim(72, 9) Error: type mismatch: got <proc (a: int): int{.nimcall.}> but expected 'proc (a: int): int{.cdecl.}'
   Calling convention mismatch: got '{.nimcall.}', but expected '{.cdecl.}'.
-tproc_mismatch.nim(70, 9) Error: type mismatch: got <proc (a: int): int{.cdecl.}> but expected 'proc (a: int): int{.nimcall.}'
+tproc_mismatch.nim(73, 9) Error: type mismatch: got <proc (a: int): int{.cdecl.}> but expected 'proc (a: int): int{.nimcall.}'
   Calling convention mismatch: got '{.cdecl.}', but expected '{.nimcall.}'.
-tproc_mismatch.nim(74, 9) Error: type mismatch: got <proc (a: int){.closure, locks: 3.}> but expected 'proc (a: int){.closure, locks: 1.}'
+tproc_mismatch.nim(77, 9) Error: type mismatch: got <proc (a: int){.closure, locks: 3.}> but expected 'proc (a: int){.closure, locks: 1.}'
   Pragma mismatch: got '{.locks: 3.}', but expected '{.locks: 1.}'.
 lock levels differ
 '''