summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-05-21 01:11:43 +0200
committerAndreas Rumpf <rumpf_a@web.de>2019-05-22 07:41:16 +0200
commit90e882d55b69020b52efd891c935e942d10829ee (patch)
tree7539e199ada2ef5900d98d4cdd4a8aa167bb89a2
parent11fca968b2cb3714b55141acf39bd1691d7ae8eb (diff)
downloadNim-90e882d55b69020b52efd891c935e942d10829ee.tar.gz
fixes #11239
-rw-r--r--compiler/renderer.nim1
-rw-r--r--compiler/sigmatch.nim89
-rw-r--r--tests/generics/tgenerics_issues.nim2
-rw-r--r--tests/overload/toverload_issues.nim16
4 files changed, 55 insertions, 53 deletions
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index b51bd3162..8d3f234b7 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1517,6 +1517,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     internalError(g.config, n.info, "rnimsyn.gsub(" & $n.kind & ')')
 
 proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string =
+  if n == nil: return "<nil tree>"
   var g: TSrcGen
   initSrcGen(g, renderFlags, newPartialConfigRef())
   # do not indent the initial statement list so that
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 978ee37fa..541ef63da 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -130,6 +130,9 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
       echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old)
       if typeToString(old) == "seq[string]":
         writeStackTrace()
+    if typeToString(key) == "K":
+      echo "putting to K ", typeToString(val)
+      writeStackTrace()
   idTablePut(c.bindings, key, val.skipIntLit)
 
 proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
@@ -321,32 +324,8 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
     add(result, argTypeToString(arg, prefer))
     if i != sonsLen(n) - 1: add(result, ", ")
 
-proc typeRelImpl*(c: var TCandidate, f, aOrig: PType,
-                  flags: TTypeRelFlags = {}): TTypeRelation
-
-const traceTypeRel = false
-
-when traceTypeRel:
-  var nextTypeRel = 0
-
-template typeRel*(c: var TCandidate, f, aOrig: PType,
-                 flags: TTypeRelFlags = {}): TTypeRelation =
-  when traceTypeRel:
-    var enteringAt = nextTypeRel
-    if mdbg:
-      inc nextTypeRel
-      echo "----- TYPE REL ", enteringAt
-      debug f
-      debug aOrig
-      # writeStackTrace()
-
-  let r = typeRelImpl(c, f, aOrig, flags)
-
-  when traceTypeRel:
-    if enteringAt != nextTypeRel:
-      echo "----- TYPE REL ", enteringAt, " RESULT: ", r
-
-  r
+proc typeRel*(c: var TCandidate, f, aOrig: PType,
+              flags: TTypeRelFlags = {}): TTypeRelation
 
 proc concreteType(c: TCandidate, t: PType): PType =
   case t.kind
@@ -441,10 +420,10 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
 proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
   if fGenericOrigin != nil and last.kind == tyGenericInst and
      last.len-1 == fGenericOrigin.len:
-   for i in 1 ..< sonsLen(fGenericOrigin):
-     let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
-     if x == nil:
-       put(c, fGenericOrigin.sons[i], last.sons[i])
+    for i in 1 ..< sonsLen(fGenericOrigin):
+      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
@@ -489,7 +468,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
       break
   if r.kind == tyObject and ptrs <= 1: result = r
 
-proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType = nil): bool =
+proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin: PType): bool =
   assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody}
   var askip = skippedNone
   var fskip = skippedNone
@@ -973,8 +952,8 @@ when false:
 template skipOwned(a) =
   if a.kind == tyOwned: a = a.skipTypes({tyOwned, tyGenericInst})
 
-proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
-                 flags: TTypeRelFlags = {}): TTypeRelation =
+proc typeRel(c: var TCandidate, f, aOrig: PType,
+             flags: TTypeRelFlags = {}): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
   # 1) When used with concrete types, it will check for type equivalence
@@ -1021,7 +1000,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
 
       case f.kind
       of tyGenericParam:
-        var prev  = PType(idTableGet(c.bindings, f))
+        var prev = PType(idTableGet(c.bindings, f))
         if prev != nil: candidate = prev
       of tyFromExpr:
         let computedType = tryResolvingStaticExpr(c, f.n).typ
@@ -1413,11 +1392,15 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
       if roota.base == rootf.base:
         let nextFlags = flags + {trNoCovariance}
         var hasCovariance = false
+        const noBug {.booldefine.} = false
+        result = when noBug: isGeneric else: isEqual
+
         for i in 1 .. rootf.sonsLen-2:
           let ff = rootf.sons[i]
           let aa = roota.sons[i]
-          result = typeRel(c, ff, aa, nextFlags)
-          if result notin {isEqual, isGeneric}:
+          let res = typeRel(c, ff, aa, nextFlags)
+          if res != isEqual: result = isGeneric
+          if res notin {isEqual, isGeneric}:
             if trNoCovariance notin flags and ff.kind == aa.kind:
               let paramFlags = rootf.base.sons[i-1].flags
               hasCovariance =
