summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semexprs.nim41
1 files changed, 24 insertions, 17 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index c0aaccf56..db26e385d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -2343,7 +2343,7 @@ proc checkPar(c: PContext; n: PNode): TParKind =
     for i in 0 ..< length:
       if result == paTupleFields:
         if (n.sons[i].kind != nkExprColonExpr) or
-            not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
+            n.sons[i].sons[0].kind notin {nkSym, nkIdent}:
           localError(c.config, n.sons[i].info, errNamedExprExpected)
           return paNone
       else:
@@ -2366,6 +2366,11 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       localError(c.config, n.sons[i].info, errFieldInitTwice % id.s)
     n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
                                         flags*{efAllowDestructor})
+
+    if n.sons[i].sons[1].typ.kind == tyTypeDesc:
+      localError(c.config, n.sons[i].sons[1].info, "typedesc not allowed as tuple field.")
+      n.sons[i].sons[1].typ = errorType(c)
+
     var f = newSymS(skField, n.sons[i].sons[0], c)
     f.typ = skipIntLit(n.sons[i].sons[1].typ)
     f.position = i
@@ -2384,14 +2389,6 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     addSonSkipIntLit(typ, n.sons[i].typ)
   result.typ = typ
 
-proc isTupleType(n: PNode): bool =
-  if n.len == 0:
-    return false # don't interpret () as type
-  for i in 0 ..< n.len:
-    if n[i].typ == nil or n[i].typ.kind != tyTypeDesc:
-      return false
-  return true
-
 include semobjconstr
 
 proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
@@ -2462,6 +2459,23 @@ proc semExport(c: PContext, n: PNode): PNode =
           strTableAdd(c.module.tab, s)
         s = nextOverloadIter(o, c, a)
 
+proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
+  var tupexp = semTuplePositionsConstr(c, n, flags)
+  var isTupleType: bool
+  if tupexp.len > 0: # don't interpret () as type
+    isTupleType = tupexp[0].typ.kind == tyTypeDesc
+    # check if either everything or nothing is tyTypeDesc
+    for i in 1 ..< tupexp.len:
+      if isTupleType != (tupexp[i].typ.kind == tyTypeDesc):
+        localError(c.config, tupexp[i].info, "Mixing types and values in tuples is not allowed.")
+        return(errorNode(c,n))
+  if isTupleType: # expressions as ``(int, string)`` are reinterpret as type expressions
+    result = n
+    var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
+    result.typ = makeTypeDesc(c, typ)
+  else:
+    result = tupexp
+
 proc shouldBeBracketExpr(n: PNode): bool =
   assert n.kind in nkCallKinds
   let a = n.sons[0]
@@ -2641,14 +2655,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkPar, nkTupleConstr:
     case checkPar(c, n)
     of paNone: result = errorNode(c, n)
-    of paTuplePositions:
-      var tupexp = semTuplePositionsConstr(c, n, flags)
-      if isTupleType(tupexp):
-        # reinterpret as type
-        var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
-        result.typ = makeTypeDesc(c, typ)
-      else:
-        result = tupexp
+    of paTuplePositions: result = semTupleConstr(c, n, flags)
     of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
     of paSingle: result = semExpr(c, n.sons[0], flags)
   of nkCurly: result = semSetConstr(c, n)