fixes #5264 (#5520); inheriting from generic object

This commit is contained in:
andri lim
2017-03-15 03:40:09 +07:00
committed by Andreas Rumpf
parent 976095c894
commit 0ff1190fe7
6 changed files with 184 additions and 2 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -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]

View File

@@ -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