mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-03 03:32:32 +00:00
Merge pull request #7550 from jangko/fix4799
fixes #4799, varargs now can accept polymorphic types
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
245
tests/typerel/t4799.nim
Normal file
245
tests/typerel/t4799.nim
Normal file
@@ -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"
|
||||
20
tests/typerel/t4799_1.nim
Normal file
20
tests/typerel/t4799_1.nim
Normal file
@@ -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
|
||||
20
tests/typerel/t4799_2.nim
Normal file
20
tests/typerel/t4799_2.nim
Normal file
@@ -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])
|
||||
20
tests/typerel/t4799_3.nim
Normal file
20
tests/typerel/t4799_3.nim
Normal file
@@ -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])
|
||||
Reference in New Issue
Block a user