summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semtypes.nim23
-rw-r--r--tests/types/taliasassignment.nim50
-rw-r--r--tests/types/taliasinequality.nim66
3 files changed, 135 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)
diff --git a/tests/types/taliasassignment.nim b/tests/types/taliasassignment.nim
new file mode 100644
index 000000000..bf4fe8520
--- /dev/null
+++ b/tests/types/taliasassignment.nim
@@ -0,0 +1,50 @@
+discard """
+  output: '''19
+(c: 0)
+(c: 13)
+@[(c: 11)]
+@[(c: 17)]'''
+"""
+# bug #5238
+
+type
+  Rgba8 = object
+    c: int
+  BlenderRgb*[ColorT] = object
+
+template getColorType*[C](x: typedesc[BlenderRgb[C]]): typedesc = C
+
+type
+  ColorT = getColorType(BlenderRgb[int])
+
+proc setColor(c: var ColorT) =
+  c = 19
+
+var n: ColorT
+n.setColor()
+echo n
+
+type
+  ColorType = getColorType(BlenderRgb[Rgba8])
+
+var x: ColorType
+echo x
+
+proc setColor(c: var ColorType) =
+  c = Rgba8(c: 13)
+
+proc setColor(c: var seq[ColorType]) =
+  c[0] = Rgba8(c: 11)
+
+proc setColorArray(c: var openArray[ColorType]) =
+  c[0] = Rgba8(c: 17)
+
+x.setColor()
+echo x
+
+var y = @[Rgba8(c:15)]
+y.setColor()
+echo y
+
+y.setColorArray()
+echo y
\ No newline at end of file
diff --git a/tests/types/taliasinequality.nim b/tests/types/taliasinequality.nim
new file mode 100644
index 000000000..c64933fa2
--- /dev/null
+++ b/tests/types/taliasinequality.nim
@@ -0,0 +1,66 @@
+discard """
+  msg: '''true
+true
+true
+true
+true
+true'''
+  output: '''true
+true
+true
+true
+true
+true
+R
+R
+R
+R'''
+"""
+
+# bug #5360
+import macros
+
+type
+  Order = enum
+    R
+  OrderAlias = Order
+
+template getOrderTypeA(): typedesc = Order
+template getOrderTypeB(): typedesc = OrderAlias
+
+type
+  OrderR    = getOrderTypeA()
+  OrderG    = getOrderTypeB()
+
+macro typeRep(a, b: typed): untyped =
+  if sameType(a, b):
+    echo "true"
+  else:
+    echo "false"
+
+template test(a, b: typedesc) =
+  when a is b:
+    echo "true"
+  else:
+    echo "false"
+
+test(OrderAlias, Order)
+test(OrderR, Order)
+test(OrderG, Order)
+
+test(OrderR, OrderG)
+test(OrderR, OrderAlias)
+test(OrderG, OrderAlias)
+
+typeRep(OrderAlias, Order)  # true
+typeRep(OrderR, Order)      # true
+typeRep(OrderG, Order)      # true
+
+typeRep(OrderR, OrderAlias) # true
+typeRep(OrderG, OrderAlias) # true
+typeRep(OrderR, OrderG)     # true
+
+echo OrderR.R      # R
+echo OrderG.R      # R
+echo OrderAlias.R  # R
+echo Order.R       # R
\ No newline at end of file