diff options
-rw-r--r-- | compiler/semtypes.nim | 23 | ||||
-rw-r--r-- | tests/types/taliasassignment.nim | 50 | ||||
-rw-r--r-- | tests/types/taliasinequality.nim | 66 |
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 |