summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-08-08 18:03:52 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-08-08 18:03:52 +0200
commit09f122f68c18876dd53576386a3c82779358812c (patch)
treefa04bb6148cf1dd9cebb61f901e9541af37c778f /compiler
parentce4d9e40fe23b08ff240e28f79eb44b89c4c7384 (diff)
downloadNim-09f122f68c18876dd53576386a3c82779358812c.tar.gz
fixes #4528
Diffstat (limited to 'compiler')
-rw-r--r--compiler/sigmatch.nim67
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: