diff options
Diffstat (limited to 'tests/proc')
-rw-r--r-- | tests/proc/t23874.nim | 26 | ||||
-rw-r--r-- | tests/proc/texplicitgenericcount.nim | 24 | ||||
-rw-r--r-- | tests/proc/texplicitgenericcountverbose.nim | 22 | ||||
-rw-r--r-- | tests/proc/texplicitgenerics.nim | 55 | ||||
-rw-r--r-- | tests/proc/tgenericdefaultparam.nim | 98 | ||||
-rw-r--r-- | tests/proc/tinferlambdareturn.nim | 36 | ||||
-rw-r--r-- | tests/proc/tstaticsignature.nim | 268 | ||||
-rw-r--r-- | tests/proc/twrongdefaultvalue.nim | 25 |
8 files changed, 554 insertions, 0 deletions
diff --git a/tests/proc/t23874.nim b/tests/proc/t23874.nim new file mode 100644 index 000000000..940bc4ac8 --- /dev/null +++ b/tests/proc/t23874.nim @@ -0,0 +1,26 @@ +block: + type Head[T] = object + wasc: bool + + proc `=destroy`[T](x: var Head[T]) = + discard + + proc `=copy`[T](x: var Head[T], y: Head[T]) = + x.wasc = true + + proc `=dup`[T](x: Head[T]): Head[T] = + result.wasc = true + + proc update(h: var Head) = + discard + + proc digest(h: sink Head) = + assert h.wasc + + var h = Head[int](wasc: false) + h.digest() # sink h + h.update() # use after sink + +block: + proc two(a: sink auto) =discard + assert typeof(two[int]) is proc(a: sink int) {.nimcall.} diff --git a/tests/proc/texplicitgenericcount.nim b/tests/proc/texplicitgenericcount.nim new file mode 100644 index 000000000..8654a1d13 --- /dev/null +++ b/tests/proc/texplicitgenericcount.nim @@ -0,0 +1,24 @@ +discard """ + cmd: "nim check -d:testsConciseTypeMismatch $file" +""" + +proc foo[T, U](x: T, y: U): (T, U) = (x, y) + +let x = foo[int](1, 2) #[tt.Error + ^ type mismatch +Expression: foo[int](1, 2) + [1] 1: int literal(1) + [2] 2: int literal(2) + +Expected one of (first mismatch at [position]): +[2] proc foo[T, U](x: T; y: U): (T, U) + missing generic parameter: U]# +let y = foo[int, float, string](1, 2) #[tt.Error + ^ type mismatch +Expression: foo[int, float, string](1, 2) + [1] 1: int literal(1) + [2] 2: int literal(2) + +Expected one of (first mismatch at [position]): +[3] proc foo[T, U](x: T; y: U): (T, U) + extra generic param given]# diff --git a/tests/proc/texplicitgenericcountverbose.nim b/tests/proc/texplicitgenericcountverbose.nim new file mode 100644 index 000000000..76228eeaf --- /dev/null +++ b/tests/proc/texplicitgenericcountverbose.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim check $file" +""" + +proc foo[T, U](x: T, y: U): (T, U) = (x, y) + +let x = foo[int](1, 2) #[tt.Error + ^ type mismatch: got <int literal(1), int literal(2)> +but expected one of: +proc foo[T, U](x: T; y: U): (T, U) + first type mismatch at position: 2 in generic parameters + missing generic parameter: U + +expression: foo[int](1, 2)]# +let y = foo[int, float, string](1, 2) #[tt.Error + ^ type mismatch: got <int literal(1), int literal(2)> +but expected one of: +proc foo[T, U](x: T; y: U): (T, U) + first type mismatch at position: 3 in generic parameters + extra generic param given + +expression: foo[int, float, string](1, 2)]# diff --git a/tests/proc/texplicitgenerics.nim b/tests/proc/texplicitgenerics.nim new file mode 100644 index 000000000..833d77b3b --- /dev/null +++ b/tests/proc/texplicitgenerics.nim @@ -0,0 +1,55 @@ +block: # issue #16376 + type + Matrix[T] = object + data: T + proc randMatrix[T](m, n: int, max: T): Matrix[T] = discard + proc randMatrix[T](m, n: int, x: Slice[T]): Matrix[T] = discard + template randMatrix[T](m, n: int): Matrix[T] = randMatrix[T](m, n, T(1.0)) + let B = randMatrix[float32](20, 10) + +block: # different generic param counts + type + Matrix[T] = object + data: T + proc randMatrix[T](m: T, n: T): Matrix[T] = Matrix[T](data: T(1.0)) + proc randMatrix[T; U: not T](m: T, n: U): (Matrix[T], U) = (Matrix[T](data: T(1.0)), default(U)) + let b = randMatrix[float32](20, 10) + doAssert b == Matrix[float32](data: 1.0) + +block: # above for templates + type + Matrix[T] = object + data: T + template randMatrix[T](m: T, n: T): Matrix[T] = Matrix[T](data: T(1.0)) + template randMatrix[T; U: not T](m: T, n: U): (Matrix[T], U) = (Matrix[T](data: T(1.0)), default(U)) + let b = randMatrix[float32](20, 10) + doAssert b == Matrix[float32](data: 1.0) + +block: # sigmatch can't handle this without pre-instantiating the type: + # minimized from numericalnim + type Foo[T] = proc (x: T) + proc foo[T](x: T) = discard + proc bar[T](f: Foo[T]) = discard + bar[int](foo) + +block: # ditto but may be wrong minimization + # minimized from measuremancer + type Foo[T] = object + proc foo[T](): Foo[T] = Foo[T]() + # this is the actual issue but there are other instantiation problems + proc bar[T](x = foo[T]()) = discard + bar[int](Foo[int]()) + bar[int]() + # alternative version, also causes instantiation issue + proc baz[T](x: typeof(foo[T]())) = discard + baz[int](Foo[int]()) + +block: # issue #21346 + type K[T] = object + template s[T](x: int) = doAssert T is K[K[int]] + proc b1(n: bool | bool) = s[K[K[int]]](3) + proc b2(n: bool) = s[K[K[int]]](3) + template b3(n: bool) = s[K[K[int]]](3) + b1(false) # Error: cannot instantiate K; got: <T> but expected: <T> + b2(false) # Builds, on its own + b3(false) diff --git a/tests/proc/tgenericdefaultparam.nim b/tests/proc/tgenericdefaultparam.nim new file mode 100644 index 000000000..7bce591ce --- /dev/null +++ b/tests/proc/tgenericdefaultparam.nim @@ -0,0 +1,98 @@ +block: # issue #16700 + type MyObject[T] = object + x: T + proc initMyObject[T](value = T.default): MyObject[T] = + MyObject[T](x: value) + var obj = initMyObject[int]() + +block: # issue #20916 + type + SomeX = object + v: int + var val = 0 + proc f(_: type int, x: SomeX, v = x.v) = + doAssert v == 42 + val = v + proc a(): proc() = + let v = SomeX(v: 42) + var tmp = proc() = + int.f(v) + tmp + a()() + doAssert val == 42 + +import std/typetraits + +block: # issue #24099, original example + type + ColorRGBU = distinct array[3, uint8] ## RGB range 0..255 + ColorRGBAU = distinct array[4, uint8] ## RGB range 0..255 + ColorRGBUAny = ColorRGBU | ColorRGBAU + template componentType(t: typedesc[ColorRGBUAny]): typedesc = + ## Returns component type of a given color type. + arrayType distinctBase t + func `~=`[T: ColorRGBUAny](a, b: T, e = componentType(T)(1.0e-11)): bool = + ## Compares colors with given accuracy. + abs(a[0] - b[0]) < e and abs(a[1] - b[1]) < e and abs(a[2] - b[2]) < e + +block: # issue #24099, modified to actually work + type + ColorRGBU = distinct array[3, uint8] ## RGB range 0..255 + ColorRGBAU = distinct array[4, uint8] ## RGB range 0..255 + ColorRGBUAny = ColorRGBU | ColorRGBAU + template arrayType[I, T](t: typedesc[array[I, T]]): typedesc = + T + template `[]`(a: ColorRGBUAny, i: untyped): untyped = distinctBase(a)[i] + proc abs(a: uint8): uint8 = a + template componentType(t: typedesc[ColorRGBUAny]): typedesc = + ## Returns component type of a given color type. + arrayType distinctBase t + func `~=`[T: ColorRGBUAny](a, b: T, e = componentType(T)(1.0e-11)): bool = + ## Compares colors with given accuracy. + abs(a[0] - b[0]) <= e and abs(a[1] - b[1]) <= e and abs(a[2] - b[2]) <= e + doAssert ColorRGBU([1.uint8, 1, 1]) ~= ColorRGBU([1.uint8, 1, 1]) + +block: # issue #24099, modified to work but using float32 + type + ColorRGBU = distinct array[3, float32] ## RGB range 0..255 + ColorRGBAU = distinct array[4, float32] ## RGB range 0..255 + ColorRGBUAny = ColorRGBU | ColorRGBAU + template arrayType[I, T](t: typedesc[array[I, T]]): typedesc = + T + template `[]`(a: ColorRGBUAny, i: untyped): untyped = distinctBase(a)[i] + template componentType(t: typedesc[ColorRGBUAny]): typedesc = + ## Returns component type of a given color type. + arrayType distinctBase t + func `~=`[T: ColorRGBUAny](a, b: T, e = componentType(T)(1.0e-11)): bool = + ## Compares colors with given accuracy. + abs(a[0] - b[0]) < e and abs(a[1] - b[1]) < e and abs(a[2] - b[2]) < e + doAssert ColorRGBU([1.float32, 1, 1]) ~= ColorRGBU([1.float32, 1, 1]) + +block: # issue #13270 + type + A = object + B = object + proc f(a: A) = discard + proc g[T](value: T, cb: (proc(a: T)) = f) = + cb value + g A() + # This should fail because there is no f(a: B) overload available + doAssert not compiles(g B()) + +block: # issue #24121 + type + Foo = distinct int + Bar = distinct int + FooBar = Foo | Bar + + proc foo[T: distinct](x: T): string = "a" + proc foo(x: Foo): string = "b" + proc foo(x: Bar): string = "c" + + proc bar(x: FooBar, y = foo(x)): string = y + doAssert bar(Foo(123)) == "b" + doAssert bar(Bar(123)) == "c" + + proc baz[T: FooBar](x: T, y = foo(x)): string = y + doAssert baz(Foo(123)) == "b" + doAssert baz(Bar(123)) == "c" diff --git a/tests/proc/tinferlambdareturn.nim b/tests/proc/tinferlambdareturn.nim new file mode 100644 index 000000000..e9e592871 --- /dev/null +++ b/tests/proc/tinferlambdareturn.nim @@ -0,0 +1,36 @@ +import std/[sugar, sequtils] + +block: # issue #23200 + proc dosomething(iter: int -> (iterator: int)) = + discard + proc dosomething(iter: int -> seq[int]) = + discard + proc makeSeq(x: int): seq[int] = + @[x] + # Works fine with 1.6.12 and 1.6.14 + dosomething(makeSeq) + # Works with 1.6.12, fails with 1.6.14 + dosomething((y) => makeSeq(y)) + dosomething(proc (y: auto): auto = makeSeq(y)) + proc foo(y: auto): auto = makeSeq(y) + dosomething(foo) + +block: # issue #18866 + proc somefn[T](list: openarray[T], op: proc (v: T): float) = + discard op(list[0]) + + type TimeD = object + year: Natural + month: 1..12 + day: 1..31 + + doAssert not compiles(@[TimeD()].somefn(proc (v: auto): auto = + v + )) + @[TimeD()].somefn(proc (v: auto): auto = + v.year.float + ) + proc foo(v: auto): auto = v + doAssert not compiles(@[TimeD()].somefn(foo)) + proc bar(v: auto): auto = v.year.float + @[TimeD()].somefn(bar) diff --git a/tests/proc/tstaticsignature.nim b/tests/proc/tstaticsignature.nim new file mode 100644 index 000000000..25aa09c5d --- /dev/null +++ b/tests/proc/tstaticsignature.nim @@ -0,0 +1,268 @@ +block: # issue #4228 + template seqType(t: typedesc): typedesc = + when t is int: + seq[int] + else: + seq[string] + + proc mkSeq[T: int|string](v: T): seqType(T) = + result = newSeq[T](1) + result[0] = v + + doAssert mkSeq("a") == @["a"] + doAssert mkSeq(1) == @[1] + +block: # expanded version of t8545 + template bar(a: static[bool]): untyped = + when a: + int + else: + float + + proc main() = + proc foo1(a: static[bool]): auto = 1 + doAssert foo1(true) == 1 + + proc foo2(a: static[bool]): bar(a) = 1 + doAssert foo2(true) == 1 + doAssert foo2(true) is int + doAssert foo2(false) == 1.0 + doAssert foo2(false) is float + + proc foo3(a: static[bool]): bar(cast[bool](a)) = 1 + doAssert foo3(true) == 1 + doAssert foo3(true) is int + doAssert foo3(false) == 1.0 + doAssert foo3(false) is float + + proc foo4(a: static[bool]): bar(static(a)) = 1 + doAssert foo4(true) == 1 + doAssert foo4(true) is int + doAssert foo4(false) == 1.0 + doAssert foo4(false) is float + + static: main() + main() + +block: # issue #8406 + macro f(x: static[int]): untyped = discard + proc g[X: static[int]](v: f(X)) = discard + +import macros + +block: # issue #8551 + macro distinctBase2(T: typedesc): untyped = + let typeNode = getTypeImpl(T) + expectKind(typeNode, nnkBracketExpr) + if typeNode[0].typeKind != ntyTypeDesc: + error "expected typeDesc, got " & $typeNode[0] + var typeSym = typeNode[1] + + typeSym = getTypeImpl(typeSym) + + if typeSym.typeKind != ntyDistinct: + error "type is not distinct: " & $typeSym.typeKind + + typeSym = typeSym[0] + typeSym + + func distinctBase[T](a: T): distinctBase2(T) = distinctBase2(T)(a) + + type T = distinct int + doAssert distinctBase(T(0)) is int + +block: + type Foo[T] = object + x: T + + proc foo(x: Foo): Foo[x.T] = + doAssert typeof(result) is typeof(x) + + var a: Foo[int] + let b: Foo[int] = foo(a) + doAssert b.x is int + +block: + type Foo[T: static int] = object + x: array[T, int] + + proc double(x: int): int = x * 2 + + proc foo[T: static int](x: Foo[T]): Foo[T.double] = + doAssert typeof(result).T == double(typeof(x).T) + + var a: Foo[3] + let b: Foo[6] = foo(a) + doAssert $typeof(foo(a)) == "Foo[6]" + +block: + type Foo[T: static int] = object + x: array[T, int] + + proc foo(x: Foo): Foo[x.T] = + doAssert typeof(result).T == typeof(x).T + doAssert typeof(result) is typeof(x) + + var a: Foo[3] + let b: Foo[3] = foo(a) + doAssert $typeof(foo(a)) == "Foo[3]" + +block: # issue #7006 + type + Node[T] = object + val: T + next: ref Node[T] + HHSet[T, Key] = object + data: seq[Node[T]] + proc rawGet(hhs:HHSet; key: hhs.Key): ptr Node[hhs.T] = + return nil # body doesn't matter + var hhs: HHSet[string, cstring] + discard hhs.rawGet("hello".cstring) + +block: # issue #7008 + type Node[T] = object + val: T + # Compiles fine + proc concreteProc(s: Node[cstring]; key: s.T) = discard + # Also fine + proc implicitGenericProc1(s: Node; key: s.T) = discard + # still fine + proc explicitGenericProc1[T](s: Node[T]; key: T) = discard + # Internal Compiler Error! + proc explicitGenericProc2[T](s: Node[T]; key: s.T) = discard + let n = Node[int](val: 5) + implicitGenericProc1(n, 5) # works + explicitGenericProc1(n, 5) # works + explicitGenericProc2(n, 5) # doesn't + +block: # issue #20027 + block: + type Test[T] = object + proc run(self: Test): self.T = discard + discard run(Test[int]()) + block: + type Test[T] = object + proc run[T](self: Test[T]): self.T = discard + discard run(Test[int]()) + block: + type Test[T] = object + proc run(self: Test[auto]): self.T = discard + discard run(Test[int]()) + +block: # issue #11112 + proc foo[A, B]: type(A.default + B.default) = + discard + doAssert foo[int, int]() is int + +block: # tyStatic and tyFromExpr instantiation mid-match + proc bar(x: int): int = x * 3 + proc bar2(x: static int): int = x * 4 + type Foo[T: static int] = distinct array[T, int] + proc foo[T: static int](x: Foo[T], y: Foo[bar(T)]) = discard + proc foo2[T: static int](x: Foo[T], y: Foo[bar2(T)]) = discard + foo(Foo[1]([1]), Foo[3]([1, 2, 3])) + foo2(Foo[1]([1]), Foo[4]([1, 2, 3, 4])) + +block: # issue #4990 + type Foo[I: static[int], A: static[array[I, int]]] = object + curIndex: int + + proc next[I: static[int], A: static[array[I, int]]](f: Foo[I, A]): string = + discard + const arr = [1, 2, 3] + var f: Foo[arr.len, arr] + discard next(f) + +block: # issue #4990 comment + type + Foo[A: static[int], B: static[int], TokenType: enum, EofToken: static[TokenType]] = object + curIndex: int + MyEnum = enum + meA, meB + Bar = Foo[2, 3, MyEnum, meA] + proc next[A: static[int], B: static[int], TokenType: enum, + EofToken: static[TokenType]](f: Foo[A, B, TokenType, EofToken], + a: static[(array[A, int], array[B, int])]): TokenType = + TokenType(a[0][f.curIndex]) + const + a = [1, 2] + b = [3, 4, 5] + template next(bar: Bar): MyEnum = + next(Foo[2, 3, MyEnum, meA](bar), (a, b)) + let bar = Bar(curIndex: 0) + doAssert bar.next() == meB + +block: # issue #14053 + template returnType(value: static[int]): typedesc = + when value == 1: + int + else: + float + proc fun(value: static[int]): returnType(value) = discard + doAssert fun(1) is int + template returnType2(value: static[int]): typedesc = + int + proc fun2(value: static[int]): returnType2(value) = discard + doAssert fun2(1) is int + +block: # issue #7547 + macro foo(N: static[int]): untyped = + result = getType(int) + type + Foo[N: static[int]] = foo(N) + ContainsFoo[N: static[int]] = object + Ffoo: Foo[N] + proc initFoo(N: static[int]): Foo[N] = discard + proc initContainsFoo(size: static[int]): ContainsFoo[size] = discard + var a: Foo[10] # Works + doAssert a is int + let b = initFoo(10) # Works + doAssert b is int + let c = ContainsFoo[5]() # Works + doAssert c.Ffoo is int + let z = initContainsFoo(5) # Error: undeclared identifier: 'N' + doAssert z.Ffoo is int + +block: # issue #22607, needs nkWhenStmt to be handled like nkRecWhen + proc test[x: static bool]( + t: ( + when x: + int + else: + float + ) + ) = discard + test[true](1.int) + test[false](1.0) + doAssert not compiles(test[]) + +block: # `when` in static signature + template ctAnd(a, b): bool = + when a: + when b: true + else: false + else: false + template test(): untyped = + when ctAnd(declared(SharedTable), typeof(result) is SharedTable): + result = SharedTable() + else: + result = 123 + proc foo[T](): T = test() + proc bar[T](x = foo[T]()): T = x + doAssert bar[int]() == 123 + +block: # issue #22276 + type Foo = enum A, B + macro test(y: static[Foo]): untyped = + if y == A: + result = parseExpr("proc (x: int)") + else: + result = parseExpr("proc (x: float)") + proc foo(y: static[Foo], x: test(y)) = # We want to make the type of `x` depend on what `y` is + x(9) + foo(A, proc (x: int) = doAssert x == 9) + var a: int + foo(A, proc (x: int) = + a = x * 2) + doAssert a == 18 + foo(B, proc (x: float) = doAssert x == 9) diff --git a/tests/proc/twrongdefaultvalue.nim b/tests/proc/twrongdefaultvalue.nim new file mode 100644 index 000000000..2c36c2247 --- /dev/null +++ b/tests/proc/twrongdefaultvalue.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim check $file" + action: reject + nimout: ''' +twrongdefaultvalue.nim(20, 12) template/generic instantiation of `doit` from here +twrongdefaultvalue.nim(17, 37) Error: type mismatch: got <proc (p: int): Item[initItem.T]> but expected 'Item[system.string]' +twrongdefaultvalue.nim(25, 3) template/generic instantiation of `foo` from here +twrongdefaultvalue.nim(23, 33) Error: type mismatch: got <string> but expected 'int' +''' +""" + +block: # issue #21258 + type Item[T] = object + pos: int + proc initItem[T](p:int=10000) : Item[T] = + result = Item[T](p) + proc doit[T](x:Item[T], s:Item[T]=initItem) : string = + return $x.pos + let x = Item[string](pos:100) + echo doit(x) + +block: # issue #21258, reduced case + proc foo[T](x: seq[T], y: T = "foo") = + discard + foo @[1, 2, 3] |