mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-06 04:57:49 +00:00
Merge pull request #4398 from vegansk/issue88
Fix generics inheritance issues
This commit is contained in:
@@ -363,6 +363,25 @@ proc isObjectSubtype(a, f: PType): int =
|
||||
if t != nil:
|
||||
result = depth
|
||||
|
||||
proc skipToGenericBody(t: PType): PType =
|
||||
var r = t
|
||||
while r != nil:
|
||||
if r.kind in {tyGenericInst, tyGenericInvocation}:
|
||||
return r.sons[0]
|
||||
r = if r.len > 0: r.lastSon else: nil
|
||||
|
||||
proc isGenericSubtype(a, f: PType, d: var int): bool =
|
||||
assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
|
||||
var t = if a.kind == tyGenericBody: a else: a.skipToGenericBody
|
||||
var r = if f.kind == tyGenericBody: f else: f.skipToGenericBody
|
||||
var depth = 0
|
||||
while t != nil and not sameObjectTypes(r, t):
|
||||
t = t.skipToGenericBody
|
||||
inc depth
|
||||
if t != nil:
|
||||
d = depth
|
||||
result = true
|
||||
|
||||
proc minRel(a, b: TTypeRelation): TTypeRelation =
|
||||
if a <= b: result = a
|
||||
else: result = b
|
||||
@@ -647,7 +666,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
template bindingRet(res) =
|
||||
if doBind:
|
||||
let bound = aOrig.skipTypes({tyRange}).skipIntLit
|
||||
if doBind: put(c.bindings, f, bound)
|
||||
put(c.bindings, f, bound)
|
||||
return res
|
||||
|
||||
template considerPreviousT(body: stmt) {.immediate.} =
|
||||
@@ -945,17 +964,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
|
||||
of tyGenericInvocation:
|
||||
var x = a.skipGenericAlias
|
||||
var depth = 0
|
||||
if x.kind == tyGenericInvocation or f.sons[0].kind != tyGenericBody:
|
||||
#InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
|
||||
# simply no match for now:
|
||||
discard
|
||||
elif x.kind == tyGenericInst and
|
||||
(f.sons[0] == x.sons[0]) and
|
||||
((f.sons[0] == x.sons[0]) or isGenericSubtype(x, f, depth)) and
|
||||
(sonsLen(x) - 1 == sonsLen(f)):
|
||||
for i in countup(1, sonsLen(f) - 1):
|
||||
if x.sons[i].kind == tyGenericParam:
|
||||
internalError("wrong instantiated type!")
|
||||
elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return
|
||||
c.inheritancePenalty += depth
|
||||
result = isGeneric
|
||||
else:
|
||||
let genericBody = f.sons[0]
|
||||
|
||||
25
tests/generics/t88.nim
Normal file
25
tests/generics/t88.nim
Normal file
@@ -0,0 +1,25 @@
|
||||
# Issue 88
|
||||
|
||||
type
|
||||
BaseClass[V] = object of RootObj
|
||||
b: V
|
||||
|
||||
proc new[V](t: typedesc[BaseClass], v: V): BaseClass[V] =
|
||||
BaseClass[V](b: v)
|
||||
|
||||
proc baseMethod[V](v: BaseClass[V]): V = v.b
|
||||
proc overridedMethod[V](v: BaseClass[V]): V = v.baseMethod
|
||||
|
||||
type
|
||||
ChildClass[V] = object of BaseClass[V]
|
||||
c: V
|
||||
|
||||
proc new[V](t: typedesc[ChildClass], v1, v2: V): ChildClass[V] =
|
||||
ChildClass[V](b: v1, c: v2)
|
||||
|
||||
proc overridedMethod[V](v: ChildClass[V]): V = v.c
|
||||
|
||||
let c = ChildClass[string].new("Base", "Child")
|
||||
|
||||
assert c.baseMethod == "Base"
|
||||
assert c.overridedMethod == "Child"
|
||||
Reference in New Issue
Block a user