summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/sigmatch.nim8
-rw-r--r--tests/typerel/t4799.nim245
-rw-r--r--tests/typerel/t4799_1.nim20
-rw-r--r--tests/typerel/t4799_2.nim20
-rw-r--r--tests/typerel/t4799_3.nim20
6 files changed, 316 insertions, 1 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 4e919fc8c..20b68b0aa 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -351,7 +351,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     else:
       useStringh(p.module)
       linefmt(p, cpsStmts,
-           "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n",
+           # bug #4799, keep the memcpy for a while
+           #"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n",
+           "$1 = $2;$n",
            rdLoc(dest), rdLoc(src))
   of tySet:
     if mapType(ty) == ctArray:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 41cac2a4a..fcfdda8bb 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -2013,6 +2013,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
           if r == isGeneric:
             result.typ = getInstantiatedType(c, arg, m, base(f))
           m.baseTypeMatch = true
+        # bug #4799, varargs accepting subtype relation object
+        elif r == isSubtype:
+          inc(m.subtypeMatches)
+          if f.kind == tyTypeDesc:
+            result = arg
+          else:
+            result = implicitConv(nkHiddenSubConv, f, arg, m, c)
+          m.baseTypeMatch = true
         else:
           result = userConvMatch(c, m, base(f), a, arg)
           if result != nil: m.baseTypeMatch = true
