summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorandri lim <jangko128@gmail.com>2017-03-16 14:04:36 +0700
committerAndreas Rumpf <rumpf_a@web.de>2017-03-16 08:04:36 +0100
commite99721a593cfceb43b8b0c3869d82565c03f3fae (patch)
tree7e2df46e8eaa62fe1e6ddce49436d0b81274a54a /compiler
parent19c436ab20ff1749455ef1606b0884387cb21f5e (diff)
downloadNim-e99721a593cfceb43b8b0c3869d82565c03f3fae.tar.gz
fixes #5360, fixes #5238 (#5539); fixes type alias inequality for types coming from templates/macros
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semtypes.nim23
1 files changed, 19 insertions, 4 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index cb3d24a76..e86b527d6 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1145,14 +1145,29 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
   if tx != result and tx.kind == tyObject and tx.sons[0] != nil:
     semObjectTypeForInheritedGenericInst(c, n, tx)
 
+proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType
+
 proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
   var n = semExprWithType(c, n, {efDetermineType})
   if n.typ.kind == tyTypeDesc:
     result = n.typ.base
-    # fix types constructed by macros:
-    if prev != nil and prev.sym != nil and result.sym.isNil:
-      result.sym = prev.sym
-      result.sym.typ = result
+    # fix types constructed by macros/template:
+    if prev != nil and prev.sym != nil:
+      if result.sym.isNil:
+        # Behold! you're witnessing enormous power yielded
+        # by macros. Only macros can summon unnamed types
+        # and cast spell upon AST. Here we need to give
+        # it a name taken from left hand side's node
+        result.sym = prev.sym
+        result.sym.typ = result
+      else:
+        # Less powerful routine like template do not have
+        # the ability to produce unnamed types. But still
+        # it has wild power to push a type a bit too far.
+        # So we need to hold it back using alias and prevent
+        # unnecessary new type creation
+        let alias = maybeAliasType(c, result, prev)
+        if alias != nil: result = alias
   else:
     localError(n.info, errTypeExpected, n.renderTree)
     result = errorType(c)