fixes #5241, fixes #5411 inherit from specialized generic typeRel problem (#5573)

This commit is contained in:
andri lim
2017-03-24 05:39:29 +07:00
committed by Andreas Rumpf
parent 0cad2896ae
commit 568c954062
2 changed files with 89 additions and 10 deletions

View File

@@ -350,6 +350,14 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
else: result = isIntConv
else: result = isNone
proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
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])
proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
var t = a
assert t.kind == tyObject
@@ -363,12 +371,7 @@ proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
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])
genericParamPut(c, last, fGenericOrigin)
result = depth
else:
result = -1
@@ -398,7 +401,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
break
if r.kind == tyObject and ptrs <= 1: result = r
proc isGenericSubtype(a, f: PType, d: var int): bool =
proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType = nil): bool =
assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
var askip = skippedNone
var fskip = skippedNone
@@ -406,14 +409,17 @@ proc isGenericSubtype(a, f: PType, d: var int): bool =
let r = f.skipToObject(fskip)
if r == nil: return false
var depth = 0
var last = a
# 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
if t == nil: break
last = t
t = t.skipToObject(askip)
inc depth
if t != nil and askip == fskip:
genericParamPut(c, last, fGenericOrigin)
d = depth
result = true
@@ -999,7 +1005,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# simply no match for now:
discard
elif x.kind == tyGenericInst and
((f.sons[0] == x.sons[0]) or isGenericSubtype(x, f, depth)) and
((f.sons[0] == x.sons[0]) or isGenericSubType(c, x, f, depth)) and
(sonsLen(x) - 1 == sonsLen(f)):
for i in countup(1, sonsLen(f) - 1):
if x.sons[i].kind == tyGenericParam:
@@ -1039,6 +1045,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else:
put(c, f.sons[i], x)
if result == isNone:
# Here object inheriting from generic/specialized generic object
# crossing path with metatypes/aliases, so we need to separate them
# by checking sym.id
let genericSubtype = isGenericSubType(c, x, f, depth, f)
if not (genericSubtype and aobj.sym.id != fobj.sym.id):
depth = -1
if depth >= 0:
c.inheritancePenalty += depth
# bug #4863: We still need to bind generic alias crap, so

View File

@@ -0,0 +1,65 @@
discard """
output: '''(peel: 0, color: 15)
(color: 15)
17
(width: 0.0, taste: nil, color: 13)
(width: 0.0, taste: nil, color: 15)
cool'''
"""
# bug #5241
type
BaseFruit[T] = object of RootObj
color: T
MidLevel[T] = object of BaseFruit[T]
Mango = object of MidLevel[int]
peel: int
Peach[X, T, Y] = object of T
width: X
taste: Y
proc setColor[T](self: var BaseFruit[T]) =
self.color = 15
proc setColor[T](self: var BaseFruit[T], c: int) =
self.color = c
var c: Mango
setColor(c)
echo c
var d: MidLevel[int]
setColor(d)
echo d
type
FooBase[T] = ref object of RootRef
v: T
BarClient = ref object of FooBase[int]
proc getColor[T](f: FooBase[T]): T = 17
var b: BarClient
echo getColor(b)
var z: Peach[float64, BaseFruit[int], string]
z.setColor(13)
echo z
z.setColor()
echo z
# bug #5411
type
Foo[T] = ref object of RootRef
v: T
Bar = ref object of Foo[int]
method m(o: RootRef) {.base.} = assert(false, "Abstract method called")
method m[T](o: Foo[T]) = echo "cool"
var v: Bar
v.new()
v.m() # Abstract method not called anymore