diff --git a/tests/typerel/t4799.nim b/tests/typerel/t4799.nim
new file mode 100644
index 000000000..075893476
--- /dev/null
+++ b/tests/typerel/t4799.nim
@@ -0,0 +1,245 @@
+discard """
+  output: "OK"
+"""
+
+type
+  GRBase[T] = ref object of RootObj
+    val: T
+  GRC[T] = ref object of GRBase[T]
+  GRD[T] = ref object of GRBase[T]
+
+proc testGR[T](x: varargs[GRBase[T]]): string =
+  result = ""
+  for c in x:
+    result.add $c.val
+
+block test_t4799_1:
+  var rgv = GRBase[int](val: 3)
+  var rgc = GRC[int](val: 4)
+  var rgb = GRD[int](val: 2)
+  doAssert(testGR(rgb, rgc, rgv) == "243")
+  doAssert(testGR(rgc, rgv, rgb) == "432")
+  doAssert(testGR(rgv, rgb, rgc) == "324")
+  doAssert(testGR([rgb, rgc, rgv]) == "243")
+  doAssert(testGR([rgc, rgv, rgb]) == "432")
+  doAssert(testGR([rgv, rgb, rgc]) == "324")
+
+type
+  PRBase[T] = object of RootObj
+    val: T
+  PRC[T] = object of PRBase[T]
+  PRD[T] = object of PRBase[T]
+
+proc testPR[T](x: varargs[ptr PRBase[T]]): string =
+  result = ""
+  for c in x:
+    result.add $c.val
+
+block test_t4799_2:
+  var pgv = PRBase[int](val: 3)
+  var pgc = PRC[int](val: 4)
+  var pgb = PRD[int](val: 2)
+  doAssert(testPR(pgb.addr, pgc.addr, pgv.addr) == "243")
+  doAssert(testPR(pgc.addr, pgv.addr, pgb.addr) == "432")
+  doAssert(testPR(pgv.addr, pgb.addr, pgc.addr) == "324")
+  doAssert(testPR([pgb.addr, pgc.addr, pgv.addr]) == "243")
+  doAssert(testPR([pgc.addr, pgv.addr, pgb.addr]) == "432")
+  doAssert(testPR([pgv.addr, pgb.addr, pgc.addr]) == "324")
+
+type
+  RBase = ref object of RootObj
+    val: int
+  RC = ref object of RBase
+  RD = ref object of RBase
+
+proc testR(x: varargs[RBase]): string =
+  result = ""
+  for c in x:
+    result.add $c.val
+
+block test_t4799_3:
+  var rv = RBase(val: 3)
+  var rc = RC(val: 4)
+  var rb = RD(val: 2)
+  doAssert(testR(rb, rc, rv) == "243")
+  doAssert(testR(rc, rv, rb) == "432")
+  doAssert(testR(rv, rb, rc) == "324")
+  doAssert(testR([rb, rc, rv]) == "243")
+  doAssert(testR([rc, rv, rb]) == "432")
+  doAssert(testR([rv, rb, rc]) == "324")
+
+type
+  PBase = object of RootObj
+    val: int
+  PC = object of PBase
+  PD = object of PBase
+
+proc testP(x: varargs[ptr PBase]): string =
+  result = ""
+  for c in x:
+    result.add $c.val
+
+block test_t4799_4:
+  var pv = PBase(val: 3)
+  var pc = PC(val: 4)
+  var pb = PD(val: 2)
+  doAssert(testP(pb.addr, pc.addr, pv.addr) == "243")
+  doAssert(testP(pc.addr, pv.addr, pb.addr) == "432")
+  doAssert(testP(pv.addr, pb.addr, pc.addr) == "324")
+  doAssert(testP([pb.addr, pc.addr, pv.addr]) == "243")
+  doAssert(testP([pc.addr, pv.addr, pb.addr]) == "432")
+  doAssert(testP([pv.addr, pb.addr, pc.addr]) == "324")
+
+type
+  PSBase[T, V] = ref object of RootObj
+    val: T
+    color: V
+  PSRC[T] = ref object of PSBase[T, int]
+  PSRD[T] = ref object of PSBase[T, int]
+
+proc testPS[T, V](x: varargs[PSBase[T, V]]): string =
+  result = ""
+  for c in x:
+    result.add c.val
+    result.add $c.color
+
+block test_t4799_5:
+  var a = PSBase[string, int](val: "base", color: 1)
+  var b = PSRC[string](val: "rc", color: 2)
+  var c = PSRD[string](val: "rd", color: 3)
+
+  doAssert(testPS(a, b, c) == "base1rc2rd3")
+  doAssert(testPS(b, a, c) == "rc2base1rd3")
+  doAssert(testPS(c, b, a) == "rd3rc2base1")
+  doAssert(testPS([a, b, c]) == "base1rc2rd3")
+  doAssert(testPS([b, a, c]) == "rc2base1rd3")
+  doAssert(testPS([c, b, a]) == "rd3rc2base1")
+
+type
+  SBase[T, V] = ref object of RootObj
+    val: T
+    color: V
+  SRC = ref object of SBase[string, int]
+  SRD = ref object of SBase[string, int]
+
+proc testS[T, V](x: varargs[SBase[T, V]]): string =
+  result = ""
+  for c in x:
+    result.add c.val
+    result.add $c.color
+
+block test_t4799_6:
+  var a = SBase[string, int](val: "base", color: 1)
+  var b = SRC(val: "rc", color: 2)
+  var c = SRD(val: "rd", color: 3)
+
+  doAssert(testS(a, b, c) == "base1rc2rd3")
+  doAssert(testS(b, a, c) == "rc2base1rd3")
+  doAssert(testS(c, b, a) == "rd3rc2base1")
+  doAssert(testS([a, b, c]) == "base1rc2rd3")
+  # this is not varargs bug, but array construction bug
+  # see #7955
+  #doAssert(testS([b, c, a]) == "rc2rd3base1")
+  #doAssert(testS([c, b, a]) == "rd3rc2base1")
+
+proc test_inproc() =
+  block test_inproc_1:
+    var rgv = GRBase[int](val: 3)
+    var rgc = GRC[int](val: 4)
+    var rgb = GRD[int](val: 2)
+    doAssert(testGR(rgb, rgc, rgv) == "243")
+    doAssert(testGR(rgc, rgv, rgb) == "432")
+    doAssert(testGR(rgv, rgb, rgc) == "324")
+    doAssert(testGR([rgb, rgc, rgv]) == "243")
+    doAssert(testGR([rgc, rgv, rgb]) == "432")
+    doAssert(testGR([rgv, rgb, rgc]) == "324")
+
+  block test_inproc_2:
+    var pgv = PRBase[int](val: 3)
+    var pgc = PRC[int](val: 4)
+    var pgb = PRD[int](val: 2)
+    doAssert(testPR(pgb.addr, pgc.addr, pgv.addr) == "243")
+    doAssert(testPR(pgc.addr, pgv.addr, pgb.addr) == "432")
+    doAssert(testPR(pgv.addr, pgb.addr, pgc.addr) == "324")
+    doAssert(testPR([pgb.addr, pgc.addr, pgv.addr]) == "243")
+    doAssert(testPR([pgc.addr, pgv.addr, pgb.addr]) == "432")
+    doAssert(testPR([pgv.addr, pgb.addr, pgc.addr]) == "324")
+
+test_inproc()
+
+template reject(x) =
+  static: assert(not compiles(x))
+
+block test_t4799_7:
+  type
+    Vehicle[T] = ref object of RootObj
+      tire: T
+    Car[T] = object of Vehicle[T]
+    Bike[T] = object of Vehicle[T]
+
+  proc testVehicle[T](x: varargs[Vehicle[T]]): string {.used.} =
+    result = ""
+    for c in x:
+      result.add $c.tire
+
+  var v = Vehicle[int](tire: 3)
+  var c = Car[int](tire: 4)
+  var b = Bike[int](tire: 2)
+
+  reject:
+    echo testVehicle(b, c, v)
+
+block test_t4799_8:
+  type
+    Vehicle = ref object of RootObj
+      tire: int
+    Car = object of Vehicle
+    Bike = object of Vehicle
+
+  proc testVehicle(x: varargs[Vehicle]): string {.used.} =
+    result = ""
+    for c in x:
+      result.add $c.tire
+
+  var v = Vehicle(tire: 3)
+  var c = Car(tire: 4)
+  var b = Bike(tire: 2)
+
+  reject:
+    echo testVehicle(b, c, v)
+
+type
+  PGVehicle[T] = ptr object of RootObj
+    tire: T
+  PGCar[T] = object of PGVehicle[T]
+  PGBike[T] = object of PGVehicle[T]
+
+proc testVehicle[T](x: varargs[PGVehicle[T]]): string {.used.} =
+  result = ""
+  for c in x:
+    result.add $c.tire
+
+var pgc = PGCar[int](tire: 4)
+var pgb = PGBike[int](tire: 2)
+
+reject:
+  echo testVehicle(pgb, pgc)
+
+type
+  RVehicle = ptr object of RootObj
+    tire: int
+  RCar = object of RVehicle
+  RBike = object of RVehicle
+
+proc testVehicle(x: varargs[RVehicle]): string {.used.} =
+  result = ""
+  for c in x:
+    result.add $c.tire
+
+var rc = RCar(tire: 4)
+var rb = RBike(tire: 2)
+
+reject:
+  echo testVehicle(rb, rc)
+
+echo "OK"
diff --git a/tests/typerel/t4799_1.nim b/tests/typerel/t4799_1.nim
new file mode 100644
index 000000000..549b6bf3c
--- /dev/null
+++ b/tests/typerel/t4799_1.nim
@@ -0,0 +1,20 @@
+discard """
+  outputsub: '''ObjectAssignmentError'''
+  exitcode: "1"
+"""
+
+type
+  Vehicle[T] = object of RootObj
+    tire: T
+  Car[T] = object of Vehicle[T]
+  Bike[T] = object of Vehicle[T]
+
+proc testVehicle[T](x: varargs[Vehicle[T]]): string =
+  result = ""
+  for c in x:
+    result.add $c.tire
+
+var v = Vehicle[int](tire: 3)
+var c = Car[int](tire: 4)
+var b = Bike[int](tire: 2)
+echo testVehicle b, c, v
diff --git a/tests/typerel/t4799_2.nim b/tests/typerel/t4799_2.nim
new file mode 100644
index 000000000..cfd399a6e
--- /dev/null
+++ b/tests/typerel/t4799_2.nim
@@ -0,0 +1,20 @@
+discard """
+  outputsub: '''ObjectAssignmentError'''
+  exitcode: "1"
+"""
+
+type
+  Vehicle[T] = object of RootObj
+    tire: T
+  Car[T] = object of Vehicle[T]
+  Bike[T] = object of Vehicle[T]
+
+proc testVehicle[T](x: varargs[Vehicle[T]]): string =
+  result = ""
+  for c in x:
+    result.add $c.tire
+
+var v = Vehicle[int](tire: 3)
+var c = Car[int](tire: 4)
+var b = Bike[int](tire: 2)
+echo testVehicle([b, c, v])
\ No newline at end of file
diff --git a/tests/typerel/t4799_3.nim b/tests/typerel/t4799_3.nim
new file mode 100644
index 000000000..784eee8fc
--- /dev/null
+++ b/tests/typerel/t4799_3.nim
@@ -0,0 +1,20 @@
+discard """
+  outputsub: '''ObjectAssignmentError'''
+  exitcode: "1"
+"""
+
+type
+  Vehicle = object of RootObj
+    tire: int
+  Car = object of Vehicle
+  Bike = object of Vehicle
+
+proc testVehicle(x: varargs[Vehicle]): string =
+  result = ""
+  for c in x:
+    result.add $c.tire
+
+var v = Vehicle(tire: 3)
+var c = Car(tire: 4)
+var b = Bike(tire: 2)
+echo testVehicle([b, c, v])
\ No newline at end of file