This commit is contained in:
Andreas Rumpf
2016-09-01 13:01:22 +02:00
parent f6a2ff731b
commit 3a13706d7d
19 changed files with 74 additions and 31 deletions

View File

@@ -46,7 +46,8 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
case a.kind
of tyObject:
result = isPartOfAux(a.sons[0], b, marker)
if a.sons[0] != nil:
result = isPartOfAux(a.sons[0].skipTypes(skipPtrs), b, marker)
if result == arNo: result = isPartOfAux(a.n, b, marker)
of tyGenericInst, tyDistinct:
result = isPartOfAux(lastSon(a), b, marker)

View File

@@ -726,6 +726,7 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
var ty = ty
assert r != nil
while ty != nil:
ty = ty.skipTypes(skipPtrs)
assert(ty.kind in {tyTuple, tyObject})
result = lookupInRecord(ty.n, field.name)
if result != nil: break
@@ -1257,7 +1258,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
if not p.module.compileToCpp:
while t.kind == tyObject and t.sons[0] != nil:
add(r, ~".Sup")
t = skipTypes(t.sons[0], typedescInst)
t = skipTypes(t.sons[0], skipPtrs)
if isObjLackingTypeField(t):
globalError(x.info, errGenerated,
"no 'of' operator available for pure objects")
@@ -1875,7 +1876,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
if not p.module.compileToCpp:
while t.kind == tyObject and t.sons[0] != nil:
add(r, ".Sup")
t = skipTypes(t.sons[0], abstractInst)
t = skipTypes(t.sons[0], skipPtrs)
if nilCheck != nil:
linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
nilCheck, r, genTypeInfo(p.module, dest))

View File

@@ -73,7 +73,9 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i])
var x = typ.sons[i]
if x != nil: x = x.skipTypes(skipPtrs)
genTraverseProc(c, accessor.parentObj(c.p.module), x)
if typ.n != nil: genTraverseProc(c, accessor, typ.n)
of tyTuple:
let typ = getUniqueType(typ)

View File

@@ -475,11 +475,11 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
hasField = true
elif m.compileToCpp:
appcg(m, result, " : public $1 {$n",
[getTypeDescAux(m, typ.sons[0], check)])
[getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
hasField = true
else:
appcg(m, result, " {$n $1 Sup;$n",
[getTypeDescAux(m, typ.sons[0], check)])
[getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
hasField = true
else:
addf(result, " {$n", [name])
@@ -901,7 +901,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope) =
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
var t = typ.sons[0]
while t != nil:
t = t.skipTypes(abstractInst)
t = t.skipTypes(skipPtrs)
t.flags.incl tfObjHasKids
t = t.sons[0]

View File

@@ -246,7 +246,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
if not p.module.compileToCpp:
while (s.kind == tyObject) and (s.sons[0] != nil):
add(r, ".Sup")
s = skipTypes(s.sons[0], abstractInst)
s = skipTypes(s.sons[0], skipPtrs)
linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t))
of frEmbedded:
# worst case for performance:

View File

@@ -1364,7 +1364,7 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
if output.len > 0: output.add(", ")
addf(output, "m_type: $1" | "'m_type' => $#", [genTypeInfo(p, t)])
while t != nil:
createRecordVarAux(p, t.n, excludedFieldIDs, output)
createRecordVarAux(p, t.skipTypes(skipPtrs).n, excludedFieldIDs, output)
t = t.sons[0]
proc arrayTypeForElemType(typ: PType): string =

View File

@@ -76,7 +76,7 @@ proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ.sons[0] != nil):
addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0])])
[name, genTypeInfo(p, typ.sons[0].skipTypes(skipPtrs))])
proc genTupleFields(p: PProc, typ: PType): Rope =
var s: Rope = nil

View File

@@ -172,7 +172,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
if field != nil: break
t = t.sons[0]
if t == nil: break
t = t.skipTypes(abstractInst)
t = t.skipTypes(skipPtrs)
#if field == nil:
# echo "FIELD ", b
# debug deref.typ
@@ -193,7 +193,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
if result != nil: break
t = t.sons[0]
if t == nil: break
t = t.skipTypes(abstractInst)
t = t.skipTypes(skipPtrs)
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
# returns a[].b as a node

