diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-08-08 18:03:52 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-08-08 18:03:52 +0200 |
commit | 09f122f68c18876dd53576386a3c82779358812c (patch) | |
tree | fa04bb6148cf1dd9cebb61f901e9541af37c778f /compiler | |
parent | ce4d9e40fe23b08ff240e28f79eb44b89c4c7384 (diff) | |
download | Nim-09f122f68c18876dd53576386a3c82779358812c.tar.gz |
fixes #4528
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/sigmatch.nim | 67 |
1 files changed, 37 insertions, 30 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 7cde101cb..3918bb74b 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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: |