summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-07-22 16:32:56 +0200
committerAraq <rumpf_a@web.de>2015-07-22 16:32:56 +0200
commitb0b716fca73293328d4290d6407f9f3cbcdfe164 (patch)
tree06d8f84489960e8be1b66558a10c1c4c68b98093
parent862ee8d1d3f76dbbae0866f9048292a74fc07b71 (diff)
downloadNim-b0b716fca73293328d4290d6407f9f3cbcdfe164.tar.gz
fixes #3079, fixes #1146, fixes #2879
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/semexprs.nim1
-rw-r--r--compiler/semtypes.nim7
-rw-r--r--compiler/sigmatch.nim11
-rw-r--r--tests/typerel/ttypedesc_as_genericparam1.nim6
-rw-r--r--tests/typerel/ttypedesc_as_genericparam2.nim9
6 files changed, 33 insertions, 3 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 83d170e26..3a4158204 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -525,6 +525,8 @@ const
   tfOldSchoolExprStmt* = tfVarargs # for now used to distinguish \
     # 'varargs[expr]' from 'varargs[untyped]'. Eventually 'expr' will be
     # deprecated and this mess can be cleaned up.
+  tfVoid* = tfVarargs # for historical reasons we conflated 'void' with
+                      # 'empty' ('@[]' has the type 'seq[empty]').
   skError* = skUnknown
 
   # type flags that are essential for type equality:
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 886f9458d..fba64776d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -33,6 +33,7 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     if result.typ.kind == tyVar: result = newDeref(result)
   elif {efWantStmt, efAllowStmt} * flags != {}:
     result.typ = newTypeS(tyEmpty, c)
+    result.typ.flags.incl tfVoid
   else:
     localError(n.info, errExprXHasNoType,
                renderTree(result, {renderNoComments}))
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 144a41ff0..b518f0fb9 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1051,6 +1051,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     return newOrPrevType(tyError, prev, c)
   else:
     var m = newCandidate(c, t)
+    m.isNoCall = true
     matches(c, n, copyTree(n), m)
 
     if m.state != csMatch and not m.typedescMatched:
@@ -1338,7 +1339,11 @@ proc processMagicType(c: PContext, m: PSym) =
   of mTypeDesc:
     setMagicType(m, tyTypeDesc, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
-  of mVoidType: setMagicType(m, tyEmpty, 0)
+  of mVoidType:
+    setMagicType(m, tyEmpty, 0)
+    # for historical reasons we conflate 'void' with 'empty' so that '@[]'
+    # has the type 'seq[void]'.
+    m.typ.flags.incl tfVoid
   of mArray:
     setMagicType(m, tyArray, 0)
   of mOpenArray:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 540f0a04f..a44df5783 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -47,6 +47,7 @@ type
     coerceDistincts*: bool   # this is an explicit coercion that can strip away
                              # a distrinct type
     typedescMatched*: bool
+    isNoCall*: bool          # misused for generic type instantiations C[T]
     inheritancePenalty: int  # to prefer closest father object type
     errors*: CandidateErrors # additional clarifications to be displayed to the
                              # user if overload resolution fails
@@ -259,7 +260,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
     if i != sonsLen(n) - 1: add(result, ", ")
 
 proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
-proc concreteType(c: TCandidate, t: PType): PType =
+proc concreteType(c: TCandidate, t: PType; forAny=false): PType =
   case t.kind
   of tyArrayConstr:
     # make it an array
@@ -268,6 +269,12 @@ proc concreteType(c: TCandidate, t: PType): PType =
     addSonSkipIntLit(result, t.sons[1]) # XXX: semantic checking for the type?
   of tyNil:
     result = nil              # what should it be?
+  of tyEmpty:
+    if tfVoid in t.flags and not forAny: result = nil
+    else: result = t
+  of tyTypeDesc:
+    if c.isNoCall: result = t
+    else: result = nil
   of tySequence, tySet:
     if t.sons[0].kind == tyEmpty: result = nil
     else: result = t
@@ -967,7 +974,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyAnything:
     considerPreviousT:
-      var concrete = concreteType(c, a)
+      var concrete = concreteType(c, a, forAny=true)
       if concrete != nil and doBind:
         put(c.bindings, f, concrete)
       return isGeneric
diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim
new file mode 100644
index 000000000..677bf6fc8
--- /dev/null
+++ b/tests/typerel/ttypedesc_as_genericparam1.nim
@@ -0,0 +1,6 @@
+discard """
+  line: 6
+  errormsg: "type mismatch: got (typedesc[int])"
+"""
+# bug #3079, #1146
+echo repr(int)
diff --git a/tests/typerel/ttypedesc_as_genericparam2.nim b/tests/typerel/ttypedesc_as_genericparam2.nim
new file mode 100644
index 000000000..49d8eea3c
--- /dev/null
+++ b/tests/typerel/ttypedesc_as_genericparam2.nim
@@ -0,0 +1,9 @@
+discard """
+  line: 9
+  errormsg: "type mismatch: got (empty)"
+"""
+
+# bug #2879
+
+var s: seq[int]
+echo repr(s.new_seq(3))