This commit is contained in:
Andreas Rumpf
2016-08-08 18:03:52 +02:00
parent ce4d9e40fe
commit 09f122f68c
2 changed files with 45 additions and 30 deletions

View File

@@ -97,8 +97,8 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
c.calleeSym = nil
initIdTable(c.bindings)
proc put(t: var TIdTable, key, val: PType) {.inline.} =
idTablePut(t, key, val.skipIntLit)
proc put(c: var TCandidate, key, val: PType) {.inline.} =
idTablePut(c.bindings, key, val.skipIntLit)
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
binding: PNode, calleeScope = -1) =
@@ -130,7 +130,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
bound = makeTypeDesc(ctx, bound)
else:
bound = bound.skipTypes({tyTypeDesc})
put(c.bindings, formalTypeParam, bound)
put(c, formalTypeParam, bound)
proc newCandidate*(ctx: PContext, callee: PSym,
binding: PNode, calleeScope = -1): TCandidate =
@@ -367,15 +367,14 @@ proc isObjectSubtype(a, f: PType): int =
type
SkippedPtr = enum skippedNone, skippedRef, skippedPtr
proc skipToGenericBody(t: PType; skipped: var SkippedPtr): PType =
proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
var r = t
# we're allowed to skip one level of ptr/ref:
var ptrs = 0
while r != nil:
case r.kind
of tyGenericInst, tyGenericInvocation:
result = r.sons[0]
break
of tyGenericInvocation:
r = r.sons[0]
of tyRef:
inc ptrs
skipped = skippedRef
@@ -384,21 +383,26 @@ proc skipToGenericBody(t: PType; skipped: var SkippedPtr): PType =
inc ptrs
skipped = skippedPtr
r = r.lastSon
of tyGenericBody, tyObject:
of tyGenericBody, tyGenericInst:
r = r.lastSon
else:
break
if ptrs > 1: result = nil
if r.kind == tyObject and ptrs <= 1: result = r
proc isGenericSubtype(a, f: PType, d: var int): bool =
assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
var askip = skippedNone
var fskip = skippedNone
var t = if a.kind == tyGenericBody: a else: a.skipToGenericBody(askip)
var r = if f.kind == tyGenericBody: f else: f.skipToGenericBody(fskip)
var t = a.skipToObject(askip)
let r = f.skipToObject(fskip)
if r == nil: return false
var depth = 0
while t != nil and not sameObjectTypes(r, t) and askip == fskip:
t = t.skipToGenericBody(askip)
# XXX sameObjectType can return false here. Need to investigate
# why that is but sameObjectType does way too much work here anyway.
while t != nil and r.sym != t.sym and askip == fskip:
t = t.sons[0]
if t != nil: t = t.skipToObject(askip)
else: break
inc depth
if t != nil and askip == fskip:
d = depth
@@ -667,7 +671,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
assert(f != nil)
if f.kind == tyExpr:
if aOrig != nil: put(c.bindings, f, aOrig)
if aOrig != nil: put(c, f, aOrig)
return isGeneric
assert(aOrig != nil)
@@ -688,7 +692,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
template bindingRet(res) =
if doBind:
let bound = aOrig.skipTypes({tyRange}).skipIntLit
put(c.bindings, f, bound)
put(c, f, bound)
return res
template considerPreviousT(body: untyped) =
@@ -795,7 +799,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if fRange.kind == tyGenericParam:
var prev = PType(idTableGet(c.bindings, fRange))
if prev == nil:
put(c.bindings, fRange, a.sons[0])
put(c, fRange, a.sons[0])
fRange = a
else:
fRange = prev
@@ -813,7 +817,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# we must correct for the off-by-one discrepancy between
# ranges and static params:
replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
put(c.bindings, rangeStaticT, replacementT)
put(c, rangeStaticT, replacementT)
return isGeneric
let len = tryResolvingStaticExpr(c, fRange.n[1])
@@ -981,10 +985,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyGenericBody:
considerPreviousT:
if a.kind == tyGenericInst and a.sons[0] == f:
bindingRet isGeneric
let ff = lastSon(f)
if ff != nil: result = typeRel(c, ff, a)
var depth = 0
if a.kind == tyGenericInst and (a.sons[0] == f): #or (ff != nil and ff.kind == tyObject and isGenericSubtype(a.sons[0], ff, depth))):
c.inheritancePenalty += depth
bindingRet isGeneric
if ff != nil:
result = typeRel(c, ff, a)
of tyGenericInvocation:
var x = a.skipGenericAlias
@@ -1023,7 +1030,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
elif x.kind in {tyGenericInvocation, tyGenericParam}:
internalError("wrong instantiated type!")
else:
put(c.bindings, f.sons[i], x)
put(c, f.sons[i], x)
of tyAnd:
considerPreviousT:
@@ -1061,7 +1068,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
considerPreviousT:
var concrete = concreteType(c, a)
if concrete != nil and doBind:
put(c.bindings, f, concrete)
put(c, f, concrete)
return isGeneric
of tyBuiltInTypeClass:
@@ -1069,7 +1076,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
let targetKind = f.sons[0].kind
if targetKind == a.skipTypes({tyRange, tyGenericInst}).kind or
(targetKind in {tyProc, tyPointer} and a.kind == tyNil):
put(c.bindings, f, a)
put(c, f, a)
return isGeneric
else:
return isNone
@@ -1078,7 +1085,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric:
put(c.bindings, f, a)
put(c, f, a)
of tyCompositeTypeClass:
considerPreviousT:
@@ -1094,7 +1101,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else:
result = typeRel(c, rootf.lastSon, a)
if result != isNone:
put(c.bindings, f, a)
put(c, f, a)
result = isGeneric
of tyGenericParam:
var x = PType(idTableGet(c.bindings, f))
@@ -1128,7 +1135,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if doBind and result notin {isNone, isGeneric}:
let concrete = concreteType(c, a)
if concrete == nil: return isNone
put(c.bindings, f, concrete)
put(c, f, concrete)
else:
result = isGeneric
@@ -1142,7 +1149,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if concrete == nil:
return isNone
if doBind:
put(c.bindings, f, concrete)
put(c, f, concrete)
elif result > isGeneric:
result = isGeneric
elif a.kind == tyEmpty:
@@ -1161,7 +1168,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if result != isNone and f.n != nil:
if not exprStructuralEquivalent(f.n, aOrig.n):
result = isNone
if result != isNone: put(c.bindings, f, aOrig)
if result != isNone: put(c, f, aOrig)
else:
result = isNone
elif prev.kind == tyStatic:
@@ -1189,7 +1196,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = typeRel(c, f.base, a.base)
if result != isNone:
put(c.bindings, f, a)
put(c, f, a)
else:
if tfUnresolved in f.flags:
result = typeRel(c, prev.base, a)
@@ -1207,7 +1214,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyStmt:
if aOrig != nil and tfOldSchoolExprStmt notin f.flags:
put(c.bindings, f, aOrig)
put(c, f, aOrig)
result = isGeneric
of tyProxy:

View File

@@ -23,3 +23,11 @@ let c = ChildClass[string].new("Base", "Child")
assert c.baseMethod == "Base"
assert c.overridedMethod == "Child"
# bug #4528
type GenericBase[T] = ref object of RootObj
type GenericSubclass[T] = ref object of GenericBase[T]
proc foo[T](g: GenericBase[T]) = discard
var bar: GenericSubclass[int]
foo(bar)