View File

@@ -203,7 +203,8 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyObject, tyDistinct:
if not considerOverloadedOp(c, t, body, x, y):
if t.sons[0] != nil: liftBodyAux(c, t.sons[0], body, x, y)
if t.sons[0] != nil:
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
if t.kind == tyObject: liftBodyObj(c, t.n, body, x, y)
of tyTuple:
liftBodyTup(c, t, body, x, y)

View File

@@ -1070,7 +1070,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = check
return result
if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], {tyGenericInst})
ty = skipTypes(ty.sons[0], skipPtrs)
# old code, not sure if it's live code:
markUsed(n.info, s)
styleCheckUse(n.info, s)
@@ -1148,7 +1148,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
f = lookupInRecordAndBuildCheck(c, n, ty.n, i, check)
if f != nil: break
if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], {tyGenericInst})
ty = skipTypes(ty.sons[0], skipPtrs)
if f != nil:
if fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend?
@@ -2108,7 +2108,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
f = lookupInRecordAndBuildCheck(c, it, t.n, id, check)
if f != nil: break
if t.sons[0] == nil: break
t = skipTypes(t.sons[0], {tyGenericInst})
t = skipTypes(t.sons[0], skipPtrs)
if f != nil and fieldVisible(c, f):
it.sons[0] = newSymNode(f)
e = fitNode(c, f.typ, e)

View File

@@ -152,7 +152,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
while t.kind == tyObject:
semForObjectFields(fc, t.n, n, stmts)
if t.sons[0] == nil: break
t = skipTypes(t.sons[0], abstractPtrs)
t = skipTypes(t.sons[0], skipPtrs)
dec(c.p.nestedLoopCounter)
# for TR macros this 'while true: ...; break' loop is pretty bad, so
# we avoid it now if we can:

View File

@@ -47,7 +47,7 @@ proc rawHandleSelf(c: PContext; owner: PSym) =
while t.kind == tyObject:
addObjFieldsToLocalScope(c, t.n)
if t.sons[0] == nil: break
t = t.sons[0].skipTypes(abstractPtrs)
t = t.sons[0].skipTypes(skipPtrs)
proc pushProcCon*(c: PContext; owner: PSym) =
rawPushProcCon(c, owner)

View File

@@ -131,7 +131,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
if field != nil: break
ty = ty.sons[0]
if ty == nil: break
ty = ty.skipTypes(abstractPtrs)
ty = ty.skipTypes(skipPtrs)
if field == nil:
localError(n.info, errGenerated, "invalid guard field: " & g.name.s)
return

View File

@@ -659,7 +659,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
if n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0])
var typ = n.sons[0].typ
if typ.kind != tyRef or typ.sons[0].kind != tyObject:
if typ.kind != tyRef or typ.lastSon.kind != tyObject:
localError(n.info, errExprCannotBeRaised)
proc addGenericParamListToScope(c: PContext, n: PNode) =

View File

@@ -661,11 +661,12 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
if n.sonsLen == 0: return newConstraint(c, tyObject)
var check = initIntSet()
var pos = 0
var base: PType = nil
var base, realBase: PType = nil
# n.sons[0] contains the pragmas (if any). We process these later...
checkSonsLen(n, 3)
if n.sons[1].kind != nkEmpty:
base = skipTypesOrNil(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs)
realBase = semTypeNode(c, n.sons[1].sons[0], nil)
base = skipTypesOrNil(realBase, skipPtrs)
if base.isNil:
localError(n.info, errIllegalRecursionInTypeX, "object")
else:
@@ -676,9 +677,10 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
if concreteBase.kind != tyError:
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
base = nil
realBase = nil
if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c)
rawAddSon(result, base)
rawAddSon(result, realBase)
if result.n.isNil:
result.n = newNodeI(nkRecList, n.info)
else:

View File

