diff options
author | Miran <narimiran@users.noreply.github.com> | 2018-10-29 17:07:27 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-10-29 17:07:27 +0100 |
commit | 1b17c9f693754b69b249ca604533dccb2a421fab (patch) | |
tree | c9aa286cc1beab61c60da1ee3b52c01f59acd7d3 /tests/generics/tgenerics_issues.nim | |
parent | 8d9866a6d46acfd17e273c1906c705c7d96a4b73 (diff) | |
download | Nim-1b17c9f693754b69b249ca604533dccb2a421fab.tar.gz |
More descriptive names of test files (#9531)
* change generic `tissues` name to more specific * change `tvarious` to more specific names
Diffstat (limited to 'tests/generics/tgenerics_issues.nim')
-rw-r--r-- | tests/generics/tgenerics_issues.nim | 773 |
1 files changed, 773 insertions, 0 deletions
diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim new file mode 100644 index 000000000..c215ea2c2 --- /dev/null +++ b/tests/generics/tgenerics_issues.nim @@ -0,0 +1,773 @@ +discard """ + output: ''' +4 +3 +(weight: 17.0, color: 100) +perm: 22 det: 22 +TMatrix[3, 3, system.int] +3 +@[0.9, 0.1] +U[3] +U[(f: 3)] +U[[3]] +b() +@[1, 2] +@[3, 4] +1 +concrete 88 +123 +1 +2 +3 +!!Hi!! +G:0,1:0.1 +G:0,1:0.1 +H:1:0.1 +''' +""" + + +import macros, sequtils, sets, sugar, tables, typetraits + + +block t88: + type + BaseClass[V] = object of RootObj + b: V + + proc new[V](t: typedesc[BaseClass], v: V): BaseClass[V] = + BaseClass[V](b: v) + + proc baseMethod[V](v: BaseClass[V]): V = v.b + proc overriddenMethod[V](v: BaseClass[V]): V = v.baseMethod + + type + ChildClass[V] = object of BaseClass[V] + c: V + + proc new[V](t: typedesc[ChildClass], v1, v2: V): ChildClass[V] = + ChildClass[V](b: v1, c: v2) + + proc overriddenMethod[V](v: ChildClass[V]): V = v.c + + let c = ChildClass[string].new("Base", "Child") + + assert c.baseMethod == "Base" + assert c.overriddenMethod == "Child" + + + +block t4528: + type GenericBase[T] = ref object of RootObj + type GenericSubclass[T] = ref object of GenericBase[T] + proc foo[T](g: GenericBase[T]) = discard + var bar: GenericSubclass[int] + foo(bar) + + + +block t1050_5597: + type ArrayType[T] = distinct T + + proc arrayItem(a: ArrayType): auto = + static: echo(name(type(a).T)) + result = (type(a).T)(4) + + var arr: ArrayType[int] + echo arrayItem(arr) + + # bug #5597 + + template fail() = "what" + + proc g[T](x: var T) = + x.fail = 3 + + type + Obj = object + fail: int + + var y: Obj + g y + + + +block t1789: + type + Foo[N: static[int]] = object + + proc bindStaticN[N](foo: Foo[N]) = + var ar0: array[3, int] + var ar1: array[N, int] + var ar2: array[1..N, int] + var ar3: array[0..(N+10), float] + echo N + + var f: Foo[3] + f.bindStaticN + + # case 2 + + type + ObjectWithStatic[X, Y: static[int], T] = object + bar: array[X * Y, T] # this one works + + AliasWithStatic[X, Y: static[int], T] = array[X * Y, T] + + var + x: ObjectWithStatic[1, 2, int] + y: AliasWithStatic[2, 3, int] + + # case 3 + + type + Bar[N: static[int], T] = object + bar: array[N, T] + + proc `[]`[N, T](f: Bar[N, T], n: range[0..(N - 1)]): T = + assert high(n) == N-1 + result = f.bar[n] + + var b: Bar[3, int] + doAssert b[2] == 0 + + + +block t3977: + type Foo[N: static[int]] = object + + proc foo[N](x: Foo[N]) = + let n = N + doAssert N == n + + var f1: Foo[42] + f1.foo + + + +block t5570: + type + BaseFruit[T] = object of RootObj + color: T + + Banana[T] = object of BaseFruit[uint32] + weight: T + + macro printTypeName(typ: typed): untyped = + echo "type ", getType(typ).repr + + proc setColor[K](self: var BaseFruit[K], c: int) = + printTypeName(self.color) + self.color = uint32(c) + + var x: Banana[float64] + x.weight = 17 + printTypeName(x.color) + x.setColor(100) + echo x + + + +block t5643: + type + Matrix[M, N: static[int], T: SomeFloat] = object + data: ref array[N * M, T] + Matrix64[M, N: static[int]] = Matrix[M, N, float64] + + proc zeros64(M,N: static[int]): Matrix64[M,N] = + new result.data + for i in 0 ..< (M * N): + result.data[i] = 0'f64 + + proc bar[M,N: static[int], T](a: Matrix[M,N,T], b: Matrix[M,N,T]) = + discard + + let a = zeros64(2,2) + bar(a,a) + # https://github.com/nim-lang/Nim/issues/5643 + # + # The test case was failing here, because the compiler failed to + # detect the two matrix instantiations as the same type. + # + # The root cause was that the `T` type variable is a different + # type after the first Matrix type has been matched. + # + # Sigmatch was failing to match the second version of `T`, but + # due to some complex interplay between tyOr, tyTypeDesc and + # tyGenericParam this was allowed to went through. The generic + # instantiation of the second matrix was incomplete and the + # generic cache lookup failed, producing two separate types. + + + +block t5683: + type Matrix[M,N: static[int]] = array[M, array[N, float]] + + proc det[M,N](a: Matrix[M,N]): int = N*10 + M + proc perm[M,N](a: Matrix[M,N]): int = M*10 + N + + const + a = [ [1.0, 2.0] + , [3.0, 4.0] + ] + + echo "perm: ", a.perm, " det: ", a.det + + # This tests multiple instantiations of a generic + # proc involving static params: + type + Vector64[N: static[int]] = ref array[N, float64] + Array64[N: static[int]] = array[N, float64] + + proc vector[N: static[int]](xs: Array64[N]): Vector64[N] = + new result + for i in 0 ..< N: + result[i] = xs[i] + + let v1 = vector([1.0, 2.0, 3.0, 4.0, 5.0]) + let v2 = vector([1.0, 2.0, 3.0, 4.0, 5.0]) + let v3 = vector([1.0, 2.0, 3.0, 4.0]) + + + +block t7794: + type + Data[T:SomeNumber, U:SomeFloat] = ref object + x: T + value*: U + + var d = Data[int, float64](x:10.int, value:2'f64) + doAssert d.x == 10 + doAssert d.value == 2.0 + + + +block t8403: + proc sum[T](s: seq[T], R: typedesc): R = + var sum: R = 0 + for x in s: + sum += R(x) + return sum + + doAssert @[1, 2, 3].sum(float) == 6.0 + + + +block t8439: + type + Cardinal = enum + north, east, south, west + + proc foo[cardinal: static[Cardinal]](): int = 1 + doAssert foo[north]() == 1 + + + +block t8694: + when true: + # Error: undeclared identifier: '|' + proc bar[T](t:T): bool = + runnableExamples: + type Foo = int | float + true + doAssert bar(0) + + when true: + # ok + proc bar(t:int): bool = + runnableExamples: + type Foo = int | float + true + doAssert bar(0) + + when true: + # Error: undeclared identifier: '|' + proc bar(t:typedesc): bool = + runnableExamples: + type Foo = int | float + true + doAssert bar(int) + + + +block t9130: + when true: + # stack overflow + template baz1(iter: untyped): untyped = + runnableExamples: + import sugar + proc fun(a: proc(x:int): int) = discard + baz1(fun(x:int => x)) + discard + + proc foo1[A](ts: A) = + baz1(ts) + + when true: + # ok + template baz2(iter: untyped): untyped = + runnableExamples: + import sugar + proc fun(a: proc(x:int): int) = discard + baz2(fun(x:int => x)) + discard + + proc foo2(ts: int) = + baz2(ts) + + when true: + # stack overflow + template baz3(iter: untyped): untyped = + runnableExamples: + baz3(fun(x:int => x)) + discard + + proc foo3[A](ts: A) = + baz3(ts) + + + +block t1056: + type + TMatrix[N,M: static[int], T] = object + data: array[0..N*M-1, T] + + TMat2[T] = TMatrix[2,2,T] + + proc echoMatrix(a: TMatrix) = + echo a.type.name + echo TMatrix.N + + proc echoMat2(a: TMat2) = + echo TMat2.M + + var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9]) + + echoMatrix m + + + +block t4884: + type + Vec[N: static[int], T] = object + arr*: array[N, T] + + Mat[N,M: static[int], T] = object + arr: array[N, Vec[M,T]] + + var m : Mat[3,3,float] + var strMat : Mat[m.N, m.M, string] + var lenMat : Mat[m.N, m.M, int] + + + +block t2221: + var tblo: TableRef[string, int] + doAssert tblo == nil + + + +block t2304: + type TV2[T:SomeNumber] = array[0..1, T] + proc newV2T[T](x, y: T=0): TV2[T] = [x, y] + + let x = newV2T[float](0.9, 0.1) + echo(@x) + + + +block t2752: + proc myFilter[T](it: (iterator(): T), f: (proc(anything: T):bool)): (iterator(): T) = + iterator aNameWhichWillConflict(): T {.closure.}= + for x in it(): + if f(x): + yield x + result = aNameWhichWillConflict + + iterator testIt():int {.closure.}= + yield -1 + yield 2 + + #let unusedVariable = myFilter(testIt, (x: int) => x > 0) + + proc onlyPos(it: (iterator(): int)): (iterator(): int)= + iterator aNameWhichWillConflict(): int {.closure.}= + var filtered = onlyPos(myFilter(it, (x:int) => x > 0)) + for x in filtered(): + yield x + result = aNameWhichWillConflict + + let x = onlyPos(testIt) + + + +block t5106: + block: + type T = distinct int + + proc `+`(a, b: T): T = + T(int(a) + int(b)) + + type U[F: static[T]] = distinct int + + proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] = + U[P1 + P2](int(a) + int(b)) + + var a = U[T(1)](1) + var b = U[T(2)](2) + var c = a + b + echo c.type.name + + block: + type T = object + f: int + + proc `+`(a, b: T): T = + T(f: a.f + b.f) + + type U[F: static[T]] = distinct int + + proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] = + U[P1 + P2](int(a) + int(b)) + + var a = U[T(f: 1)](1) + var b = U[T(f: 2)](2) + var c = a + b + echo c.type.name + + block: + type T = distinct array[0..0, int] + + proc `+`(a, b: T): T = + T([array[0..0, int](a)[0] + array[0..0, int](b)[0]]) + + type U[F: static[T]] = distinct int + + proc `+`[P1, P2: static[T]](a: U[P1], b: U[P2]): U[P1 + P2] = + U[P1 + P2](int(a) + int(b)) + + var a = U[T([1])](1) + var b = U[T([2])](2) + var c = a + b + echo c.type.name + + + +block t3055: + proc b(t: int | string) + proc a(t: int) = b(t) + proc b(t: int | string) = echo "b()" + a(1) + + # test recursive generics still work: + proc fac[T](x: T): T = + if x == 0: return 1 + else: return fac(x-1)*x + + doAssert fac(6) == 720 + doAssert fac(5.0) == 120.0 + + + # test recursive generic with forwarding: + proc fac2[T](x: T): T + + doAssert fac2(6) == 720 + doAssert fac2(5.0) == 120.0 + + proc fac2[T](x: T): T = + if x == 0: return 1 + else: return fac2(x-1)*x + + + +block t1187: + type + TEventArgs = object + skip: bool + TEventHandler[T] = proc (e: var TEventArgs, data: T) {.closure.} + TEvent[T] = object + #handlers: seq[TEventHandler[T]] # Does not work + handlers: seq[proc (e: var TEventArgs, d: T) {.closure.}] # works + + TData = object + x: int + + TSomething = object + s: TEvent[TData] + + proc init[T](e: var TEvent[T]) = + e.handlers.newSeq(0) + + #proc add*[T](e: var TEvent[T], h: proc (e: var TEventArgs, data: T) {.closure.}) = + # this line works + proc add[T](e: var TEvent[T], h: TEventHandler[T]) = + # this line does not work + e.handlers.add(h) + + proc main () = + var something: TSomething + something.s.init() + var fromOutside = 4711 + + something.s.add() do (e: var TEventArgs, data: TData): + var x = data.x + x = fromOutside + + main() + + + +block t1919: + type + Base[M] = object of RootObj + a : M + Sub1[M] = object of Base[M] + b : int + Sub2[M] = object of Sub1[M] + c : int + + var x: Sub2[float] + doAssert x.a == 0.0 + + + +block t5756: + type + Vec[N : static[int]] = object + x: int + arr: array[N, int32] + + Mat[M,N: static[int]] = object + x: int + arr: array[M, Vec[N]] + + proc vec2(x,y:int32) : Vec[2] = + result.arr = [x,y] + result.x = 10 + + proc mat2(a,b: Vec[2]): Mat[2,2] = + result.arr = [a,b] + result.x = 20 + + const M = mat2(vec2(1, 2), vec2(3, 4)) + + let m1 = M + echo @(m1.arr[0].arr) + echo @(m1.arr[1].arr) + + proc foo = + let m2 = M + echo m1.arr[0].arr[0] + + foo() + + + +block t7854: + type + Stream = ref StreamObj + StreamObj = object of RootObj + + InhStream = ref InhStreamObj + InhStreamObj = object of Stream + f: string + + proc newInhStream(f: string): InhStream = + new(result) + result.f = f + + var val: int + let str = newInhStream("input_file.json") + + block: + # works: + proc load[T](data: var T, s: Stream) = + discard + load(val, str) + + block: + # works + proc load[T](s: Stream, data: T) = + discard + load(str, val) + + block: + # broken + proc load[T](s: Stream, data: var T) = + discard + load(str, val) + + + +block t5864: + proc defaultStatic(s: openarray, N: static[int] = 1): int = N + proc defaultGeneric[T](a: T = 2): int = a + + let a = [1, 2, 3, 4].defaultStatic() + let b = defaultGeneric() + + doAssert a == 1 + doAssert b == 2 + + + +block t3498: + template defaultOf[T](t: T): untyped = (var d: T; d) + + doAssert defaultOf(1) == 0 + + # assignment using template + + template tassign[T](x: var seq[T]) = + x = @[1, 2, 3] + + var y: seq[int] + tassign(y) #<- x is expected = @[1, 2, 3] + tassign(y) + + doAssert y[0] == 1 + doAssert y[1] == 2 + doAssert y[2] == 3 + + + +block t3499: + proc foo[T](x: proc(): T) = + echo "generic ", x() + + proc foo(x: proc(): int) = + echo "concrete ", x() + + # note the following 'proc' is not .closure! + foo(proc (): auto {.nimcall.} = 88) + + # bug #3499 last snippet fixed + # bug 705 last snippet fixed + + + + +block t797: + proc foo[T](s:T):string = $s + + type IntStringProc = proc(x: int): string + + var f1 = IntStringProc(foo) + var f2: proc(x: int): string = foo + var f3: IntStringProc = foo + + echo f1(1), f2(2), f3(3) + + for x in map([1,2,3], foo): echo x + + + +block t4658: + var x = 123 + proc twice[T](f: T -> T): T -> T = (x: T) => f(f(x)) + proc quote(s: string): string = "!" & s & "!" + echo twice(quote)("Hi") + + + +block t4589: + type SimpleTable[TKey, TVal] = TableRef[TKey, TVal] + template newSimpleTable(TKey, TVal: typedesc): SimpleTable[TKey, TVal] = newTable[TKey, TVal]() + var fontCache : SimpleTable[string, SimpleTable[int32, int]] + fontCache = newSimpleTable(string, SimpleTable[int32, int]) + + + +block t4600: + template foo(x: untyped): untyped = echo 1 + template foo(x,y: untyped): untyped = echo 2 + + proc bar1[T](x: T) = foo(x) + proc bar2(x: float) = foo(x,x) + proc bar3[T](x: T) = foo(x,x) + + + +block t4672: + type + EnumContainer[T: enum] = object + v: T + SomeEnum {.pure.} = enum + A,B,C + + proc value[T: enum](this: EnumContainer[T]): T = + this.v + + var enumContainer: EnumContainer[SomeEnum] + discard enumContainer.value() + + + +block t4863: + type + G[i,j: static[int]] = object + v:float + H[j: static[int]] = G[0,j] + proc p[i,j: static[int]](x:G[i,j]) = echo "G:", i, ",", j, ":", x.v + proc q[j: static[int]](x:H[j]) = echo "H:", j, ":", x.v + + var + g0 = G[0,1](v: 0.1) + h0:H[1] = g0 + p(g0) + p(h0) + q(h0) + + + +block t1684: + type + BaseType {.inheritable pure.} = object + idx: int + + DerivedType {.final pure.} = object of BaseType + + proc index[Toohoo: BaseType](h: Toohoo): int {.inline.} = h.idx + proc newDerived(idx: int): DerivedType {.inline.} = DerivedType(idx: idx) + + let d = newDerived(2) + assert(d.index == 2) + + + +block t5632: + type Option[T] = object + + proc point[A](v: A, t: typedesc[Option[A]]): Option[A] = + discard + + discard point(1, Option) + + + +block t7247: + type n8 = range[0'i8..127'i8] + var tab = initSet[n8]() + doAssert tab.contains(8) == false + + + +block t3717: + type + Foo[T] = object + a: T + Foo1[T] = Foo[T] | int + + proc foo[T](s: Foo1[Foo[T]]): T = + 5 + + var f: Foo[Foo[int]] + discard foo(f) + + + +block t5707: + proc foo[T]: seq[int] = + return lc[x | (x <- 1..10, x mod 2 == 0), int] + + doAssert foo[float32]() == @[2, 4, 6, 8, 10] |