mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-18 23:11:36 +00:00
fixes #4528
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user