fixes #4673
This commit is contained in:
parent
f6a2ff731b
commit
3a13706d7d
19 changed files with 74 additions and 31 deletions
|
|
@ -46,7 +46,8 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
|
||||||
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
|
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyObject:
|
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)
|
if result == arNo: result = isPartOfAux(a.n, b, marker)
|
||||||
of tyGenericInst, tyDistinct:
|
of tyGenericInst, tyDistinct:
|
||||||
result = isPartOfAux(lastSon(a), b, marker)
|
result = isPartOfAux(lastSon(a), b, marker)
|
||||||
|
|
|
||||||
|
|
@ -726,6 +726,7 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
||||||
var ty = ty
|
var ty = ty
|
||||||
assert r != nil
|
assert r != nil
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
|
ty = ty.skipTypes(skipPtrs)
|
||||||
assert(ty.kind in {tyTuple, tyObject})
|
assert(ty.kind in {tyTuple, tyObject})
|
||||||
result = lookupInRecord(ty.n, field.name)
|
result = lookupInRecord(ty.n, field.name)
|
||||||
if result != nil: break
|
if result != nil: break
|
||||||
|
|
@ -1257,7 +1258,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
if not p.module.compileToCpp:
|
if not p.module.compileToCpp:
|
||||||
while t.kind == tyObject and t.sons[0] != nil:
|
while t.kind == tyObject and t.sons[0] != nil:
|
||||||
add(r, ~".Sup")
|
add(r, ~".Sup")
|
||||||
t = skipTypes(t.sons[0], typedescInst)
|
t = skipTypes(t.sons[0], skipPtrs)
|
||||||
if isObjLackingTypeField(t):
|
if isObjLackingTypeField(t):
|
||||||
globalError(x.info, errGenerated,
|
globalError(x.info, errGenerated,
|
||||||
"no 'of' operator available for pure objects")
|
"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:
|
if not p.module.compileToCpp:
|
||||||
while t.kind == tyObject and t.sons[0] != nil:
|
while t.kind == tyObject and t.sons[0] != nil:
|
||||||
add(r, ".Sup")
|
add(r, ".Sup")
|
||||||
t = skipTypes(t.sons[0], abstractInst)
|
t = skipTypes(t.sons[0], skipPtrs)
|
||||||
if nilCheck != nil:
|
if nilCheck != nil:
|
||||||
linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
|
linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
|
||||||
nilCheck, r, genTypeInfo(p.module, dest))
|
nilCheck, r, genTypeInfo(p.module, dest))
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,9 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
|
||||||
lineF(p, cpsStmts, "}$n", [])
|
lineF(p, cpsStmts, "}$n", [])
|
||||||
of tyObject:
|
of tyObject:
|
||||||
for i in countup(0, sonsLen(typ) - 1):
|
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)
|
if typ.n != nil: genTraverseProc(c, accessor, typ.n)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
let typ = getUniqueType(typ)
|
let typ = getUniqueType(typ)
|
||||||
|
|
|
||||||
|
|
@ -475,11 +475,11 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
hasField = true
|
hasField = true
|
||||||
elif m.compileToCpp:
|
elif m.compileToCpp:
|
||||||
appcg(m, result, " : public $1 {$n",
|
appcg(m, result, " : public $1 {$n",
|
||||||
[getTypeDescAux(m, typ.sons[0], check)])
|
[getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
|
||||||
hasField = true
|
hasField = true
|
||||||
else:
|
else:
|
||||||
appcg(m, result, " {$n $1 Sup;$n",
|
appcg(m, result, " {$n $1 Sup;$n",
|
||||||
[getTypeDescAux(m, typ.sons[0], check)])
|
[getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
|
||||||
hasField = true
|
hasField = true
|
||||||
else:
|
else:
|
||||||
addf(result, " {$n", [name])
|
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])
|
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
|
||||||
var t = typ.sons[0]
|
var t = typ.sons[0]
|
||||||
while t != nil:
|
while t != nil:
|
||||||
t = t.skipTypes(abstractInst)
|
t = t.skipTypes(skipPtrs)
|
||||||
t.flags.incl tfObjHasKids
|
t.flags.incl tfObjHasKids
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
|
||||||
if not p.module.compileToCpp:
|
if not p.module.compileToCpp:
|
||||||
while (s.kind == tyObject) and (s.sons[0] != nil):
|
while (s.kind == tyObject) and (s.sons[0] != nil):
|
||||||
add(r, ".Sup")
|
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))
|
linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t))
|
||||||
of frEmbedded:
|
of frEmbedded:
|
||||||
# worst case for performance:
|
# worst case for performance:
|
||||||
|
|
|
||||||
|
|
@ -1364,7 +1364,7 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
|
||||||
if output.len > 0: output.add(", ")
|
if output.len > 0: output.add(", ")
|
||||||
addf(output, "m_type: $1" | "'m_type' => $#", [genTypeInfo(p, t)])
|
addf(output, "m_type: $1" | "'m_type' => $#", [genTypeInfo(p, t)])
|
||||||
while t != nil:
|
while t != nil:
|
||||||
createRecordVarAux(p, t.n, excludedFieldIDs, output)
|
createRecordVarAux(p, t.skipTypes(skipPtrs).n, excludedFieldIDs, output)
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
|
|
||||||
proc arrayTypeForElemType(typ: PType): string =
|
proc arrayTypeForElemType(typ: PType): string =
|
||||||
|
|
|
||||||
|
|
@ -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)])
|
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
|
||||||
if (typ.kind == tyObject) and (typ.sons[0] != nil):
|
if (typ.kind == tyObject) and (typ.sons[0] != nil):
|
||||||
addf(p.g.typeInfo, "$1.base = $2;$n",
|
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 =
|
proc genTupleFields(p: PProc, typ: PType): Rope =
|
||||||
var s: Rope = nil
|
var s: Rope = nil
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
|
||||||
if field != nil: break
|
if field != nil: break
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
if t == nil: break
|
if t == nil: break
|
||||||
t = t.skipTypes(abstractInst)
|
t = t.skipTypes(skipPtrs)
|
||||||
#if field == nil:
|
#if field == nil:
|
||||||
# echo "FIELD ", b
|
# echo "FIELD ", b
|
||||||
# debug deref.typ
|
# debug deref.typ
|
||||||
|
|
@ -193,7 +193,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
|
||||||
if result != nil: break
|
if result != nil: break
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
if t == nil: break
|
if t == nil: break
|
||||||
t = t.skipTypes(abstractInst)
|
t = t.skipTypes(skipPtrs)
|
||||||
|
|
||||||
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
|
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
|
||||||
# returns a[].b as a node
|
# returns a[].b as a node
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,8 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyObject, tyDistinct:
|
of tyObject, tyDistinct:
|
||||||
if not considerOverloadedOp(c, t, body, x, y):
|
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)
|
if t.kind == tyObject: liftBodyObj(c, t.n, body, x, y)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
liftBodyTup(c, t, body, x, y)
|
liftBodyTup(c, t, body, x, y)
|
||||||
|
|
|
||||||
|
|
@ -1070,7 +1070,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
result = check
|
result = check
|
||||||
return result
|
return result
|
||||||
if ty.sons[0] == nil: break
|
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:
|
# old code, not sure if it's live code:
|
||||||
markUsed(n.info, s)
|
markUsed(n.info, s)
|
||||||
styleCheckUse(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)
|
f = lookupInRecordAndBuildCheck(c, n, ty.n, i, check)
|
||||||
if f != nil: break
|
if f != nil: break
|
||||||
if ty.sons[0] == nil: break
|
if ty.sons[0] == nil: break
|
||||||
ty = skipTypes(ty.sons[0], {tyGenericInst})
|
ty = skipTypes(ty.sons[0], skipPtrs)
|
||||||
if f != nil:
|
if f != nil:
|
||||||
if fieldVisible(c, f):
|
if fieldVisible(c, f):
|
||||||
# is the access to a public field or in the same module or in a friend?
|
# 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)
|
f = lookupInRecordAndBuildCheck(c, it, t.n, id, check)
|
||||||
if f != nil: break
|
if f != nil: break
|
||||||
if t.sons[0] == 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):
|
if f != nil and fieldVisible(c, f):
|
||||||
it.sons[0] = newSymNode(f)
|
it.sons[0] = newSymNode(f)
|
||||||
e = fitNode(c, f.typ, e)
|
e = fitNode(c, f.typ, e)
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||||
while t.kind == tyObject:
|
while t.kind == tyObject:
|
||||||
semForObjectFields(fc, t.n, n, stmts)
|
semForObjectFields(fc, t.n, n, stmts)
|
||||||
if t.sons[0] == nil: break
|
if t.sons[0] == nil: break
|
||||||
t = skipTypes(t.sons[0], abstractPtrs)
|
t = skipTypes(t.sons[0], skipPtrs)
|
||||||
dec(c.p.nestedLoopCounter)
|
dec(c.p.nestedLoopCounter)
|
||||||
# for TR macros this 'while true: ...; break' loop is pretty bad, so
|
# for TR macros this 'while true: ...; break' loop is pretty bad, so
|
||||||
# we avoid it now if we can:
|
# we avoid it now if we can:
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ proc rawHandleSelf(c: PContext; owner: PSym) =
|
||||||
while t.kind == tyObject:
|
while t.kind == tyObject:
|
||||||
addObjFieldsToLocalScope(c, t.n)
|
addObjFieldsToLocalScope(c, t.n)
|
||||||
if t.sons[0] == nil: break
|
if t.sons[0] == nil: break
|
||||||
t = t.sons[0].skipTypes(abstractPtrs)
|
t = t.sons[0].skipTypes(skipPtrs)
|
||||||
|
|
||||||
proc pushProcCon*(c: PContext; owner: PSym) =
|
proc pushProcCon*(c: PContext; owner: PSym) =
|
||||||
rawPushProcCon(c, owner)
|
rawPushProcCon(c, owner)
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
|
||||||
if field != nil: break
|
if field != nil: break
|
||||||
ty = ty.sons[0]
|
ty = ty.sons[0]
|
||||||
if ty == nil: break
|
if ty == nil: break
|
||||||
ty = ty.skipTypes(abstractPtrs)
|
ty = ty.skipTypes(skipPtrs)
|
||||||
if field == nil:
|
if field == nil:
|
||||||
localError(n.info, errGenerated, "invalid guard field: " & g.name.s)
|
localError(n.info, errGenerated, "invalid guard field: " & g.name.s)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -659,7 +659,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||||
var typ = n.sons[0].typ
|
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)
|
localError(n.info, errExprCannotBeRaised)
|
||||||
|
|
||||||
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -661,11 +661,12 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if n.sonsLen == 0: return newConstraint(c, tyObject)
|
if n.sonsLen == 0: return newConstraint(c, tyObject)
|
||||||
var check = initIntSet()
|
var check = initIntSet()
|
||||||
var pos = 0
|
var pos = 0
|
||||||
var base: PType = nil
|
var base, realBase: PType = nil
|
||||||
# n.sons[0] contains the pragmas (if any). We process these later...
|
# n.sons[0] contains the pragmas (if any). We process these later...
|
||||||
checkSonsLen(n, 3)
|
checkSonsLen(n, 3)
|
||||||
if n.sons[1].kind != nkEmpty:
|
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:
|
if base.isNil:
|
||||||
localError(n.info, errIllegalRecursionInTypeX, "object")
|
localError(n.info, errIllegalRecursionInTypeX, "object")
|
||||||
else:
|
else:
|
||||||
|
|
@ -676,9 +677,10 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if concreteBase.kind != tyError:
|
if concreteBase.kind != tyError:
|
||||||
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
||||||
base = nil
|
base = nil
|
||||||
|
realBase = nil
|
||||||
if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
|
if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
|
||||||
result = newOrPrevType(tyObject, prev, c)
|
result = newOrPrevType(tyObject, prev, c)
|
||||||
rawAddSon(result, base)
|
rawAddSon(result, realBase)
|
||||||
if result.n.isNil:
|
if result.n.isNil:
|
||||||
result.n = newNodeI(nkRecList, n.info)
|
result.n = newNodeI(nkRecList, n.info)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -352,18 +352,28 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
|
||||||
else: result = isIntConv
|
else: result = isIntConv
|
||||||
else: result = isNone
|
else: result = isNone
|
||||||
|
|
||||||
proc isObjectSubtype(a, f: PType): int =
|
proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
|
||||||
var t = a
|
var t = a
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
var depth = 0
|
var depth = 0
|
||||||
|
var last = a
|
||||||
while t != nil and not sameObjectTypes(f, t):
|
while t != nil and not sameObjectTypes(f, t):
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
if t == nil: break
|
if t == nil: break
|
||||||
t = skipTypes(t, {tyGenericInst})
|
last = t
|
||||||
|
t = skipTypes(t, skipPtrs)
|
||||||
inc depth
|
inc depth
|
||||||
if t != nil:
|
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
|
result = depth
|
||||||
|
else:
|
||||||
|
result = -1
|
||||||
|
|
||||||
type
|
type
|
||||||
SkippedPtr = enum skippedNone, skippedRef, skippedPtr
|
SkippedPtr = enum skippedNone, skippedRef, skippedPtr
|
||||||
|
|
@ -896,7 +906,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = isEqual
|
result = isEqual
|
||||||
# elif tfHasMeta in f.flags: result = recordRel(c, f, a)
|
# elif tfHasMeta in f.flags: result = recordRel(c, f, a)
|
||||||
else:
|
else:
|
||||||
var depth = isObjectSubtype(a, f)
|
var depth = isObjectSubtype(c, a, f, nil)
|
||||||
if depth > 0:
|
if depth > 0:
|
||||||
inc(c.inheritancePenalty, depth)
|
inc(c.inheritancePenalty, depth)
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
|
|
@ -1012,6 +1022,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
let genericBody = f.sons[0]
|
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)
|
result = typeRel(c, genericBody, x)
|
||||||
if result != isNone:
|
if result != isNone:
|
||||||
# see tests/generics/tgeneric3.nim for an example that triggers this
|
# see tests/generics/tgeneric3.nim for an example that triggers this
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
|
||||||
while true:
|
while true:
|
||||||
suggestObject(c, t.n, outputs)
|
suggestObject(c, t.n, outputs)
|
||||||
if t.sons[0] == nil: break
|
if t.sons[0] == nil: break
|
||||||
t = skipTypes(t.sons[0], {tyGenericInst})
|
t = skipTypes(t.sons[0], skipPtrs)
|
||||||
suggestOperations(c, n, typ, outputs)
|
suggestOperations(c, n, typ, outputs)
|
||||||
elif typ.kind == tyTuple and typ.n != nil:
|
elif typ.kind == tyTuple and typ.n != nil:
|
||||||
suggestSymList(c, typ.n, outputs)
|
suggestSymList(c, typ.n, outputs)
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,8 @@ proc invalidGenericInst(f: PType): bool =
|
||||||
|
|
||||||
proc isPureObject(typ: PType): bool =
|
proc isPureObject(typ: PType): bool =
|
||||||
var t = typ
|
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
|
result = t.sym != nil and sfPure in t.sym.flags
|
||||||
|
|
||||||
proc getOrdValue(n: PNode): BiggestInt =
|
proc getOrdValue(n: PNode): BiggestInt =
|
||||||
|
|
@ -228,7 +229,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
|
||||||
if result: return
|
if result: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyObject:
|
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)
|
if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
|
||||||
of tyGenericInst, tyDistinct:
|
of tyGenericInst, tyDistinct:
|
||||||
result = searchTypeForAux(lastSon(t), predicate, marker)
|
result = searchTypeForAux(lastSon(t), predicate, marker)
|
||||||
|
|
@ -265,7 +267,9 @@ proc analyseObjectWithTypeFieldAux(t: PType,
|
||||||
if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
|
if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
|
||||||
return frEmbedded
|
return frEmbedded
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
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:
|
if res == frEmbedded:
|
||||||
return frEmbedded
|
return frEmbedded
|
||||||
if res == frHeader: result = frHeader
|
if res == frHeader: result = frHeader
|
||||||
|
|
@ -1293,7 +1297,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
|
||||||
a = maxAlign
|
a = maxAlign
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
result = computeSizeAux(typ.sons[0], a)
|
result = computeSizeAux(typ.sons[0].skipTypes(skipPtrs), a)
|
||||||
if result < 0: return
|
if result < 0: return
|
||||||
maxAlign = a
|
maxAlign = a
|
||||||
elif isObjectWithTypeFieldPredicate(typ):
|
elif isObjectWithTypeFieldPredicate(typ):
|
||||||
|
|
|
||||||
13
tests/objects/tinherit_from_generic.nim
Normal file
13
tests/objects/tinherit_from_generic.nim
Normal 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'
|
||||||
Loading…
Add table
Add a link
Reference in a new issue