@@ -1425,7 +1408,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
                   if tfWeakCovariant in paramFlags:
                     isCovariantPtr(c, ff, aa)
                   else:
-                    ff.kind notin {tyRef, tyPtr} and result == isSubtype
+                    ff.kind notin {tyRef, tyPtr} and res == isSubtype
                 else:
                   tfContravariant in paramFlags and
                     typeRel(c, aa, ff) == isSubtype
@@ -1434,7 +1417,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
 
             return isNone
         if prev == nil: put(c, f, a)
-        result = isGeneric
       else:
         let fKind = rootf.lastSon.kind
         if fKind in {tyAnd, tyOr}:
@@ -1480,6 +1462,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
        c.calleeSym != nil and
        c.calleeSym.kind in {skProc, skFunc} and c.call != nil:
       let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
+      #echo "inferred ", typeToString(inst), " for ", f
       return typeRel(c, inst, a)
 
     var depth = 0
@@ -1487,16 +1470,26 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
       #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
       # simply no match for now:
       discard
-    elif x.kind == tyGenericInst and
-          ((f.sons[0] == x.sons[0]) or isGenericSubType(c, x, f, depth)) and
+    elif x.kind == tyGenericInst and isGenericSubType(c, x, f, depth, f) and
           (sonsLen(x) - 1 == sonsLen(f)):
+      # do not recurse here in order to not K bind twice for this code:
+      #
+      # type
+      #   BaseFruit[T] = object of RootObj
+      #   Banana[T] = object of BaseFruit[uint32] # Concrete type here, not T!
+      # proc setColor[K](self: var BaseFruit[K])
+      # var x: Banana[float64]
+      # x.setColor()
+      c.inheritancePenalty += depth
+      result = isGeneric
+    elif x.kind == tyGenericInst and f.sons[0] == x.sons[0] and
+          sonsLen(x) - 1 == sonsLen(f):
       for i in 1 ..< sonsLen(f):
         if x.sons[i].kind == tyGenericParam:
           internalError(c.c.graph.config, "wrong instantiated type!")
         elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
           # Workaround for regression #4589
           if f.sons[i].kind != tyTypeDesc: return
-      c.inheritancePenalty += depth
       result = isGeneric
     else:
       let genericBody = f.sons[0]
@@ -1664,6 +1657,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
         else:
           result = isNone
       else:
+        # check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)'
         if f.sonsLen > 0 and f.sons[0].kind != tyNone:
           let oldInheritancePenalty = c.inheritancePenalty
           result = typeRel(c, f.lastSon, a, flags + {trDontBind})
@@ -1699,16 +1693,6 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
     elif x.kind == tyGenericParam:
       result = isGeneric
     else:
-      # Special type binding rule for numeric types.
-      # See section "Generic type inference for numeric types" of the
-      # manual for further details:
-      when false:
-        let rebinding = maxNumericType(x.skipTypes({tyRange}), a)
-        if rebinding != nil:
-          put(c, f, rebinding)
-          result = isGeneric
-        else:
-          discard
       result = typeRel(c, x, a) # check if it fits
       if result > isGeneric: result = isGeneric
   of tyStatic:
@@ -2075,7 +2059,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
   of isEqual:
     inc(m.exactMatches)
     result = arg
-    if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
+    if skipTypes(f, abstractVar-{tyTypeDesc}).kind == tyTuple or
+      (arg.typ != nil and skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple):
       result = implicitConv(nkHiddenSubConv, f, arg, m, c)
   of isNone:
     # do not do this in ``typeRel`` as it then can't infer T in ``ref T``:
diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim
index a1d464b97..3d5d65c75 100644
--- a/tests/generics/tgenerics_issues.nim
+++ b/tests/generics/tgenerics_issues.nim
@@ -746,7 +746,7 @@ block t5632:
 
 block t7247:
   type n8 = range[0'i8..127'i8]
-  var tab = initSet[n8]()
+  var tab = initHashSet[n8]()
   doAssert tab.contains(8) == false
 
 
diff --git a/tests/overload/toverload_issues.nim b/tests/overload/toverload_issues.nim
index fe1603a44..5db7b54fa 100644
--- a/tests/overload/toverload_issues.nim
+++ b/tests/overload/toverload_issues.nim
@@ -179,3 +179,19 @@ proc varargProc(args: varargs[AbstractObject, convert]): int =
 
 var obj = SomeObject(a: 17)
 discard varargProc(obj)
+
+
+
+# bug #11239
+
+type MySeq*[T] = object
+
+proc foo(a: seq[int]): string = "foo: seq[int]"
+proc foo[T](a: seq[T]): string = "foo: seq[T]"
+proc foo(a: MySeq[int]): string = "foo: MySeq[int]"
+proc foo[T](a: MySeq[T]): string = "foo: MySeq[T]"
+
+doAssert foo(@[1,2,3]) == "foo: seq[int]"
+doAssert foo(@["WER"]) == "foo: seq[T]"
+doAssert foo(MySeq[int]()) == "foo: MySeq[int]"
+doAssert foo(MySeq[string]()) == "foo: MySeq[T]"