summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorjcosborn <jcosborn@users.noreply.github.com>2020-08-18 01:23:19 -0500
committerGitHub <noreply@github.com>2020-08-18 08:23:19 +0200
commite194cb41a4502d3d8b5e4426fbd72e8d80513c3b (patch)
tree236cdad9cc77c9d1036b748de3a5ddca1a0e5e35
parente9df8ebcfd475a715756d24e1718a5c1455689d2 (diff)
downloadNim-e194cb41a4502d3d8b5e4426fbd72e8d80513c3b.tar.gz
fix overloading issue with generic invocation (#15135)
* fix overloading issue with generic alias

* add test for inheritance depth
-rw-r--r--compiler/sigmatch.nim15
-rw-r--r--tests/overload/toverload_various.nim60
2 files changed, 61 insertions, 14 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 786cca01f..1d648c32a 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -579,7 +579,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
     if f.isMetaType:
       # We are matching a generic proc (as proc param)
       # to another generic type appearing in the proc
-      # signature. There is a change that the target
+      # signature. There is a chance that the target
       # type is already fully-determined, so we are
       # going to try resolve it
       if c.call != nil:
@@ -1496,7 +1496,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
       #echo "inferred ", typeToString(inst), " for ", f
       return typeRel(c, inst, a)
 
-    var depth = 0
     if x.kind == tyGenericInvocation or f[0].kind != tyGenericBody:
       #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
       # simply no match for now:
@@ -1510,18 +1509,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
           # Workaround for regression #4589
           if f[i].kind != tyTypeDesc: return
       result = isGeneric
-    elif x.kind == tyGenericInst and isGenericSubtype(c, x, f, depth, f) and
-          (x.len - 1 == f.len):
-      # 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
     else:
       let genericBody = f[0]
       var askip = skippedNone
diff --git a/tests/overload/toverload_various.nim b/tests/overload/toverload_various.nim
index 96cb9a736..e8a0108e3 100644
--- a/tests/overload/toverload_various.nim
+++ b/tests/overload/toverload_various.nim
@@ -375,3 +375,63 @@ block:
   test(c)
   var d: FooBarBazX
   test(d)
+
+
+# overloading on tuples with generic alias
+block:
+  type
+    Foo[F,T] = object
+      exArgs: T
+    FooUn[F,T] = Foo[F,tuple[a:T]]
+    FooBi[F,T1,T2] = Foo[F,tuple[a:T1,b:T2]]
+
+  proc foo1[F,T](x: Foo[F,tuple[a:T]]): int = 1
+  proc foo1[F,T1,T2](x: Foo[F,tuple[a:T1,b:T2]]): int = 2
+  proc foo2[F,T](x: FooUn[F,T]): int = 1
+  proc foo2[F,T1,T2](x: FooBi[F,T1,T2]):int = 2
+
+  template bar1[F,T](x: Foo[F,tuple[a:T]]): int = 1
+  template bar1[F,T1,T2](x: Foo[F,tuple[a:T1,b:T2]]): int = 2
+  template bar2[F,T](x: FooUn[F,T]): int = 1
+  template bar2[F,T1,T2](x: FooBi[F,T1,T2]): int = 2
+
+  proc test(x: any, n: int) =
+    doAssert(foo1(x) == n)
+    doAssert(foo2(x) == n)
+    doAssert(bar1(x) == n)
+    doAssert(bar2(x) == n)
+
+  var a: Foo[int, tuple[a:int]]
+  test(a, 1)
+  var b: FooUn[int, int]
+  test(b, 1)
+  var c: Foo[int, tuple[a:int,b:int]]
+  test(c, 2)
+  var d: FooBi[int, int, int]
+  test(d, 2)
+
+
+# inheritance depth
+block:
+  type
+    Foo[T] = object of RootObj
+      x: T
+    Bar[T] = object of Foo[T]
+      y: T
+    Baz[T] = object of Bar[T]
+      z: T
+
+  template t0[T](x: Foo[T]): int = 0
+  template t0[T](x: Bar[T]): int = 1
+  proc p0[T](x: Foo[T]): int = 0
+  proc p0[T](x: Bar[T]): int = 1
+
+  var a: Foo[int]
+  var b: Bar[int]
+  var c: Baz[int]
+  doAssert(t0(a) == 0)
+  doAssert(t0(b) == 1)
+  doAssert(t0(c) == 1)
+  doAssert(p0(a) == 0)
+  doAssert(p0(b) == 1)
+  doAssert(p0(c) == 1)