diff options
-rw-r--r-- | compiler/semtypes.nim | 35 | ||||
-rw-r--r-- | tests/types/tparameterizedparent0.nim | 15 | ||||
-rw-r--r-- | tests/types/tparameterizedparent1.nim | 14 | ||||
-rw-r--r-- | tests/types/tparameterizedparent2.nim | 77 | ||||
-rw-r--r-- | tests/types/tparameterizedparent3.nim | 15 | ||||
-rw-r--r-- | tests/types/tparameterizedparent4.nim | 30 |
6 files changed, 184 insertions, 2 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 7877a26a9..bffa12f33 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -622,6 +622,13 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, else: addSon(a, newSymNode(f)) styleCheckDef(f) if a.kind != nkEmpty: addSon(father, a) + of nkSym: + # this branch only valid during generic object + # with parameterized parent second check. + # There is no branch validity check here + if containsOrIncl(check, n.sym.name.id): + localError(n.info, errAttemptToRedefine, n.sym.name.s) + addSon(father, n) of nkEmpty: discard else: illFormedAst(n) @@ -673,8 +680,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = localError(n.info, errIllegalRecursionInTypeX, "object") else: var concreteBase = skipGenericInvocation(base) - if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: - addInheritedFields(c, check, pos, concreteBase) + if concreteBase.kind in {tyObject, tyGenericParam} and tfFinal notin concreteBase.flags: + if concreteBase.kind == tyObject: + addInheritedFields(c, check, pos, concreteBase) else: if concreteBase.kind != tyError: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects) @@ -1045,6 +1053,23 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType = proc semGenericParamInInvocation(c: PContext, n: PNode): PType = result = semTypeNode(c, n, nil) +proc semObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType) = + var check = initIntSet() + var realBase = t.sons[0] + var pos = 0 + var base = skipTypesOrNil(realBase, skipPtrs) + if base.isNil: + localError(n.info, errIllegalRecursionInTypeX, "object") + else: + var concreteBase = skipGenericInvocation(base) + if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: + addInheritedFields(c, check, pos, concreteBase) + else: + if concreteBase.kind != tyError: + localError(n.info, errInheritanceOnlyWithNonFinalObjects) + var newf = newNodeI(nkRecList, n.info) + semRecordNodeAux(c, t.n, check, pos, newf, t) + proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = if s.typ == nil: localError(n.info, "cannot instantiate the '$1' $2" % @@ -1107,6 +1132,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = result = instGenericContainer(c, n.info, result, allowMetaTypes = false) + # special check for generic object with + # parameterized parent + let tx = result.skipTypes(abstractPtrs) + if tx != result and tx.kind == tyObject and tx.sons[0] != nil: + semObjectTypeForInheritedGenericInst(c, n, tx) + proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType = var n = semExprWithType(c, n, {efDetermineType}) if n.typ.kind == tyTypeDesc: diff --git a/tests/types/tparameterizedparent0.nim b/tests/types/tparameterizedparent0.nim new file mode 100644 index 000000000..1b72a4e21 --- /dev/null +++ b/tests/types/tparameterizedparent0.nim @@ -0,0 +1,15 @@ +discard """ + file: "tparameterizedparent0.nim" + line: 14 + errormsg: "inheritance only works with non-final objects" +""" +# bug #5264 +type + Kapal* = enum + Besar + + Apple[T] = object of T + color: int + +var x = Apple[Kapal](color: 13) +echo x diff --git a/tests/types/tparameterizedparent1.nim b/tests/types/tparameterizedparent1.nim new file mode 100644 index 000000000..24fb9a565 --- /dev/null +++ b/tests/types/tparameterizedparent1.nim @@ -0,0 +1,14 @@ +discard """ + file: "tparameterizedparent1.nim" + line: 14 + errormsg: "inheritance only works with non-final objects" +""" +# bug #5264 +type + FruitBase = object + color: int + + Apple[T] = object of T + width: int + +var x: Apple[FruitBase] diff --git a/tests/types/tparameterizedparent2.nim b/tests/types/tparameterizedparent2.nim new file mode 100644 index 000000000..999db2ac5 --- /dev/null +++ b/tests/types/tparameterizedparent2.nim @@ -0,0 +1,77 @@ +discard """ + output: '''(width: 11, color: 13) +(width: 15, weight: 13, taste: 11, color: 14) +(width: 17, color: 16) +(width: 12.0, taste: yummy, color: 13) +(width: 0, tast_e: 0.0, kind: Smooth, skin: 1.5, color: 12)''' +""" +# bug #5264 +type + Texture = enum + Smooth + Coarse + + FruitBase = object of RootObj + color: int + + Level2Fruit = object of FruitBase + taste: int + + AppleBanana = object of Level2Fruit + weight: int + + BaseFruit[T] = object of RootObj + color: T + + Apple[T] = object of T + width: int + + Peach[X, T, Y] = object of T + width: X + taste: Y + + Lemon[T] = object of T + width: int + tast_e: float64 + case kind: Texture + of Smooth: + skin: float64 + of Coarse: + grain: int + +var x: Apple[FruitBase] +x.color = 13 +x.width = 11 +echo x + +proc setColor(self: var FruitBase, c: int) = + self.color = c + +proc setTaste[T](self: var Apple[T], c: int) = + self.taste = c + +#proc setColor[T](self: var BaseFruit[T], c: int) = +# self.color = c + +var y: Apple[AppleBanana] +y.setColor(14) +y.setTaste(11) +y.weight = 13 +y.width = 15 +echo y + +var w: Apple[BaseFruit[int]] +w.width = 17 +w.color = 16 +echo w + +var z: Peach[float64, BaseFruit[int], string] +z.width = 12 +z.taste = "yummy" +#z.setColor(13) #this trigger other bug +z.color = 13 +echo z + +var k = Lemon[FruitBase](kind: Smooth, skin: 1.5) +k.setColor(12) +echo k diff --git a/tests/types/tparameterizedparent3.nim b/tests/types/tparameterizedparent3.nim new file mode 100644 index 000000000..3fc83cb4d --- /dev/null +++ b/tests/types/tparameterizedparent3.nim @@ -0,0 +1,15 @@ +discard """ + file: "tparameterizedparent3.nim" + line: 13 + errormsg: "redefinition of 'color'" +""" +# bug #5264 +type + FruitBase = object of RootObj + color: int + + Apple[T] = object of T + width: int + color: int + +var x: Apple[FruitBase] diff --git a/tests/types/tparameterizedparent4.nim b/tests/types/tparameterizedparent4.nim new file mode 100644 index 000000000..fa8b525c1 --- /dev/null +++ b/tests/types/tparameterizedparent4.nim @@ -0,0 +1,30 @@ +discard """ + file: "tparameterizedparent4.nim" + line: 23 + errormsg: "redefinition of 'grain'" +""" +# bug #5264 +type + Texture = enum + Smooth + Coarse + + FruitBase = object of RootObj + color: int + grain: string + + Apple[T] = object of T + width: int + tast_e: float64 + case kind: Texture + of Smooth: + skin: float64 + of Coarse: + grain: int + +proc setColor(self: var FruitBase, c: int) = + self.color = c + +var x = Apple[FruitBase](kind: Smooth, skin: 1.5) +x.setColor(14) +echo x |