@@ -352,18 +352,28 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
else: result = isIntConv
else: result = isNone
proc isObjectSubtype(a, f: PType): int =
proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
var t = a
assert t.kind == tyObject
var depth = 0
var last = a
while t != nil and not sameObjectTypes(f, t):
assert t.kind == tyObject
t = t.sons[0]
if t == nil: break
t = skipTypes(t, {tyGenericInst})
last = t
t = skipTypes(t, skipPtrs)
inc depth
if t != nil:
if fGenericOrigin != nil and last.kind == tyGenericInst and
last.len-1 == fGenericOrigin.len:
for i in countup(1, sonsLen(fGenericOrigin) - 1):
let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
if x == nil:
put(c, fGenericOrigin.sons[i], last.sons[i])
result = depth
else:
result = -1
type
SkippedPtr = enum skippedNone, skippedRef, skippedPtr
@@ -896,7 +906,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = isEqual
# elif tfHasMeta in f.flags: result = recordRel(c, f, a)
else:
var depth = isObjectSubtype(a, f)
var depth = isObjectSubtype(c, a, f, nil)
if depth > 0:
inc(c.inheritancePenalty, depth)
result = isSubtype
@@ -1012,6 +1022,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = isGeneric
else:
let genericBody = f.sons[0]
var askip = skippedNone
var fskip = skippedNone
let aobj = x.skipToObject(askip)
let fobj = genericBody.lastSon.skipToObject(fskip)
if fobj != nil and aobj != nil and askip == fskip:
let depth = isObjectSubtype(c, aobj, fobj, f)
if depth >= 0:
c.inheritancePenalty += depth
return if depth == 0: isGeneric else: isSubtype
result = typeRel(c, genericBody, x)
if result != isNone:
# see tests/generics/tgeneric3.nim for an example that triggers this

View File

@@ -273,7 +273,7 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
while true:
suggestObject(c, t.n, outputs)
if t.sons[0] == nil: break
t = skipTypes(t.sons[0], {tyGenericInst})
t = skipTypes(t.sons[0], skipPtrs)
suggestOperations(c, n, typ, outputs)
elif typ.kind == tyTuple and typ.n != nil:
suggestSymList(c, typ.n, outputs)

View File

@@ -94,7 +94,8 @@ proc invalidGenericInst(f: PType): bool =
proc isPureObject(typ: PType): bool =
var t = typ
while t.kind == tyObject and t.sons[0] != nil: t = t.sons[0]
while t.kind == tyObject and t.sons[0] != nil:
t = t.sons[0].skipTypes(skipPtrs)
result = t.sym != nil and sfPure in t.sym.flags
proc getOrdValue(n: PNode): BiggestInt =
@@ -228,7 +229,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
if result: return
case t.kind
of tyObject:
result = searchTypeForAux(t.sons[0], predicate, marker)
if t.sons[0] != nil:
result = searchTypeForAux(t.sons[0].skipTypes(skipPtrs), predicate, marker)
if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
of tyGenericInst, tyDistinct:
result = searchTypeForAux(lastSon(t), predicate, marker)
@@ -265,7 +267,9 @@ proc analyseObjectWithTypeFieldAux(t: PType,
if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
return frEmbedded
for i in countup(0, sonsLen(t) - 1):
res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
var x = t.sons[i]
if x != nil: x = x.skipTypes(skipPtrs)
res = analyseObjectWithTypeFieldAux(x, marker)
if res == frEmbedded:
return frEmbedded
if res == frHeader: result = frHeader
@@ -1293,7 +1297,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
a = maxAlign
of tyObject:
if typ.sons[0] != nil:
result = computeSizeAux(typ.sons[0], a)
result = computeSizeAux(typ.sons[0].skipTypes(skipPtrs), a)
if result < 0: return
maxAlign = a
elif isObjectWithTypeFieldPredicate(typ):

View File

@@ -0,0 +1,13 @@
discard """
output: '''true'''
"""
# bug #4673
type
BaseObj[T] = ref object of RootObj
SomeObj = ref object of BaseObj[int]
proc doSomething[T](o: BaseObj[T]) =
echo "true"
var o = new(SomeObj)
o.doSomething() # Error: cannot instantiate: 'T'