summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-04-29 22:30:00 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-04-29 22:30:00 +0200
commite04f3195407cc99f958dd81e0a9d58fe5414e631 (patch)
tree5a39590d3d11c78b7e511d3a9253434e4ef86dca
parentc870e831c8ab53adacffa80939be70de85de7601 (diff)
downloadNim-e04f3195407cc99f958dd81e0a9d58fe5414e631.tar.gz
fixes #4084
-rw-r--r--compiler/sem.nim9
-rw-r--r--compiler/semcall.nim14
-rw-r--r--compiler/types.nim9
-rw-r--r--tests/generics/twrong_explicit_typeargs.nim16
4 files changed, 38 insertions, 10 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 97a20a4da..c29cbe384 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -65,15 +65,6 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
       #  echo "passing to safeSemExpr: ", renderTree(n)
       discard safeSemExpr(c, n)
 
-proc typeMismatch(n: PNode, formal, actual: PType) =
-  if formal.kind != tyError and actual.kind != tyError:
-    let named = typeToString(formal)
-    let desc = typeToString(formal, preferDesc)
-    let x = if named == desc: named else: named & " = " & desc
-    localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
-        typeToString(actual) & ") " &
-        `%`(msgKindToString(errButExpectedX), [x]))
-
 proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
   if arg.typ.isNil:
     localError(arg.info, errExprXHasNoType,
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 916d897c9..17dd39595 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -361,7 +361,19 @@ proc explicitGenericInstError(n: PNode): PNode =
 
 proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
   var m: TCandidate
-  initCandidate(c, m, s, n)
+  # binding has to stay 'nil' for this to work!
+  initCandidate(c, m, s, nil)
+
+  for i in 1..sonsLen(n)-1:
+    let formal = s.ast.sons[genericParamsPos].sons[i-1].typ
+    let arg = n[i].typ
+    let tm = typeRel(m, formal, arg, true)
+    if tm in {isNone, isConvertible}:
+      if formal.sonsLen > 0 and formal.sons[0].kind != tyNone:
+        typeMismatch(n, formal.sons[0], arg)
+      else:
+        typeMismatch(n, formal, arg)
+      break
   var newInst = generateInstance(c, s, m.bindings, n.info)
   markUsed(n.info, s)
   styleCheckUse(n.info, s)
diff --git a/compiler/types.nim b/compiler/types.nim
index c9cbfedb1..bada47075 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1505,3 +1505,12 @@ proc skipHiddenSubConv*(n: PNode): PNode =
       result.typ = dest
   else:
     result = n
+
+proc typeMismatch*(n: PNode, formal, actual: PType) =
+  if formal.kind != tyError and actual.kind != tyError:
+    let named = typeToString(formal)
+    let desc = typeToString(formal, preferDesc)
+    let x = if named == desc: named else: named & " = " & desc
+    localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
+        typeToString(actual) & ") " &
+        `%`(msgKindToString(errButExpectedX), [x]))
diff --git a/tests/generics/twrong_explicit_typeargs.nim b/tests/generics/twrong_explicit_typeargs.nim
new file mode 100644
index 000000000..37d5b1e38
--- /dev/null
+++ b/tests/generics/twrong_explicit_typeargs.nim
@@ -0,0 +1,16 @@
+discard """
+  errormsg: "type mismatch: got (string) but expected 'int32 or int64'"
+  line: 16
+"""
+
+# bug #4084
+type
+  Image[T] = object
+    data: seq[T]
+
+proc newImage[T: int32|int64](w, h: int): ref Image[T] =
+  new(result)
+  result.data = newSeq[T](w * h)
+
+var correct = newImage[int32](320, 200)
+var wrong = newImage[string](320, 200)