diff options
Diffstat (limited to 'tests')
1216 files changed, 23962 insertions, 3242 deletions
diff --git a/tests/alias/t19349.nim b/tests/alias/t19349.nim new file mode 100644 index 000000000..1e1e58264 --- /dev/null +++ b/tests/alias/t19349.nim @@ -0,0 +1,19 @@ +discard """ + action: "compile" +""" + +type + Vec3[T: SomeNumber] = object + arr: array[3, T] + +var + cfloatArr: array[3, array[3, cfloat]] + cfloatSeq = newSeq[Vec3[cfloat]]() +for row in cfloatArr: + cfloatSeq.add(Vec3[float32](arr: [row[0], row[1], row[2]])) + +var + cuintArr: array[3, array[3, cuint]] + cuintSeq = newSeq[Vec3[cuint]]() +for row in cuintArr: + cuintSeq.add(Vec3[uint32](arr: [row[0], row[1], row[2]])) diff --git a/tests/align/talign.nim b/tests/align/talign.nim index 3b8f6b4df..08373ee49 100644 --- a/tests/align/talign.nim +++ b/tests/align/talign.nim @@ -51,3 +51,19 @@ type Bug[T] = object var bug: Bug[int] doAssert sizeof(bug) == 128, "Oops my size is " & $sizeof(bug) # 16 + + +block: # bug #22419 + type + ValidatorPubKey = object + blob: array[96, byte] + + proc f(): auto = + return iterator() = + var pad: int8 = 0 + var y {.align: 16.}: ValidatorPubKey + let value = cast[uint64](addr y) + doAssert value mod 16 == 0 + + f()() + diff --git a/tests/alloc/tmembug.nim b/tests/alloc/tmembug.nim new file mode 100644 index 000000000..63b51ec5d --- /dev/null +++ b/tests/alloc/tmembug.nim @@ -0,0 +1,54 @@ +discard """ + joinable: false +""" + +import std / [atomics, strutils, sequtils] + +type + BackendMessage* = object + field*: seq[int] + +var + chan1: Channel[BackendMessage] + chan2: Channel[BackendMessage] + +chan1.open() +chan2.open() + +proc routeMessage*(msg: BackendMessage) = + discard chan2.trySend(msg) + +var + recv: Thread[void] + stopToken: Atomic[bool] + +proc recvMsg() = + while not stopToken.load(moRelaxed): + let resp = chan1.tryRecv() + if resp.dataAvailable: + routeMessage(resp.msg) + echo "child consumes ", formatSize getOccupiedMem() + +createThread[void](recv, recvMsg) + +const MESSAGE_COUNT = 100 + +proc main() = + let msg: BackendMessage = BackendMessage(field: (0..500).toSeq()) + for j in 0..0: #100: + echo "New iteration" + + for _ in 1..MESSAGE_COUNT: + chan1.send(msg) + echo "After sending" + + var counter = 0 + while counter < MESSAGE_COUNT: + let resp = recv(chan2) + counter.inc + echo "After receiving ", formatSize getOccupiedMem() + + stopToken.store true, moRelaxed + joinThreads(recv) + +main() diff --git a/tests/alloc/tmembug2.nim b/tests/alloc/tmembug2.nim new file mode 100644 index 000000000..01bce6f14 --- /dev/null +++ b/tests/alloc/tmembug2.nim @@ -0,0 +1,58 @@ +discard """ + disabled: "true" +""" + +import std / [atomics, strutils, sequtils, isolation] + +import threading / channels + +type + BackendMessage* = object + field*: seq[int] + +const MESSAGE_COUNT = 100 + +var + chan1 = newChan[BackendMessage](MESSAGE_COUNT*2) + chan2 = newChan[BackendMessage](MESSAGE_COUNT*2) + +#chan1.open() +#chan2.open() + +proc routeMessage*(msg: BackendMessage) = + var m = isolate(msg) + discard chan2.trySend(m) + +var + thr: Thread[void] + stopToken: Atomic[bool] + +proc recvMsg() = + while not stopToken.load(moRelaxed): + var resp: BackendMessage + if chan1.tryRecv(resp): + #if resp.dataAvailable: + routeMessage(resp) + echo "child consumes ", formatSize getOccupiedMem() + +createThread[void](thr, recvMsg) + +proc main() = + let msg: BackendMessage = BackendMessage(field: (0..5).toSeq()) + for j in 0..100: + echo "New iteration" + + for _ in 1..MESSAGE_COUNT: + chan1.send(msg) + echo "After sending" + + var counter = 0 + while counter < MESSAGE_COUNT: + let resp = recv(chan2) + counter.inc + echo "After receiving ", formatSize getOccupiedMem() + + stopToken.store true, moRelaxed + joinThreads(thr) + +main() diff --git a/tests/arc/t16558.nim b/tests/arc/t16558.nim index 7b6eb4669..0dbe02b33 100644 --- a/tests/arc/t16558.nim +++ b/tests/arc/t16558.nim @@ -1,6 +1,6 @@ discard """ matrix: "--gc:arc" - errormsg: "expression cannot be cast to int" + errormsg: "expression cannot be cast to 'int'" """ block: # bug #16558 diff --git a/tests/arc/t17812.nim b/tests/arc/t17812.nim index bcd5f3a93..dd8ac89b0 100644 --- a/tests/arc/t17812.nim +++ b/tests/arc/t17812.nim @@ -27,3 +27,15 @@ block: # bug #17812 proc `$`(o: MyObj): string = o.repr doAssert ($MyObj()).len > 0 + +# bug #22175 + +type Xxx = object + value: string + +proc complete(xxx: ref Xxx, v: sink string) = + xxx.value = move(v) + +let yyy = (ref Xxx)() + +yyy.complete("test") diff --git a/tests/arc/t18645.nim b/tests/arc/t18645.nim new file mode 100644 index 000000000..c5fddd4bb --- /dev/null +++ b/tests/arc/t18645.nim @@ -0,0 +1,18 @@ +discard """ + matrix: "--gc:arc; --gc:refc" + output: ''' +1 +2 +3 +''' +""" + +proc bitTypeIdUnion() = + var bitId {.global.} = block: + 0 + inc bitId + echo bitId + +bitTypeIdUnion() +bitTypeIdUnion() +bitTypeIdUnion() diff --git a/tests/arc/t18977.nim b/tests/arc/t18977.nim new file mode 100644 index 000000000..c775551a4 --- /dev/null +++ b/tests/arc/t18977.nim @@ -0,0 +1,26 @@ +discard """ + matrix: "--mm:arc" +""" + +type + E = enum + a, b, c, d + X = object + v: int + O = object + case kind: E + of a: + a: int + of {b, c}: + b: float + else: + d: X + +proc `=destroy`(x: var X) = + echo "x destroyed" + +var o = O(kind: d, d: X(v: 12345)) +doAssert o.d.v == 12345 + +doAssertRaises(FieldDefect): + o.kind = a diff --git a/tests/arc/t19231.nim b/tests/arc/t19231.nim new file mode 100644 index 000000000..40fcf277c --- /dev/null +++ b/tests/arc/t19231.nim @@ -0,0 +1,18 @@ +discard """ + matrix: "--mm:orc" + targets: "c cpp" +""" + +type + Game* = ref object + +proc free*(game: Game) = + var mixNumOpened:cint = 0 + for i in 0..<mixNumOpened: + mixNumOpened -= 1 + +proc newGame*(): Game = + new result, free + +var + game*: Game diff --git a/tests/arc/t19364.nim b/tests/arc/t19364.nim new file mode 100644 index 000000000..f520f3291 --- /dev/null +++ b/tests/arc/t19364.nim @@ -0,0 +1,30 @@ +discard """ + cmd: '''nim c --gc:arc --expandArc:fooLeaks $file''' + nimout: ''' +--expandArc: fooLeaks + +var + tmpTuple_cursor + a_cursor + b_cursor + c_cursor +tmpTuple_cursor = refTuple +a_cursor = tmpTuple_cursor[0] +b_cursor = tmpTuple_cursor[1] +c_cursor = tmpTuple_cursor[2] +-- end of expandArc ------------------------ +''' +""" + +func fooLeaks(refTuple: tuple[a, + b, + c: seq[float]]): float = + let (a, b, c) = refTuple + +let refset = (a: newSeq[float](25_000_000), + b: newSeq[float](25_000_000), + c: newSeq[float](25_000_000)) + +var res = newSeq[float](1_000_000) +for i in 0 .. res.high: + res[i] = fooLeaks(refset) diff --git a/tests/arc/t19401.nim b/tests/arc/t19401.nim new file mode 100644 index 000000000..56702a4a2 --- /dev/null +++ b/tests/arc/t19401.nim @@ -0,0 +1,32 @@ +discard """ + output: ''' +delete foo +delete foo +delete foo +''' + matrix: "--mm:arc" +""" + +type Foo = ref object + data: int +proc delete(self: Foo) +proc newFoo: Foo = + let x = 12 + discard x + new(result, delete) + result.data = x +proc delete(self: Foo) = + doAssert self.data == 12 + echo("delete foo") + +if isMainModule: + proc test() = + let x1 = newFoo() + let x2 = newFoo() + discard x1 + discard x2 + var x3: Foo + new(x3, delete) + x3.data = 12 + discard x3 + test() diff --git a/tests/arc/t19402.nim b/tests/arc/t19402.nim new file mode 100644 index 000000000..5ee6fc798 --- /dev/null +++ b/tests/arc/t19402.nim @@ -0,0 +1,32 @@ +discard """ + output: ''' +delete foo +delete foo +delete foo +''' + matrix: "--mm:arc" +""" + +type Foo = ref object of RootObj + data: int +proc delete(self: Foo) +proc newFoo: Foo = + let x = 12 + discard x + new(result, delete) + result.data = x +proc delete(self: Foo) = + doAssert self.data == 12 + echo("delete foo") + +if isMainModule: + proc test() = + let x1 = newFoo() + let x2 = newFoo() + discard x1 + discard x2 + var x3: Foo + new(x3, delete) + x3.data = 12 + discard x3 + test() \ No newline at end of file diff --git a/tests/arc/t19457.nim b/tests/arc/t19457.nim new file mode 100644 index 000000000..78447ce82 --- /dev/null +++ b/tests/arc/t19457.nim @@ -0,0 +1,16 @@ +discard """ + matrix: "--gc:refc; --gc:arc" +""" + +# bug #19457 +proc gcd(x, y: seq[int]): seq[int] = + var + a = x + b = y + while b[0] > 0: + let c = @[a[0] mod b[0]] + a = b + b = c + return a + +doAssert gcd(@[1], @[2]) == @[1] \ No newline at end of file diff --git a/tests/arc/t19862.nim b/tests/arc/t19862.nim index f7146ec26..6d3f57692 100644 --- a/tests/arc/t19862.nim +++ b/tests/arc/t19862.nim @@ -2,6 +2,8 @@ discard """ matrix: "--gc:refc; --gc:arc" """ +import std/widestrs + # bug #19862 type NewString = object diff --git a/tests/arc/t20456.nim b/tests/arc/t20456.nim new file mode 100644 index 000000000..ace79255a --- /dev/null +++ b/tests/arc/t20456.nim @@ -0,0 +1,7 @@ +discard """ + cmd: "nim check $file" + action: "compile" +""" + +when not defined(gcOrc): + {.error: "orc".} diff --git a/tests/arc/t20588.nim b/tests/arc/t20588.nim new file mode 100644 index 000000000..008bd1dcd --- /dev/null +++ b/tests/arc/t20588.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim check --warnings:off --hints:off $file" + errormsg: "" + nimout: ''' +t20588.nim(20, 12) Error: illegal type conversion to 'auto' +t20588.nim(21, 14) Error: illegal type conversion to 'typed' +t20588.nim(22, 16) Error: illegal type conversion to 'untyped' +t20588.nim(24, 7) Error: illegal type conversion to 'any' +''' +""" + + + + + + + + + +discard 0.0.auto +discard typed("abc") +discard untyped(4) +var a = newSeq[bool](1000) +if any(a): + echo "ok?" \ No newline at end of file diff --git a/tests/arc/t21184.nim b/tests/arc/t21184.nim new file mode 100644 index 000000000..91d0c42c7 --- /dev/null +++ b/tests/arc/t21184.nim @@ -0,0 +1,77 @@ +discard """ + matrix: "--mm:orc" +""" + +import std/[with] + +type + Node* {.acyclic.} = ref object of RootObj + name: string + data: pointer + children: seq[Node] + TextNode = ref object of Node + text: string + +proc fakeEcho(s: string) = + if s.len < 0: + echo s + +proc newNode[T: Node](parent: Node): T = + new result + result.data = alloc0(250) + parent.children.add(result) + +proc newRootNode(): Node = + new result + result.data = alloc0(250) + +method printNode(node: Node) {.base.} = + fakeEcho node.name + +method printNode(node: TextNode) = + procCall printNode(Node(node)) + fakeEcho node.text + +proc printChildren(node: Node) = + for child in node.children: + child.printNode() + printChildren(child) + +proc free(node: Node) = + for child in node.children: + free(child) + dealloc(node.data) + +template node(parent: Node, body: untyped): untyped = + var node = newNode[Node](parent) + with node: + body + +proc textNode(parent: Node, text: string) = + var node = newNode[TextNode](parent) + node.text = text + +template withRootNode(body: untyped): untyped = + var root = newRootNode() + root.name = "root" + with root: + body + root.printNode() + printChildren(root) + root.free() + +proc doTest() = + withRootNode: + node: + name = "child1" + node: + name = "child2" + node: + name = "child3" + textNode "Hello, world!" + + +# bug #21171 +if isMainModule: + for i in 0..100000: + doTest() diff --git a/tests/arc/t22218.nim b/tests/arc/t22218.nim new file mode 100644 index 000000000..7837ed1d0 --- /dev/null +++ b/tests/arc/t22218.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim c --mm:arc $file" + errormsg: "'=copy' is not available for type <Obj>; requires a copy because it's not the last read of 'chan[]'; routine: test" +""" + +# bug #22218 +type Obj[T] = object + v: T + +proc `=copy`[T]( + dest: var Obj[T], + source: Obj[T] + ) {.error: "A channel cannot be copied".} + +from system/ansi_c import c_calloc + +proc test() = + var v: bool = true + var chan = cast[ptr Obj[int]](c_calloc(1, csize_t sizeof(Obj[int]))) + var copy = chan[] + + echo chan.v + echo v + +test() \ No newline at end of file diff --git a/tests/arc/t22237.nim b/tests/arc/t22237.nim new file mode 100644 index 000000000..c6dbf768a --- /dev/null +++ b/tests/arc/t22237.nim @@ -0,0 +1,55 @@ +discard """ + matrix: "--mm:arc; --mm:orc" +""" + +import std/macros +import std/streams + +# bug #22237 + +proc iterlines_closure2(f: File | Stream): iterator (): string = + result = iterator(): string = + for line in f.lines: + if line.len == 0: + break + yield line + +proc test() = + let f = newStringStream(""" + 1 + 2 + + 3 + 4 + + 5 + 6 + 7 + + 8 +""") + while not f.atEnd(): + let iterator_inst = iterlines_closure2(f) + for item in iterator_inst(): # Fails with "SIGSEGV: Illegal storage access. (Attempt to read from nil?)" + discard + +test() + +# bug #21160 +import sequtils + +iterator allMoves(fls: seq[int]): seq[int] = + yield fls + +proc neighbors(flrs: seq[int]): iterator: seq[int] = + return iterator(): seq[int] = + for flrs2 in allMoves(flrs): + yield flrs2 + for flrs3 in allMoves(flrs2): + yield flrs3 + +let f = @[1] +for _ in neighbors(f): + discard +for _ in neighbors(f): + discard diff --git a/tests/arc/t22478.nim b/tests/arc/t22478.nim new file mode 100644 index 000000000..5373fa161 --- /dev/null +++ b/tests/arc/t22478.nim @@ -0,0 +1,46 @@ +discard """ + matrix: "-d:nimNoLentIterators --mm:arc" + output: '''PUSH DATA: {"test.message":{"test":{"nested":"v1"}}}''' + joinable: false +""" + +# bug #22748 +import std/[json, typetraits, times] + +# publish + +proc publish*[T](payload: T) = + discard + +type MetricsPoint* = JsonNode + +proc push*(stat: string, data: JsonNode, usec: int64 = 0) = + let payload = newJObject() + + # this results in a infinite recursion unless we deepCopy() + payload[stat] = data #.deepCopy + + echo "PUSH DATA: ", payload + + publish[MetricsPoint](payload) + +var scopes {.threadvar.}: seq[JsonNode] + +type WithTimeCallback*[T] = proc(data: var JsonNode): T + +proc pushScoped*[T](metric: string, blk: WithTimeCallback[T]): T {.gcsafe.} = + scopes.add newJObject() + defer: discard scopes.pop() + + let stc = (cpuTime() * 1000_000).int64 + result = blk(scopes[^1]) + let dfc = (cpuTime() * 1000_000).int64 - stc + + push(metric, scopes[^1], dfc) + +# demo code + +discard pushScoped[int]("test.message") do (data: var JsonNode) -> int: + data["test"] = %*{ + "nested": "v1" + } \ No newline at end of file diff --git a/tests/arc/t22787.nim b/tests/arc/t22787.nim new file mode 100644 index 000000000..5840a984b --- /dev/null +++ b/tests/arc/t22787.nim @@ -0,0 +1,37 @@ +discard """ + joinable: false +""" + +import std/assertions + +proc foo = + var s:seq[string] + var res = "" + + for i in 0..3: + s.add ("test" & $i) + s.add ("test" & $i) + + var lastname:string + + for i in s: + var name = i[0..4] + + if name != lastname: + res.add "NEW:" & name & "\n" + else: + res.add name & ">" & lastname & "\n" + + lastname = name + + doAssert res == """ +NEW:test0 +test0>test0 +NEW:test1 +test1>test1 +NEW:test2 +test2>test2 +NEW:test3 +test3>test3 +""" +foo() \ No newline at end of file diff --git a/tests/arc/t23247.nim b/tests/arc/t23247.nim new file mode 100644 index 000000000..0fadc50cd --- /dev/null +++ b/tests/arc/t23247.nim @@ -0,0 +1,52 @@ +discard """ + matrix: ";-d:useMalloc" +""" + +# bug #23247 +import std/hashes + +func baseAddr[T](x: openArray[T]): ptr T = + # Return the address of the zero:th element of x or `nil` if x is empty + if x.len == 0: nil else: cast[ptr T](x) + +func makeUncheckedArray[T](p: ptr T): ptr UncheckedArray[T] = + cast[ptr UncheckedArray[T]](p) + +type + LabelKey = object + data: seq[string] + refs: ptr UncheckedArray[string] + refslen: int + + Gauge = ref object + metrics: seq[seq[seq[string]]] + +template values(key: LabelKey): openArray[string] = + if key.refslen > 0: + key.refs.toOpenArray(0, key.refslen - 1) + else: + key.data + +proc hash(key: LabelKey): Hash = + hash(key.values) + +proc view(T: type LabelKey, values: openArray[string]): T = + # TODO some day, we might get view types - until then.. + LabelKey(refs: baseAddr(values).makeUncheckedArray(), refslen: values.len()) + +template withValue2(k: untyped) = + discard hash(k) + +proc setGauge( + collector: Gauge, + labelValues: openArray[string], +) = + let v = LabelKey.view(labelValues) + withValue2(v) + collector.metrics.add @[@labelValues, @labelValues] + discard @labelValues + +var nim_gc_mem_bytes = Gauge() +let threadID = $getThreadId() +setGauge(nim_gc_mem_bytes, @[threadID]) +setGauge(nim_gc_mem_bytes, @[threadID]) \ No newline at end of file diff --git a/tests/arc/taliased_reassign.nim b/tests/arc/taliased_reassign.nim new file mode 100644 index 000000000..5563fae8c --- /dev/null +++ b/tests/arc/taliased_reassign.nim @@ -0,0 +1,41 @@ +discard """ + matrix: "--mm:orc" +""" + +# bug #20993 + +type + Dual[int] = object # must be generic (even if fully specified) + p: int +proc D(p: int): Dual[int] = Dual[int](p: p) +proc `+`(x: Dual[int], y: Dual[int]): Dual[int] = D(x.p + y.p) + +type + Tensor[T] = object + buf: seq[T] +proc newTensor*[T](s: int): Tensor[T] = Tensor[T](buf: newSeq[T](s)) +proc `[]`*[T](t: Tensor[T], idx: int): T = t.buf[idx] +proc `[]=`*[T](t: var Tensor[T], idx: int, val: T) = t.buf[idx] = val + +proc `+.`[T](t1, t2: Tensor[T]): Tensor[T] = + let n = t1.buf.len + result = newTensor[T](n) + for i in 0 ..< n: + result[i] = t1[i] + t2[i] + +proc toTensor*[T](a: sink seq[T]): Tensor[T] = + ## This breaks it: Using `T` instead makes it work + type U = typeof(a[0]) + var t: Tensor[U] # Tensor[T] works + t.buf = a + result = t + +proc loss() = + var B = toTensor(@[D(123)]) + let a = toTensor(@[D(-10)]) + B = B +. a + doAssert B[0].p == 113, "I want to be 113, but I am " & $B[0].p + +loss() + + diff --git a/tests/arc/tarc_macro.nim b/tests/arc/tarc_macro.nim new file mode 100644 index 000000000..33ade1da4 --- /dev/null +++ b/tests/arc/tarc_macro.nim @@ -0,0 +1,57 @@ +import macros + +var destroyCalled = false +macro bar() = + let s = newTree(nnkAccQuoted, ident"=destroy") + # let s = ident"`=destroy`" # this would not work + result = quote do: + type Foo = object + # proc `=destroy`(a: var Foo) = destroyCalled = true # this would not work + proc `s`(a: var Foo) = destroyCalled = true + block: + let a = Foo() +bar() +doAssert destroyCalled + +# custom `op` +var destroyCalled2 = false +macro bar(ident) = + var x = 1.5 + result = quote("@") do: + type Foo = object + let `@ident` = 0 # custom op interpolated symbols need quoted (``) + proc `=destroy`(a: var Foo) = + doAssert @x == 1.5 + doAssert compiles(@x == 1.5) + let b1 = @[1,2] + let b2 = @@[1,2] + doAssert $b1 == "[1, 2]" + doAssert $b2 == "@[1, 2]" + destroyCalled2 = true + block: + let a = Foo() +bar(someident) +doAssert destroyCalled2 + +proc `&%`(x: int): int = 1 +proc `&%`(x, y: int): int = 2 + +macro bar2() = + var x = 3 + result = quote("&%") do: + var y = &%x # quoting operator + doAssert &%&%y == 1 # unary operator => need to escape + doAssert y &% y == 2 # binary operator => no need to escape + doAssert y == 3 +bar2() + +block: + macro foo(a: openArray[string] = []): string = + echo a # Segfault doesn't happen if this is removed + newLit "" + + proc bar(a: static[openArray[string]] = []) = + const tmp = foo(a) + + # bug #22909 + doAssert not compiles(bar()) diff --git a/tests/arc/tarc_orc.nim b/tests/arc/tarc_orc.nim index c6a7845b0..f2c7de2fc 100644 --- a/tests/arc/tarc_orc.nim +++ b/tests/arc/tarc_orc.nim @@ -33,3 +33,154 @@ proc bug20303() = doAssert res == "are" bug20303() + +proc main() = # todo bug with templates + block: # bug #11267 + var a: seq[char] = block: @[] + doAssert a == @[] + # 2 + proc b: seq[string] = + discard + @[] + doAssert b() == @[] +static: main() +main() + + +type Obj = tuple + value: int + arr: seq[int] + +proc bug(): seq[Obj] = + result.add (value: 0, arr: @[]) + result[^1].value = 1 + result[^1].arr.add 1 + +# bug #19990 +let s = bug() +doAssert s[0] == (value: 1, arr: @[1]) + +block: # bug #21974 + type Test[T] = ref object + values : seq[T] + counter: int + + proc newTest[T](): Test[T] = + result = new(Test[T]) + result.values = newSeq[T](16) + result.counter = 0 + + proc push[T](self: Test[T], value: T) = + self.counter += 1 + if self.counter >= self.values.len: + self.values.setLen(self.values.len * 2) + self.values[self.counter - 1] = value + + proc pop[T](self: Test[T]): T = + result = self.values[0] + self.values[0] = self.values[self.counter - 1] # <--- This line + self.counter -= 1 + + + type X = tuple + priority: int + value : string + + var a = newTest[X]() + a.push((1, "One")) + doAssert a.pop.value == "One" + +# bug #21987 + +type + EmbeddedImage* = distinct Image + Image = object + len: int + +proc imageCopy*(image: Image): Image {.nodestroy.} + +proc `=destroy`*(x: var Image) = + discard +proc `=sink`*(dest: var Image; source: Image) = + `=destroy`(dest) + wasMoved(dest) + +proc `=dup`*(source: Image): Image {.nodestroy.} = + result = imageCopy(source) + +proc `=copy`*(dest: var Image; source: Image) = + dest = imageCopy(source) # calls =sink implicitly + +proc `=destroy`*(x: var EmbeddedImage) = discard + +proc `=dup`*(source: EmbeddedImage): EmbeddedImage {.nodestroy.} = source + +proc `=copy`*(dest: var EmbeddedImage; source: EmbeddedImage) {.nodestroy.} = + dest = source + +proc imageCopy*(image: Image): Image = + result = image + +proc main2 = + block: + var a = Image(len: 2).EmbeddedImage + var b = Image(len: 1).EmbeddedImage + b = a + doAssert Image(a).len == 2 + doAssert Image(b).len == 2 + + block: + var a = Image(len: 2) + var b = Image(len: 1) + b = a + doAssert a.len == 2 + doAssert b.len == 0 + +main2() + +block: + type + TestObj = object of RootObj + name: string + + TestSubObj = object of TestObj + objname: string + + proc `=destroy`(x: TestObj) = + `=destroy`(x.name) + + proc `=destroy`(x: TestSubObj) = + `=destroy`(x.objname) + `=destroy`(TestObj(x)) + + proc testCase() = + let t1 {.used.} = TestSubObj(objname: "tso1", name: "to1") + + proc main() = + testCase() + + main() + +block: # bug #23858 + type Object = object + a: int + b: ref int + var x = 0 + proc fn(): auto {.cdecl.} = + inc x + return Object() + discard fn() + doAssert x == 1 + +block: # bug #24147 + type + O = object of RootObj + val: string + OO = object of O + + proc `=copy`(dest: var O, src: O) = + dest.val = src.val + + let oo = OO(val: "hello world") + var ooCopy : OO + `=copy`(ooCopy, oo) diff --git a/tests/arc/tarcmisc.nim b/tests/arc/tarcmisc.nim index 45d1514cd..b4476ef4f 100644 --- a/tests/arc/tarcmisc.nim +++ b/tests/arc/tarcmisc.nim @@ -1,5 +1,7 @@ discard """ output: ''' +Destructor for TestTestObj +=destroy called 123xyzabc destroyed: false destroyed: false @@ -26,18 +28,90 @@ new line after - @['a'] finalizer aaaaa hello -ok true copying 123 42 -closed +@["", "d", ""] +ok destroying variable: 20 destroying variable: 10 +closed ''' - cmd: "nim c --gc:arc --deepcopy:on -d:nimAllocPagesViaMalloc $file" + cmd: "nim c --mm:arc --deepcopy:on -d:nimAllocPagesViaMalloc $file" """ +block: # bug #23627 + type + TestObj = object of RootObj + + Test2 = object of RootObj + foo: TestObj + + TestTestObj = object of RootObj + shit: TestObj + + proc `=destroy`(x: TestTestObj) = + echo "Destructor for TestTestObj" + let test = Test2(foo: TestObj()) + + proc testCaseT() = + let tt1 {.used.} = TestTestObj(shit: TestObj()) + + + proc main() = + testCaseT() + + main() + + +# bug #9401 + +type + MyObj = object + len: int + data: ptr UncheckedArray[float] + +proc `=destroy`*(m: MyObj) = + + echo "=destroy called" + + if m.data != nil: + deallocShared(m.data) + +type + MyObjDistinct = distinct MyObj + +proc `=copy`*(m: var MyObj, m2: MyObj) = + if m.data == m2.data: return + if m.data != nil: + `=destroy`(m) + m.len = m2.len + if m.len > 0: + m.data = cast[ptr UncheckedArray[float]](allocShared(sizeof(float) * m.len)) + copyMem(m.data, m2.data, sizeof(float) * m.len) + + +proc `=sink`*(m: var MyObj, m2: MyObj) = + if m.data != m2.data: + if m.data != nil: + `=destroy`(m) + m.len = m2.len + m.data = m2.data + +proc newMyObj(len: int): MyObj = + result.len = len + result.data = cast[ptr UncheckedArray[float]](allocShared(sizeof(float) * len)) + +proc newMyObjDistinct(len: int): MyObjDistinct = + MyObjDistinct(newMyObj(len)) + +proc fooDistinct = + doAssert newMyObjDistinct(2).MyObj.len == 2 + +fooDistinct() + + proc takeSink(x: sink string): bool = true proc b(x: sink string): string = @@ -55,7 +129,7 @@ bbb("123") type Variable = ref object value: int -proc `=destroy`(self: var typeof(Variable()[])) = +proc `=destroy`(self: typeof(Variable()[])) = echo "destroying variable: ",self.value proc newVariable(value: int): Variable = @@ -75,7 +149,7 @@ proc test(count: int) = test(3) proc test2(count: int) = - #block: #XXX: Fails with block currently + block: #XXX: Fails with block currently var v {.global.} = newVariable(20) var count = count - 1 @@ -109,7 +183,7 @@ type B = ref object of A x: int -proc `=destroy`(x: var AObj) = +proc `=destroy`(x: AObj) = close(x.io) echo "closed" @@ -497,3 +571,266 @@ proc fooz(sec: var InputSectionBase) = var sec = create(InputSection) sec[] = InputSection(relocations: newSeq[int]()) fooz sec[] + +block: + type + Data = ref object + id: int + proc main = + var x = Data(id: 99) + var y = x + x[] = Data(id: 778)[] + doAssert y.id == 778 + doAssert x[].id == 778 + main() + +block: # bug #19857 + type + ValueKind = enum VNull, VFloat, VObject # need 3 elements. Cannot remove VNull or VObject + + Value = object + case kind: ValueKind + of VFloat: fnum: float + of VObject: tab: Table[int, int] # OrderedTable[T, U] also makes it fail. + # "simpler" types also work though + else: discard # VNull can be like this, but VObject must be filled + + # required. Pure proc works + FormulaNode = proc(c: OrderedTable[string, int]): Value + + proc toF(v: Value): float = + doAssert v.kind == VFloat + case v.kind + of VFloat: result = v.fnum + else: discard + + + proc foo() = + let fuck = initOrderedTable[string, int]() + proc cb(fuck: OrderedTable[string, int]): Value = + # works: + #result = Value(kind: VFloat, fnum: fuck["field_that_does_not_exist"].float) + # broken: + discard "actuall runs!" + let t = fuck["field_that_does_not_exist"] + echo "never runs, but we crash after! ", t + + doAssertRaises(KeyError): + let fn = FormulaNode(cb) + let v = fn(fuck) + #echo v + let res = v.toF() + + foo() + +import std/options + +# bug #21592 +type Event* = object + code*: string + +type App* = ref object of RootObj + id*: string + +method process*(self: App): Option[Event] {.base.} = + raise Exception.new_exception("not impl") + +# bug #21617 +type Test2 = ref object of RootObj + +method bug(t: Test2): seq[float] {.base.} = discard + +block: # bug #22664 + type + ElementKind = enum String, Number + Element = object + case kind: ElementKind + of String: + str: string + of Number: + num: float + Calc = ref object + stack: seq[Element] + + var calc = new Calc + + calc.stack.add Element(kind: Number, num: 200.0) + doAssert $calc.stack == "@[(kind: Number, num: 200.0)]" + let calc2 = calc + calc2.stack = calc.stack # This nulls out the object in the stack + doAssert $calc.stack == "@[(kind: Number, num: 200.0)]" + doAssert $calc2.stack == "@[(kind: Number, num: 200.0)]" + +block: # bug #19250 + type + Bar[T] = object + err: proc(): string + + Foo[T] = object + run: proc(): Bar[T] + + proc bar[T](err: proc(): string): Bar[T] = + assert not err.isNil + Bar[T](err: err) + + proc foo(): Foo[char] = + result.run = proc(): Bar[char] = + # works + # result = Bar[char](err: proc(): string = "x") + # not work + result = bar[char](proc(): string = "x") + + proc bug[T](fs: Foo[T]): Foo[T] = + result.run = proc(): Bar[T] = + let res = fs.run() + + # works + # var errors = @[res.err] + + # not work + var errors: seq[proc(): string] + errors.add res.err + + return bar[T] do () -> string: + for err in errors: + result.add res.err() + + doAssert bug(foo()).run().err() == "x" + +block: # bug #22259 + type + ProcWrapper = tuple + p: proc() {.closure.} + + + proc f(wrapper: ProcWrapper) = + let s = @[wrapper.p] + let a = [wrapper.p] + + proc main = + # let wrapper: ProcWrapper = ProcWrapper(p: proc {.closure.} = echo 10) + let wrapper: ProcWrapper = (p: proc {.closure.} = echo 10) + f(wrapper) + + main() + +block: + block: # bug #22923 + block: + let + a: int = 100 + b: int32 = 200'i32 + + let + x = arrayWith(a, 8) # compiles + y = arrayWith(b, 8) # internal error + z = arrayWith(14, 8) # integer literal also results in a crash + + doAssert x == [100, 100, 100, 100, 100, 100, 100, 100] + doAssert $y == "[200, 200, 200, 200, 200, 200, 200, 200]" + doAssert z == [14, 14, 14, 14, 14, 14, 14, 14] + + block: + let a: string = "nim" + doAssert arrayWith(a, 3) == ["nim", "nim", "nim"] + + let b: char = 'c' + doAssert arrayWith(b, 3) == ['c', 'c', 'c'] + + let c: uint = 300'u + doAssert $arrayWith(c, 3) == "[300, 300, 300]" + +block: # bug #23505 + type + K = object + C = object + value: ptr K + + proc init(T: type C): C = + let tmp = new K + C(value: addr tmp[]) + + discard init(C) + +block: # bug #23524 + type MyType = object + a: int + + proc `=destroy`(typ: MyType) = discard + + var t1 = MyType(a: 100) + var t2 = t1 # Should be a copy? + + proc main() = + t2 = t1 + doAssert t1.a == 100 + doAssert t2.a == 100 + + main() + +block: # bug #23907 + type + Thingy = object + value: int + + ExecProc[C] = proc(value: sink C): int {.nimcall.} + + proc `=copy`(a: var Thingy, b: Thingy) {.error.} + + var thingyDestroyCount = 0 + + proc `=destroy`(thingy: Thingy) = + assert(thingyDestroyCount <= 0) + thingyDestroyCount += 1 + + proc store(value: sink Thingy): int = + result = value.value + + let callback: ExecProc[Thingy] = store + + doAssert callback(Thingy(value: 123)) == 123 + +import std/strutils + +block: # bug #23974 + func g(e: seq[string]): lent seq[string] = result = e + proc k(f: string): seq[string] = f.split("/") + proc n() = + const r = "/d/" + let t = + if true: + k(r).g() + else: + k("/" & r).g() + echo t + + n() + +block: # bug #23973 + func g(e: seq[string]): lent seq[string] = result = e + proc k(f: string): seq[string] = f.split("/") + proc n() = + const r = "/test/empty" # or "/test/empty/1" + let a = k(r).g() + let t = + if true: + k(r).g() + else: + k("/" & r).g() # or raiseAssert "" + doAssert t == a + + n() + +block: # bug #24141 + func reverse(s: var openArray[char]) = + s[0] = 'f' + + func rev(s: var string) = + s.reverse + + proc main = + var abc = "abc" + abc.rev + doAssert abc == "fbc" + + main() diff --git a/tests/arc/tasyncleak.nim b/tests/arc/tasyncleak.nim index eb0c45213..8e3a7b3e7 100644 --- a/tests/arc/tasyncleak.nim +++ b/tests/arc/tasyncleak.nim @@ -1,5 +1,5 @@ discard """ - outputsub: "(allocCount: 4302, deallocCount: 4300)" + outputsub: "(allocCount: 4050, deallocCount: 4048)" cmd: "nim c --gc:orc -d:nimAllocStats $file" """ diff --git a/tests/arc/tcaseobj.nim b/tests/arc/tcaseobj.nim index a967a509b..3499f5c1e 100644 --- a/tests/arc/tcaseobj.nim +++ b/tests/arc/tcaseobj.nim @@ -10,6 +10,7 @@ begin end prevented (ok: true, value: "ok") +@[(kind: P, pChildren: @[])] myobj destroyed ''' """ @@ -59,7 +60,7 @@ proc `=destroy`(o: var TMyObj) = o.p = nil echo "myobj destroyed" -proc `=`(dst: var TMyObj, src: TMyObj) = +proc `=copy`(dst: var TMyObj, src: TMyObj) = `=destroy`(dst) dst.p = alloc(src.len) dst.len = src.len @@ -169,18 +170,24 @@ proc test_myobject = x.x1 = "x1" x.x2 = "x2" x.y1 = "ljhkjhkjh" - x.kind1 = true + {.cast(uncheckedAssign).}: + x.kind1 = true x.y2 = @["1", "2"] - x.kind2 = true + {.cast(uncheckedAssign).}: + x.kind2 = true x.z1 = "yes" - x.kind2 = false + {.cast(uncheckedAssign).}: + x.kind2 = false x.z2 = @["1", "2"] - x.kind2 = true + {.cast(uncheckedAssign).}: + x.kind2 = true x.z1 = "yes" x.kind2 = true # should be no effect doAssert(x.z1 == "yes") - x.kind2 = false - x.kind1 = x.kind2 # support self assignment with effect + {.cast(uncheckedAssign).}: + x.kind2 = false + {.cast(uncheckedAssign).}: + x.kind1 = x.kind2 # support self assignment with effect try: x.kind1 = x.flag # flag is not accesible @@ -206,8 +213,9 @@ type error*: string proc init(): RocksDBResult[string] = - result.ok = true - result.value = "ok" + {.cast(uncheckedAssign).}: + result.ok = true + result.value = "ok" echo init() @@ -221,7 +229,8 @@ type MyObj = object of true: x1: string var a = MyObj(kind: false, x0: 1234) -a.kind = true +{.cast(uncheckedAssign).}: + a.kind = true doAssert(a.x1 == "") block: @@ -244,3 +253,114 @@ block: doAssert j1.x1 == 2 doAssert j0.x0 == 2 + +# ------------------------------------ +# bug #20305 + +type + ContentNodeKind = enum + P, Br, Text + ContentNode = object + case kind: ContentNodeKind + of P: pChildren: seq[ContentNode] + of Br: discard + of Text: textStr: string + +proc bug20305 = + var x = ContentNode(kind: P, pChildren: @[ + ContentNode(kind: P, pChildren: @[ContentNode(kind: Text, textStr: "brrr")]) + ]) + x.pChildren.add ContentNode(kind: Br) + x.pChildren.del(0) + {.cast(uncheckedAssign).}: + x.pChildren[0].kind = P + echo x.pChildren + +bug20305() + +# bug #21023 +block: + block: + type + MGErrorKind = enum + mgeUnexpected, mgeNotFound + + type Foo = object + kind: MGErrorKind + ex: Exception + + type Boo = object + a: seq[int] + + type + Result2 = object + case o: bool + of false: + e: Foo + of true: + v: Boo + + proc startSessionSync(): Result2 = + return Result2(o: true) + + proc mainSync = + let ff = startSessionSync() + doAssert ff.o == true + + mainSync() + + block: + type + MGErrorKind = enum + mgeUnexpected, mgeNotFound + + type Foo = object + kind: MGErrorKind + ex: Exception + + type Boo = object + a: seq[int] + + type + Result2 = object + case o: bool + of false: + e: Foo + of true: + v: Boo + s: int + + proc startSessionSync(): Result2 = + return Result2(o: true, s: 12) + + proc mainSync = + let ff = startSessionSync() + doAssert ff.s == 12 + + mainSync() + +import std/sequtils + +# bug #23690 +type + SomeObj* = object of RootObj + + Item* = object + case kind*: 0..1 + of 0: + a*: int + b*: SomeObj + of 1: + c*: string + + ItemExt* = object + a*: Item + b*: string + +proc do1(x: int): seq[(string, Item)] = + result = @[("zero", Item(kind: 1, c: "first"))] + +proc do2(x: int, e: ItemExt): seq[(string, ItemExt)] = + do1(x).map(proc(v: (string, Item)): auto = (v[0], ItemExt(a: v[1], b: e.b))) + +doAssert $do2(0, ItemExt(a: Item(kind: 1, c: "second"), b: "third")) == """@[("zero", (a: (kind: 1, c: "first"), b: "third"))]""" diff --git a/tests/arc/tcaseobjcopy.nim b/tests/arc/tcaseobjcopy.nim index ed07b404e..fb26a4973 100644 --- a/tests/arc/tcaseobjcopy.nim +++ b/tests/arc/tcaseobjcopy.nim @@ -169,18 +169,23 @@ proc test_myobject = x.x1 = "x1" x.x2 = "x2" x.y1 = "ljhkjhkjh" - x.kind1 = true + {.cast(uncheckedAssign).}: + x.kind1 = true x.y2 = @["1", "2"] - x.kind2 = true + {.cast(uncheckedAssign).}: + x.kind2 = true x.z1 = "yes" - x.kind2 = false + {.cast(uncheckedAssign).}: + x.kind2 = false x.z2 = @["1", "2"] - x.kind2 = true + {.cast(uncheckedAssign).}: + x.kind2 = true x.z1 = "yes" x.kind2 = true # should be no effect doAssert(x.z1 == "yes") - x.kind2 = false - x.kind1 = x.kind2 # support self assignment with effect + {.cast(uncheckedAssign).}: + x.kind2 = false + x.kind1 = x.kind2 # support self assignment with effect try: x.kind1 = x.flag # flag is not accesible @@ -206,7 +211,8 @@ type error*: string proc init(): RocksDBResult[string] = - result.ok = true + {.cast(uncheckedAssign).}: + result.ok = true result.value = "ok" echo init() @@ -221,7 +227,8 @@ type MyObj = object of true: x1: string var a = MyObj(kind: false, x0: 1234) -a.kind = true +{.cast(uncheckedAssign).}: + a.kind = true doAssert(a.x1 == "") block: diff --git a/tests/arc/tcomputedgoto.nim b/tests/arc/tcomputedgoto.nim index 541a748c6..07487684a 100644 --- a/tests/arc/tcomputedgoto.nim +++ b/tests/arc/tcomputedgoto.nim @@ -1,16 +1,19 @@ discard """ - cmd: '''nim c --gc:arc $file''' - output: '''2 -2''' + cmd: '''nim c --mm:arc $file''' + output: ''' +2 +2 +destroyed +''' """ type ObjWithDestructor = object a: int -proc `=destroy`(self: var ObjWithDestructor) = +proc `=destroy`(self: ObjWithDestructor) = echo "destroyed" -proc `=`(self: var ObjWithDestructor, other: ObjWithDestructor) = +proc `=copy`(self: var ObjWithDestructor, other: ObjWithDestructor) = echo "copied" proc test(a: range[0..1], arg: ObjWithDestructor) = @@ -38,4 +41,4 @@ proc test(a: range[0..1], arg: ObjWithDestructor) = if iteration == 2: break -test(1, ObjWithDestructor()) \ No newline at end of file +test(1, ObjWithDestructor()) diff --git a/tests/arc/tcomputedgotocopy.nim b/tests/arc/tcomputedgotocopy.nim index 8337123ba..07487684a 100644 --- a/tests/arc/tcomputedgotocopy.nim +++ b/tests/arc/tcomputedgotocopy.nim @@ -1,13 +1,16 @@ discard """ - cmd: '''nim c --gc:arc $file''' - output: '''2 -2''' + cmd: '''nim c --mm:arc $file''' + output: ''' +2 +2 +destroyed +''' """ type ObjWithDestructor = object a: int -proc `=destroy`(self: var ObjWithDestructor) = +proc `=destroy`(self: ObjWithDestructor) = echo "destroyed" proc `=copy`(self: var ObjWithDestructor, other: ObjWithDestructor) = diff --git a/tests/arc/tcontrolflow.nim b/tests/arc/tcontrolflow.nim index 80cc2b187..dbc115903 100644 --- a/tests/arc/tcontrolflow.nim +++ b/tests/arc/tcontrolflow.nim @@ -76,7 +76,7 @@ var c = Control(x: 7) run(c) -proc sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = +proc sysFatal(exceptn: typedesc, message: string) {.inline.} = var buf = newStringOfCap(200) add(buf, "##") add(buf, message) diff --git a/tests/arc/tdup.nim b/tests/arc/tdup.nim new file mode 100644 index 000000000..61f262a68 --- /dev/null +++ b/tests/arc/tdup.nim @@ -0,0 +1,71 @@ +discard """ + cmd: "nim c --mm:arc --expandArc:foo --hints:off $file" + nimout: ''' +--expandArc: foo + +var + x + :tmpD + s + :tmpD_1 +x = Ref(id: 8) +inc: + :tmpD = `=dup`(x) + :tmpD +inc: + let blitTmp = x + blitTmp +var id_1 = 777 +s = RefCustom(id_2: addr(id_1)) +inc_1 : + :tmpD_1 = `=dup_1`(s) + :tmpD_1 +inc_1 : + let blitTmp_1 = s + blitTmp_1 +-- end of expandArc ------------------------ +''' +""" + +type + Ref = ref object + id: int + + RefCustom = object + id: ptr int + +proc `=dup`(x: RefCustom): RefCustom = + result.id = x.id + +proc inc(x: sink Ref) = + inc x.id + +proc inc(x: sink RefCustom) = + inc x.id[] + + +proc foo = + var x = Ref(id: 8) + inc(x) + inc(x) + var id = 777 + var s = RefCustom(id: addr id) + inc s + inc s + +foo() + +proc foo2 = + var x = Ref(id: 8) + inc(x) + doAssert x.id == 9 + inc(x) + doAssert x.id == 10 + var id = 777 + var s = RefCustom(id: addr id) + inc s + doAssert s.id[] == 778 + inc s + doAssert s.id[] == 779 + +foo2() diff --git a/tests/arc/texplicit_sink.nim b/tests/arc/texplicit_sink.nim new file mode 100644 index 000000000..4b021ed62 --- /dev/null +++ b/tests/arc/texplicit_sink.nim @@ -0,0 +1,29 @@ +discard """ + output: '''de''' + cmd: '''nim c --mm:arc --expandArc:main $file''' + nimout: '''--expandArc: main + +var + a + b_cursor +try: + a = f "abc" + b_cursor = "de" + `=sink`(a, b_cursor) + echo [a] +finally: + `=destroy`(a) +-- end of expandArc ------------------------''' +""" + +# bug #20572 + +proc f(s: string): string = s + +proc main = + var a = f "abc" + var b = "de" + `=sink`(a, b) + echo a + +main() diff --git a/tests/arc/thard_alignment.nim b/tests/arc/thard_alignment.nim index baa964c77..30cfddb05 100644 --- a/tests/arc/thard_alignment.nim +++ b/tests/arc/thard_alignment.nim @@ -1,9 +1,11 @@ discard """ disabled: "arm64" -cmd: "nim c --gc:arc $file" +cmd: "nim c --mm:arc -u:nimPreviewNonVarDestructor $file" output: "y" """ +# TODO: fixme: investigate why it failed with non-var destructors + {.passC: "-march=native".} proc isAlignedCheck(p: pointer, alignment: int) = diff --git a/tests/arc/titeration_doesnt_copy.nim b/tests/arc/titeration_doesnt_copy.nim new file mode 100644 index 000000000..e510a6eff --- /dev/null +++ b/tests/arc/titeration_doesnt_copy.nim @@ -0,0 +1,67 @@ +discard """ + output: "true" +""" + +type + Idx = object + i: int + Node = object + n: int + next: seq[Idx] + FooBar = object + s: seq[Node] + +proc `=copy`(dest: var Idx; source: Idx) {.error.} +proc `=copy`(dest: var Node; source: Node) {.error.} +proc `=copy`(dest: var FooBar; source: FooBar) {.error.} + +proc doSomething(ss: var seq[int], s: FooBar) = + for i in 0 .. s.s.len-1: + for elm in items s.s[i].next: + ss.add s.s[elm.i].n + +when isMainModule: + const foo = FooBar(s: @[Node(n: 1, next: @[Idx(i: 0)])]) + var ss: seq[int] + doSomething(ss, foo) + echo ss == @[1] + +from sequtils import mapIt +from strutils import join + +proc toBinSeq*(b: uint8): seq[uint8] = + ## Return binary sequence from each bits of uint8. + runnableExamples: + from sequtils import repeat + doAssert 0'u8.toBinSeq == 0'u8.repeat(8) + doAssert 0b1010_1010.toBinSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] + result = @[] + var c = b + for i in 1..8: + result.add (uint8(c and 0b1000_0000) shr 7) + c = c shl 1 + +proc toBinString*(data: openArray[uint8], col: int): string = + ## Return binary string from each bits of uint8. + runnableExamples: + doAssert @[0b0000_1111'u8, 0b1010_1010].toBinString(8) == "0000111110101010" + doAssert @[0b1000_0000'u8, 0b0000_0000].toBinString(1) == "10" + result = "" + for b in items data.mapIt(it.toBinSeq.mapIt(it.`$`[0].char)): + for i, c in b: + if i < col: + result.add c + +doAssert @[0b0000_1111'u8, 0b1010_1010].toBinString(8) == "0000111110101010" +doAssert @[0b1000_0000'u8, 0b0000_0000].toBinString(1) == "10" + +block: # bug #23982 + iterator `..`(a, b: ptr int16): ptr int16 = discard + var a: seq[int16] #; let p = a[0].addr + var b: seq[ptr int16] + + try: + for x in a[0].addr .. b[1]: # `p .. b[1]` works + discard + except IndexDefect: + discard diff --git a/tests/arc/tmalloc.nim b/tests/arc/tmalloc.nim new file mode 100644 index 000000000..1d72646c8 --- /dev/null +++ b/tests/arc/tmalloc.nim @@ -0,0 +1,16 @@ +discard """ + matrix: "--mm:arc -d:useMalloc; --mm:arc" +""" + +block: # bug #22058 + template foo(): auto = + {.noSideEffect.}: + newSeq[byte](1) + + type V = object + v: seq[byte] + + proc bar(): V = + V(v: foo()) + + doAssert bar().v == @[byte(0)] diff --git a/tests/arc/tmove_regression.nim b/tests/arc/tmove_regression.nim new file mode 100644 index 000000000..7d9a867c3 --- /dev/null +++ b/tests/arc/tmove_regression.nim @@ -0,0 +1,22 @@ +discard """ + output: '''/1/2 +/1 +/ +''' +"""" + +# bug #22001 + +import std / [os, strutils] + +proc finOp2(path, name: string): (string, File) = # Find & open FIRST `name` + var current = path + while true: + if current.isRootDir: break # <- current=="" => current.isRootDir + current = current.parentDir + let dir = current + echo dir.replace('\\', '/') # Commenting out try/except below hides bug + try: result[0] = dir/name; result[1] = open(result[0]); return + except CatchableError: discard + +discard finOp2("/1/2/3", "4") # All same if this->inside a proc diff --git a/tests/arc/tmovebug.nim b/tests/arc/tmovebug.nim index 002bd6796..8ad7c955c 100644 --- a/tests/arc/tmovebug.nim +++ b/tests/arc/tmovebug.nim @@ -93,6 +93,7 @@ destroy destroy destroy sink +sink destroy copy (f: 1) @@ -767,8 +768,7 @@ proc initC(): C = C(o: initO()) proc pair(): tuple[a: C, b: C] = - result.a = initC() # <- when firstWrite tries to find this node to start its analysis it fails, because injectdestructors uses copyTree/shallowCopy - result.b = initC() + result = (a: initC(), b: initC())# <- when firstWrite tries to find this node to start its analysis it fails, because injectdestructors uses copyTree/shallowCopy discard pair() @@ -818,3 +818,24 @@ proc atomicClosureOp = atomicClosureOp() + +template assertEq(a, b: untyped): untyped = + block: + let + aval = a + bval = b + + if aval != bval: + quit "bug!" + +proc convoluted = + let _ = (; + var val1: string; + if true: val1 = "22" + true + ) + + assertEq val1, "22" + assertEq val1, "22" + +convoluted() diff --git a/tests/arc/topenarray.nim b/tests/arc/topenarray.nim index 03ec7adf2..ba91666ba 100644 --- a/tests/arc/topenarray.nim +++ b/tests/arc/topenarray.nim @@ -6,6 +6,8 @@ Nim ''' matrix: "--gc:arc -d:useMalloc; --gc:arc" """ +{.experimental: "views".} + block: # bug 18627 proc setPosition(params: openArray[string]) = for i in params.toOpenArray(0, params.len - 1): @@ -22,3 +24,63 @@ block: # bug 18627 for i in params.toOpenArray(0, params.len - 1): echo i uciLoop2() + +when defined(nimPreviewSlimSystem): + import std/assertions + +block: # bug #20954 + block: + doAssertRaises(IndexDefect): + var v: array[10, int] + + echo len(toOpenArray(v, 20, 30)) + + block: + doAssertRaises(IndexDefect): + var v: seq[int] + + echo len(toOpenArray(v, 20, 30)) + +# bug #20422 + +proc f(a: var string) = + var v = a.toOpenArray(1, 3) + v[0] = 'a' + +var a = "Hello" +f(a) +doAssert a == "Hallo" + +# bug #22132 +block: + func foo[T](arr: openArray[T], idx: int = arr.low): string = + doAssert idx == 0 + return $arr + + let bug = ["0", "c", "a"] + + let str = foo(bug) + + const expected = """["0", "c", "a"]""" + doAssert str == expected + + const noBugConst = ["0", "c", "a"] + doAssert foo(noBugConst) == expected + let noBugSeq = @["0", "c", "a"] + doAssert foo(noBugSeq) == expected + +block: # bug #20865 + var p: pointer + var x: array[0, int] + # echo toOpenArray(x, 0, 1)[0] # Raises IndexDefect + doAssertRaises(IndexDefect): + echo toOpenArray(cast[ptr array[0, int]](p)[], 0, 1)[0] # Does not raise IndexDefect + +block: # bug #20987 + var v: array[1, byte] + + var p = cast[ptr array[0, byte]](addr v) + + doAssertRaises(IndexDefect): + echo toOpenArray(p[], 1, 2) + diff --git a/tests/arc/topt_no_cursor.nim b/tests/arc/topt_no_cursor.nim index 9585c04a0..0a4984a69 100644 --- a/tests/arc/topt_no_cursor.nim +++ b/tests/arc/topt_no_cursor.nim @@ -1,23 +1,20 @@ discard """ - output: '''(package: "", ext: "meo") -doing shady stuff... -3 -6 -(@[1], @[2]) -192.168.0.1 -192.168.0.1 -192.168.0.1 -192.168.0.1''' - cmd: '''nim c --gc:arc --expandArc:newTarget --expandArc:delete --expandArc:p1 --expandArc:tt --hint:Performance:off --assertions:off --expandArc:extractConfig --expandArc:mergeShadowScope --expandArc:check $file''' - nimout: '''--expandArc: newTarget + nimoutFull: true + cmd: '''nim c -r --warnings:off --hints:off --mm:arc --expandArc:newTarget --expandArc:delete --expandArc:p1 --expandArc:tt --hint:Performance:off --assertions:off --expandArc:extractConfig --expandArc:mergeShadowScope --expandArc:check $file''' + nimout: ''' +--expandArc: newTarget +var + splat + :tmp + :tmp_1 splat = splitDrive do: let blitTmp = path blitTmp :tmp = splat.drive -wasMoved(splat.drive) +`=wasMoved`(splat.drive) :tmp_1 = splat.path_1 -wasMoved(splat.path_1) +`=wasMoved`(splat.path_1) result = ( let blitTmp_1 = :tmp blitTmp_1, @@ -42,14 +39,14 @@ var lresult lvalue lnext - _ + tmpTupleAsgn lresult = @[123] -_ = ( +tmpTupleAsgn = ( let blitTmp = lresult blitTmp, ";") -lvalue = _[0] -lnext = _[1] -result.value = move lvalue +lvalue = tmpTupleAsgn[0] +lnext = tmpTupleAsgn[1] +`=sink`(result.value, move lvalue) `=destroy`(lnext) `=destroy_1`(lvalue) -- end of expandArc ------------------------ @@ -64,11 +61,9 @@ var try: it_cursor = x a = ( - wasMoved(:tmpD) - `=copy`(:tmpD, it_cursor.key) + :tmpD = `=dup`(it_cursor.key) :tmpD, - wasMoved(:tmpD_1) - `=copy`(:tmpD_1, it_cursor.val) + :tmpD_1 = `=dup`(it_cursor.val) :tmpD_1) echo [ :tmpD_2 = `$$`(a) @@ -96,11 +91,14 @@ try: `=copy`(lan_ip, splitted[1]) echo [lan_ip] echo [splitted[1]] + {.push, overflowChecks: false.} inc(i, 1) + {.pop.} finally: `=destroy`(splitted) finally: `=destroy_1`(lan_ip) +-- end of expandArc ------------------------ --expandArc: mergeShadowScope var shadowScope @@ -115,10 +113,11 @@ block :tmp: var :tmpD sym = shadowScope.symbols[i] addInterfaceDecl(c): - wasMoved(:tmpD) - `=copy_1`(:tmpD, sym) + :tmpD = `=dup`(sym) :tmpD + {.push, overflowChecks: false.} inc(i, 1) + {.pop.} `=destroy`(shadowScope) -- end of expandArc ------------------------ --expandArc: check @@ -128,21 +127,18 @@ this.isValid = fileExists(this.value) if dirExists(this.value): var :tmpD par = (dir: - wasMoved(:tmpD) - `=copy`(:tmpD, this.value) + :tmpD = `=dup`(this.value) :tmpD, front: "") else: var :tmpD_1 :tmpD_2 :tmpD_3 par = (dir_1: parentDir(this.value), front_1: - wasMoved(:tmpD_1) - `=copy`(:tmpD_1, - :tmpD_3 = splitPath do: - wasMoved(:tmpD_2) - `=copy`(:tmpD_2, this.value) + :tmpD_1 = `=dup`( + :tmpD_3 = splitDrive do: + :tmpD_2 = `=dup`(this.value) :tmpD_2 - :tmpD_3.tail) + :tmpD_3.path) :tmpD_1) `=destroy`(:tmpD_3) if dirExists(par.dir): @@ -150,7 +146,21 @@ if dirExists(par.dir): else: `=sink`(this.matchDirs, []) `=destroy`(par) --- end of expandArc ------------------------''' +-- end of expandArc ------------------------ +--expandArc: check + +check(this) +-- end of expandArc ------------------------ +(package: "", ext: "meo") +doing shady stuff... +3 +6 +(@[1], @[2]) +192.168.0.1 +192.168.0.1 +192.168.0.1 +192.168.0.1 +''' """ import os, std/private/ntpath @@ -357,7 +367,7 @@ proc getSubDirs(parent, front: string): seq[string] = @[] method check(this: Foo) {.base.} = this.isValid = fileExists(this.value) let par = if dirExists(this.value): (dir: this.value, front: "") - else: (dir: parentDir(this.value), front: splitPath(this.value).tail) + else: (dir: parentDir(this.value), front: splitDrive(this.value).path) if dirExists(par.dir): this.matchDirs = getSubDirs(par.dir, par.front) else: diff --git a/tests/arc/topt_refcursors.nim b/tests/arc/topt_refcursors.nim index f097150a3..8c638a4a1 100644 --- a/tests/arc/topt_refcursors.nim +++ b/tests/arc/topt_refcursors.nim @@ -1,26 +1,35 @@ discard """ output: '''''' cmd: '''nim c --gc:arc --expandArc:traverse --hint:Performance:off $file''' - nimout: '''--expandArc: traverse + nimout: ''' +--expandArc: traverse var it_cursor - jt_cursor -it_cursor = root -block :tmp: - while ( - not (it_cursor == nil)): - echo [it_cursor.s] - it_cursor = it_cursor.ri -jt_cursor = root -block :tmp_1: - while ( - not (jt_cursor == nil)): - var ri_1_cursor - ri_1_cursor = jt_cursor.ri - echo [jt_cursor.s] - jt_cursor = ri_1_cursor --- end of expandArc ------------------------''' + jt +try: + it_cursor = root + block :tmp: + while ( + not (it_cursor == nil)): + echo [it_cursor.s] + it_cursor = it_cursor.ri + `=copy`(jt, root) + block :tmp_1: + while ( + not (jt == nil)): + var ri_1 + try: + `=copy`(ri_1, jt.ri) + echo [jt.s] + `=sink`(jt, ri_1) + `=wasMoved`(ri_1) + finally: + `=destroy`(ri_1) +finally: + `=destroy`(jt) +-- end of expandArc ------------------------ +''' """ type diff --git a/tests/arc/topt_wasmoved_destroy_pairs.nim b/tests/arc/topt_wasmoved_destroy_pairs.nim index 2f971f112..c96340a30 100644 --- a/tests/arc/topt_wasmoved_destroy_pairs.nim +++ b/tests/arc/topt_wasmoved_destroy_pairs.nim @@ -1,7 +1,8 @@ discard """ output: '''''' cmd: '''nim c --gc:arc --expandArc:main --expandArc:tfor --hint:Performance:off $file''' - nimout: '''--expandArc: main + nimout: ''' +--expandArc: main var a @@ -29,6 +30,7 @@ try: x = f() block :tmp: var i_cursor + mixin inc var i_1 = 0 block :tmp_1: while i_1 < 4: @@ -37,25 +39,25 @@ try: if i_cursor == 2: return add(a): - wasMoved(:tmpD) - `=copy`(:tmpD, x) + :tmpD = `=dup`(x) :tmpD inc i_1, 1 if cond: add(a): let blitTmp = x - wasMoved(x) + `=wasMoved`(x) blitTmp else: add(b): let blitTmp_1 = x - wasMoved(x) + `=wasMoved`(x) blitTmp_1 finally: `=destroy`(x) `=destroy_1`(b) `=destroy_1`(a) --- end of expandArc ------------------------''' +-- end of expandArc ------------------------ +''' """ proc f(): seq[int] = diff --git a/tests/arc/tref_cast_error.nim b/tests/arc/tref_cast_error.nim index b0d2faf77..20139c1be 100644 --- a/tests/arc/tref_cast_error.nim +++ b/tests/arc/tref_cast_error.nim @@ -1,6 +1,6 @@ discard """ cmd: "nim c --gc:arc $file" - errormsg: "expression cannot be cast to ref RootObj" + errormsg: "expression cannot be cast to 'ref RootObj'" joinable: false """ diff --git a/tests/arc/trepr.nim b/tests/arc/trepr.nim index 50d433208..abf28330a 100644 --- a/tests/arc/trepr.nim +++ b/tests/arc/trepr.nim @@ -9,6 +9,7 @@ nil 2 Obj(member: ref @["hello"]) ref (member: ref @["hello"]) +ObjUa(v: 0, a: [...]) ''' """ @@ -87,3 +88,10 @@ macro extract(): untyped = test(parseExpr("discard")) extract() + +type + ObjUa = ref object + v: int + a: UncheckedArray[char] + +echo ObjUa().repr diff --git a/tests/arc/tstringliteral.nim b/tests/arc/tstringliteral.nim new file mode 100644 index 000000000..c5fac22d8 --- /dev/null +++ b/tests/arc/tstringliteral.nim @@ -0,0 +1,17 @@ +discard """ + matrix: "--mm:arc; --mm:orc" +""" + +block: # issue #24080 + var a = (s: "a") + var b = "a" + a.s.setLen 0 + b = a.s + doAssert b == "" + +block: # issue #24080, longer string + var a = (s: "abc") + var b = "abc" + a.s.setLen 2 + b = a.s + doAssert b == "ab" diff --git a/tests/arc/tweave.nim b/tests/arc/tweave.nim index 220d65f97..1c60ac403 100644 --- a/tests/arc/tweave.nim +++ b/tests/arc/tweave.nim @@ -8,6 +8,9 @@ discard """ import std/atomics +when defined(nimPreviewSlimSystem): + import std/[assertions, typedthreads] + const MemBlockSize = 256 type diff --git a/tests/arc/twrong_sinkinference.nim b/tests/arc/twrong_sinkinference.nim index 59930a9fa..ecf09d28a 100644 --- a/tests/arc/twrong_sinkinference.nim +++ b/tests/arc/twrong_sinkinference.nim @@ -1,6 +1,6 @@ discard """ cmd: "nim c --gc:arc $file" - errormsg: "type mismatch: got <proc (a: string, b: sink string){.noSideEffect, gcsafe, locks: 0.}>" + errormsg: "type mismatch: got <proc (a: string, b: sink string){.noSideEffect, gcsafe.}>" line: 18 """ diff --git a/tests/array/t15117.nim b/tests/array/t15117.nim new file mode 100644 index 000000000..157b04bee --- /dev/null +++ b/tests/array/t15117.nim @@ -0,0 +1,27 @@ +discard """ + matrix: "--cc:vcc" + disabled: "linux" + disabled: "bsd" + disabled: "osx" + disabled: "unix" + disabled: "posix" +""" +{.experimental: "views".} + +let a: array[0, byte] = [] +discard a + +type B = object + a:int +let b: array[0, B] = [] +let c: array[0, ptr B] = [] +let d: array[0, ref B] = [] +discard b +discard c +discard d + +discard default(array[0, B]) + +type + View1 = openArray[byte] +discard default(View1) diff --git a/tests/array/t20248.nim b/tests/array/t20248.nim new file mode 100644 index 000000000..66142548b --- /dev/null +++ b/tests/array/t20248.nim @@ -0,0 +1,14 @@ +discard """ +cmd: "nim check --hints:off $file" +errormsg: "ordinal type expected; given: Error Type" +nimout: ''' +t20248.nim(10, 36) Error: ordinal type expected; given: Error Type +t20248.nim(14, 20) Error: ordinal type expected; given: Error Type +''' +""" + +type Vec[N: static[int]] = array[0 ..< N, float] + +var v: Vec[32] + +var stuff: array[0 ..< 16, int] diff --git a/tests/misc/tinvalidarrayaccess.nim b/tests/array/tinvalidarrayaccess.nim index f8bce45ef..f8bce45ef 100644 --- a/tests/misc/tinvalidarrayaccess.nim +++ b/tests/array/tinvalidarrayaccess.nim diff --git a/tests/misc/tinvalidarrayaccess2.nim b/tests/array/tinvalidarrayaccess2.nim index 0a0703834..0a0703834 100644 --- a/tests/misc/tinvalidarrayaccess2.nim +++ b/tests/array/tinvalidarrayaccess2.nim diff --git a/tests/array/tlargeindex.nim b/tests/array/tlargeindex.nim new file mode 100644 index 000000000..61bcbd61d --- /dev/null +++ b/tests/array/tlargeindex.nim @@ -0,0 +1,18 @@ +discard """ + cmd: "nim check --hints:off $file" +""" + +# issue #17163 +var e: array[int32, byte] #[tt.Error + ^ index type 'int32' for array is too large]# +var f: array[uint32, byte] #[tt.Error + ^ index type 'uint32' for array is too large]# +var g: array[int64, byte] #[tt.Error + ^ index type 'int64' for array is too large]# +var h: array[uint64, byte] #[tt.Error + ^ index type 'uint64' for array is too large]# + +# crash in issue #23204 +proc y[N](): array[N, int] = default(array[N, int]) #[tt.Error + ^ index type 'int' for array is too large]# +discard y[int]() diff --git a/tests/assert/panicoverride.nim b/tests/assert/panicoverride.nim new file mode 100644 index 000000000..53ad64215 --- /dev/null +++ b/tests/assert/panicoverride.nim @@ -0,0 +1,15 @@ +# panicoverride.nim + +proc printf(fmt: cstring) {.varargs, importc, header:"stdio.h".} +proc exit(code: cint) {.importc, header:"stdlib.h".} + +{.push stack_trace: off, profiler:off.} + +proc rawoutput(s: cstring) = + printf("RAW: %s\n", s) + +proc panic(s: cstring) {.noreturn.} = + printf("PANIC: %s\n", s) + exit(0) + +{.pop.} \ No newline at end of file diff --git a/tests/assert/t21195.nim b/tests/assert/t21195.nim new file mode 100644 index 000000000..b690d22a0 --- /dev/null +++ b/tests/assert/t21195.nim @@ -0,0 +1,6 @@ +discard """ + matrix: "--verbosity:0 --os:standalone --mm:none" +""" +# bug #21195 +var n = 11 +assert(n == 12) diff --git a/tests/assert/tassert2.nim b/tests/assert/tassert2.nim index 5d849aaad..e32ab72e1 100644 --- a/tests/assert/tassert2.nim +++ b/tests/assert/tassert2.nim @@ -24,7 +24,7 @@ except AssertionDefect as e: try: assert false # assert test with no msg except AssertionDefect as e: - assert e.msg.endsWith "tassert2.nim(25, 10) `false` " + assert e.msg.endsWith "tassert2.nim(25, 3) `false` " try: let a = 1 @@ -100,7 +100,7 @@ block: ## checks for issue https://github.com/nim-lang/Nim/issues/9301 doAssert 1 + 1 == 3 except AssertionDefect as e: # used to const fold as false - assert e.msg.endsWith "tassert2.nim(100, 14) `1 + 1 == 3` " + assert e.msg.endsWith "tassert2.nim(100, 5) `1 + 1 == 3` " block: ## checks AST isn't transformed as it used to let a = 1 @@ -108,4 +108,4 @@ block: ## checks AST isn't transformed as it used to doAssert a > 1 except AssertionDefect as e: # used to rewrite as `1 < a` - assert e.msg.endsWith "tassert2.nim(108, 14) `a > 1` " + assert e.msg.endsWith "tassert2.nim(108, 5) `a > 1` " diff --git a/tests/assert/tassert_c.nim b/tests/assert/tassert_c.nim index 5c8f529ad..e3e3b8147 100644 --- a/tests/assert/tassert_c.nim +++ b/tests/assert/tassert_c.nim @@ -1,14 +1,14 @@ discard """ - cmd: "nim $target $options --excessiveStackTrace:off $file" + matrix: "-d:nimPreviewSlimSystem --stackTrace:on --excessiveStackTrace:off" output: '''true''' """ - +import std/assertions const expected = """ tassert_c.nim(35) tassert_c tassert_c.nim(34) foo assertions.nim(*) failedAssertImpl assertions.nim(*) raiseAssert -fatal.nim(*) sysFatal""" +""" proc tmatch(x, p: string): bool = var i = 0 diff --git a/tests/assign/moverload_asgn2.nim b/tests/assign/moverload_asgn2.nim index 6620adbeb..cfea48cd1 100644 --- a/tests/assign/moverload_asgn2.nim +++ b/tests/assign/moverload_asgn2.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc" +""" + type Concrete* = object a*, b*: string diff --git a/tests/assign/tvariantasgn.nim b/tests/assign/tvariantasgn.nim index 1c3deeae1..4c3c38ca5 100644 --- a/tests/assign/tvariantasgn.nim +++ b/tests/assign/tvariantasgn.nim @@ -24,3 +24,16 @@ s = TAny(kind: nkInt, intVal: 78) # s = nr # works nr = s # fails! echo "came here" + +block: # bug #12464 + type + Foo = object + case isFunc: bool + of false: nil + of true: + fun: proc(): int + + const i = Foo(isFunc: false) + + let j = i + doAssert not j.isFunc diff --git a/tests/async/t11558.nim b/tests/async/t11558.nim new file mode 100644 index 000000000..99961e7b6 --- /dev/null +++ b/tests/async/t11558.nim @@ -0,0 +1,13 @@ +discard """ +output: "Hello\n9" +""" +import std/asyncdispatch + +proc foo(): Future[string] {.async.} = + "Hello" + +proc bar(): Future[int] {.async.} = + result = 9 + +echo waitFor foo() +echo waitFor bar() diff --git a/tests/async/t17045.nim b/tests/async/t17045.nim new file mode 100644 index 000000000..2b5acf48a --- /dev/null +++ b/tests/async/t17045.nim @@ -0,0 +1,28 @@ +discard """ + targets: "c cpp" + matrix: "--mm:refc; --mm:arc" +""" + +type Future = ref object + +iterator paths: string = + # without "when nimvm" everything works + when nimvm: + yield "test.md" + else: + yield "test.md" + +template await(f: Future): string = + # need this yield, also the template has to return something + yield f + "hello world" + +proc generatePostContextsAsync() = + iterator generatePostContextsAsyncIter(): Future {.closure.} = + for filePath in paths(): + var temp = await Future() + + # need this line + var nameIterVar = generatePostContextsAsyncIter + +generatePostContextsAsync() \ No newline at end of file diff --git a/tests/async/t20111.nim b/tests/async/t20111.nim new file mode 100644 index 000000000..0aaa7d886 --- /dev/null +++ b/tests/async/t20111.nim @@ -0,0 +1,19 @@ +discard """ + action: "run" +""" +import asyncdispatch +type + Sync = object + Async = object + SyncRes = (Sync, string) + AsyncRes = (Async, string) + +proc foo(val: Sync | Async): Future[(Async, string) | (Sync, string)] {.multisync.} = + return (val, "hello") + +let + myAsync = Async() + mySync = Sync() + +doAssert typeof(waitFor foo(myAsync)) is AsyncRes +doAssert typeof(foo(mySync)) is SyncRes diff --git a/tests/async/t21447.nim b/tests/async/t21447.nim new file mode 100644 index 000000000..e4f7ae31f --- /dev/null +++ b/tests/async/t21447.nim @@ -0,0 +1,6 @@ +discard """ + action: "compile" + cmd: "nim c -d:release -d:futureLogging $file" +""" + +import std/asyncdispatch diff --git a/tests/async/t21893.nim b/tests/async/t21893.nim new file mode 100644 index 000000000..658cb02eb --- /dev/null +++ b/tests/async/t21893.nim @@ -0,0 +1,13 @@ +discard """ +output: "@[97]\ntrue" +""" + +import asyncdispatch + +proc test(): Future[bool] {.async.} = + const S4 = @[byte('a')] + echo S4 + return true + +echo waitFor test() + diff --git a/tests/async/t22210.nim b/tests/async/t22210.nim new file mode 100644 index 000000000..fcf939472 --- /dev/null +++ b/tests/async/t22210.nim @@ -0,0 +1,41 @@ +discard """ +output: ''' +stage 1 +stage 2 +stage 3 +(status: 200, data: "SOMEDATA") +''' +""" + +import std/asyncdispatch + + +# bug #22210 +type + ClientResponse = object + status*: int + data*: string + +proc subFoo1(): Future[int] {.async.} = + await sleepAsync(100) + return 200 + +proc subFoo2(): Future[string] {.async.} = + await sleepAsync(100) + return "SOMEDATA" + +proc testFoo(): Future[ClientResponse] {.async.} = + try: + let status = await subFoo1() + doAssert(status == 200) + let data = await subFoo2() + return ClientResponse(status: status, data: data) + finally: + echo "stage 1" + await sleepAsync(100) + echo "stage 2" + await sleepAsync(200) + echo "stage 3" + +when isMainModule: + echo waitFor testFoo() \ No newline at end of file diff --git a/tests/async/t22210_2.nim b/tests/async/t22210_2.nim new file mode 100644 index 000000000..9db664a32 --- /dev/null +++ b/tests/async/t22210_2.nim @@ -0,0 +1,73 @@ +import std/asyncdispatch + + +# bug #22210 +type + ClientResponse = object + status*: int + data*: string + +proc subFoo1(): Future[int] {.async.} = + await sleepAsync(100) + return 200 + +proc subFoo2(): Future[string] {.async.} = + await sleepAsync(100) + return "SOMEDATA" + + +proc testFoo2(): Future[ClientResponse] {.async.} = + var flag = 0 + try: + let status = await subFoo1() + doAssert(status == 200) + let data = await subFoo2() + result = ClientResponse(status: status, data: data) + finally: + inc flag + await sleepAsync(100) + inc flag + await sleepAsync(200) + inc flag + doAssert flag == 3 + +discard waitFor testFoo2() + +proc testFoo3(): Future[ClientResponse] {.async.} = + var flag = 0 + try: + let status = await subFoo1() + doAssert(status == 200) + let data = await subFoo2() + if false: + return ClientResponse(status: status, data: data) + finally: + inc flag + await sleepAsync(100) + inc flag + await sleepAsync(200) + inc flag + doAssert flag == 3 + +discard waitFor testFoo3() + + +proc testFoo4(): Future[ClientResponse] {.async.} = + var flag = 0 + try: + let status = await subFoo1() + doAssert(status == 200) + let data = await subFoo2() + if status == 200: + return ClientResponse(status: status, data: data) + else: + return ClientResponse() + finally: + inc flag + await sleepAsync(100) + inc flag + await sleepAsync(200) + inc flag + doAssert flag == 3 + +discard waitFor testFoo4() diff --git a/tests/async/tasync_gcunsafe.nim b/tests/async/tasync_gcunsafe.nim index 00c92b109..f3e6bc691 100644 --- a/tests/async/tasync_gcunsafe.nim +++ b/tests/async/tasync_gcunsafe.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'" + errormsg: "'anotherGCSafeAsyncProc (Async)' is not GC-safe as it calls 'asyncGCUnsafeProc'" cmd: "nim c --threads:on $file" file: "asyncmacro.nim" """ diff --git a/tests/async/tasync_traceback.nim b/tests/async/tasync_traceback.nim index cd16b2257..98f71b192 100644 --- a/tests/async/tasync_traceback.nim +++ b/tests/async/tasync_traceback.nim @@ -1,6 +1,5 @@ discard """ exitcode: 0 - disabled: "windows" output: "Matched" """ import asyncdispatch, strutils @@ -68,51 +67,22 @@ import re const expected = """ b failure Async traceback: - tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback - asyncmacro\.nim\(\d+?\)\s+?a - asyncmacro\.nim\(\d+?\)\s+?aNimAsyncContinue - ## Resumes an async procedure - tasync_traceback\.nim\(\d+?\)\s+?aIter - asyncmacro\.nim\(\d+?\)\s+?b - asyncmacro\.nim\(\d+?\)\s+?bNimAsyncContinue - ## Resumes an async procedure - tasync_traceback\.nim\(\d+?\)\s+?bIter - #\[ - tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback - asyncmacro\.nim\(\d+?\)\s+?a - asyncmacro\.nim\(\d+?\)\s+?aNimAsyncContinue - ## Resumes an async procedure - asyncmacro\.nim\(\d+?\)\s+?aIter - asyncfutures\.nim\(\d+?\)\s+?read - \]# + tasync_traceback\.nim\(\d+?\) tasync_traceback + tasync_traceback\.nim\(\d+?\) a \(Async\) + tasync_traceback\.nim\(\d+?\) b \(Async\) Exception message: b failure bar failure Async traceback: - tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback - asyncdispatch\.nim\(\d+?\)\s+?waitFor - asyncdispatch\.nim\(\d+?\)\s+?poll + tasync_traceback\.nim\(\d+?\) tasync_traceback + asyncdispatch\.nim\(\d+?\) waitFor + asyncdispatch\.nim\(\d+?\) poll ## Processes asynchronous completion events - asyncdispatch\.nim\(\d+?\)\s+?runOnce - asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks + asyncdispatch\.nim\(\d+?\) runOnce + asyncdispatch\.nim\(\d+?\) processPendingCallbacks ## Executes pending callbacks - asyncmacro\.nim\(\d+?\)\s+?barNimAsyncContinue - ## Resumes an async procedure - tasync_traceback\.nim\(\d+?\)\s+?barIter - #\[ - tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback - asyncdispatch\.nim\(\d+?\)\s+?waitFor - asyncdispatch\.nim\(\d+?\)\s+?poll - ## Processes asynchronous completion events - asyncdispatch\.nim\(\d+?\)\s+?runOnce - asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks - ## Executes pending callbacks - asyncmacro\.nim\(\d+?\)\s+?fooNimAsyncContinue - ## Resumes an async procedure - asyncmacro\.nim\(\d+?\)\s+?fooIter - asyncfutures\.nim\(\d+?\)\s+?read - \]# + tasync_traceback\.nim\(\d+?\) bar \(Async\) Exception message: bar failure """ @@ -122,28 +92,31 @@ Exception message: bar failure let resLines = splitLines(result.strip) let expLines = splitLines(expected.strip) -if resLines.len != expLines.len: - echo("Not matched! Wrong number of lines!") - echo expLines.len - echo resLines.len - echo("Expected: -----------") - echo expected - echo("Gotten: -------------") - echo result - echo("---------------------") - quit(QuitFailure) - -var ok = true -for i in 0 ..< resLines.len: - if not resLines[i].match(re(expLines[i])): - echo "Not matched! Line ", i + 1 - echo "Expected:" - echo expLines[i] - echo "Actual:" - echo resLines[i] - ok = false - -if ok: - echo("Matched") +when not defined(cpp): # todo fixme + if resLines.len != expLines.len: + echo("Not matched! Wrong number of lines!") + echo expLines.len + echo resLines.len + echo("Expected: -----------") + echo expected + echo("Gotten: -------------") + echo result + echo("---------------------") + quit(QuitFailure) + + var ok = true + for i in 0 ..< resLines.len: + if not resLines[i].match(re(expLines[i])): + echo "Not matched! Line ", i + 1 + echo "Expected:" + echo expLines[i] + echo "Actual:" + echo resLines[i] + ok = false + + if ok: + echo("Matched") + else: + quit(QuitFailure) else: - quit(QuitFailure) + echo("Matched") diff --git a/tests/async/tasyncssl.nim b/tests/async/tasyncssl.nim index 222aaa3a1..57de3271d 100644 --- a/tests/async/tasyncssl.nim +++ b/tests/async/tasyncssl.nim @@ -1,5 +1,6 @@ discard """ cmd: "nim $target --hints:on --define:ssl $options $file" + disabled: osx """ import asyncdispatch, asyncnet, net, strutils diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim index 77d03f8f6..f53767408 100644 --- a/tests/async/tioselectors.nim +++ b/tests/async/tioselectors.nim @@ -58,7 +58,11 @@ when not defined(windows): registerHandle(selector, client_socket, {Event.Write}, 0) freeAddrInfo(aiList) - discard selector.select(100) + + # make sure both sockets are selected + var nevs = 0 + while nevs < 2: + nevs += selector.select(100).len var sockAddress: SockAddr var addrLen = sizeof(sockAddress).Socklen @@ -427,6 +431,20 @@ when not defined(windows): doAssert(res[0].fd == dirfd and {Event.Vnode, Event.VnodeDelete} <= res[0].events) + proc pipe_test(): bool = + # closing the read end of a pipe will result in it automatically + # being removed from the kqueue; make sure no exception is raised + var s = newSelector[int]() + var fds: array[2, cint] + discard pipe(fds) + s.registerHandle(fds[1], {Write}, 0) + discard close(fds[0]) + let res = s.select(-1) + doAssert(res.len == 1) + s.unregister(fds[1]) + discard close(fds[1]) + return true + when hasThreadSupport: var counter = 0 @@ -468,6 +486,7 @@ when not defined(windows): when defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd): processTest("File notification test...", vnode_test()) + processTest("Pipe test...", pipe_test()) echo("All tests passed!") else: import nativesockets, winlean, os, osproc diff --git a/tests/async/tnewasyncudp.nim b/tests/async/tnewasyncudp.nim index ba1e4134e..68de796a0 100644 --- a/tests/async/tnewasyncudp.nim +++ b/tests/async/tnewasyncudp.nim @@ -58,7 +58,7 @@ proc launchSwarm(name: ptr SockAddr) {.async.} = 16384, cast[ptr SockAddr](addr saddr), addr slen) size = 0 - var grammString = $cstring(addr buffer) + var grammString = $cast[cstring](addr buffer) if grammString == message: saveSendingPort(sockport) inc(recvCount) @@ -80,7 +80,7 @@ proc readMessages(server: AsyncFD) {.async.} = 16384, cast[ptr SockAddr](addr(saddr)), addr(slen)) size = 0 - var grammString = $cstring(addr buffer) + var grammString = $cast[cstring](addr buffer) if grammString.startsWith("Message ") and saddr.sin_addr.s_addr == nativesockets.ntohl(INADDR_LOOPBACK.uint32): await sendTo(server, addr grammString[0], len(grammString), diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim index ad27ca38f..f0a8f6a62 100644 --- a/tests/async/twinasyncrw.nim +++ b/tests/async/twinasyncrw.nim @@ -19,7 +19,7 @@ when defined(windows): retFuture.complete() return true else: - retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret)))) + retFuture.fail(newOSError(OSErrorCode(ret))) return true var aiList = getAddrInfo(address, port, domain) @@ -45,7 +45,7 @@ when defined(windows): freeAddrInfo(aiList) if not success: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) return retFuture proc winRecv*(socket: AsyncFD, size: int, @@ -63,7 +63,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete("") else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) elif res == 0: # Disconnected retFuture.complete("") @@ -88,7 +88,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete(0) else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: retFuture.complete(res) # TODO: The following causes a massive slowdown. @@ -112,7 +112,7 @@ when defined(windows): if flags.isDisconnectionError(lastError): retFuture.complete() else: - retFuture.fail(newException(OSError, osErrorMsg(lastError))) + retFuture.fail(newOSError(lastError)) else: written.inc(res) if res != netSize: @@ -136,7 +136,7 @@ when defined(windows): var client = nativesockets.accept(sock.SocketHandle, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen)) if client == osInvalidSocket: - retFuture.fail(newException(OSError, osErrorMsg(osLastError()))) + retFuture.fail(newOSError(osLastError())) else: retFuture.complete((getAddrString(cast[ptr SockAddr](addr sockAddress)), client.AsyncFD)) diff --git a/tests/bind/tdatabind.nim b/tests/bind/tdatabind.nim deleted file mode 100644 index f6455749c..000000000 --- a/tests/bind/tdatabind.nim +++ /dev/null @@ -1,95 +0,0 @@ -discard """ - disabled: true -""" - -import events -type - TProperty*[T] = object of TObject - getProc: proc(property: TProperty[T]): T {.nimcall.} - setProc: proc(property: var TProperty[T], value: T) {.nimcall.} - value: T - ValueChanged*: TEventHandler - Binders: seq[TProperty[T]] - EEmitter: TEventEmitter - # Not a descriptive name but it was that or TPropertyValueChangeEventArgs. - TValueEventArgs[T] = object of TEventArgs - Property*: TProperty[T] - - -proc newProperty*[T](value: T): TProperty[T] = - var prop: TProperty[T] - - prop.EEmitter = initEventEmitter() - prop.Binders = @[] - prop.ValueChanged = initEventHandler("ValueChanged") - prop.value = value - - proc getter(property: TProperty[T]): T = - return property.value - - prop.getProc = getter - - proc setter(property: var TProperty[T], v: T) = - property.value = v - - # fire event here - var args: TValueEventArgs[T] - args.Property = property - property.EEmitter.emit(property.ValueChanged, args) - - prop.setProc = setter - - return prop - -proc `prop`[T] (p: TProperty[T]): T = - # I'm assuming this is trying to get a value from the property. - # i.e. myVar = myProperty - return p.getProc(p) - -proc `~=`[T] (p: var TProperty[T], v: T) = - # Assuming this is setting the value. - p.setProc(p, v) - -proc `$`[T] (p: TProperty[T]): string = - var value = p.getProc(p) - return $value - -proc propertyBind*[T](p1: var TProperty[T], p2: var TProperty[T]) = - p1.Binders.add(p2) - - # make handler -> handler[T] so trigger even more generics bugs ... - proc handler(e: TEventArgs) = - type TEA = TValueEventArgs[T] - var args = TEA(e) - var val = args.Property.getProc(p1) - for i in countup(0, len(e.Property.ValueChanged.Binders) -1): - var binded = e.Property.ValueChanged.Binders[i] - binded.setProc(binded, val) - - echo("Property 1 has changed to " & $val) - - if p1.ValueChanged.containsHandler(handler) == false: - addHandler(p1.ValueChanged, handler) - -proc `->`[T](p1: var TProperty[T], p2: var TProperty[T]) = - propertyBind(p2,p1) - -when true: - # Initial value testing - var myProp = newProperty(5) - - echo(myProp) - - myProp ~= 7 # Temp operator until overloading of '=' is implemented. - echo(myProp) - - # Binding testing - - var prop1 = newProperty(9) - var prop2: TProperty[int] - - prop2 -> prop1 # Binds prop2 to prop1 - - prop1 ~= 7 - echo(prop2) # Output: 7 - diff --git a/tests/borrow/tinvalidborrow.nim b/tests/borrow/tinvalidborrow.nim deleted file mode 100644 index 08148608d..000000000 --- a/tests/borrow/tinvalidborrow.nim +++ /dev/null @@ -1,25 +0,0 @@ -discard """ - cmd: "nim check --hints:off --warnings:off $file" - action: "reject" - nimout:''' -tinvalidborrow.nim(18, 3) Error: only a 'distinct' type can borrow `.` -tinvalidborrow.nim(19, 3) Error: only a 'distinct' type can borrow `.` -tinvalidborrow.nim(20, 1) Error: no symbol to borrow from found -''' -""" - -# bug #516 - -type - TAtom = culong - Test {.borrow:`.`.} = distinct int - Foo[T] = object - a: int - Bar[T] {.borrow:`.`.} = Foo[T] - OtherFoo {.borrow:`.`.} = Foo[int] -proc `==`*(a, b: TAtom): bool {.borrow.} - -var - d, e: TAtom - -discard( $(d == e) ) diff --git a/tests/compilepragma/test.c b/tests/c/tcompile.c index fc0482e40..fc0482e40 100644 --- a/tests/compilepragma/test.c +++ b/tests/c/tcompile.c diff --git a/tests/compilepragma/test.nim b/tests/c/tcompile.nim index 56087fa57..cf99fd7ed 100644 --- a/tests/compilepragma/test.nim +++ b/tests/c/tcompile.nim @@ -3,7 +3,7 @@ discard """ joinable: "false" """ -{.compile: "test.c".} +{.compile: "tcompile.c".} proc foo(a, b: cint): cint {.importc: "foo", cdecl.} diff --git a/tests/misc/temit.nim b/tests/c/temit.nim index ee7455d4c..1943c94ea 100644 --- a/tests/misc/temit.nim +++ b/tests/c/temit.nim @@ -4,6 +4,7 @@ discard """ # Test the new ``emit`` pragma: {.emit: """ +#include <stdio.h> static int cvariable = 420; """.} diff --git a/tests/misc/treservedcidentsasfields.nim b/tests/c/treservedcidentsasfields.nim index a9a954651..6cdf9e855 100644 --- a/tests/misc/treservedcidentsasfields.nim +++ b/tests/c/treservedcidentsasfields.nim @@ -1,39 +1,39 @@ -discard """ - targets: "c cpp" -""" - -import macros - -macro make_test_type(idents: varargs[untyped]): untyped = - result = nnkStmtList.newTree() - - var ident_defs: seq[NimNode] = @[] - for i in idents: - ident_defs.add newIdentDefs(i, ident("int")) - - result.add newTree(nnkTypeSection, - newTree(nnkTypeDef, - ident("TestType"), - newEmptyNode(), - newTree(nnkObjectTy, - newEmptyNode(), - newEmptyNode(), - newTree(nnkRecList, - ident_defs - ) - ) - ) - ) - -make_test_type( - auto, bool, catch, char, class, compl, const_cast, default, delete, double, - dynamic_cast, explicit, extern, false, float, friend, goto, int, long, - mutable, namespace, new, operator, private, protected, public, register, - reinterpret_cast, restrict, short, signed, sizeof, static_cast, struct, switch, - this, throw, true, typedef, typeid, typeof, typename, union, packed, unsigned, - virtual, void, volatile, wchar_t, alignas, alignof, constexpr, decltype, nullptr, - noexcept, thread_local, static_assert, char16_t, char32_t -) - -# Make sure the type makes it to codegen. -var test_instance: TestType +discard """ + targets: "c cpp" +""" + +import macros + +macro make_test_type(idents: varargs[untyped]): untyped = + result = nnkStmtList.newTree() + + var ident_defs: seq[NimNode] = @[] + for i in idents: + ident_defs.add newIdentDefs(i, ident("int")) + + result.add newTree(nnkTypeSection, + newTree(nnkTypeDef, + ident("TestType"), + newEmptyNode(), + newTree(nnkObjectTy, + newEmptyNode(), + newEmptyNode(), + newTree(nnkRecList, + ident_defs + ) + ) + ) + ) + +make_test_type( + auto, bool, catch, char, class, compl, const_cast, default, delete, double, + dynamic_cast, explicit, extern, false, float, friend, goto, int, long, + mutable, namespace, new, operator, private, protected, public, register, + reinterpret_cast, restrict, short, signed, sizeof, static_cast, struct, switch, + this, throw, true, typedef, typeid, typeof, typename, union, packed, unsigned, + virtual, void, volatile, wchar_t, alignas, alignof, constexpr, decltype, nullptr, + noexcept, thread_local, static_assert, char16_t, char32_t +) + +# Make sure the type makes it to codegen. +var test_instance: TestType diff --git a/tests/casestmt/t18964.nim b/tests/casestmt/t18964.nim new file mode 100644 index 000000000..1d2de2bbc --- /dev/null +++ b/tests/casestmt/t18964.nim @@ -0,0 +1,12 @@ +discard """ +errormsg: "invalid order of case branches" +""" + +import macros + +macro genCase(val: string): untyped = + result = nnkCaseStmt.newTree(val, + nnkElse.newTree(quote do: echo "else"), + nnkOfBranch.newTree(newLit("miauz"), quote do: echo "first branch")) + +genCase("miauz") diff --git a/tests/casestmt/tcase_issues.nim b/tests/casestmt/tcase_issues.nim new file mode 100644 index 000000000..20a79df2c --- /dev/null +++ b/tests/casestmt/tcase_issues.nim @@ -0,0 +1,7 @@ +discard """ + targets: "c js" +""" + +block: # bug #24031 + case 0 + else: discard \ No newline at end of file diff --git a/tests/casestmt/tcasestmt.nim b/tests/casestmt/tcasestmt.nim index 3a4907494..66de4183d 100644 --- a/tests/casestmt/tcasestmt.nim +++ b/tests/casestmt/tcasestmt.nim @@ -41,6 +41,11 @@ block t8333: case 0 of 'a': echo 0 else: echo 1 +block: # issue #11422 + var c: int = 5 + case c + of 'a' .. 'c': discard + else: discard block emptyset_when: @@ -298,3 +303,17 @@ proc main(a: uint64) = static: main(10) main(10) + +block: + # Just needs to compile + proc bar(): int {.discardable.} = discard + + proc foo() {.noreturn.} = discard + + case "*" + of "*": + bar() + else: + # Make sure this noreturn doesn't + # cause the discardable to not discard + foo() diff --git a/tests/casestmt/trangeexhaustiveness.nim b/tests/casestmt/trangeexhaustiveness.nim new file mode 100644 index 000000000..2b7f3558e --- /dev/null +++ b/tests/casestmt/trangeexhaustiveness.nim @@ -0,0 +1,7 @@ +block: # issue #22661 + template foo(a: typed) = + a + + foo: + case false + of false..true: discard diff --git a/tests/cast/tcast.nim b/tests/cast/tcast.nim new file mode 100644 index 000000000..205444ea3 --- /dev/null +++ b/tests/cast/tcast.nim @@ -0,0 +1,21 @@ +discard """ + targets: "c cpp js" +""" + +proc main() = + block: # bug #16806 + let + a = 42u16 + b = cast[int16](a) + doAssert a.int16 == 42 + doAssert b in int16.low..int16.high + + block: # bug #16808 + doAssert cast[int8](cast[uint8](int8(-12))) == int8(-12) + doAssert cast[int16](cast[uint16](int16(-12))) == int16(-12) + doAssert cast[int32](cast[uint32](int32(-12))) == int32(-12) + + doAssert cast[int8](int16.high) == -1 + +static: main() +main() diff --git a/tests/ccgbugs/m1/defs.nim b/tests/ccgbugs/m1/defs.nim new file mode 100644 index 000000000..ed78d8b72 --- /dev/null +++ b/tests/ccgbugs/m1/defs.nim @@ -0,0 +1,4 @@ +type MyObj* = object + field1*: int + s*: string + ch*: char diff --git a/tests/ccgbugs/m2/defs.nim b/tests/ccgbugs/m2/defs.nim new file mode 100644 index 000000000..798d1fea8 --- /dev/null +++ b/tests/ccgbugs/m2/defs.nim @@ -0,0 +1,4 @@ +type MyObj* = object + s*: string + field1*: int + ch*: char diff --git a/tests/ccgbugs/t10964.nim b/tests/ccgbugs/t10964.nim new file mode 100644 index 000000000..c19db6997 --- /dev/null +++ b/tests/ccgbugs/t10964.nim @@ -0,0 +1,7 @@ +func test*(input: var openArray[int32], start: int = 0, fin: int = input.len - 1) = + discard + +var someSeq = @[1'i32] + +test(someSeq) +# bug with gcc 14 \ No newline at end of file diff --git a/tests/ccgbugs/t13062.nim b/tests/ccgbugs/t13062.nim index fed32a1f7..cfda1da7c 100644 --- a/tests/ccgbugs/t13062.nim +++ b/tests/ccgbugs/t13062.nim @@ -1,5 +1,5 @@ discard """ - output: "[p = nil]" + matrix: "--mm:refc; --mm:orc" targets: "c cpp" """ @@ -24,4 +24,10 @@ type fulfilled: Atomic[bool] var x: Pledge -echo x.repr +when defined(cpp): + # TODO: fixme + discard "it doesn't work for refc/orc because of contrived `Atomic` in cpp" +elif defined(gcRefc): + doAssert x.repr == "[p = nil]" +else: # fixme # bug #20081 + doAssert x.repr == "Pledge(p: nil)" diff --git a/tests/ccgbugs/t15428.nim b/tests/ccgbugs/t15428.nim new file mode 100644 index 000000000..d9ae8ff16 --- /dev/null +++ b/tests/ccgbugs/t15428.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim $target --mm:refc $file" + output: '''5 +5 +[1, 2, 3, 4, 5] +(data: [1, 2, 3, 4, 5]) +''' +""" + +proc take[T](f: openArray[T]) = + echo f.len +let f = @[0,1,2,3,4] +take(f.toOpenArray(0,4)) + +{.experimental: "views".} +type + Foo = object + data: openArray[int] +let f2 = Foo(data: [1,2,3,4,5]) +echo f2.data.len +echo f2.data +echo f2 \ No newline at end of file diff --git a/tests/ccgbugs/t20139.nim b/tests/ccgbugs/t20139.nim new file mode 100644 index 000000000..4592b994d --- /dev/null +++ b/tests/ccgbugs/t20139.nim @@ -0,0 +1,10 @@ +discard """ + joinable: false +""" + +# bug #20139 +import m1/defs as md1 +import m2/defs as md2 + +doAssert $(md1.MyObj(field1: 1)) == """(field1: 1, s: "", ch: '\x00')""" +doAssert $(md2.MyObj(field1: 1)) == """(s: "", field1: 1, ch: '\x00')""" diff --git a/tests/ccgbugs/t20141.nim b/tests/ccgbugs/t20141.nim new file mode 100644 index 000000000..60e130690 --- /dev/null +++ b/tests/ccgbugs/t20141.nim @@ -0,0 +1,27 @@ +discard """ + joinable: false +""" + +# bug #20141 +type + A = object + B = object + U = proc() + +proc m(h: var B) = discard + +template n[T, U](x: U): T = + static: doAssert true + cast[ptr T](addr x)[] + +proc k() = + var res: A + m(n[B, A](res)) + +proc w(mounter: U) = discard + +proc mount(proto: U) = discard +proc v() = mount k + +# This is required for failure +w(v) diff --git a/tests/ccgbugs/t20787.nim b/tests/ccgbugs/t20787.nim new file mode 100644 index 000000000..c2d848c2c --- /dev/null +++ b/tests/ccgbugs/t20787.nim @@ -0,0 +1,4 @@ +type + Obj = object + f: UncheckedArray[byte] +let o = new Obj \ No newline at end of file diff --git a/tests/ccgbugs/t21116.nim b/tests/ccgbugs/t21116.nim new file mode 100644 index 000000000..cc77de198 --- /dev/null +++ b/tests/ccgbugs/t21116.nim @@ -0,0 +1,10 @@ +discard """ + targets: "c cpp" + disabled: windows +""" +# bug #21116 +import std/os + +proc p(glob: string) = + for _ in walkFiles(glob): discard +p("dir/*") diff --git a/tests/ccgbugs/t21972.nim b/tests/ccgbugs/t21972.nim new file mode 100644 index 000000000..58d0cfc62 --- /dev/null +++ b/tests/ccgbugs/t21972.nim @@ -0,0 +1,33 @@ +discard """ + targets: "c cpp" + outputsub: "Error: unhandled exception: Err2 [IOError]" + exitcode: "1" +""" + +proc bar(x: var int) = + inc x + if x == 3: + raise newException(ValueError, "H0") + + elif x == 5: + raise newException(IOError, "H1") + + elif x > 7: + raise newException(IOError, "H2") + + +proc foo() = + var i = 0 + while true: + try: + bar(i) + echo i + + except ValueError: + debugEcho("ValueError") + + except IOError: + raise newException(IOError, "Err2") + +when isMainModule: + foo() \ No newline at end of file diff --git a/tests/ccgbugs/t21995.nim b/tests/ccgbugs/t21995.nim new file mode 100644 index 000000000..0ec88aa59 --- /dev/null +++ b/tests/ccgbugs/t21995.nim @@ -0,0 +1,9 @@ +discard """ + targets: "c cpp" + output: "Hi!" +""" + +try: + raise +except: + echo "Hi!" \ No newline at end of file diff --git a/tests/ccgbugs/t22462.nim b/tests/ccgbugs/t22462.nim new file mode 100644 index 000000000..9adfbb19b --- /dev/null +++ b/tests/ccgbugs/t22462.nim @@ -0,0 +1,20 @@ +discard """ + action: "run" + output: ''' +1 +1 +1 +''' + matrix: "--mm:refc" + targets: "c cpp" +""" + +type Object = object + someComplexType: seq[int] + index: Natural + +func newObject(): Object = result.index.inc + +for i in 1..3: + let o = newObject() + echo o.index diff --git a/tests/ccgbugs/t23796.nim b/tests/ccgbugs/t23796.nim new file mode 100644 index 000000000..421ec04d8 --- /dev/null +++ b/tests/ccgbugs/t23796.nim @@ -0,0 +1,25 @@ +discard """ + targets: "c cpp" +""" + +# bug #23796 + +{.emit: """ +#ifdef __cplusplus +extern "C" { +#endif + +void fooArr(float data[3]) {} +void fooIntArr(int id, float data[3]) {} + +#ifdef __cplusplus +} +#endif +""".} + +proc fooArr(data: var array[3, cfloat]) {.importc.} +proc fooIntArr(id: cint, data: var array[3, cfloat]) {.importc, nodecl.} + +var arr = [cfloat 1, 2, 3] +fooArr(arr) +fooIntArr(1, arr) diff --git a/tests/ccgbugs/tassign_nil_strings.nim b/tests/ccgbugs/tassign_nil_strings.nim index f6fab7baa..e32bfcade 100644 --- a/tests/ccgbugs/tassign_nil_strings.nim +++ b/tests/ccgbugs/tassign_nil_strings.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim $target $options $file" + matrix: "--mm:refc" output: "Hello" ccodecheck: "\\i@'a = ((NimStringDesc*) NIM_NIL)'" """ diff --git a/tests/ccgbugs/tbug21505.nim b/tests/ccgbugs/tbug21505.nim new file mode 100644 index 000000000..0c0811ec5 --- /dev/null +++ b/tests/ccgbugs/tbug21505.nim @@ -0,0 +1,39 @@ +discard """ + action: "compile" + targets: "cpp" + cmd: "nim cpp $file" +""" + +# see #21505: ensure compilation of imported C++ objects with explicit constructors while retaining default initialization through codegen changes due to #21279 + +{.emit:"""/*TYPESECTION*/ + +struct ExplObj +{ + explicit ExplObj(int bar = 0) {} +}; + +struct BareObj +{ + BareObj() {} +}; + +""".} + +type + ExplObj {.importcpp.} = object + BareObj {.importcpp.} = object + +type + Composer = object + explObj: ExplObj + bareObj: BareObj + +proc foo = + var composer1 {.used.}: Composer + let composer2 {.used.} = Composer() + +var composer1 {.used.}: Composer +let composer2 {.used.} = Composer() + +foo() \ No newline at end of file diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim index 0fe4b8852..2eddc6fdd 100644 --- a/tests/ccgbugs/tcgbug.nim +++ b/tests/ccgbugs/tcgbug.nim @@ -4,6 +4,7 @@ success M1 M2 ok ''' +matrix: "--mm:refc;--mm:orc" """ type @@ -24,6 +25,7 @@ q(a) # bug #914 when defined(windows): + import std/widestrs var x = newWideCString("Hello") echo "success" @@ -122,3 +124,40 @@ proc bug19613 = doAssert x.bid.root.data[0] == 42 bug19613() + +proc foo = # bug #23280 + let foo = @[1,2,3,4,5,6] + doAssert toOpenArray(foo, 0, 5).len == 6 + doAssert toOpenArray(foo, 0, 5).len mod 6 == 0 # this should output 0 + doAssert toOpenArray(foo, 0, 5).max mod 6 == 0 + let L = toOpenArray(foo, 0, 5).len + doAssert L mod 6 == 0 + +foo() + +block: # bug #9940 + {.emit:"""/*TYPESECTION*/ +typedef struct { int base; } S; +""".} + + type S {.importc: "S", completeStruct.} = object + base: cint + proc init(x:ptr S) = + x.base = 1 + + type + Foo = object + a: seq[float] + b: seq[float] + c: seq[float] + d: seq[float] + s: S + + proc newT(): Foo = + var t: Foo + t.s.addr.init + doAssert t.s.base == 1 + t + + var t = newT() + doAssert t.s.base == 1 diff --git a/tests/ccgbugs/tcodegenbug1.nim b/tests/ccgbugs/tcodegenbug1.nim index c62bae1ef..d2ab97ede 100644 --- a/tests/ccgbugs/tcodegenbug1.nim +++ b/tests/ccgbugs/tcodegenbug1.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''obj = (inner: (kind: Just, id: 7)) obj.inner.id = 7 id = 7 diff --git a/tests/ccgbugs/tdeepcopy_addr_rval.nim b/tests/ccgbugs/tdeepcopy_addr_rval.nim index 07fb8f8ef..4a0b0deaa 100644 --- a/tests/ccgbugs/tdeepcopy_addr_rval.nim +++ b/tests/ccgbugs/tdeepcopy_addr_rval.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc --deepcopy:on" output: "3" """ diff --git a/tests/ccgbugs/tderefblock.nim b/tests/ccgbugs/tderefblock.nim index fd21a19b8..d3ba07667 100644 --- a/tests/ccgbugs/tderefblock.nim +++ b/tests/ccgbugs/tderefblock.nim @@ -1,6 +1,5 @@ discard """ - cmd: "nim c -d:release -d:danger $file" - matrix: ";--gc:orc" + matrix: "--mm:refc -d:release -d:danger;--mm:orc -d:useMalloc -d:release -d:danger" output: "42" """ @@ -23,3 +22,55 @@ proc m() = echo $f.a m() + +block: # bug #21540 + type + Option = object + val: string + has: bool + + proc some(val: string): Option = + result.has = true + result.val = val + + # Remove lent and it works + proc get(self: Option): lent string = + result = self.val + + type + StringStream = ref object + data: string + pos: int + + proc readAll(s: StringStream): string = + result = newString(s.data.len) + copyMem(addr(result[0]), addr(s.data[0]), s.data.len) + + proc newStringStream(s: string = ""): StringStream = + new(result) + result.data = s + + proc parseJson(s: string): string = + let stream = newStringStream(s) + result = stream.readAll() + + proc main = + let initialFEN = block: + let initialFEN = some parseJson("startpos") + initialFEN.get + + doAssert initialFEN == "startpos" + + main() + +import std/[ + json, + options +] + +block: # bug #21540 + let cheek = block: + let initialFEN = some("""{"initialFen": "startpos"}""".parseJson{"initialFen"}.getStr) + initialFEN.get + + doAssert cheek == "startpos" diff --git a/tests/ccgbugs/tforward_decl_only.nim b/tests/ccgbugs/tforward_decl_only.nim index 416e50eb5..b115dcbe7 100644 --- a/tests/ccgbugs/tforward_decl_only.nim +++ b/tests/ccgbugs/tforward_decl_only.nim @@ -1,7 +1,5 @@ discard """ -ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' {')" -ccodecheck: "\\i !@('mymoduleInit')" -ccodecheck: "\\i @('atmmymoduledotnim_DatInit000')" +ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' _')" output: "hello" """ diff --git a/tests/ccgbugs/thtiobj.nim b/tests/ccgbugs/thtiobj.nim index 7a656905f..6db24dad0 100644 --- a/tests/ccgbugs/thtiobj.nim +++ b/tests/ccgbugs/thtiobj.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" targets: "c cpp" """ diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim index 8806a2f21..9eb58221c 100644 --- a/tests/ccgbugs/tmissinginit.nim +++ b/tests/ccgbugs/tmissinginit.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''0 0 0 diff --git a/tests/ccgbugs/tmissingvolatile.nim b/tests/ccgbugs/tmissingvolatile.nim index 1eccdc6b1..b877eff71 100644 --- a/tests/ccgbugs/tmissingvolatile.nim +++ b/tests/ccgbugs/tmissingvolatile.nim @@ -1,6 +1,6 @@ discard """ output: "1" - cmd: r"nim c --hints:on $options -d:release $file" + cmd: r"nim c --hints:on $options --mm:refc -d:release $file" ccodecheck: "'NI volatile state;'" targets: "c" """ diff --git a/tests/ccgbugs/tnoalias.nim b/tests/ccgbugs/tnoalias.nim index f200992d7..2c3c2f0f4 100644 --- a/tests/ccgbugs/tnoalias.nim +++ b/tests/ccgbugs/tnoalias.nim @@ -1,5 +1,5 @@ discard """ - ccodecheck: "\\i@'NI* NIM_NOALIAS field;' @'NIM_CHAR* NIM_NOALIAS x,' @'void* NIM_NOALIAS q'" + ccodecheck: "\\i@'NI* NIM_NOALIAS field;' @'NIM_CHAR* NIM_NOALIAS x_p0,' @'void* NIM_NOALIAS q'" """ type diff --git a/tests/ccgbugs/tsamename3.nim b/tests/ccgbugs/tsamename3.nim index a69391e5c..ded18e9f8 100644 --- a/tests/ccgbugs/tsamename3.nim +++ b/tests/ccgbugs/tsamename3.nim @@ -109,3 +109,12 @@ block: # make sure `hashType` doesn't recurse infinitely a, b: PFoo c: int var a: PFoo + +block: # issue #22571 + macro foo(x: typed) = + result = x + + block: # or `proc main =` + foo: + type Foo = object + doAssert $Foo() == "()" diff --git a/tests/ccgbugs/twrong_tupleconv.nim b/tests/ccgbugs/twrong_tupleconv.nim index 7a887d183..031712dac 100644 --- a/tests/ccgbugs/twrong_tupleconv.nim +++ b/tests/ccgbugs/twrong_tupleconv.nim @@ -1,3 +1,8 @@ +discard """ + targets: "c cpp" + matrix: "--gc:refc; --gc:arc" +""" + # bug #1833 iterator myitems*[T](a: var seq[T]): var T {.inline.} = ## iterates over each item of `a` so that you can modify the yielded value. @@ -18,3 +23,13 @@ var ys = @[(1,"a"),(2,"b"),(3,"c")] for y in myitems(ys): inc y[0] +# bug #16331 +type T1 = tuple[a, b: int] + +proc p(b: bool): string = + var x: T1 = (10, 20) + x = if b: (x.b, x.a) else: (-x.b, -x.a) + $x + +assert p(false) == "(a: -20, b: -10)" +assert p(true) == "(a: 20, b: 10)" diff --git a/tests/ccgbugs2/tcodegen.nim b/tests/ccgbugs2/tcodegen.nim index 84cd76e2f..aac1ecaf3 100644 --- a/tests/ccgbugs2/tcodegen.nim +++ b/tests/ccgbugs2/tcodegen.nim @@ -1,28 +1,47 @@ -discard """ - targets: "c cpp" -""" - -# bug #19094 -type - X = object - filler: array[2048, int] - innerAddress: uint - -proc initX(): X = - result.innerAddress = cast[uint](result.addr) - -proc initXInPlace(x: var X) = - x.innerAddress = cast[uint](x.addr) - -block: # NRVO1 - var x = initX() - let innerAddress = x.innerAddress - let outerAddress = cast[uint](x.addr) - doAssert(innerAddress == outerAddress) # [OK] - -block: # NRVO2 - var x: X - initXInPlace(x) - let innerAddress = x.innerAddress - let outerAddress = cast[uint](x.addr) - doAssert(innerAddress == outerAddress) # [OK] +discard """ + targets: "c cpp" +""" + +# bug #19094 +type + X = object + filler: array[2048, int] + innerAddress: uint + +proc initX(): X = + result.innerAddress = cast[uint](result.addr) + +proc initXInPlace(x: var X) = + x.innerAddress = cast[uint](x.addr) + +block: # NRVO1 + var x = initX() + let innerAddress = x.innerAddress + let outerAddress = cast[uint](x.addr) + doAssert(innerAddress == outerAddress) # [OK] + +block: # NRVO2 + var x: X + initXInPlace(x) + let innerAddress = x.innerAddress + let outerAddress = cast[uint](x.addr) + doAssert(innerAddress == outerAddress) # [OK] + +block: # bug #22354 + type Object = object + foo: int + + proc takeFoo(self: var Object): int = + result = self.foo + self.foo = 999 + + proc doSomething(self: var Object; foo: int = self.takeFoo()) = + discard + + proc main() = + var obj = Object(foo: 2) + obj.doSomething() + doAssert obj.foo == 999 + + + main() diff --git a/tests/closure/t19095.nim b/tests/closure/t19095.nim new file mode 100644 index 000000000..880456e02 --- /dev/null +++ b/tests/closure/t19095.nim @@ -0,0 +1,35 @@ +discard """ + action: compile +""" + +block: + func inCheck() = + discard + + iterator iter(): int = + yield 0 + yield 0 + + func search() = + let inCheck = 0 + + for i in iter(): + + proc hello() = + inCheck() + + search() +block: + iterator iter(): int = + yield 0 + yield 0 + + func search() = + let lmrMoveCounter = 0 + + for i in iter(): + + proc hello() = + discard lmrMoveCounter + + search() diff --git a/tests/closure/t20152.nim b/tests/closure/t20152.nim new file mode 100644 index 000000000..484ea0741 --- /dev/null +++ b/tests/closure/t20152.nim @@ -0,0 +1,20 @@ +discard """ + action: compile +""" + +proc foo() = + iterator it():int {.closure.} = + yield 1 + proc useIter() {.nimcall.} = + var iii = it # <-- illegal capture + doAssert iii() == 1 + useIter() +foo() + +proc foo2() = + proc bar() = # Local function, but not a closure, because no captures + echo "hi" + proc baz() {.nimcall.} = # Calls local function + bar() + baz() +foo2() diff --git a/tests/closure/t8550.nim b/tests/closure/t8550.nim index 153246f08..a07f45cdc 100644 --- a/tests/closure/t8550.nim +++ b/tests/closure/t8550.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: "@[\"42\"]" """ diff --git a/tests/closure/t9334.nim b/tests/closure/t9334.nim new file mode 100644 index 000000000..36a9a7d77 --- /dev/null +++ b/tests/closure/t9334.nim @@ -0,0 +1,19 @@ +discard """ + cmd: "nim $target --hints:off $options -r $file" + nimout: '''@[1] +@[1, 1] +''' + nimoutFull: true +""" +proc p(s: var seq[int]): auto = + let sptr = addr s + return proc() = sptr[].add 1 + +proc f = + var data = @[1] + p(data)() + echo repr data + +static: + f() # prints [1] +f() # prints [1, 1] diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim index 8ae6c44bb..401a71d40 100644 --- a/tests/closure/tclosure.nim +++ b/tests/closure/tclosure.nim @@ -65,7 +65,7 @@ block tclosure: # bug #5015 - type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.} + type Mutator = proc(matched: string): string {.noSideEffect, gcsafe.} proc putMutated( MutatorCount: static[int], @@ -239,19 +239,19 @@ block doNotation: b.onClick do (e: Event): echo "click at ", e.x, ",", e.y - b.onFocusLost: + b.onFocusLost do (): echo "lost focus 1" - b.onFocusLost do: + b.onFocusLost do (): echo "lost focus 2" - b.onUserEvent("UserEvent 1") do: + b.onUserEvent("UserEvent 1") do (): discard - b.onUserEvent "UserEvent 2": + onUserEvent(b, "UserEvent 2") do (): discard - b.onUserEvent("UserEvent 3"): + b.onUserEvent("UserEvent 3") do (): discard b.onUserEvent("UserEvent 4", () => echo "event 4") @@ -491,3 +491,14 @@ block tnoclosure: row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1]) echo row pascal(10) + +block: # bug #22297 + iterator f: int {.closure.} = + try: + yield 12 + finally: + return 14 + + let s = f + doAssert s() == 12 + doAssert s() == 14 diff --git a/tests/closure/tclosure_issues.nim b/tests/closure/tclosure_issues.nim index 4688834de..b1a2d7c6b 100644 --- a/tests/closure/tclosure_issues.nim +++ b/tests/closure/tclosure_issues.nim @@ -71,12 +71,12 @@ block tissue7104: proc sp(cb: proc())= cb() - sp: + sp do (): var i = 0 echo "ok ", i - sp(): + sp do (): inc i echo "ok ", i - sp do: + sp do (): inc i echo "ok ", i diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim index 47f3f105f..37d0f68a2 100644 --- a/tests/closure/tinvalidclosure.nim +++ b/tests/closure/tinvalidclosure.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe, locks: 0.}>" + errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe.}>" line: 12 """ diff --git a/tests/closure/tinvalidclosure5.nim b/tests/closure/tinvalidclosure5.nim index d03d93867..3b5f46a40 100644 --- a/tests/closure/tinvalidclosure5.nim +++ b/tests/closure/tinvalidclosure5.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got <proc (){.closure, gcsafe, locks: 0.}> but expected 'A = proc (){.nimcall.}'" + errormsg: "type mismatch: got <proc (){.closure, gcsafe.}> but expected 'A = proc (){.nimcall.}'" line: 9 """ diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim index ca8d0e08b..ec5af9b13 100644 --- a/tests/closure/tnested.nim +++ b/tests/closure/tnested.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' foo88 23 24foo 88 @@ -33,7 +34,7 @@ py py px 6 -proc (){.closure, gcsafe, locks: 0.} +proc (){.closure, noSideEffect, gcsafe.} ''' """ @@ -183,14 +184,32 @@ block tclosure2: import typetraits -proc myDiscard[T](a: T) = discard +block: + proc myDiscard[T](a: T) = discard -proc foo() = - let a = 5 - let f = (proc() = - myDiscard (proc() = echo a) - ) - echo name(typeof(f)) + proc foo() = + let a = 5 + let f = (proc() = + myDiscard (proc() = echo a) + ) + echo name(typeof(f)) -foo() + foo() + +block: + iterator foo: int {.closure.} = + yield 1 + yield 2 + yield 3 + + proc pork = + let call = foo + for i in call(): + discard i + + let call2 = foo + while not finished(call2): + discard call2() + + pork() diff --git a/tests/closure/tstmtlist.nim b/tests/closure/tstmtlist.nim new file mode 100644 index 000000000..6a1390617 --- /dev/null +++ b/tests/closure/tstmtlist.nim @@ -0,0 +1,9 @@ +discard """ + action: compile +""" + +proc foo(x: proc()) = x() +foo: echo "a" #[tt.Warning + ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]# +foo do: echo "b" #[tt.Warning + ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]# diff --git a/tests/codegen/titaniummangle.nim b/tests/codegen/titaniummangle.nim new file mode 100644 index 000000000..4b45e59ae --- /dev/null +++ b/tests/codegen/titaniummangle.nim @@ -0,0 +1,193 @@ +discard """ + targets: "c" + matrix: "--debugger:native" + ccodecheck: "'_ZN14titaniummangle8testFuncE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE6stringN14titaniummangle3FooE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3int7varargsI6stringE'" + ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle3BooE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE8typeDescIN14titaniummangle17EnumAnotherSampleEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI14uncheckedArrayI3intEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3setIN14titaniummangle10EnumSampleEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE4procI6string6stringE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3intN10Comparable10ComparableE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'" + ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'" + ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'" + ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'" + ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI3int3intE7cstring'" + ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI5float5floatE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3intE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrIN14titaniummangle3FooEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3ptrI3intEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3refIN14titaniummangle3FooEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3varIN14titaniummangle3FooEE5int325int323refIN14titaniummangle3FooEE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE3varI3intE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE9openArrayI6stringE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE5arrayI7range013intE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI3intE'" + ccodecheck: "'_ZN14titaniummangle8testFuncE10Container2I5int325int32E'" + ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI10Container2I5int325int32EE'" +""" + +#When debugging this notice that if one check fails, it can be due to any of the above. + +type + Comparable = concept x, y + (x < y) is bool + + Foo = object + a: int32 + b: int32 + + FooTuple = tuple + a: int + b: int + + Container[T] = object + data: T + + Container2[T, T2] = object + data: T + data2: T2 + + Boo = distinct Foo + + Coo = Foo + + Doo = Boo | Foo + + TestProc = proc(a:string): string + +type EnumSample = enum + a, b, c + +type EnumAnotherSample = enum + a, b, c + +proc testFunc(a: set[EnumSample]) = + echo $a + +proc testFunc(a: typedesc) = + echo $a + +proc testFunc(a: ptr Foo) = + echo repr a + +proc testFunc(s: string, a: Coo) = + echo repr a + +proc testFunc(s: int, a: Comparable) = + echo repr a + +proc testFunc(a: TestProc) = + let b = "" + echo repr a("") + +proc testFunc(a: ref Foo) = + echo repr a + +proc testFunc(b: Boo) = + echo repr b + +proc testFunc(a: ptr UncheckedArray[int]) = + echo repr a + +proc testFunc(a: ptr int) = + echo repr a + +proc testFunc(a: ptr ptr int) = + echo repr a + +proc testFunc(e: FooTuple, str: cstring) = + echo e + +proc testFunc(e: (float, float)) = + echo e + +proc testFunc(e: EnumSample) = + echo e + +proc testFunc(e: var int) = + echo e + +proc testFunc(e: var Foo, a, b: int32, refFoo: ref Foo) = + echo e + +proc testFunc(xs: Container[int]) = + let a = 2 + echo xs + +proc testFunc(xs: Container2[int32, int32]) = + let a = 2 + echo xs + +proc testFunc(xs: Container[Container2[int32, int32]]) = + let a = 2 + echo xs + +proc testFunc(xs: seq[int]) = + let a = 2 + echo xs + +proc testFunc(xs: openArray[string]) = + let a = 2 + echo xs + +proc testFunc(xs: array[2, int]) = + let a = 2 + echo xs + +proc testFunc(e: EnumAnotherSample) = + echo e + +proc testFunc(a, b: int) = + echo "hola" + discard + +proc testFunc(a: int, xs: varargs[string]) = + let a = 10 + for x in xs: + echo x + +proc testFunc() = + var a = 2 + var aPtr = a.addr + var foo = Foo() + let refFoo : ref Foo = new(Foo) + let b = Foo().Boo() + let d: Doo = Foo() + testFunc("", Coo()) + testFunc(1, ) + testFunc(b) + testFunc(EnumAnotherSample) + var t = [1, 2] + let uArr = cast[ptr UncheckedArray[int]](t.addr) + testFunc(uArr) + testFunc({}) + testFunc(proc(s:string): string = "test") + testFunc(20, a.int32) + testFunc(20, 2) + testFunc(EnumSample.c) + testFunc(EnumAnotherSample.c) + testFunc((2, 1), "adios") + testFunc((22.1, 1.2)) + testFunc(a.addr) + testFunc(foo.addr) + testFunc(aPtr.addr) + testFunc(refFoo) + testFunc(foo, 2, 1, refFoo) + testFunc(a) + testFunc(@[2, 1, 2]) + testFunc(@["hola"]) + testFunc(2, "hola", "adios") + let arr: array[2, int] = [2, 1] + testFunc(arr) + testFunc(Container[int](data: 10)) + let c2 = Container2[int32, int32](data: 10, data2: 20) + testFunc(c2) + testFunc(Container[Container2[int32, int32]](data: c2)) + + +testFunc() \ No newline at end of file diff --git a/tests/actiontable/tactiontable.nim b/tests/collections/tactiontable.nim index 3f15a70bd..3f15a70bd 100644 --- a/tests/actiontable/tactiontable.nim +++ b/tests/collections/tactiontable.nim diff --git a/tests/collections/tseq.nim b/tests/collections/tseq.nim index a7a0c724e..0f8084c78 100644 --- a/tests/collections/tseq.nim +++ b/tests/collections/tseq.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: ''' Hithere, what's your name?Hathere, what's your name? fA13msg1falsefB14msg2truefC15msg3false @@ -11,8 +12,7 @@ FilterIt: [1, 3, 7] Concat: [1, 3, 5, 7, 2, 4, 6] Deduplicate: [1, 2, 3, 4, 5, 7] @[()] -@[1, 42, 3] -@[1, 42, 3] +Minmax: (1, 7) 2345623456 ''' """ @@ -157,42 +157,51 @@ block tsequtils: let someObjSeq = aSeq.mapIt(it.field) echo someObjSeq - - -block tshallowseq: - proc xxx() = - var x: seq[int] = @[1, 2, 3] - var y: seq[int] - system.shallowCopy(y, x) - y[1] = 42 - echo y - echo x - xxx() - - -block tshallowemptyseq: - proc test() = - var nilSeq: seq[int] = @[] - var emptySeq: seq[int] = newSeq[int]() - block: - var t = @[1,2,3] - shallow(nilSeq) - t = nilSeq - doAssert t == @[] - block: - var t = @[1,2,3] - shallow(emptySeq) - t = emptySeq - doAssert t == @[] - block: - var t = @[1,2,3] - shallowCopy(t, nilSeq) - doAssert t == @[] - block: - var t = @[1,2,3] - shallowCopy(t, emptySeq) - doAssert t == @[] - test() + block minmax: + doAssert minmax(@[0]) == (0, 0) + doAssert minmax(@[0, 1]) == (0, 1) + doAssert minmax(@[1, 0]) == (0, 1) + doAssert minmax(@[8,2,1,7,3,9,4,0,5]) == (0, 9) + echo "Minmax: ", $(minmax(concat(seq1, seq2))) + + +when not defined(nimseqsv2): + block tshallowseq: + proc xxx() = + var x: seq[int] = @[1, 2, 3] + var y: seq[int] + system.shallowCopy(y, x) + y[1] = 42 + doAssert y == @[1, 42, 3] + doAssert x == @[1, 42, 3] + xxx() + + + block tshallowemptyseq: + proc test() = + var nilSeq: seq[int] = @[] + var emptySeq: seq[int] = newSeq[int]() + block: + var t = @[1,2,3] + when defined(gcRefc): + shallow(nilSeq) + t = nilSeq + doAssert t == @[] + block: + var t = @[1,2,3] + when defined(gcRefc): + shallow(emptySeq) + t = emptySeq + doAssert t == @[] + block: + var t = @[1,2,3] + shallowCopy(t, nilSeq) + doAssert t == @[] + block: + var t = @[1,2,3] + shallowCopy(t, emptySeq) + doAssert t == @[] + test() import strutils @@ -214,3 +223,20 @@ for i in 0..100: var test = newSeqOfCap[uint32](1) test.setLen(1) doAssert test[0] == 0, $(test[0], i) + + +# bug #22560 +doAssert len(newSeqOfCap[int](42)) == 0 + +block: # bug #17197 + type Matrix = seq[seq[int]] + + proc needlemanWunsch(sequence1: string, sequence2: string, gap_penal: int8, match: int8, indel_penal: int8): bool = + let seq2_len = sequence2.len + + var grid: Matrix + for i in sequence1: + grid.add(newSeqOfCap[seq[int]](seq2_len)) + result = true + + doAssert needlemanWunsch("ABC", "DEFG", 1, 2, 3) diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim index 638f4241b..95f9418a0 100644 --- a/tests/collections/ttables.nim +++ b/tests/collections/ttables.nim @@ -177,16 +177,14 @@ block tableconstr: block ttables2: proc TestHashIntInt() = var tab = initTable[int,int]() - let n = 100_000 + let n = 10 for i in 1..n: tab[i] = i for i in 1..n: var x = tab[i] if x != i : echo "not found ", i - proc run1() = - for i in 1 .. 50: - TestHashIntInt() + TestHashIntInt() # bug #2107 @@ -198,7 +196,6 @@ block ttables2: delTab[5] = 5 - run1() echo "2" block tablesref: diff --git a/tests/compileoption/texperimental.nim b/tests/compileoption/texperimental.nim new file mode 100644 index 000000000..be637e58a --- /dev/null +++ b/tests/compileoption/texperimental.nim @@ -0,0 +1,20 @@ +static: + doAssert compileOption("experimental", "dotOperators") + doAssert compileOption("experimental", "callOperator") + doAssert compileOption("experimental", "parallel") + doAssert compileOption("experimental", "destructor") + doAssert compileOption("experimental", "notnil") + doAssert compileOption("experimental", "dynamicBindSym") + doAssert compileOption("experimental", "codeReordering") + doAssert compileOption("experimental", "compiletimeFFI") + doAssert compileOption("experimental", "vmopsDanger") + doAssert compileOption("experimental", "strictFuncs") + doAssert compileOption("experimental", "views") + doAssert compileOption("experimental", "strictNotNil") + doAssert compileOption("experimental", "strictEffects") + doAssert compileOption("experimental", "flexibleOptionalParams") + doAssert compileOption("experimental", "strictDefs") + doAssert compileOption("experimental", "strictCaseObjects") + doAssert compileOption("experimental", "inferGenericTypes") + doAssert compileOption("experimental", "openSym") + doAssert compileOption("experimental", "vtables") diff --git a/tests/compileoption/texperimental.nims b/tests/compileoption/texperimental.nims new file mode 100644 index 000000000..c2c357caa --- /dev/null +++ b/tests/compileoption/texperimental.nims @@ -0,0 +1,19 @@ +switch("experimental", "dotOperators") +switch("experimental", "callOperator") +switch("experimental", "parallel") +switch("experimental", "destructor") +switch("experimental", "notnil") +switch("experimental", "dynamicBindSym") +switch("experimental", "codeReordering") +switch("experimental", "compiletimeFFI") +switch("experimental", "vmopsDanger") +switch("experimental", "strictFuncs") +switch("experimental", "views") +switch("experimental", "strictNotNil") +switch("experimental", "strictEffects") +switch("experimental", "flexibleOptionalParams") +switch("experimental", "strictDefs") +switch("experimental", "strictCaseObjects") +switch("experimental", "inferGenericTypes") +switch("experimental", "openSym") +switch("experimental", "vtables") diff --git a/tests/compiler/tbrees.nim b/tests/compiler/tbtrees.nim index 5f6482ed9..973c26420 100644 --- a/tests/compiler/tbrees.nim +++ b/tests/compiler/tbtrees.nim @@ -68,7 +68,7 @@ proc main = when true: var b2 = initBTree[int, string]() var t2 = initTable[int, string]() - const iters = 100_000 + const iters = 100 for i in 1..iters: let x = rand(high(int)) if not t2.hasKey(x): diff --git a/tests/compiler/tgrammar.nim b/tests/compiler/tgrammar.nim new file mode 100644 index 000000000..772d0f0cc --- /dev/null +++ b/tests/compiler/tgrammar.nim @@ -0,0 +1,7 @@ +discard """ + matrix: "-d:nimTestGrammar" +""" + +import compiler/parser + +checkSameGrammar() diff --git a/tests/compilerapi/tcompilerapi.nim b/tests/compilerapi/tcompilerapi.nim index ab995cb6d..2d6cfa0ca 100644 --- a/tests/compilerapi/tcompilerapi.nim +++ b/tests/compilerapi/tcompilerapi.nim @@ -23,7 +23,7 @@ proc initInterpreter(script: string): Interpreter = proc main() = let i = initInterpreter("myscript.nim") - i.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) = + i.implementRoutine("nim", "exposed", "addFloats", proc (a: VmArgs) = setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2)) ) i.evalScript() @@ -69,3 +69,30 @@ block error_hook: doAssertRaises(VMQuit): i.evalScript() + +block resetmacrocache: + let std = findNimStdLibCompileTime() + let intr = createInterpreter("script.nim", [std, std / "pure", std / "core"]) + proc evalString(intr: Interpreter; code: string) = + let stream = llStreamOpen(code) + intr.evalScript(stream) + llStreamClose(stream) + let code = """ +import std/[macrocache, macros] +static: + let counter = CacheCounter"valTest" + inc counter + assert counter.value == 1 + + const mySeq = CacheSeq"addTest" + mySeq.add(newLit(5)) + mySeq.add(newLit("hello ic")) + assert mySeq.len == 2 + + const mcTable = CacheTable"subTest" + mcTable["toAdd"] = newStmtList() #would crash if not empty + assert mcTable.len == 1 +""" + intr.evalString(code) + intr.evalString(code) + destroyInterpreter(intr) \ No newline at end of file diff --git a/tests/concepts/t20237.nim b/tests/concepts/t20237.nim new file mode 100644 index 000000000..175c7a9d1 --- /dev/null +++ b/tests/concepts/t20237.nim @@ -0,0 +1,3 @@ +type Foo* = concept + ## doc comment + proc foo(x: Self) diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim index b92af5485..901f8d2f4 100644 --- a/tests/concepts/t3330.nim +++ b/tests/concepts/t3330.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" errormsg: "type mismatch: got <Bar[system.int]>" nimout: ''' t3330.nim(70, 4) Error: type mismatch: got <Bar[system.int]> @@ -48,7 +49,6 @@ expression: test(bar)''' - ## line 60 type Foo[T] = concept k diff --git a/tests/concepts/t976.nim b/tests/concepts/t976.nim new file mode 100644 index 000000000..776d53827 --- /dev/null +++ b/tests/concepts/t976.nim @@ -0,0 +1,57 @@ +discard """ + output: ''' +Printable +''' +joinable: false +""" + +#[ + The converter is a proper example of a confounding variable + Moved to an isolated file +]# + +type + Obj1[T] = object + v: T +converter toObj1[T](t: T): Obj1[T] = + return Obj1[T](v: t) +block t976: + type + int1 = distinct int + int2 = distinct int + int1g = concept x + x is int1 + int2g = concept x + x is int2 + + proc take[T: int1g](value: int1) = + when T is int2: + static: error("killed in take(int1)") + + proc take[T: int2g](vale: int2) = + when T is int1: + static: error("killed in take(int2)") + + var i1: int1 = 1.int1 + var i2: int2 = 2.int2 + + take[int1](i1) + take[int2](i2) + + template reject(e) = + static: assert(not compiles(e)) + + reject take[string](i2) + reject take[int1](i2) + + # bug #6249 + type + Obj2 = ref object + PrintAble = concept x + $x is string + + proc `$`[T](nt: Obj1[T]): string = + when T is PrintAble: result = "Printable" + else: result = "Non Printable" + + echo Obj2() \ No newline at end of file diff --git a/tests/concepts/tconcepts.nim b/tests/concepts/tconcepts.nim index acdff6f24..ea3ddc401 100644 --- a/tests/concepts/tconcepts.nim +++ b/tests/concepts/tconcepts.nim @@ -31,6 +31,7 @@ e 20 10 5 +9 ''' """ @@ -438,3 +439,13 @@ import mvarconcept block tvar: # bug #2346, bug #2404 echo randomInt(5) + +block tcomment: + type + Foo = concept + ## Some comment + proc bar(x: Self) + + proc bar(x: int) = echo x + proc foo(x: Foo) = x.bar + foo(9) diff --git a/tests/concepts/tconcepts_issues.nim b/tests/concepts/tconcepts_issues.nim index 802582f57..c6d0267c5 100644 --- a/tests/concepts/tconcepts_issues.nim +++ b/tests/concepts/tconcepts_issues.nim @@ -1,7 +1,6 @@ discard """ output: ''' 20.0 USD -Printable true true true @@ -27,6 +26,8 @@ false true -1 Meow +10 0.0 +1 2.0 ''' joinable: false """ @@ -76,55 +77,6 @@ block t3414: let s2 = s1.find(10) - -type - Obj1[T] = object - v: T -converter toObj1[T](t: T): Obj1[T] = - return Obj1[T](v: t) -block t976: - type - int1 = distinct int - int2 = distinct int - int1g = concept x - x is int1 - int2g = concept x - x is int2 - - proc take[T: int1g](value: int1) = - when T is int2: - static: error("killed in take(int1)") - - proc take[T: int2g](vale: int2) = - when T is int1: - static: error("killed in take(int2)") - - var i1: int1 = 1.int1 - var i2: int2 = 2.int2 - - take[int1](i1) - take[int2](i2) - - template reject(e) = - static: assert(not compiles(e)) - - reject take[string](i2) - reject take[int1](i2) - - # bug #6249 - type - Obj2 = ref object - PrintAble = concept x - $x is string - - proc `$`[T](nt: Obj1[T]): string = - when T is PrintAble: result = "Printable" - else: result = "Non Printable" - - echo Obj2() - - - block t1128: type TFooContainer[T] = object @@ -500,3 +452,105 @@ var r, b: Fp2[6, uint64] prod(r, b) + +block: # bug #21263 + type + DateDayFraction = concept # no T, an atom + proc date(a: Self): int + proc fraction(b: Self): float + Date = distinct int + DateDayFractionImpl = object + date : int + fraction : float + + proc date(a: Date): int = a.int + proc fraction(a:Date): float = 0.0 + + proc date(a: DateDayFractionImpl): int = a.date + proc fraction(b: DateDayFractionImpl): float = b.fraction + + + proc print(a: DateDayFraction) = + echo a.date, " ", a.fraction + + print(10.Date) # ok + print(DateDayFractionImpl(date: 1, fraction: 2)) # error + +import sets +import deques + +type AnyTree[V] = concept t, type T + for v in t.leaves(V): + v is V + +type BreadthOrder[V] = ref object + frontier: Deque[V] + visited: HashSet[V] + +proc expand[V, T](order: ref BreadthOrder[T], tree: AnyTree[V], node: V, transform: (V) -> (T)) = + for leaf in tree.leaves(node): + if not order.visited.containsOrIncl(transform(leaf)): + order.frontier.addLast(transform(leaf)) + +proc hasNext[V](order: ref BreadthOrder[V]): bool = + order.frontier.len > 0 + +proc init[V](_: typedesc[BreadthOrder]): ref BreadthOrder[V] = + result.new() + result[] = BreadthOrder[V](frontier: initDeque[V](), visited: initHashSet[V]()) + +proc popNext[V](order: ref BreadthOrder[V]): V = + order.frontier.popFirst() + +type LevelNode[V] = tuple + depth: uint + node: V + +proc depthOf*[V](orderType: typedesc[BreadthOrder], tree: AnyTree[V], root, goal: V): uint = + if root == goal: + return 0 + var order = init[LevelNode[V]](orderType) + order.expand(tree, root, (leaf) => (1.uint, leaf)) + while order.hasNext(): + let depthNode: LevelNode[V] = order.popNext() + if depthNode.node == goal: + return depthNode.depth + order.expand(tree, depthNode.node, (leaf) => (depthNode.depth + 1, leaf)) + +type CappedStringTree = ref object + symbols: string + cap: Natural + +iterator leaves*(t: CappedStringTree, s: string): string = + if s.len < t.cap: + for c in t.symbols: + yield s & c + +block: # bug #12852 + var tree = CappedStringTree(symbols: "^v><", cap: 5) + + doAssert BreadthOrder.depthOf(tree, "", ">>>") == 3 + +block: #bug #22723 + type + Node = concept n, type T + for i in n.children: + i is T + n.parent is T + + Nd = ref object + parent: Nd + children: seq[Nd] + + proc addChild(parent, child: Node) = + parent.children.add(child) + child.parent = parent + + proc foo = + var + a = Nd() + b = Nd() + a.addChild(b) + doAssert a.children.len == 1 + + foo() diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim index 49eb8eb6b..8cf04ae82 100644 --- a/tests/concepts/texplain.nim +++ b/tests/concepts/texplain.nim @@ -13,14 +13,8 @@ proc e(o: ExplainedConcept): int required type for o: ExplainedConcept but expression '10' is of type: int literal(10) texplain.nim(128, 6) ExplainedConcept: undeclared field: 'foo' -texplain.nim(128, 6) ExplainedConcept: undeclared field: '.' -texplain.nim(128, 6) ExplainedConcept: expression '.' cannot be called -texplain.nim(128, 6) ExplainedConcept: expression '' has no type (or is ambiguous) texplain.nim(128, 5) ExplainedConcept: concept predicate failed texplain.nim(129, 6) ExplainedConcept: undeclared field: 'bar' -texplain.nim(129, 6) ExplainedConcept: undeclared field: '.' -texplain.nim(129, 6) ExplainedConcept: expression '.' cannot be called -texplain.nim(129, 6) ExplainedConcept: expression '' has no type (or is ambiguous) texplain.nim(128, 5) ExplainedConcept: concept predicate failed texplain.nim(168, 10) Hint: Non-matching candidates for e(10) @@ -29,14 +23,8 @@ proc e(o: ExplainedConcept): int required type for o: ExplainedConcept but expression '10' is of type: int literal(10) texplain.nim(128, 6) ExplainedConcept: undeclared field: 'foo' -texplain.nim(128, 6) ExplainedConcept: undeclared field: '.' -texplain.nim(128, 6) ExplainedConcept: expression '.' cannot be called -texplain.nim(128, 6) ExplainedConcept: expression '' has no type (or is ambiguous) texplain.nim(128, 5) ExplainedConcept: concept predicate failed texplain.nim(129, 6) ExplainedConcept: undeclared field: 'bar' -texplain.nim(129, 6) ExplainedConcept: undeclared field: '.' -texplain.nim(129, 6) ExplainedConcept: expression '.' cannot be called -texplain.nim(129, 6) ExplainedConcept: expression '' has no type (or is ambiguous) texplain.nim(128, 5) ExplainedConcept: concept predicate failed texplain.nim(172, 20) Error: type mismatch: got <NonMatchingType> @@ -88,14 +76,8 @@ proc f(o: NestedConcept) required type for o: NestedConcept but expression 'y' is of type: MatchingType texplain.nim(132, 6) RegularConcept: undeclared field: 'foo' -texplain.nim(132, 6) RegularConcept: undeclared field: '.' -texplain.nim(132, 6) RegularConcept: expression '.' cannot be called -texplain.nim(132, 6) RegularConcept: expression '' has no type (or is ambiguous) texplain.nim(132, 5) RegularConcept: concept predicate failed texplain.nim(133, 6) RegularConcept: undeclared field: 'bar' -texplain.nim(133, 6) RegularConcept: undeclared field: '.' -texplain.nim(133, 6) RegularConcept: expression '.' cannot be called -texplain.nim(133, 6) RegularConcept: expression '' has no type (or is ambiguous) texplain.nim(132, 5) RegularConcept: concept predicate failed texplain.nim(136, 5) NestedConcept: concept predicate failed @@ -121,7 +103,25 @@ expression: f(y)''' -# line 120 HERE + + + + + + + + + + + + + + + + + + +# line 124 HERE type ExplainedConcept {.explain.} = concept o diff --git a/tests/concepts/tusertypeclasses.nim b/tests/concepts/tusertypeclasses.nim index c7104f2a6..83e2b176e 100644 --- a/tests/concepts/tusertypeclasses.nim +++ b/tests/concepts/tusertypeclasses.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''Sortable Sortable Container @@ -9,6 +10,8 @@ int ''' """ +# todo wait for https://github.com/nim-lang/Nim/pull/20380 + import typetraits template reject(expr) = assert(not compiles(x)) diff --git a/tests/concepts/tusertypeclasses2.nim b/tests/concepts/tusertypeclasses2.nim index c9978f6ef..6132bc2d8 100644 --- a/tests/concepts/tusertypeclasses2.nim +++ b/tests/concepts/tusertypeclasses2.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + block: type hasFieldX = concept z @@ -42,3 +46,18 @@ block: foo2(x) foo3(x) foo4(x) + +block: # bug #9550 + block: + type Foo = concept c + for v in c: (v is char) + + func foo(c: Foo) = (for v in c: discard) + foo @['a', 'b' ,'c'] + + block: + type Foo = concept c + for v in c: (v is char) + + func foo(c: Foo) = (for v in c: discard) + foo ['a', 'b' ,'c'] diff --git a/tests/config.nims b/tests/config.nims index 894c4bea0..0b2b66d81 100644 --- a/tests/config.nims +++ b/tests/config.nims @@ -32,11 +32,18 @@ hint("Processing", off) # experimental APIs are enabled in testament, refs https://github.com/timotheecour/Nim/issues/575 # sync with `kochdocs.docDefines` or refactor. -switch("define", "nimExperimentalAsyncjsThen") switch("define", "nimExperimentalLinenoiseExtra") # preview APIs are expected to be the new default in upcoming versions switch("define", "nimPreviewFloatRoundtrip") -switch("define", "nimPreviewDotLikeOps") +#switch("define", "nimPreviewDotLikeOps") # deprecated? switch("define", "nimPreviewJsonutilsHoleyEnum") switch("define", "nimPreviewHashRef") +switch("define", "nimPreviewRangeDefault") +switch("define", "nimPreviewNonVarDestructor") + +switch("warningAserror", "UnnamedBreak") +when not defined(testsConciseTypeMismatch): + switch("legacy", "verboseTypeMismatch") +switch("experimental", "vtables") +switch("experimental", "openSym") diff --git a/tests/constr/tglobal.nim b/tests/constr/tglobal.nim deleted file mode 100644 index 056ac9f81..000000000 --- a/tests/constr/tglobal.nim +++ /dev/null @@ -1,7 +0,0 @@ -discard """ -output: "0" -""" - -# b.nim -import a_module -echo foo() \ No newline at end of file diff --git a/tests/constructors/a.nim b/tests/constructors/a.nim new file mode 100644 index 000000000..03788fc57 --- /dev/null +++ b/tests/constructors/a.nim @@ -0,0 +1,2 @@ +type A* = object + a: uint8 \ No newline at end of file diff --git a/tests/constructors/b.nim b/tests/constructors/b.nim new file mode 100644 index 000000000..437dd0550 --- /dev/null +++ b/tests/constructors/b.nim @@ -0,0 +1,2 @@ +type B* = object +proc A*(a, b: float): B = discard \ No newline at end of file diff --git a/tests/constructors/t18990.nim b/tests/constructors/t18990.nim new file mode 100644 index 000000000..2f60f3c2c --- /dev/null +++ b/tests/constructors/t18990.nim @@ -0,0 +1,3 @@ +import a, b +discard A(1f, 1f) # works +proc x(b = A(1f, 1f)) = discard # doesn't work \ No newline at end of file diff --git a/tests/constr/tconstr1.nim b/tests/constructors/tconstr1.nim index a169bf453..a169bf453 100644 --- a/tests/constr/tconstr1.nim +++ b/tests/constructors/tconstr1.nim diff --git a/tests/constr/tconstr2.nim b/tests/constructors/tconstr2.nim index 2557d7db9..2557d7db9 100644 --- a/tests/constr/tconstr2.nim +++ b/tests/constructors/tconstr2.nim diff --git a/tests/controlflow/tcontrolflow.nim b/tests/controlflow/tcontrolflow.nim index 258f3f50d..dd21a2bb6 100644 --- a/tests/controlflow/tcontrolflow.nim +++ b/tests/controlflow/tcontrolflow.nim @@ -19,7 +19,7 @@ block tbreak: run = false block myblock: if true: - break + break myblock echo "leaving myblock" x = true doAssert(x) @@ -95,3 +95,22 @@ block tnestif: else: writeLine(stdout, "looks like Python") #OUT i == 2 + +# bug https://github.com/nim-lang/RFCs/issues/451 +for i in 1..2: # works + break + +block: # works + for i in 1..2: + break + +block: # works + block: + discard 12 + 3 + for i in 1..2: + break + +block named: # works + if true: + break named + doAssert false, "not reached" diff --git a/tests/controlflow/tunamedbreak.nim b/tests/controlflow/tunamedbreak.nim new file mode 100644 index 000000000..46113cabc --- /dev/null +++ b/tests/controlflow/tunamedbreak.nim @@ -0,0 +1,15 @@ + +discard """ + cmd: "nim check $file" + action: "reject" + nimout: ''' +tunamedbreak.nim(12, 5) Error: Using an unnamed break in a block is deprecated; Use a named block with a named break instead [UnnamedBreak] +tunamedbreak.nim(15, 3) Error: Using an unnamed break in a block is deprecated; Use a named block with a named break instead [UnnamedBreak] + ''' +""" +for i in 1..2: # errors + block: + break + +block: # errors + break diff --git a/tests/controlflow/tunreachable.nim b/tests/controlflow/tunreachable.nim new file mode 100644 index 000000000..06321ce8a --- /dev/null +++ b/tests/controlflow/tunreachable.nim @@ -0,0 +1,79 @@ +discard """ + cmd: "nim check --warningAsError:UnreachableCode $file" + action: "reject" + nimout: ''' +tunreachable.nim(26, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode] +tunreachable.nim(33, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode] +tunreachable.nim(42, 3) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode] +tunreachable.nim(65, 5) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode] +tunreachable.nim(77, 5) Error: unreachable code after 'return' statement or '{.noReturn.}' proc [UnreachableCode] +''' +""" + +# bug #9839 +template myquit1():untyped= + ## foo + quit(1) +template myquit2():untyped= + echo 123 + myquit1() + +proc main1()= + + # BUG: uncommenting this doesn't give `Error: unreachable statement` + myquit2() + + echo "after" + +main1() + +proc main2() = + myquit1() + + echo "after" + +main2() + +proc main3() = + if true: + return + else: + return + echo "after" + +main3() + + +block: + # Cases like strings are not checked for exhaustiveness unless they have an else + proc main4(x: string) = + case x + of "a": + return + # reachable + echo "after" + + main4("a") + + proc main5(x: string) = + case x + of "a": + return + else: + return + # unreachable + echo "after" + + main5("a") + +block: + # In this case no else is needed because it's exhaustive + proc exhaustive(x: bool) = + case x + of true: + return + of false: + return + echo "after" + + exhaustive(true) diff --git a/tests/controlflow/tunreachable2.nim b/tests/controlflow/tunreachable2.nim new file mode 100644 index 000000000..a658880f0 --- /dev/null +++ b/tests/controlflow/tunreachable2.nim @@ -0,0 +1,12 @@ +discard """ + matrix: "--warningAsError:UnreachableCode" +""" + +proc test(): bool = + block okay: + if true: break okay + return false + + return true # Line 7 is here + +doAssert test() diff --git a/tests/converter/t21531.nim b/tests/converter/t21531.nim new file mode 100644 index 000000000..b0198684d --- /dev/null +++ b/tests/converter/t21531.nim @@ -0,0 +1,10 @@ +import std/typetraits + +type Foo* = distinct string + +converter toBase*(headers: var Foo): var string = + headers.distinctBase + +proc bar*(headers: var Foo) = + for x in headers: discard + diff --git a/tests/converter/t7097.nim b/tests/converter/t7097.nim index fdb573588..d8e953080 100644 --- a/tests/converter/t7097.nim +++ b/tests/converter/t7097.nim @@ -10,8 +10,8 @@ proc initBytesRange*(s: var Bytes, ibegin = 0, iend = -1): BytesRange = let e = if iend < 0: s.len + iend + 1 else: iend assert ibegin > 0 and e <= s.len - - shallow(s) + when defined(gcRefc): + shallow(s) result.bytes = s result.ibegin = ibegin result.iend = e diff --git a/tests/converter/t7098.nim b/tests/converter/t7098.nim index 8e7634882..30c9c1e25 100644 --- a/tests/converter/t7098.nim +++ b/tests/converter/t7098.nim @@ -14,8 +14,8 @@ proc initBytesRange*(s: var Bytes, ibegin = 0, iend = -1): BytesRange = let e = if iend < 0: s.len + iend + 1 else: iend assert ibegin >= 0 and e <= s.len - - shallow(s) + when defined(gcRefc): + shallow(s) result.bytes = s result.ibegin = ibegin result.iend = e diff --git a/tests/converter/tconverter_unique_ptr.nim b/tests/converter/tconverter_unique_ptr.nim index 23c1a3d96..6902f9e9e 100644 --- a/tests/converter/tconverter_unique_ptr.nim +++ b/tests/converter/tconverter_unique_ptr.nim @@ -22,12 +22,11 @@ proc `$`(x: MyLen): string {.borrow.} proc `==`(x1, x2: MyLen): bool {.borrow.} -proc `=destroy`*(m: var MySeq) {.inline.} = +proc `=destroy`*(m: MySeq) {.inline.} = if m.data != nil: deallocShared(m.data) - m.data = nil -proc `=`*(m: var MySeq, m2: MySeq) = +proc `=copy`*(m: var MySeq, m2: MySeq) = if m.data == m2.data: return if m.data != nil: `=destroy`(m) @@ -77,13 +76,12 @@ converter literalToLen*(x: int{lit}): MyLen = # Unique pointer implementation #------------------------------------------------------------- -proc `=destroy`*[T](p: var UniquePtr[T]) = +proc `=destroy`*[T](p: UniquePtr[T]) = if p.val != nil: `=destroy`(p.val[]) dealloc(p.val) - p.val = nil -proc `=`*[T](dest: var UniquePtr[T], src: UniquePtr[T]) {.error.} +proc `=copy`*[T](dest: var UniquePtr[T], src: UniquePtr[T]) {.error.} proc `=sink`*[T](dest: var UniquePtr[T], src: UniquePtr[T]) {.inline.} = if dest.val != nil and dest.val != src.val: @@ -118,13 +116,12 @@ type ## as it returns only `lent T` val: ptr T -proc `=destroy`*[T](p: var ConstPtr[T]) = +proc `=destroy`*[T](p: ConstPtr[T]) = if p.val != nil: `=destroy`(p.val[]) dealloc(p.val) - p.val = nil -proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.} +proc `=copy`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.} proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} = if dest.val != nil and dest.val != src.val: diff --git a/tests/coroutines/tgc.nim b/tests/coroutines/tgc.nim index e2f8b6469..770d413f5 100644 --- a/tests/coroutines/tgc.nim +++ b/tests/coroutines/tgc.nim @@ -1,6 +1,6 @@ discard """ matrix: "--gc:refc; --gc:arc; --gc:orc" - target: "c" + targets: "c" """ when compileOption("gc", "refc") or not defined(openbsd): diff --git a/tests/coroutines/twait.nim b/tests/coroutines/twait.nim index 71782ece1..2edfcf675 100644 --- a/tests/coroutines/twait.nim +++ b/tests/coroutines/twait.nim @@ -1,7 +1,7 @@ discard """ output: "Exit 1\nExit 2" matrix: "--gc:refc; --gc:arc; --gc:orc" - target: "c" + targets: "c" """ when compileOption("gc", "refc") or not defined(openbsd): diff --git a/tests/cpp/23962.h b/tests/cpp/23962.h new file mode 100644 index 000000000..2d8147bfb --- /dev/null +++ b/tests/cpp/23962.h @@ -0,0 +1,17 @@ +#include <iostream> + +struct Foo { + + Foo(int inX): x(inX) { + std::cout << "Ctor Foo(" << x << ")\n"; + } + ~Foo() { + std::cout << "Destory Foo(" << x << ")\n"; + } + + void print() { + std::cout << "Foo.x = " << x << '\n'; + } + + int x; +}; \ No newline at end of file diff --git a/tests/cpp/fam.h b/tests/cpp/fam.h new file mode 100644 index 000000000..ad576425b --- /dev/null +++ b/tests/cpp/fam.h @@ -0,0 +1,4 @@ +struct Test{ + ~Test() { + } +}; diff --git a/tests/cpp/t12946.nim b/tests/cpp/t12946.nim new file mode 100644 index 000000000..79cd56251 --- /dev/null +++ b/tests/cpp/t12946.nim @@ -0,0 +1,8 @@ +discard """ + targets: "c cpp" +""" + +import std/atomics +type Futex = distinct Atomic[int32] + +var x: Futex diff --git a/tests/cpp/t22679.nim b/tests/cpp/t22679.nim new file mode 100644 index 000000000..81defcb58 --- /dev/null +++ b/tests/cpp/t22679.nim @@ -0,0 +1,50 @@ +discard """ + cmd: "nim cpp $file" + output:''' +cppNZ.x = 123 +cppNZInit.x = 123 +hascpp.cppnz.x = 123 +hasCppInit.cppnz.x = 123 +hasCppCtor.cppnz.x = 123 +''' +""" +{.emit:"""/*TYPESECTION*/ +struct CppNonZero { + int x = 123; +}; +""".} + +import sugar +type + CppNonZero {.importcpp, inheritable.} = object + x: cint + + HasCpp = object + cppnz: CppNonZero + +proc initCppNonZero: CppNonZero = + CppNonZero() + +proc initHasCpp: HasCpp = + HasCpp() + +proc ctorHasCpp: HasCpp {.constructor.} = + discard + +proc main = + var cppNZ: CppNonZero + dump cppNZ.x + + var cppNZInit = initCppNonZero() + dump cppNZInit.x + + var hascpp: HasCpp + dump hascpp.cppnz.x + + var hasCppInit = initHasCpp() + dump hasCppInit.cppnz.x + + var hasCppCtor = ctorHasCpp() + dump hasCppCtor.cppnz.x + +main() \ No newline at end of file diff --git a/tests/cpp/t22680.nim b/tests/cpp/t22680.nim new file mode 100644 index 000000000..80f1a8319 --- /dev/null +++ b/tests/cpp/t22680.nim @@ -0,0 +1,50 @@ +discard """ + cmd: "nim cpp $file" + output:''' +cppNZ.x = 123 +cppNZInit.x = 123 +inheritCpp.x = 123 +inheritCppInit.x = 123 +inheritCppCtor.x = 123 +''' +""" +import std/sugar + +{.emit:"""/*TYPESECTION*/ +struct CppNonZero { + int x = 123; +}; +""".} + +type + CppNonZero {.importcpp, inheritable.} = object + x: cint + + InheritCpp = object of CppNonZero + +proc initCppNonZero: CppNonZero = + CppNonZero() + +proc initInheritCpp: InheritCpp = + InheritCpp() + +proc ctorInheritCpp: InheritCpp {.constructor.} = + discard + +proc main = + var cppNZ: CppNonZero + dump cppNZ.x + + var cppNZInit = initCppNonZero() + dump cppNZInit.x + + var inheritCpp: InheritCpp + dump inheritCpp.x + + var inheritCppInit = initInheritCpp() + dump inheritCppInit.x + + var inheritCppCtor = ctorInheritCpp() + dump inheritCppCtor.x + +main() \ No newline at end of file diff --git a/tests/cpp/t22712.nim b/tests/cpp/t22712.nim new file mode 100644 index 000000000..34ef67ac8 --- /dev/null +++ b/tests/cpp/t22712.nim @@ -0,0 +1,15 @@ +discard """ +targets: "cpp" +errormsg: "constructor in an imported type needs importcpp pragma" +line: 14 +""" +{.emit: """/*TYPESECTION*/ +struct CppStruct { + CppStruct(); +}; +""".} + +type CppStruct {.importcpp.} = object + +proc makeCppStruct(): CppStruct {.constructor.} = + discard \ No newline at end of file diff --git a/tests/cpp/t23306.nim b/tests/cpp/t23306.nim new file mode 100644 index 000000000..ebb4edb8d --- /dev/null +++ b/tests/cpp/t23306.nim @@ -0,0 +1,12 @@ +discard """ +targets: "cpp" +""" + +type K = object + h: iterator(f: K): K + +iterator d(g: K): K {.closure.} = + defer: + discard + +discard K(h: d) \ No newline at end of file diff --git a/tests/cpp/t23434.nim b/tests/cpp/t23434.nim new file mode 100644 index 000000000..04a83227e --- /dev/null +++ b/tests/cpp/t23434.nim @@ -0,0 +1,17 @@ +discard """ +cmd:"nim cpp $file" +errormsg: "type mismatch: got <proc (self: SomeObject){.member, gcsafe.}>" +line: 17 +""" +type SomeObject = object + value: int + +proc printValue(self: SomeObject) {.virtual.} = + echo "The value is ", self.value + +proc callAProc(p: proc(self: SomeObject){.noconv.}) = + let someObj = SomeObject(value: 4) + echo "calling param proc" + p(someObj) + +callAProc(printValue) \ No newline at end of file diff --git a/tests/cpp/t23657.nim b/tests/cpp/t23657.nim new file mode 100644 index 000000000..63deb7fb0 --- /dev/null +++ b/tests/cpp/t23657.nim @@ -0,0 +1,54 @@ +discard """ + targets: "cpp" + cmd: "nim cpp -r $file" + output: ''' +1.0 +1.0 +''' + +""" +{.emit:"""/*TYPESECTION*/ +struct Point { + float x, y, z; + Point(float x, float y, float z): x(x), y(y), z(z) {} + Point() = default; +}; +struct Direction { + float x, y, z; + Direction(float x, float y, float z): x(x), y(y), z(z) {} + Direction() = default; +}; +struct Axis { + Point origin; + Direction direction; + Axis(Point origin, Direction direction): origin(origin), direction(direction) {} + Axis() = default; +}; + +""".} + +type + Point {.importcpp.} = object + x, y, z: float + + Direction {.importcpp.} = object + x, y, z: float + + Axis {.importcpp.} = object + origin: Point + direction: Direction + +proc makeAxis(origin: Point, direction: Direction): Axis {. constructor, importcpp:"Axis(@)".} +proc makePoint(x, y, z: float): Point {. constructor, importcpp:"Point(@)".} +proc makeDirection(x, y, z: float): Direction {. constructor, importcpp:"Direction(@)".} + +var axis1 = makeAxis(Point(x: 1.0, y: 2.0, z: 3.0), Direction(x: 4.0, y: 5.0, z: 6.0)) #Triggers the error (T1) +var axis2Ctor = makeAxis(makePoint(1.0, 2.0, 3.0), makeDirection(4.0, 5.0, 6.0)) #Do not triggers + +proc main() = #Do not triggers as Tx are inside the body + let test = makeAxis(Point(x: 1.0, y: 2.0, z: 3.0), Direction(x: 4.0, y: 5.0, z: 6.0)) + echo test.origin.x + +main() + +echo $axis1.origin.x #Make sures it's init \ No newline at end of file diff --git a/tests/cpp/t23962.nim b/tests/cpp/t23962.nim new file mode 100644 index 000000000..c79d888df --- /dev/null +++ b/tests/cpp/t23962.nim @@ -0,0 +1,32 @@ +discard """ + cmd: "nim cpp $file" + output: ''' +Ctor Foo(-1) +Destory Foo(-1) +Ctor Foo(-1) +Destory Foo(-1) +Ctor Foo(-1) +Destory Foo(-1) +Foo.x = 1 +Foo.x = 2 +Foo.x = -1 +''' +""" + +type + Foo {.importcpp, header: "23962.h".} = object + x: cint + +proc print(f: Foo) {.importcpp.} + +#also tests the right constructor is used +proc makeFoo(x: int32 = -1): Foo {.importcpp:"Foo(#)", constructor.} + +proc test = + var xs = newSeq[Foo](3) + xs[0].x = 1 + xs[1].x = 2 + for x in xs: + x.print + +test() \ No newline at end of file diff --git a/tests/cpp/tasync_cpp.nim b/tests/cpp/tasync_cpp.nim index 696274ec4..3f4ec6208 100644 --- a/tests/cpp/tasync_cpp.nim +++ b/tests/cpp/tasync_cpp.nim @@ -1,7 +1,7 @@ discard """ targets: "cpp" output: "hello" - cmd: "nim cpp --clearNimblePath --nimblePath:build/deps/pkgs $file" + cmd: "nim cpp --clearNimblePath --nimblePath:build/deps/pkgs2 $file" """ # bug #3299 diff --git a/tests/cpp/tcasts.nim b/tests/cpp/tcasts.nim index d968d87db..80527efff 100644 --- a/tests/cpp/tcasts.nim +++ b/tests/cpp/tcasts.nim @@ -1,6 +1,5 @@ discard """ cmd: "nim cpp $file" - output: '''{"vas": "kas", "123": "123"}''' targets: "cpp" """ @@ -18,4 +17,4 @@ import tables var t = initTable[string, string]() discard t.hasKeyOrPut("123", "123") discard t.mgetOrPut("vas", "kas") -echo t \ No newline at end of file +doAssert t.len == 2 diff --git a/tests/cpp/tcodegendecl.nim b/tests/cpp/tcodegendecl.nim new file mode 100644 index 000000000..e128c5eb7 --- /dev/null +++ b/tests/cpp/tcodegendecl.nim @@ -0,0 +1,17 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: "3" +""" + +{.emit:"""/*TYPESECTION*/ + int operate(int x, int y, int (*func)(const int&, const int&)){ + return func(x, y); + }; +""".} + +proc operate(x, y: int32, fn: proc(x, y: int32 ): int32 {.cdecl.}): int32 {.importcpp:"$1(@)".} + +proc add(a {.codegenDecl:"const $#& $#".}, b {.codegenDecl:"const $# $#", byref.}: int32): int32 {.cdecl.} = a + b + +echo operate(1, 2, add) \ No newline at end of file diff --git a/tests/cpp/tconstructor.nim b/tests/cpp/tconstructor.nim new file mode 100644 index 000000000..922ee54fd --- /dev/null +++ b/tests/cpp/tconstructor.nim @@ -0,0 +1,131 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: ''' +1 +0 +123 +0 +123 +___ +0 +777 +10 +123 +0 +777 +10 +123 +() +''' +""" + +{.emit:"""/*TYPESECTION*/ +struct CppClass { + int x; + int y; + CppClass(int inX, int inY) { + this->x = inX; + this->y = inY; + } + //CppClass() = default; +}; +""".} + +type CppClass* {.importcpp, inheritable.} = object + x: int32 + y: int32 + +proc makeCppClass(x, y: int32): CppClass {.importcpp: "CppClass(@)", constructor.} +#test globals are init with the constructor call +var shouldCompile {.used.} = makeCppClass(1, 2) + +proc newCpp*[T](): ptr T {.importcpp:"new '*0()".} + +#creation +type NimClassNoNarent* = object + x: int32 + +proc makeNimClassNoParent(x:int32): NimClassNoNarent {. constructor.} = + result.x = x + discard + +let nimClassNoParent = makeNimClassNoParent(1) +echo nimClassNoParent.x #acess to this just fine. Notice the field will appear last because we are dealing with constructor calls here + +var nimClassNoParentDef {.used.}: NimClassNoNarent #test has a default constructor. + +#inheritance +type NimClass* = object of CppClass + +proc makeNimClass(x:int32): NimClass {. constructor:"NimClass('1 #1) : CppClass(0, #1) ".} = + result.x = x + +#optinially define the default constructor so we get rid of the cpp warn and we can declare the obj (note: default constructor of 'tyObject_NimClass__apRyyO8cfRsZtsldq1rjKA' is implicitly deleted because base class 'CppClass' has no default constructor) +proc makeCppClass(): NimClass {. constructor: "NimClass() : CppClass(0, 0) ".} = + result.x = 1 + +let nimClass = makeNimClass(1) +var nimClassDef {.used.}: NimClass #since we explictly defined the default constructor we can declare the obj + +#bug: 22662 +type + BugClass* = object + x: int # Not initialized + +proc makeBugClass(): BugClass {.constructor.} = + discard + +proc main = + for i in 0 .. 1: + var n = makeBugClass() + echo n.x + n.x = 123 + echo n.x + +main() +#bug: +echo "___" +type + NimClassWithDefault = object + x: int + y = 777 + case kind: bool = true + of true: + z: int = 10 + else: discard + +proc makeNimClassWithDefault(): NimClassWithDefault {.constructor.} = + result = NimClassWithDefault() + +proc init = + for i in 0 .. 1: + var n = makeNimClassWithDefault() + echo n.x + echo n.y + echo n.z + n.x = 123 + echo n.x + +init() + +#tests that the ctor is not declared with nodecl. +#nodelc also prevents the creation of a default one when another is created. +type Foo {.exportc.} = object + +proc makeFoo(): Foo {.used, constructor, nodecl.} = discard + +echo $Foo() + +type Boo = object +proc `=copy`(dest: var Boo; src: Boo) = discard + +proc makeBoo(): Boo {.constructor.} = Boo() +proc makeBoo2(): Boo = Boo() + +block: + proc main = + var b = makeBoo() + var b2 = makeBoo2() + + main() \ No newline at end of file diff --git a/tests/cpp/tfam.nim b/tests/cpp/tfam.nim new file mode 100644 index 000000000..6bd89fe24 --- /dev/null +++ b/tests/cpp/tfam.nim @@ -0,0 +1,7 @@ +discard """ + targets: "cpp" +""" +type + Test {.importcpp, header: "fam.h".} = object + +let test = newSeq[Test]() \ No newline at end of file diff --git a/tests/cpp/tinitializers.nim b/tests/cpp/tinitializers.nim new file mode 100644 index 000000000..0199fb96b --- /dev/null +++ b/tests/cpp/tinitializers.nim @@ -0,0 +1,60 @@ +discard """ + cmd: "nim cpp $file" +""" + +{.emit:"""/*TYPESECTION*/ +struct CppStruct { + CppStruct(int x, char* y): x(x), y(y){} + void doSomething() {} + int x; + char* y; +}; +""".} +type + CppStruct {.importcpp, inheritable.} = object + ChildStruct = object of CppStruct + HasCppStruct = object + cppstruct: CppStruct + +proc constructCppStruct(a:cint = 5, b:cstring = "hello"): CppStruct {.importcpp: "CppStruct(@)", constructor.} +proc doSomething(this: CppStruct) {.importcpp.} +proc returnCppStruct(): CppStruct = discard +proc initChildStruct: ChildStruct = ChildStruct() +proc makeChildStruct(): ChildStruct {.constructor:"""ChildStruct(): CppStruct(5, "10")""".} = discard +proc initHasCppStruct(x: cint): HasCppStruct = + HasCppStruct(cppstruct: constructCppStruct(x)) + +proc main = + var hasCppStruct = initHasCppStruct(2) #generates cppstruct = { 10 } inside the struct + hasCppStruct.cppstruct.doSomething() + discard returnCppStruct() #generates result = { 10 } + discard initChildStruct() #generates ChildStruct temp ({}) bypassed with makeChildStruct + (proc (s:CppStruct) = discard)(CppStruct()) #CppStruct temp ({10}) +main() + + +#Should handle ObjectCalls +{.emit:"""/*TYPESECTION*/ +struct Foo { +}; +struct Boo { + Boo(int x, char* y, Foo f): x(x), y(y), foo(f){} + int x; + char* y; + Foo foo; +}; +""".} +type + Foo {.importcpp, inheritable, bycopy.} = object + Boo {.importcpp, inheritable.} = object + x: int32 + y: cstring + foo: Foo + +proc makeBoo(a:cint = 10, b:cstring = "hello", foo: Foo = Foo()): Boo {.importcpp, constructor.} + +proc main2() = + let cppStruct = makeBoo() + (proc (s:Boo) = discard)(Boo()) + +main2() \ No newline at end of file diff --git a/tests/cpp/tmember.nim b/tests/cpp/tmember.nim new file mode 100644 index 000000000..1a5b6fd97 --- /dev/null +++ b/tests/cpp/tmember.nim @@ -0,0 +1,75 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: ''' +2 +false +hello foo +hello boo +hello boo +FunctorSupport! +static +static +destructing +destructing +''' +""" +proc print(s: cstring) {.importcpp:"printf(@)", header:"<stdio.h>".} + +type + Doo {.exportc.} = object + test: int + +proc memberProc(f: Doo) {.exportc, member.} = + echo $f.test + +proc destructor(f: Doo) {.member: "~'1()", used.} = + print "destructing\n" + +proc `==`(self, other: Doo): bool {.member:"operator==('2 const & #2) const -> '0"} = + self.test == other.test + +let doo = Doo(test: 2) +doo.memberProc() +echo doo == Doo(test: 1) + +#virtual +proc newCpp*[T](): ptr T {.importcpp:"new '*0()".} +type + Foo {.exportc.} = object of RootObj + FooPtr = ptr Foo + Boo = object of Foo + BooPtr = ptr Boo + +proc salute(self: FooPtr) {.member: "virtual $1()".} = + echo "hello foo" + +proc salute(self: BooPtr) {.member: "virtual $1()".} = + echo "hello boo" + +let foo = newCpp[Foo]() +let boo = newCpp[Boo]() +let booAsFoo = cast[FooPtr](newCpp[Boo]()) + +foo.salute() +boo.salute() +booAsFoo.salute() + +type + NimFunctor = object + discard +proc invoke(f: NimFunctor, n:int) {.member:"operator ()('2 #2)" .} = + echo "FunctorSupport!" + +{.experimental: "callOperator".} +proc `()`(f: NimFunctor, n:int) {.importcpp:"#(@)" .} +NimFunctor()(1) + +#static +proc staticProc(self: FooPtr) {.member: "static $1()".} = + echo "static" + +proc importedStaticProc() {.importcpp:"Foo::staticProc()".} + +foo.staticProc() +importedStaticProc() diff --git a/tests/cpp/tmember_forward_declaration.nim b/tests/cpp/tmember_forward_declaration.nim new file mode 100644 index 000000000..2f4a79daa --- /dev/null +++ b/tests/cpp/tmember_forward_declaration.nim @@ -0,0 +1,27 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: ''' +abc called +def called +abc called +''' +""" + +type Foo = object + +proc abc(this: Foo, x: int): void {.member: "$1('2 #2)".} +proc def(this: Foo, y: int): void {.virtual: "$1('2 #2)".} + +proc abc(this: Foo, x: int): void = + echo "abc called" + if x > 0: + this.def(x - 1) + +proc def(this: Foo, y: int): void = + echo "def called" + this.abc(y) + +var x = Foo() +x.abc(1) + diff --git a/tests/cpp/tnoinitfield.nim b/tests/cpp/tnoinitfield.nim new file mode 100644 index 000000000..4deffece8 --- /dev/null +++ b/tests/cpp/tnoinitfield.nim @@ -0,0 +1,30 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: ''' +''' +""" +{.emit: """/*TYPESECTION*/ + struct Foo { + Foo(int a){}; + }; + struct Boo { + Boo(int a){}; + }; + + """.} + +type + Foo {.importcpp.} = object + Boo {.importcpp, noInit.} = object + Test {.exportc.} = object + foo {.noInit.}: Foo + boo: Boo + +proc makeTest(): Test {.constructor: "Test() : foo(10), boo(1)".} = + discard + +proc main() = + var t = makeTest() + +main() \ No newline at end of file diff --git a/tests/cpp/torc.nim b/tests/cpp/torc.nim index 7fc474f94..9f1a41a21 100644 --- a/tests/cpp/torc.nim +++ b/tests/cpp/torc.nim @@ -12,4 +12,64 @@ type proc p(): Option[O] = none(O) -doAssert $p() == "none(O)" \ No newline at end of file +doAssert $p() == "none(O)" + +# bug #17351 +type + Foo = object of RootObj + Foo2 = object of Foo + Bar = object + x: Foo2 + +var b = Bar() +discard b + +# bug #4678 +{.emit: """/*TYPESECTION*/ +enum class SomeEnum {A,B,C}; +""".} +type + EnumVector[T: enum] {.importcpp: "std::vector", header: "vector".} = object + SomeEnum {.importcpp, nodecl.} = enum + A,B,C + +proc asVector*[T](t: T): EnumVector[T] = + discard +# Nim generates this signature here: +# N_NIMCALL(std::vector<> , asvector_106028_3197418230)(SomeEnum t0) + +discard asVector(SomeEnum.A) + + +block: # bug #10219 + type + Vector[T] {.importcpp: "std::vector", header: "vector".} = object + + proc initVector[T](n: csize_t): Vector[T] + {.importcpp: "std::vector<'*0>(@)", header: "vector".} + + proc unsafeIndex[T](this: var Vector[T], i: csize_t): var T + {.importcpp: "#[#]", header: "vector".} + + proc `[]`[T](this: var Vector[T], i: Natural): var T {.inline, noinit.} = + when compileOption("boundChecks"): + # this.checkIndex i + discard + result = this.unsafeIndex(csize_t(i)) + + var v1 = initVector[int](10) + doAssert v1[0] == 0 + +block: # bug #12703 bug #19588 + type + cstringConstImpl {.importc:"const char*".} = cstring + constChar = distinct cstringConstImpl + + {.emit: """ + const char* foo() { + return "hello"; + } + """.} + proc foo(): constChar {.importcpp.} # change to importcpp for C++ backend + doAssert $(foo().cstring) == "hello" + diff --git a/tests/cpp/tpassbypragmas.nim b/tests/cpp/tpassbypragmas.nim new file mode 100644 index 000000000..f4301656a --- /dev/null +++ b/tests/cpp/tpassbypragmas.nim @@ -0,0 +1,27 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" +""" +{.emit:"""/*TYPESECTION*/ + + template<typename T> + struct Box { + T first; + }; + struct Foo { + void test(void (*func)(Box<Foo>& another)){ + + }; + }; +""".} + +type + Foo {.importcpp.} = object + Box[T] {.importcpp:"Box<'0>".} = object + first: T + +proc test(self: Foo, fn: proc(another {.byref.}: Box[Foo]) {.cdecl.}) {.importcpp.} + +proc fn(another {.byref.} : Box[Foo]) {.cdecl.} = discard + +Foo().test(fn) \ No newline at end of file diff --git a/tests/cpp/tretvar.nim b/tests/cpp/tretvar.nim index 83c37721e..0c3765346 100644 --- a/tests/cpp/tretvar.nim +++ b/tests/cpp/tretvar.nim @@ -16,9 +16,9 @@ type proc c_str(a: stdString): cstring {.importcpp: "(char *)(#.c_str())", header: "<string>".} -proc len(a: stdString): csize {.importcpp: "(#.length())", header: "<string>".} +proc len(a: stdString): csize_t {.importcpp: "(#.length())", header: "<string>".} -proc setChar(a: var stdString, i: csize, c: char) {.importcpp: "(#[#] = #)", header: "<string>".} +proc setChar(a: var stdString, i: csize_t, c: char) {.importcpp: "(#[#] = #)", header: "<string>".} proc `*`*[T](this: stdUniquePtr[T]): var T {.noSideEffect, importcpp: "(* #)", header: "<memory>".} diff --git a/tests/cpp/tvirtual.nim b/tests/cpp/tvirtual.nim new file mode 100644 index 000000000..385d052b8 --- /dev/null +++ b/tests/cpp/tvirtual.nim @@ -0,0 +1,126 @@ +discard """ + targets: "cpp" + cmd: "nim cpp $file" + output: ''' +hello foo +hello boo +hello boo +Const Message: hello world +NimPrinter: hello world +NimPrinterConstRef: hello world +NimPrinterConstRefByRef: hello world +''' +""" + +{.emit:"""/*TYPESECTION*/ +#include <iostream> + class CppPrinter { + public: + + virtual void printConst(char* message) const { + std::cout << "Const Message: " << message << std::endl; + } + virtual void printConstRef(char* message, const int& flag) const { + std::cout << "Const Ref Message: " << message << std::endl; + } + virtual void printConstRef2(char* message, const int& flag) const { + std::cout << "Const Ref2 Message: " << message << std::endl; + } + +}; +""".} + +proc newCpp*[T](): ptr T {.importcpp:"new '*0()".} +type + Foo = object of RootObj + FooPtr = ptr Foo + Boo = object of Foo + BooPtr = ptr Boo + CppPrinter {.importcpp, inheritable.} = object + NimPrinter {.exportc.} = object of CppPrinter + +proc salute(self: FooPtr) {.virtual.} = + echo "hello foo" + +proc salute(self: BooPtr) {.virtual.} = + echo "hello boo" + +let foo = newCpp[Foo]() +let boo = newCpp[Boo]() +let booAsFoo = cast[FooPtr](newCpp[Boo]()) + +#polymorphism works +foo.salute() +boo.salute() +booAsFoo.salute() +let message = "hello world".cstring + +proc printConst(self: CppPrinter, message: cstring) {.importcpp.} +CppPrinter().printConst(message) + +#notice override is optional. +#Will make the cpp compiler to fail if not virtual function with the same signature if found in the base type +proc printConst(self: NimPrinter, message: cstring) {.virtual:"$1('2 #2) const override".} = + echo "NimPrinter: " & $message + +proc printConstRef(self: NimPrinter, message: cstring, flag: int32) {.virtual:"$1('2 #2, const '3& #3 ) const override".} = + echo "NimPrinterConstRef: " & $message + +proc printConstRef2(self: NimPrinter, message: cstring, flag {.byref.}: int32) {.virtual:"$1('2 #2, const '3 #3 ) const override".} = + echo "NimPrinterConstRefByRef: " & $message + +NimPrinter().printConst(message) +var val : int32 = 10 +NimPrinter().printConstRef(message, val) +NimPrinter().printConstRef2(message, val) + +#bug 22269 +type Doo = object +proc naiveMember(x: Doo): int {. virtual .} = 2 +discard naiveMember(Doo()) + +#asmnostackframe works with virtual +{.emit:"""/*TYPESECTION*/ + template<typename T> + struct Box { + T* first; + + Box(int x){ + first = new T(x); + }; + }; + struct Inner { + int val; + //Coo() = default; + Inner(int x){ + val = x; + }; + }; + struct Base { + virtual Box<Inner> test() = 0; + }; +""".} + +type + Inner {.importcpp.} = object + Base {.importcpp, inheritable.} = object + Child = object of Base + Box[T] {.importcpp, inheritable.} = object + first: T + +proc makeBox[T](x:int32): Box[T] {.importcpp:"Box<'0>(@)", constructor.} + +proc test(self: Child): Box[Inner] {.virtual, asmnostackframe.} = + let res {.exportc.} = makeBox[Inner](100) + {.emit:"return res;".} + + +discard Child().test() + +import virtualptr + +#We dont want to pull Loo directly by using it as we are testing that the pointer pulls it. +proc makeMoo(): Moo {.importcpp:"{ new Loo() }".} + +makeMoo().loo.salute() + diff --git a/tests/cpp/virtualptr.nim b/tests/cpp/virtualptr.nim new file mode 100644 index 000000000..f96264081 --- /dev/null +++ b/tests/cpp/virtualptr.nim @@ -0,0 +1,9 @@ +type + Loo* {.exportc.} = object + LooPtr* = ptr Loo + Moo* {.exportc.} = object + loo*: LooPtr + + +proc salute*(foo: LooPtr) {.virtual.} = + discard diff --git a/tests/defer/t22309.nim b/tests/defer/t22309.nim new file mode 100644 index 000000000..34ca4843b --- /dev/null +++ b/tests/defer/t22309.nim @@ -0,0 +1,11 @@ +block: + defer: + let a = 42 + doAssert not declared(a) + +proc lol() = + defer: + let a = 42 + doAssert not declared(a) + +lol() diff --git a/tests/deprecated/tannot.nim b/tests/deprecated/tannot.nim deleted file mode 100644 index d14f6cc23..000000000 --- a/tests/deprecated/tannot.nim +++ /dev/null @@ -1,9 +0,0 @@ -discard """ - nimout: '''tannot.nim(9, 1) Warning: efgh; foo1 is deprecated [Deprecated] -tannot.nim(9, 8) Warning: abcd; foo is deprecated [Deprecated] -''' -""" - -let foo* {.deprecated: "abcd".} = 42 -var foo1* {.deprecated: "efgh".} = 42 -foo1 = foo diff --git a/tests/deprecated/tmessages.nim b/tests/deprecated/tmessages.nim deleted file mode 100644 index 5884e396d..000000000 --- a/tests/deprecated/tmessages.nim +++ /dev/null @@ -1,10 +0,0 @@ -discard """ - nimout:'''tmessages.nim(10, 1) Warning: Deprecated since v1.2.0, use 'HelloZ'; hello is deprecated [Deprecated] -''' -""" - -proc hello[T](a: T) {.deprecated: "Deprecated since v1.2.0, use 'HelloZ'".} = - discard - - -hello[int](12) diff --git a/tests/deprecated/tmodule1.nim b/tests/deprecated/tmodule1.nim deleted file mode 100644 index f26e4ce3f..000000000 --- a/tests/deprecated/tmodule1.nim +++ /dev/null @@ -1,33 +0,0 @@ -discard """ - matrix: "--hint:all:off" - nimoutFull: true - nimout: ''' -tmodule1.nim(21, 8) Warning: goodbye; importme is deprecated [Deprecated] -tmodule1.nim(24, 10) Warning: Ty is deprecated [Deprecated] -tmodule1.nim(27, 10) Warning: hello; Ty1 is deprecated [Deprecated] -tmodule1.nim(30, 8) Warning: aVar is deprecated [Deprecated] -tmodule1.nim(32, 3) Warning: aProc is deprecated [Deprecated] -tmodule1.nim(33, 3) Warning: hello; aProc1 is deprecated [Deprecated] -''' -""" - - - - - - - -# line 20 -import importme - -block: - var z: Ty - z = 0 -block: - var z: Ty1 - z = 0 -block: - echo aVar -block: - aProc() - aProc1() diff --git a/tests/destructor/const_smart_ptr.nim b/tests/destructor/const_smart_ptr.nim index 4d8c7c9a3..25dd46500 100644 --- a/tests/destructor/const_smart_ptr.nim +++ b/tests/destructor/const_smart_ptr.nim @@ -2,13 +2,12 @@ type ConstPtr*[T] = object val: ptr T -proc `=destroy`*[T](p: var ConstPtr[T]) = +proc `=destroy`*[T](p: ConstPtr[T]) = if p.val != nil: `=destroy`(p.val[]) dealloc(p.val) - p.val = nil -proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.} +proc `=copy`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.} proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} = if dest.val != nil and dest.val != src.val: @@ -31,12 +30,11 @@ type len: int data: ptr UncheckedArray[float] -proc `=destroy`*(m: var MySeqNonCopyable) {.inline.} = +proc `=destroy`*(m: MySeqNonCopyable) {.inline.} = if m.data != nil: deallocShared(m.data) - m.data = nil -proc `=`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.error.} +proc `=copy`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.error.} proc `=sink`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.inline.} = if m.data != m2.data: diff --git a/tests/destructor/t16607.nim b/tests/destructor/t16607.nim index 5cc9d4a08..f98a6d517 100644 --- a/tests/destructor/t16607.nim +++ b/tests/destructor/t16607.nim @@ -15,8 +15,7 @@ proc initO(): O = O(initialized: true) proc pair(): tuple[a, b: O] = - result.a = initO() - result.b = initO() + result = (a: initO(), b: initO()) proc main() = discard pair() diff --git a/tests/destructor/t23748.nim b/tests/destructor/t23748.nim new file mode 100644 index 000000000..a3738733e --- /dev/null +++ b/tests/destructor/t23748.nim @@ -0,0 +1,31 @@ +discard """ + matrix: "--gc:refc; --gc:arc" + output: ''' +hello 42 +hello 42 +len = 2 +''' +""" + +# bug #23748 + +type + O = ref object + s: string + cb: seq[proc()] + +proc push1(o: O, i: int) = + let o = o + echo o.s, " ", i + o.cb.add(proc() = echo o.s, " ", i) + +proc push2(o: O, i: int) = + let o = o + echo o.s, " ", i + proc p() = echo o.s, " ", i + o.cb.add(p) + +let o = O(s: "hello", cb: @[]) +o.push1(42) +o.push2(42) +echo "len = ", o.cb.len diff --git a/tests/destructor/t23837.nim b/tests/destructor/t23837.nim new file mode 100644 index 000000000..e219dd6b5 --- /dev/null +++ b/tests/destructor/t23837.nim @@ -0,0 +1,51 @@ +discard """ + output: ''' +Deallocating OwnedString +HelloWorld +''' + matrix: "--cursorinference:on; --cursorinference:off" + target: "c" +""" + +# bug #23837 +{. + emit: [ + """ +#include <stdlib.h> +#include <string.h> +char *allocCString() { + char *result = (char *) malloc(10 + 1); + strcpy(result, "HelloWorld"); + return result; +} + +""" + ] +.} + +proc rawWrapper(): cstring {.importc: "allocCString", cdecl.} +proc free(p: pointer) {.importc: "free", cdecl.} + +# ------------------------- + +type OwnedString = distinct cstring + +proc `=destroy`(s: OwnedString) = + free(cstring s) + echo "Deallocating OwnedString" + +func `$`(s: OwnedString): string {.borrow.} + +proc leakyWrapper(): string = + let ostring = rawWrapper().OwnedString + $ostring + +# ------------------------- + +proc main() = + # destructor not called - definitely lost: 11 bytes in 1 blocks + # doesn't leak with --cursorInference:off + let s = leakyWrapper() + echo s + +main() \ No newline at end of file diff --git a/tests/destructor/tatomicptrs.nim b/tests/destructor/tatomicptrs.nim index 36f0cab8a..82870ac82 100644 --- a/tests/destructor/tatomicptrs.nim +++ b/tests/destructor/tatomicptrs.nim @@ -27,7 +27,7 @@ template decRef(x): untyped = atomicDec(x.refcount) proc makeShared*[T](x: sink T): SharedPtr[T] = # XXX could benefit from a macro that generates it. - result = cast[SharedPtr[T]](allocShared(sizeof(x))) + result = cast[SharedPtr[T]](allocShared0(sizeof(x))) result.x[] = x echo "allocating" @@ -39,7 +39,7 @@ proc `=destroy`*[T](dest: var SharedPtr[T]) = echo "deallocating" dest.x = nil -proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = +proc `=copy`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = var s = src.x if s != nil: incRef(s) #atomicSwap(dest, s) @@ -50,6 +50,9 @@ proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = deallocShared(s) echo "deallocating" +proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] = + `=copy`(result, src) + proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) = ## XXX make this an atomic store: if dest.x != src.x: @@ -120,7 +123,7 @@ proc `=destroy`*[T](m: var MySeq[T]) {.inline.} = deallocShared(m.data) m.data = nil -proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) = +proc `=copy`*[T](m: var MySeq[T], m2: MySeq[T]) = if m.data == m2.data: return if m.data != nil: `=destroy`(m) @@ -131,17 +134,22 @@ proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) = m.data = cast[ptr UncheckedArray[T]](allocShared(bytes)) copyMem(m.data, m2.data, bytes) +proc `=dup`*[T](m: MySeq[T]): MySeq[T] = + `=copy`[T](result, m) + proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} = if m.data != m2.data: if m.data != nil: `=destroy`(m) m.len = m2.len m.data = m2.data + m.refcount = m2.refcount proc len*[T](m: MySeq[T]): int {.inline.} = m.len proc newMySeq*[T](size: int, initial_value: T): MySeq[T] = result.len = size + result.refcount = 1 if size > 0: result.data = cast[ptr UncheckedArray[T]](allocShared(sizeof(T) * size)) diff --git a/tests/destructor/tbintree2.nim b/tests/destructor/tbintree2.nim index 0bc52457c..d56c2850b 100644 --- a/tests/destructor/tbintree2.nim +++ b/tests/destructor/tbintree2.nim @@ -21,21 +21,21 @@ proc merge(lower, greater: owned Node): owned Node = elif greater.isNil: result = lower elif lower.y < greater.y: - lower.right = merge(lower.right, greater) + lower.right = merge(move lower.right, greater) result = lower else: - greater.left = merge(lower, greater.left) + greater.left = merge(lower, move greater.left) result = greater proc splitBinary(orig: owned Node, value: int32): (owned Node, owned Node) = if orig.isNil: result = (nil, nil) elif orig.x < value: - let splitPair = splitBinary(orig.right, value) + let splitPair = splitBinary(move orig.right, value) orig.right = splitPair[0] result = (orig, splitPair[1]) else: - let splitPair = splitBinary(orig.left, value) + let splitPair = splitBinary(move orig.left, value) orig.left = splitPair[1] result = (splitPair[0], orig) diff --git a/tests/destructor/tdistinctseq.nim b/tests/destructor/tdistinctseq.nim new file mode 100644 index 000000000..5a2ac5ead --- /dev/null +++ b/tests/destructor/tdistinctseq.nim @@ -0,0 +1,8 @@ +discard """ + matrix: "-u:nimPreviewNonVarDestructor;" +""" +type DistinctSeq* = distinct seq[int] + +# `=destroy`(cast[ptr DistinctSeq](0)[]) +var x = @[].DistinctSeq +`=destroy`(x) diff --git a/tests/destructor/tdont_return_unowned_from_owned.nim b/tests/destructor/tdont_return_unowned_from_owned.nim index d27626dea..ffe87cd76 100644 --- a/tests/destructor/tdont_return_unowned_from_owned.nim +++ b/tests/destructor/tdont_return_unowned_from_owned.nim @@ -1,9 +1,12 @@ discard """ cmd: "nim check --newruntime --hints:off $file" nimout: ''' -tdont_return_unowned_from_owned.nim(36, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type -tdont_return_unowned_from_owned.nim(39, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type -tdont_return_unowned_from_owned.nim(42, 6) Error: type mismatch: got <Obj> +tdont_return_unowned_from_owned.nim(26, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref +tdont_return_unowned_from_owned.nim(27, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref +tdont_return_unowned_from_owned.nim(31, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type +tdont_return_unowned_from_owned.nim(43, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type +tdont_return_unowned_from_owned.nim(46, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(Obj)' as the return type +tdont_return_unowned_from_owned.nim(49, 6) Error: type mismatch: got <Obj> but expected one of: proc new[T](a: var ref T; finalizer: proc (x: ref T) {.nimcall.}) first type mismatch at position: 2 @@ -11,17 +14,21 @@ proc new[T](a: var ref T; finalizer: proc (x: ref T) {.nimcall.}) 2 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them expression: new(result) -tdont_return_unowned_from_owned.nim(42, 6) Error: illformed AST: -tdont_return_unowned_from_owned.nim(50, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref -tdont_return_unowned_from_owned.nim(51, 13) Error: assignment produces a dangling ref: the unowned ref lives longer than the owned ref -tdont_return_unowned_from_owned.nim(55, 10) Error: cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type +tdont_return_unowned_from_owned.nim(49, 6) Error: illformed AST: ''' - errormsg: "cannot return an owned pointer as an unowned pointer; use 'owned(RootRef)' as the return type" + errormsg: "illformed AST:" """ +proc testA(result: var (RootRef, RootRef)) = + let r: owned RootRef = RootRef() + result[0] = r + result[1] = RootRef() +proc testB(): RootRef = + let r: owned RootRef = RootRef() + result = r @@ -39,17 +46,11 @@ proc newObjB(): Obj = result = Obj() proc newObjC(): Obj = - new(result) + new(result) # illFormedAst raises GlobalError, + # without pipeline parsing, it needs to placed at the end + # in case that it disturbs other errors let a = newObjA() let b = newObjB() let c = newObjC() -proc testA(result: var (RootRef, RootRef)) = - let r: owned RootRef = RootRef() - result[0] = r - result[1] = RootRef() - -proc testB(): RootRef = - let r: owned RootRef = RootRef() - result = r diff --git a/tests/destructor/tgotoexc_leak.nim b/tests/destructor/tgotoexc_leak.nim new file mode 100644 index 000000000..c8a234085 --- /dev/null +++ b/tests/destructor/tgotoexc_leak.nim @@ -0,0 +1,19 @@ +discard """ + output: '''0 +true''' + cmd: "nim c --gc:arc $file" +""" + +# bug #22398 + +for i in 0 ..< 10_000: + try: + try: + raise newException(ValueError, "") + except CatchableError: + discard + raise newException(ValueError, "") # or raise getCurrentException(), just raise works ok + except ValueError: + discard +echo getOccupiedMem() +echo getCurrentException() == nil diff --git a/tests/destructor/tgotoexceptions7.nim b/tests/destructor/tgotoexceptions7.nim index 6e564a044..c04bd6ba0 100644 --- a/tests/destructor/tgotoexceptions7.nim +++ b/tests/destructor/tgotoexceptions7.nim @@ -25,7 +25,8 @@ proc helper = doAssert(false) proc main(i: int) = var obj = Obj(kind: kindA, s: "abc") - obj.kind = kindB + {.cast(uncheckedAssign).}: + obj.kind = kindB obj.i = 2 try: var objA = ObjA() diff --git a/tests/destructor/tmatrix.nim b/tests/destructor/tmatrix.nim index 98ca95c94..2fd5af789 100644 --- a/tests/destructor/tmatrix.nim +++ b/tests/destructor/tmatrix.nim @@ -31,7 +31,7 @@ proc `=sink`*(a: var Matrix; b: Matrix) = a.m = b.m a.n = b.n -proc `=`*(a: var Matrix; b: Matrix) = +proc `=copy`*(a: var Matrix; b: Matrix) = if a.data != nil and a.data != b.data: dealloc(a.data) deallocCount.inc @@ -43,6 +43,9 @@ proc `=`*(a: var Matrix; b: Matrix) = allocCount.inc copyMem(a.data, b.data, b.m * b.n * sizeof(float)) +proc `=dup`*(a: Matrix): Matrix = + `=copy`(result, a) + proc matrix*(m, n: int, s: float): Matrix = ## Construct an m-by-n constant matrix. result.m = m diff --git a/tests/destructor/tmove.nim b/tests/destructor/tmove.nim new file mode 100644 index 000000000..2762aff90 --- /dev/null +++ b/tests/destructor/tmove.nim @@ -0,0 +1,18 @@ +discard """ + targets: "c cpp" +""" + +block: + var called = 0 + + proc bar(a: var int): var int = + inc called + result = a + + proc foo = + var a = 2 + var s = move bar(a) + doAssert called == 1 + doAssert s == 2 + + foo() diff --git a/tests/destructor/tmove_objconstr.nim b/tests/destructor/tmove_objconstr.nim index 9eee4bfdb..cdc1eb1c0 100644 --- a/tests/destructor/tmove_objconstr.nim +++ b/tests/destructor/tmove_objconstr.nim @@ -50,7 +50,7 @@ proc `=destroy`(o: var Pony) = echo "Pony is dying!" proc getPony: Pony = - result.name = "Sparkles" + result = Pony(name: "Sparkles") iterator items(p: Pony): int = for i in 1..4: @@ -137,28 +137,29 @@ doAssert seq3[0] == 1.0 var seq4, seq5: MySeqNonCopyable (seq4, i, seq5) = myfunc2(2, 3) -seq4 = block: - var tmp = newMySeq(4, 1.0) - tmp[0] = 3.0 - tmp +proc foo = + seq4 = block: + var tmp = newMySeq(4, 1.0) + tmp[0] = 3.0 + tmp -doAssert seq4[0] == 3.0 + doAssert seq4[0] == 3.0 -import macros -seq4 = - if i > 0: newMySeq(2, 5.0) - elif i < -100: raise newException(ValueError, "Parse Error") - else: newMySeq(2, 3.0) + seq4 = + if i > 0: newMySeq(2, 5.0) + elif i < -100: raise newException(ValueError, "Parse Error") + else: newMySeq(2, 3.0) -seq4 = - case (char) i: - of 'A', {'W'..'Z'}: newMySeq(2, 5.0) - of 'B': quit(-1) - else: - let (x1, x2, x3) = myfunc2(2, 3) - x3 + seq4 = + case (char) i: + of 'A', {'W'..'Z'}: newMySeq(2, 5.0) + of 'B': quit(-1) + else: + let (x1, x2, x3) = myfunc2(2, 3) + x3 +foo() #------------------------------------------------------------ #-- Move into array constructor diff --git a/tests/destructor/tnonvardestructor.nim b/tests/destructor/tnonvardestructor.nim new file mode 100644 index 000000000..1b4413790 --- /dev/null +++ b/tests/destructor/tnonvardestructor.nim @@ -0,0 +1,247 @@ +discard """ + targets: "c cpp" + matrix: "--mm:arc; --mm:orc" +""" + +block: + type + PublicKey = array[32, uint8] + PrivateKey = array[64, uint8] + + proc ed25519_create_keypair(publicKey: ptr PublicKey; privateKey: ptr PrivateKey) = + publicKey[][0] = uint8(88) + + type + KeyPair = object + public: PublicKey + private: PrivateKey + + proc initKeyPair(): KeyPair = + ed25519_create_keypair(result.public.addr, result.private.addr) + + let keys = initKeyPair() + doAssert keys.public[0] == 88 + + +template minIndexByIt: untyped = + var other = 3 + other + +proc bug20303() = + var hlibs = @["hello", "world", "how", "are", "you"] + let res = hlibs[minIndexByIt()] + doAssert res == "are" + +bug20303() + +proc main() = # todo bug with templates + block: # bug #11267 + var a: seq[char] = block: @[] + doAssert a == @[] + # 2 + proc b: seq[string] = + discard + @[] + doAssert b() == @[] +static: main() +main() + + +type Obj = tuple + value: int + arr: seq[int] + +proc bug(): seq[Obj] = + result.add (value: 0, arr: @[]) + result[^1].value = 1 + result[^1].arr.add 1 + +# bug #19990 +let s = bug() +doAssert s[0] == (value: 1, arr: @[1]) + +block: # bug #21974 + type Test[T] = ref object + values : seq[T] + counter: int + + proc newTest[T](): Test[T] = + result = new(Test[T]) + result.values = newSeq[T](16) + result.counter = 0 + + proc push[T](self: Test[T], value: T) = + self.counter += 1 + if self.counter >= self.values.len: + self.values.setLen(self.values.len * 2) + self.values[self.counter - 1] = value + + proc pop[T](self: Test[T]): T = + result = self.values[0] + self.values[0] = self.values[self.counter - 1] # <--- This line + self.counter -= 1 + + + type X = tuple + priority: int + value : string + + var a = newTest[X]() + a.push((1, "One")) + doAssert a.pop.value == "One" + +# bug #21987 + +type + EmbeddedImage* = distinct Image + Image = object + len: int + +proc imageCopy*(image: Image): Image {.nodestroy.} + +proc `=destroy`*(x: Image) = + discard + +proc `=sink`*(dest: var Image; source: Image) = + `=destroy`(dest) + wasMoved(dest) + +proc `=dup`*(source: Image): Image {.nodestroy.} = + result = imageCopy(source) + +proc `=copy`*(dest: var Image; source: Image) = + dest = imageCopy(source) # calls =sink implicitly + +proc `=destroy`*(x: EmbeddedImage) = discard + +proc `=dup`*(source: EmbeddedImage): EmbeddedImage {.nodestroy.} = source + +proc `=copy`*(dest: var EmbeddedImage; source: EmbeddedImage) {.nodestroy.} = + dest = source + +proc imageCopy*(image: Image): Image = + result = image + +proc main2 = + block: + var a = Image(len: 2).EmbeddedImage + var b = Image(len: 1).EmbeddedImage + b = a + doAssert Image(a).len == 2 + doAssert Image(b).len == 2 + + block: + var a = Image(len: 2) + var b = Image(len: 1) + b = a + doAssert a.len == 2 + doAssert b.len == 0 + +main2() + +type + Edge = object + neighbor {.cursor.}: Node + + NodeObj = object + neighbors: seq[Edge] + label: string + visited: bool + Node = ref NodeObj + + Graph = object + nodes: seq[Node] + +proc `=destroy`(x: NodeObj) = + `=destroy`(x.neighbors) + `=destroy`(x.label) + +proc addNode(self: var Graph; label: string): Node = + self.nodes.add(Node(label: label)) + result = self.nodes[^1] + +proc addEdge(self: Graph; source, neighbor: Node) = + source.neighbors.add(Edge(neighbor: neighbor)) + +block: + proc main = + var graph: Graph + let nodeA = graph.addNode("a") + let nodeB = graph.addNode("b") + let nodeC = graph.addNode("c") + + graph.addEdge(nodeA, neighbor = nodeB) + graph.addEdge(nodeA, neighbor = nodeC) + + main() + +block: + type RefObj = ref object + + proc `[]`(val: static[int]) = # works with different name/overload or without static arg + discard + + template noRef(T: typedesc): typedesc = # works without template indirection + typeof(default(T)[]) + + proc `=destroy`(x: noRef(RefObj)) = + discard + + proc foo = + var x = new RefObj + doAssert $(x[]) == "()" + + # bug #11705 + foo() + +block: # bug #22197 + type + H5IdObj = object + H5Id = ref H5IdObj + + FileID = distinct H5Id + + H5GroupObj = object + file_id: FileID + H5Group = ref H5GroupObj + + ## This would make it work! + #proc `=destroy`*(x: FileID) = `=destroy`(cast[H5Id](x)) + ## If this does not exist, it also works! + proc newFileID(): FileID = FileID(H5Id()) + + proc `=destroy`(grp: H5GroupObj) = + ## Closes the group and resets all references to nil. + if cast[pointer](grp.fileId) != nil: + `=destroy`(grp.file_id) + + var grp = H5Group() + reset(grp.file_id) + reset(grp) + +import std/tables + +block: # bug #22286 + type + A = object + B = object + a: A + C = object + b: B + + proc `=destroy`(self: A) = + echo "destroyed" + + proc `=destroy`(self: C) = + `=destroy`(self.b) + + var c = C() + +block: # https://forum.nim-lang.org/t/10642 + type AObj = object + name: string + tableField: Table[string, string] + + proc `=destroy`(x: AObj) = + `=destroy`(x.name) + `=destroy`(x.tableField) diff --git a/tests/destructor/topttree.nim b/tests/destructor/topttree.nim index fa5495689..8cf757e8b 100644 --- a/tests/destructor/topttree.nim +++ b/tests/destructor/topttree.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 output: '''10.0 60.0 90.0 diff --git a/tests/destructor/tprevent_assign2.nim b/tests/destructor/tprevent_assign2.nim index ef20672d5..eb5588b1a 100644 --- a/tests/destructor/tprevent_assign2.nim +++ b/tests/destructor/tprevent_assign2.nim @@ -1,7 +1,7 @@ discard """ - errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type <Foo>, which is inferred from unavailable '=copy'; requires a copy because it's not the last read of 'otherTree'; another read is done here: tprevent_assign2.nim(51, 31); routine: preventThis" file: "tprevent_assign2.nim" - line: 48 + line: 49 """ type @@ -9,7 +9,8 @@ type x: int proc `=destroy`(f: var Foo) = f.x = 0 -proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x + proc `=sink`(a: var Foo; b: Foo) = a.x = b.x proc createTree(x: int): Foo = @@ -18,7 +19,7 @@ proc createTree(x: int): Foo = proc take2(a, b: sink Foo) = echo a.x, " ", b.x -proc allowThis() = +when false: var otherTree: Foo try: for i in 0..3: @@ -51,5 +52,5 @@ proc preventThis() = else: discard -allowThis() +#allowThis() preventThis() diff --git a/tests/destructor/tprevent_assign3.nim b/tests/destructor/tprevent_assign3.nim index 0577aa5ff..aa834a66c 100644 --- a/tests/destructor/tprevent_assign3.nim +++ b/tests/destructor/tprevent_assign3.nim @@ -1,7 +1,7 @@ discard """ - errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" + errormsg: "'=dup' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'" file: "tprevent_assign3.nim" - line: 46 + line: 47 """ type @@ -9,7 +9,8 @@ type x: int proc `=destroy`(f: var Foo) = f.x = 0 -proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x +proc `=dup`(a: Foo): Foo {.error.} proc `=sink`(a: var Foo; b: Foo) = a.x = b.x proc createTree(x: int): Foo = @@ -18,7 +19,7 @@ proc createTree(x: int): Foo = proc take2(a, b: sink Foo) = echo a.x, " ", b.x -proc allowThis() = +when false: var otherTree: Foo try: for i in 0..3: @@ -47,7 +48,7 @@ proc preventThis2() = finally: echo otherTree -allowThis() +#allowThis() preventThis2() diff --git a/tests/destructor/tsink.nim b/tests/destructor/tsink.nim new file mode 100644 index 000000000..e8750ad7c --- /dev/null +++ b/tests/destructor/tsink.nim @@ -0,0 +1,70 @@ +discard """ + matrix: "--mm:arc" +""" + +type AnObject = object of RootObj + value*: int + +proc mutate(shit: sink AnObject) = + shit.value = 1 + +proc foo = # bug #23359 + var bar = AnObject(value: 42) + mutate(bar) + doAssert bar.value == 42 + +foo() + +block: # bug #23902 + proc foo(a: sink string): auto = (a, a) + + proc bar(a: sink int): auto = return a + + proc foo(a: sink string) = + var x = (a, a) + +block: # bug #24175 + block: + func mutate(o: sink string): string = + o[1] = '1' + result = o + + static: + let s = "999" + let m = mutate(s) + doAssert s == "999" + doAssert m == "919" + + func foo() = + let s = "999" + let m = mutate(s) + doAssert s == "999" + doAssert m == "919" + + static: + foo() + foo() + + block: + type O = object + a: int + + func mutate(o: sink O): O = + o.a += 1 + o + + static: + let x = O(a: 1) + let y = mutate(x) + doAssert x.a == 1 + doAssert y.a == 2 + + proc foo() = + let x = O(a: 1) + let y = mutate(x) + doAssert x.a == 1 + doAssert y.a == 2 + + static: + foo() + foo() diff --git a/tests/destructor/tuse_ownedref_after_move.nim b/tests/destructor/tuse_ownedref_after_move.nim index ce96b741e..69348d530 100644 --- a/tests/destructor/tuse_ownedref_after_move.nim +++ b/tests/destructor/tuse_ownedref_after_move.nim @@ -1,6 +1,6 @@ discard """ cmd: '''nim c --newruntime $file''' - errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; another read is done here: tuse_ownedref_after_move.nim(52, 4)" + errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; routine: main" line: 48 """ diff --git a/tests/destructor/tv2_cast.nim b/tests/destructor/tv2_cast.nim index 917cf0eb3..48bdf67dd 100644 --- a/tests/destructor/tv2_cast.nim +++ b/tests/destructor/tv2_cast.nim @@ -3,81 +3,51 @@ discard """ @[116, 101, 115, 116] @[1953719668, 875770417] destroying O1''' - cmd: '''nim c --gc:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file''' - nimout: '''--expandArc: main + cmd: '''nim c --mm:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file''' + nimout: ''' +--expandArc: main var data :tmpD - :tmpD_1 - :tmpD_2 -data = - wasMoved(:tmpD) - `=copy`(:tmpD, cast[string]( - :tmpD_2 = encode(cast[seq[byte]]( - :tmpD_1 = newString(100) - :tmpD_1)) - :tmpD_2)) - :tmpD -`=destroy`(:tmpD_2) -`=destroy_1`(:tmpD_1) -`=destroy_1`(data) +data = cast[string](encode(cast[seq[byte]]( + :tmpD = newString(100) + :tmpD))) +`=destroy`(:tmpD) +`=destroy`(data) -- end of expandArc ------------------------ --expandArc: main1 var s data - :tmpD - :tmpD_1 s = newString(100) -data = - wasMoved(:tmpD) - `=copy`(:tmpD, cast[string]( - :tmpD_1 = encode(toOpenArrayByte(s, 0, len(s) - 1)) - :tmpD_1)) - :tmpD -`=destroy`(:tmpD_1) -`=destroy_1`(data) -`=destroy_1`(s) +data = cast[string](encode(toOpenArrayByte(s, 0, len(s) - 1))) +`=destroy`(data) +`=destroy`(s) -- end of expandArc ------------------------ --expandArc: main2 var s data - :tmpD - :tmpD_1 s = newSeq(100) -data = - wasMoved(:tmpD) - `=copy`(:tmpD, cast[string]( - :tmpD_1 = encode(s) - :tmpD_1)) - :tmpD -`=destroy`(:tmpD_1) -`=destroy_1`(data) -`=destroy`(s) +data = cast[string](encode(s)) +`=destroy`(data) +`=destroy_1`(s) -- end of expandArc ------------------------ --expandArc: main3 var data :tmpD - :tmpD_1 - :tmpD_2 -data = - wasMoved(:tmpD) - `=copy`(:tmpD, cast[string]( - :tmpD_2 = encode do: - :tmpD_1 = newSeq(100) - :tmpD_1 - :tmpD_2)) - :tmpD -`=destroy`(:tmpD_2) -`=destroy`(:tmpD_1) +data = cast[string](encode do: + :tmpD = newSeq(100) + :tmpD) +`=destroy`(:tmpD) `=destroy_1`(data) --- end of expandArc ------------------------''' +-- end of expandArc ------------------------ +''' """ func encode*(src: openArray[byte]): seq[byte] = diff --git a/tests/destructor/twasmoved.nim b/tests/destructor/twasmoved.nim new file mode 100644 index 000000000..566322702 --- /dev/null +++ b/tests/destructor/twasmoved.nim @@ -0,0 +1,14 @@ +type + Foo = object + id: int + +proc `=wasMoved`(x: var Foo) = + x.id = -1 + +proc foo = + var s = Foo(id: 999) + var m = move s + doAssert s.id == -1 + doAssert m.id == 999 + +foo() diff --git a/tests/destructor/twasmoved_error.nim b/tests/destructor/twasmoved_error.nim new file mode 100644 index 000000000..1cd57e3df --- /dev/null +++ b/tests/destructor/twasmoved_error.nim @@ -0,0 +1,37 @@ +discard """ + cmd: '''nim c --mm:arc $file''' + errormsg: "'=wasMoved' is not available for type <Game>; routine: main" +""" + +# bug #19291 + +const + screenWidth = 800 + screenHeight = 450 + +var + ready = false +type + Game = object + +proc `=destroy`(x: var Game) = + assert ready, "Window is already opened" + ready = false + +proc `=sink`(x: var Game; y: Game) {.error.} +proc `=copy`(x: var Game; y: Game) {.error.} +proc `=wasMoved`(x: var Game) {.error.} + +proc initGame(width, height: int32, title: string): Game = + assert not ready, "Window is already closed" + ready = true + +proc update(x: Game) = discard + +proc main = + var g = initGame(screenWidth, screenHeight, "Tetris raylib") + g.update() + var g2 = g + echo "hello" + +main() diff --git a/tests/discard/t23677.nim b/tests/discard/t23677.nim new file mode 100644 index 000000000..1ed7386bd --- /dev/null +++ b/tests/discard/t23677.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "expression '0' is of type 'int literal(0)' and has to be used (or discarded); start of expression here: t23677.nim(1, 1)" + line: 10 + column: 3 +""" + +# issue #23677 + +if true: + 0 +else: + raise newException(ValueError, "err") diff --git a/tests/discard/tdiscardable.nim b/tests/discard/tdiscardable.nim index 032050139..84b669ed8 100644 --- a/tests/discard/tdiscardable.nim +++ b/tests/discard/tdiscardable.nim @@ -5,6 +5,7 @@ tdiscardable 1 something defered something defered +hi ''' """ @@ -65,3 +66,110 @@ proc main2() = main1() main2() + +block: # bug #13583 + block: + proc hello(): int {.discardable.} = 12 + + iterator test(): int {.closure.} = + while true: + hello() + + let t = test + + block: + proc hello(): int {.discardable.} = 12 + + iterator test(): int {.closure.} = + while true: + block: + yield 12 + hello() + + let t = test + doAssert t() == 12 + + block: + proc hello(): int {.discardable.} = 12 + + iterator test(): int {.closure.} = + while true: + yield 12 + hello() + + let t = test + doAssert t() == 12 + +block: + proc bar(): string {.discardable.} = + "15" + + proc foo(): int = + while true: + raise newException(ValueError, "check") + 12 + + doAssertRaises(ValueError): + doAssert foo() == 12 + +block: # issue #10440 + proc x(): int {.discardable.} = discard + try: + x() + finally: + echo "hi" + +import macros + +block: # issue #14665 + macro test(): untyped = + let b = @[1, 2, 3, 4] + + result = nnkStmtList.newTree() + var i = 0 + while i < b.len: + if false: + # this quote do is mandatory, removing it fixes the problem + result.add quote do: + let testtest = 5 + else: + result.add quote do: + let test = 6 + inc i + # removing this continue fixes the problem too + continue + inc i + test() + +block: # bug #23775 + proc retInt(): int {.discardable.} = + 42 + + proc retString(): string {.discardable.} = + "text" + + type + Enum = enum + A, B, C, D + + proc doStuff(msg: Enum) = + case msg: + of A: + retString() + of B: + retInt() + of C: + discard retString() + else: + let _ = retString() + + doStuff(C) + +block: + proc test(): (int, int) {.discardable.} = + discard + + if true: + test() + else: + quit() diff --git a/tests/discard/tfinallyerrmsg.nim b/tests/discard/tfinallyerrmsg.nim new file mode 100644 index 000000000..fbc8140aa --- /dev/null +++ b/tests/discard/tfinallyerrmsg.nim @@ -0,0 +1,19 @@ +discard """ + cmd: "nim check $file" +""" + +block: # issue #19672 + try: + 10 #[tt.Error + ^ expression '10' is of type 'int literal(10)' and has to be used (or discarded); start of expression here: tfinallyerrmsg.nim(5, 1)]# + finally: + echo "Finally block" + +block: # issue #13871 + template t(body: int) = + try: + body + finally: + echo "expression" + t: 2 #[tt.Error + ^ expression '2' is of type 'int literal(2)' and has to be used (or discarded)]# diff --git a/tests/discard/tillegaldiscardtypes.nim b/tests/discard/tillegaldiscardtypes.nim new file mode 100644 index 000000000..b7877bcd2 --- /dev/null +++ b/tests/discard/tillegaldiscardtypes.nim @@ -0,0 +1,14 @@ +discard """ + cmd: "nim check $file" + errormsg: "statement returns no value that can be discarded" + nimout: ''' +tillegaldiscardtypes.nim(11, 3) Error: statement returns no value that can be discarded +tillegaldiscardtypes.nim(12, 3) Error: statement returns no value that can be discarded +''' +""" + +proc b(v: int) = # bug #21360 + discard @[] + discard [] + +b(0) \ No newline at end of file diff --git a/tests/borrow/tborrow.nim b/tests/distinct/tborrow.nim index 35652e2e0..e34248de5 100644 --- a/tests/borrow/tborrow.nim +++ b/tests/distinct/tborrow.nim @@ -88,4 +88,45 @@ block: # Borrow from generic alias c = default(C) e = default(E) assert c.i == int(0) - assert e.i == 0d \ No newline at end of file + assert e.i == 0d + +block: # issue #22069 + type + Vehicle[C: static[int]] = object + color: array[C, int] + Car[C: static[int]] {.borrow: `.`.} = distinct Vehicle[C] + MuscleCar = Car[128] + var x: MuscleCar + doAssert x.color is array[128, int] + +block: # issue #22646 + type + Vec[N : static[int], T: SomeNumber] = object + arr: array[N, T] + Vec3[T: SomeNumber] = Vec[3, T] + + proc `[]=`[N,T](v: var Vec[N,T]; ix:int; c:T): void {.inline.} = v.arr[ix] = c + proc `[]`[N,T](v: Vec[N,T]; ix: int): T {.inline.} = v.arr[ix] + + proc dot[N,T](u,v: Vec[N,T]): T {. inline .} = discard + proc length[N,T](v: Vec[N,T]): T = discard + proc cross[T](v1,v2:Vec[3,T]): Vec[3,T] = discard + proc normalizeWorks[T](v: Vec[3,T]): Vec[3,T] = discard ## <- Explicit size makes it work! + proc foo[N,T](u, v: Vec[N,T]): Vec[N,T] = discard ## <- broken + proc normalize[N,T](v: Vec[N,T]): Vec[N,T] = discard ## <- broken + + type Color = distinct Vec3[float] + + template borrowOps(typ: typedesc): untyped = + proc `[]=`(v: var typ; ix: int; c: float): void {.borrow.} + proc `[]`(v: typ; ix: int): float {.borrow.} + proc dot(v, u: typ): float {.borrow.} + proc cross(v, u: typ): typ {.borrow.} + proc length(v: typ): float {.borrow.} + proc normalizeWorks(v: typ): typ {.borrow.} ## Up to here everything works + proc foo(u, v: typ): typ {.borrow.} ## Broken + proc normalize(v: typ): typ {.borrow.} ## Broken + borrowOps(Color) + var x: Vec[3, float] + let y = Color(x) + doAssert Vec3[float](y) == x diff --git a/tests/distinct/tcomplexaddressableconv.nim b/tests/distinct/tcomplexaddressableconv.nim new file mode 100644 index 000000000..00e96bfeb --- /dev/null +++ b/tests/distinct/tcomplexaddressableconv.nim @@ -0,0 +1,21 @@ +# issue #22523 + +from std/typetraits import distinctBase + +type + V[p: static int] = distinct int + D[p: static int] = distinct int + T = V[1] + +proc f(y: var T) = discard + +var a: D[0] + +static: + doAssert distinctBase(T) is distinctBase(D[0]) + doAssert distinctBase(T) is int + doAssert distinctBase(D[0]) is int + doAssert T(a) is T + +f(cast[ptr T](addr a)[]) +f(T(a)) diff --git a/tests/distinct/tdistinct.nim b/tests/distinct/tdistinct.nim index 8ec083020..b6ba7aa99 100644 --- a/tests/distinct/tdistinct.nim +++ b/tests/distinct/tdistinct.nim @@ -159,7 +159,7 @@ block: #17322 type Foo = distinct string -template main() = +proc main() = # proc instead of template because of MCS/UFCS. # xxx put everything here to test under RT + VM block: # bug #12282 block: @@ -199,5 +199,29 @@ template main() = var c: B + block: # bug #9423 + block: + type Foo = seq[int] + type Foo2 = distinct Foo + template fn() = + var a = Foo2(@[1]) + a.Foo.add 2 + doAssert a.Foo == @[1, 2] + fn() + + block: + type Stack[T] = distinct seq[T] + proc newStack[T](): Stack[T] = + Stack[T](newSeq[T]()) + proc push[T](stack: var Stack[T], elem: T) = + seq[T](stack).add(elem) + proc len[T](stack: Stack[T]): int = + seq[T](stack).len + proc fn() = + var stack = newStack[int]() + stack.push(5) + doAssert stack.len == 1 + fn() + static: main() main() diff --git a/tests/distinct/tinvalidborrow.nim b/tests/distinct/tinvalidborrow.nim new file mode 100644 index 000000000..d4b19fa8d --- /dev/null +++ b/tests/distinct/tinvalidborrow.nim @@ -0,0 +1,42 @@ +discard """ + cmd: "nim check --hints:off --warnings:off $file" + action: "reject" + nimout:''' +tinvalidborrow.nim(25, 3) Error: only a 'distinct' type can borrow `.` +tinvalidborrow.nim(26, 3) Error: only a 'distinct' type can borrow `.` +tinvalidborrow.nim(27, 1) Error: borrow proc without distinct type parameter is meaningless +tinvalidborrow.nim(36, 1) Error: borrow with generic parameter is not supported +tinvalidborrow.nim(41, 1) Error: borrow from proc return type mismatch: 'T' +tinvalidborrow.nim(42, 1) Error: borrow from '[]=' is not supported +''' +""" + + + + + +# bug #516 + +type + TAtom = culong + Test {.borrow:`.`.} = distinct int + Foo[T] = object + a: int + Bar[T] {.borrow:`.`.} = Foo[T] + OtherFoo {.borrow:`.`.} = Foo[int] +proc `==`*(a, b: TAtom): bool {.borrow.} + +var + d, e: TAtom + +discard( $(d == e) ) + +# issue #4121 +type HeapQueue[T] = distinct seq[T] +proc len*[T](h: HeapQueue[T]): int {.borrow.} + +# issue #3564 +type vec4[T] = distinct array[4, float32] + +proc `[]`(v: vec4, i: int): float32 {.borrow.} +proc `[]=`(v: vec4, i: int, va: float32) {.borrow.} diff --git a/tests/borrow/typeclassborrow.nim b/tests/distinct/typeclassborrow.nim index 62cb77d67..5e0c63953 100644 --- a/tests/borrow/typeclassborrow.nim +++ b/tests/distinct/typeclassborrow.nim @@ -1,3 +1,5 @@ +import std/tables + type Foo = distinct seq[int] Bar[N: static[int]] = distinct seq[int] @@ -29,4 +31,26 @@ baz.doThing() assert $seq[int](foo) == $foo assert $seq[int](bar) == $bar -assert $seq[int](baz) == $baz \ No newline at end of file +assert $seq[int](baz) == $baz + +type + Fine* = distinct string + +proc `==`*(x, y: Fine): bool {.borrow.} = + ## Here is the documentation + runnableExamples: + var x = Fine("1234") + var y = Fine("1234") + doAssert x == y + doAssert false + + +var x = Fine("1234") +var y = Fine("1234") +doAssert x == y + +block: # bug #22902 + type + DistinctTable = distinct Table[int, int] + + proc `[]`(t: DistinctTable; key: int): lent int {.borrow.} diff --git a/tests/dll/nimhcr_basic.nim b/tests/dll/nimhcr_basic.nim new file mode 100644 index 000000000..2e1f39ae0 --- /dev/null +++ b/tests/dll/nimhcr_basic.nim @@ -0,0 +1,8 @@ +discard """ + output: ''' +Hello world +''' +""" +# for now orc only tests successful compilation + +echo "Hello world" diff --git a/tests/dll/nimhcr_unit.nim b/tests/dll/nimhcr_unit.nim index 0b924bdf7..249f3f9f1 100644 --- a/tests/dll/nimhcr_unit.nim +++ b/tests/dll/nimhcr_unit.nim @@ -106,14 +106,14 @@ macro carryOutTests(callingConv: untyped): untyped = echo `procName`, " implementation #1 ", x return x + 1 - let fp1 = cast[F](hcrRegisterProc("dummy_module", `procName`, `p1`)) + let fp1 = cast[F](hcrRegisterProc("dummy_module", `procName`, cast[pointer](`p1`))) echo fp1(10) proc `p2`(x: int): int {.placeholder.} = echo `procName`, " implementation #2 ", x return x + 2 - let fp2 = cast[F](hcrRegisterProc("dummy_module", `procName`, `p2`)) + let fp2 = cast[F](hcrRegisterProc("dummy_module", `procName`, cast[pointer](`p2`))) echo fp1(20) echo fp2(20) @@ -121,7 +121,7 @@ macro carryOutTests(callingConv: untyped): untyped = echo `procName`, " implementation #3 ", x return x + 3 - let fp3 = cast[F](hcrRegisterProc("dummy_module", `procName`, `p3`)) + let fp3 = cast[F](hcrRegisterProc("dummy_module", `procName`, cast[pointer](`p3`))) echo fp1(30) echo fp2(30) echo fp3(30) diff --git a/tests/effects/tdiagnostic_messages.nim b/tests/effects/tdiagnostic_messages.nim index 2ce4895a3..b1acf8c5c 100644 --- a/tests/effects/tdiagnostic_messages.nim +++ b/tests/effects/tdiagnostic_messages.nim @@ -12,7 +12,7 @@ tdiagnostic_messages.nim(36, 6) Error: 'a' can have side effects >>> tdiagnostic_messages.nim(32, 33) Hint: 'callWithSideEffects' calls `.sideEffect` 'indirectCallViaPointer' >>>> tdiagnostic_messages.nim(27, 6) Hint: 'indirectCallViaPointer' called by 'callWithSideEffects' >>>>> tdiagnostic_messages.nim(28, 32) Hint: 'indirectCallViaPointer' calls routine via pointer indirection ->>> tdiagnostic_messages.nim(33, 10) Hint: 'callWithSideEffects' calls `.sideEffect` 'myEcho' +>>> tdiagnostic_messages.nim(33, 3) Hint: 'callWithSideEffects' calls `.sideEffect` 'myEcho' >>>> tdiagnostic_messages.nim(24, 6) Hint: 'myEcho' called by 'callWithSideEffects' >>> tdiagnostic_messages.nim(34, 3) Hint: 'callWithSideEffects' accesses global state 'globalVar' >>>> tdiagnostic_messages.nim(23, 5) Hint: 'globalVar' accessed by 'callWithSideEffects' diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim index 3978d8cc2..1d267b5fa 100644 --- a/tests/effects/teffects1.nim +++ b/tests/effects/teffects1.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim check $file" + cmd: "nim check --hint:Conf:off --hint:XDeclaredButNotUsed:off $file" nimout: ''' teffects1.nim(17, 28) template/generic instantiation from here ''' @@ -17,24 +17,30 @@ proc forw: int {. .} proc lier(): int {.raises: [IO2Error].} = #[tt.Hint ^ 'lier' cannot raise 'IO2Error' [XCannotRaiseY] ]# writeLine stdout, "arg" #[tt.Error - ^ writeLine stdout, ["arg"] can raise an unlisted exception: ref IOError ]# + ^ writeLine stdout, ["arg"] can raise an unlisted exception: ref IOError ]# proc forw: int = raise newException(IOError, "arg") +block: + proc someProc(t: string) {.raises: [Defect].} = + discard + let vh: proc(topic: string) {.raises: [].} = someProc + {.push raises: [Defect].} type MyProcType* = proc(x: int): string #{.raises: [ValueError, Defect].} -proc foo(x: int): string {.raises: [ValueError].} = +proc foo(x: int): string {.nimcall, raises: [ValueError].} = if x > 9: raise newException(ValueError, "Use single digit") $x var p: MyProcType = foo #[tt.Error ^ -type mismatch: got <proc (x: int): string{.noSideEffect, gcsafe, locks: 0.}> but expected 'MyProcType = proc (x: int): string{.closure.}' +type mismatch: got <proc (x: int): string{.nimcall, raises: [ValueError], noSideEffect, gcsafe.}> but expected 'MyProcType = proc (x: int): string{.closure.}' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. .raise effects differ ]# {.pop.} diff --git a/tests/effects/teffects11.nim b/tests/effects/teffects11.nim index e4098e959..20b7026ab 100644 --- a/tests/effects/teffects11.nim +++ b/tests/effects/teffects11.nim @@ -1,6 +1,6 @@ discard """ action: compile -errormsg: "type mismatch: got <proc (x: int){.gcsafe, locks: 0.}>" +errormsg: "type mismatch: got <proc (x: int){.gcsafe.}>" line: 21 """ diff --git a/tests/effects/teffects19.nim b/tests/effects/teffects19.nim index 49fb87523..6b4ab0819 100644 --- a/tests/effects/teffects19.nim +++ b/tests/effects/teffects19.nim @@ -1,6 +1,6 @@ discard """ action: compile -errormsg: "type mismatch: got <proc (i: int){.gcsafe, locks: 0.}>" +errormsg: "type mismatch: got <proc (i: int){.gcsafe.}>" line: 23 """ diff --git a/tests/effects/teffects6.nim b/tests/effects/teffects6.nim index 4a39e0dca..d3af22434 100644 --- a/tests/effects/teffects6.nim +++ b/tests/effects/teffects6.nim @@ -21,7 +21,7 @@ createMenuItem(s, "Go to definition...", ) -proc noRaise(x: proc()) {.raises: [].} = +proc noRaise(x: proc()) {.raises: [], effectsOf: x.} = # unknown call that might raise anything, but valid: x() diff --git a/tests/effects/teffectsmisc.nim b/tests/effects/teffectsmisc.nim new file mode 100644 index 000000000..8fb95b275 --- /dev/null +++ b/tests/effects/teffectsmisc.nim @@ -0,0 +1,39 @@ +discard """ + output: ''' +printing from adder +''' +""" + +import std/sugar + +block: + proc makeAdder(a: int): (int) -> void = + proc discard_adder(x: int) {.closure.} = + discard a + x + + proc echo_adder(x: int) {.closure.} = + echo("printing from adder") + + if a > 0: + discard_adder + else: + echo_adder + + let newAdder = makeAdder(0) + newAdder(5) + +block: + proc makeAdder(a: int): (int) -> void = + proc discard_adder(x: int) {.closure.} = + discard a + x + + proc echo_adder(x: int) {.closure.} = + echo("printing from adder") + + if a > 0: + echo_adder + else: + discard_adder + + let newAdder = makeAdder(0) + newAdder(5) diff --git a/tests/effects/tfuncs_cannot_mutate.nim b/tests/effects/tfuncs_cannot_mutate.nim index 8784cbbb1..9934d27a7 100644 --- a/tests/effects/tfuncs_cannot_mutate.nim +++ b/tests/effects/tfuncs_cannot_mutate.nim @@ -1,9 +1,6 @@ discard """ - errormsg: "'mutate' can have side effects" - nimout: '''an object reachable from 'n' is potentially mutated -tfuncs_cannot_mutate.nim(39, 15) the mutation is here -tfuncs_cannot_mutate.nim(37, 7) is the statement that connected the mutation to the parameter -''' + errormsg: "cannot mutate location select(x, z).data within a strict func" + line: 35 """ {.experimental: "strictFuncs".} @@ -25,8 +22,7 @@ func len(n: Node): int = it = it.ri func doNotDistract(n: Node) = - var m = Node() - m.data = "abc" + var m = Node(data: "abc") func select(a, b: Node): Node = b diff --git a/tests/effects/tfuncs_cannot_mutate2.nim b/tests/effects/tfuncs_cannot_mutate2.nim index d5082e57b..86f811017 100644 --- a/tests/effects/tfuncs_cannot_mutate2.nim +++ b/tests/effects/tfuncs_cannot_mutate2.nim @@ -1,9 +1,6 @@ discard """ - errormsg: "'copy' can have side effects" - nimout: '''an object reachable from 'y' is potentially mutated -tfuncs_cannot_mutate2.nim(15, 7) the mutation is here -tfuncs_cannot_mutate2.nim(13, 10) is the statement that connected the mutation to the parameter -''' + errormsg: "cannot mutate location x[0].a within a strict func" + line: 12 """ {.experimental: "strictFuncs".} diff --git a/tests/effects/tfuncs_cannot_mutate3.nim b/tests/effects/tfuncs_cannot_mutate3.nim new file mode 100644 index 000000000..029152029 --- /dev/null +++ b/tests/effects/tfuncs_cannot_mutate3.nim @@ -0,0 +1,35 @@ +discard """ + errormsg: "cannot mutate location kid.parent within a strict func" + line: 16 +""" + +{.experimental: "strictFuncs".} + +type + Node = ref object + name: string + kids: seq[Node] + parent: Node + +func initParents(tree: Node) = + for kid in tree.kids: + kid.parent = tree + initParents(kid) + +proc process(intro: Node): Node = + var tree = Node(name: "root", kids: @[ + intro, + Node(name: "one", kids: @[ + Node(name: "two"), + Node(name: "three"), + ]), + Node(name: "four"), + ]) + initParents(tree) + +proc main() = + var intro = Node(name: "intro") + var tree = process(intro) + echo intro.parent.name + +main() diff --git a/tests/effects/tfuncs_cannot_mutate_simple.nim b/tests/effects/tfuncs_cannot_mutate_simple.nim index a94a8d746..0ae4a0db9 100644 --- a/tests/effects/tfuncs_cannot_mutate_simple.nim +++ b/tests/effects/tfuncs_cannot_mutate_simple.nim @@ -1,7 +1,6 @@ discard """ - errormsg: "'edit' can have side effects" - nimout: '''an object reachable from 'x' is potentially mutated -tfuncs_cannot_mutate_simple.nim(16, 4) the mutation is here''' + errormsg: '''cannot mutate location x.data within a strict func''' + line: 15 """ {.experimental: "strictFuncs".} diff --git a/tests/effects/tgcsafe.nim b/tests/effects/tgcsafe.nim index 363624f19..cfac3ddd8 100644 --- a/tests/effects/tgcsafe.nim +++ b/tests/effects/tgcsafe.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "'mainUnsafe' is not GC-safe" + errormsg: "'mainUnsafe' is not GC-safe as it performs an indirect call here" line: 26 cmd: "nim $target --hints:on --threads:on $options $file" """ @@ -13,7 +13,7 @@ proc myproc(i: int) {.gcsafe.} = if isNil(global_proc): return -proc mymap(x: proc ()) = +proc mymap(x: proc ()) {.effectsOf: x.} = x() var diff --git a/tests/effects/tgcsafe2.nim b/tests/effects/tgcsafe2.nim index 07da4e3f8..6268592a9 100644 --- a/tests/effects/tgcsafe2.nim +++ b/tests/effects/tgcsafe2.nim @@ -1,5 +1,5 @@ discard """ - errormsg: '''type mismatch: got <proc (s: string){.locks: 0.}>''' + errormsg: '''type mismatch: got <proc (s: string)>''' line: 11 """ #5620 diff --git a/tests/effects/thooks.nim b/tests/effects/thooks.nim new file mode 100644 index 000000000..23cc005cd --- /dev/null +++ b/tests/effects/thooks.nim @@ -0,0 +1,16 @@ +discard """ + matrix: "--warningAsError:Effect" +""" + +import std/isolation + +# bug #23129 +type + Thing = object + x: string + +proc send(x: string) = + let wrapper = Thing(x: x) + discard isolate(wrapper) + +send("la") \ No newline at end of file diff --git a/tests/effects/tlaxeffects.nim b/tests/effects/tlaxeffects.nim new file mode 100644 index 000000000..7eedc372a --- /dev/null +++ b/tests/effects/tlaxeffects.nim @@ -0,0 +1,11 @@ +discard """ + cmd: "nim $target $options --legacy:laxEffects $file" +""" + + +type + Foo = object + bar: seq[Foo] + +proc `==`(a, b: Foo): bool = + a.bar == b.bar diff --git a/tests/effects/tnosideeffect.nim b/tests/effects/tnosideeffect.nim index 9cabb35a2..9fc2f74d4 100644 --- a/tests/effects/tnosideeffect.nim +++ b/tests/effects/tnosideeffect.nim @@ -1,5 +1,5 @@ block: # `.noSideEffect` - func foo(bar: proc(): int): int = bar() + func foo(bar: proc(): int): int {.effectsOf: bar.} = bar() var count = 0 proc fn1(): int = 1 proc fn2(): int = (count.inc; count) diff --git a/tests/effects/toutparam.nim b/tests/effects/toutparam.nim deleted file mode 100644 index 1126aa77e..000000000 --- a/tests/effects/toutparam.nim +++ /dev/null @@ -1,28 +0,0 @@ -discard """ - cmd: '''nim c --warningAsError:Uninit:on --skipCfg --skipParentCfg $file''' - errormsg: "use explicit initialization of 'x' for clarity [Uninit]" - line: 24 - disabled: "true" -""" - -proc gah[T](x: out T) = - x = 3 - -proc main = - var a: array[2, int] - var x: int - gah(x) - a[0] = 3 - a[x] = 3 - echo x - -main() - -proc mainB = - var a: array[2, int] - var x: int - a[0] = 3 - a[x] = 3 - echo x - -mainB() diff --git a/tests/effects/tstrict_caseobjects.nim b/tests/effects/tstrict_caseobjects.nim new file mode 100644 index 000000000..20bc810e0 --- /dev/null +++ b/tests/effects/tstrict_caseobjects.nim @@ -0,0 +1,47 @@ +discard """ + errormsg: "field access outside of valid case branch: x.x" + line: 45 +""" + +{.experimental: "strictCaseObjects".} + +type + NodeKind = enum + nkParent, + nkChild + + Node {.acyclic.} = ref object + case kind: NodeKind + of nkParent: + children: seq[Node] + of nkChild: + name: string + +let list = @[Node(kind: nkParent, children: @[]), Node(kind: nkChild, name: "hello")] +for node in list: + case node.kind + of nkChild: + echo $node.name # here this time there is a warning + else: discard + + +type + Foo = object + case b: bool + of false: + s: string + of true: + x: int + +var x = Foo(b: true, x: 4) +case x.b +of true: + echo x.x +of false: + echo "no" + +case x.b +of false: + echo x.x +of true: + echo "no" diff --git a/tests/effects/tstrict_effects3.nim b/tests/effects/tstrict_effects3.nim index 027b46474..0d98a0343 100644 --- a/tests/effects/tstrict_effects3.nim +++ b/tests/effects/tstrict_effects3.nim @@ -44,3 +44,14 @@ proc fail() = discard f1() f2() +import std/json + +# bug #22254 +proc senri(a, b: seq[JsonNode]) {.raises: [].} = discard a == b + +# bug #22253 +proc serika() {.raises: [].} = discard default(JsonNode) == nil + +senri(@[newJBool(true)], @[newJBool(false)]) +serika() + diff --git a/tests/effects/tstrict_funcs_imports.nim b/tests/effects/tstrict_funcs_imports.nim index 264771a1a..bf68b61b2 100644 --- a/tests/effects/tstrict_funcs_imports.nim +++ b/tests/effects/tstrict_funcs_imports.nim @@ -7,11 +7,19 @@ discard """ when defined(linux): import linenoise +when defined(nimPreviewSlimSystem): + import std/[ + assertions, + formatfloat, + objectdollar, + syncio, + widestrs, + ] + import algorithm, asyncdispatch, asyncfile, - asyncftpclient, asyncfutures, asynchttpserver, asyncmacro, @@ -31,11 +39,6 @@ import cpuload, critbits, cstrutils, - db_common, - db_mysql, - db_odbc, - db_postgres, - db_sqlite, deques, distros, dynlib, @@ -63,7 +66,6 @@ import macros, marshal, math, - md5, memfiles, mersenne, mimetypes, @@ -87,7 +89,6 @@ import pegs, posix_utils, prelude, - punycode, random, rationals, rdstdin, @@ -102,7 +103,6 @@ import sets, sharedlist, sharedtables, - smtp, ssl_certs, ssl_config, stats, @@ -154,7 +154,6 @@ import std/[ monotimes, packedsets, setutils, - sha1, socketstreams, stackframes, sums, diff --git a/tests/effects/tstrictfuncs_misc.nim b/tests/effects/tstrictfuncs_misc.nim new file mode 100644 index 000000000..8c573bb3a --- /dev/null +++ b/tests/effects/tstrictfuncs_misc.nim @@ -0,0 +1,65 @@ +discard """ + action: compile +""" + +{.experimental: "strictFuncs".} + +func sortedFake1[T](a: openArray[T]): seq[T] = + for i in 0 .. a.high: result.add a[i] +func sortedFake2[T](a: openArray[T]): seq[T] = + result = newSeq[T](a.len) + for i in 0 .. a.high: result[i] = a[i] +type Foo1 = object +type Foo2 = ref object +block: + let a1 = sortedFake1([Foo1()]) # ok + let a2 = sortedFake1([Foo2()]) # ok +block: + let a1 = sortedFake2([Foo1()]) # ok + let a2 = sortedFake2([Foo2()]) # error: Error: 'sortedFake2' can have side effects + + +import std/sequtils +type Foob = ref object + x: int +let a1 = zip(@[1,2], @[1,2]) # ok +let a2 = zip(@[Foob(x: 1)], @[Foob(x: 2)]) # error in 1.6.0 RC2, but not 1.4.x + + +# bug #20863 +type + Fooc = ref object + +func twice(foo: Fooc) = + var a = newSeq[Fooc](2) + a[0] = foo # No error. + a[1] = foo # Error: 'twice' can have side effects. + +let foo = Fooc() +twice(foo) + +# bug #17387 +import json + +func parseColumn(columnNode: JsonNode) = + let columnName = columnNode["name"].str + +parseColumn(%*{"a": "b"}) + +type + MyTable = object + data: seq[int] + + JsonNode3 = ref object + fields: MyTable + +proc `[]`(t: MyTable, key: string): int = + result = t.data[0] + +proc `[]`(x: JsonNode3, key: string): int = + result = x.fields[key] + +func parseColumn(columnNode: JsonNode3) = + var columnName = columnNode["test"] + +parseColumn(JsonNode3()) diff --git a/tests/enum/t21863.nim b/tests/enum/t21863.nim new file mode 100644 index 000000000..d0d8b1fcd --- /dev/null +++ b/tests/enum/t21863.nim @@ -0,0 +1,28 @@ +discard """ +cmd: "nim check --hints:off $file" +action: reject +nimout: ''' +t21863.nim(28, 16) Error: undeclared field: 'A' + found 'A' [enumField declared in t21863.nim(24, 18)] + found 'A' [enumField declared in t21863.nim(25, 18)] +t21863.nim(28, 16) Error: undeclared field: '.' +t21863.nim(28, 16) Error: undeclared field: '.' +t21863.nim(28, 16) Error: expression '' has no type (or is ambiguous) +''' +""" + + + + + + + + + +block: + type + EnumA = enum A, B + EnumB = enum A + EnumC = enum C + + discard EnumC.A diff --git a/tests/enum/tambiguousoverloads.nim b/tests/enum/tambiguousoverloads.nim new file mode 100644 index 000000000..12c78c848 --- /dev/null +++ b/tests/enum/tambiguousoverloads.nim @@ -0,0 +1,26 @@ +discard """ +cmd: "nim check --hints:off $file" +""" + +block: # bug #21887 + type + EnumA = enum A = 300, B + EnumB = enum A = 10 + EnumC = enum C + + doAssert typeof(EnumC(A)) is EnumC #[tt.Error + ^ ambiguous identifier: 'A' -- use one of the following: + EnumA.A: EnumA + EnumB.A: EnumB]# + +block: # issue #22598 + type + A = enum + red + B = enum + red + + let a = red #[tt.Error + ^ ambiguous identifier: 'red' -- use one of the following: + A.red: A + B.red: B]# diff --git a/tests/enum/tcrossmodule.nim b/tests/enum/tcrossmodule.nim index 1e97fd1ee..c21072198 100644 --- a/tests/enum/tcrossmodule.nim +++ b/tests/enum/tcrossmodule.nim @@ -8,3 +8,8 @@ template t = doAssert some(Success) t() + +block: # legacy support for behavior before overloadableEnums + # warning: ambiguous enum field 'Success' assumed to be of type MyEnum + let x = {Success} + doAssert x is set[MyEnum] diff --git a/tests/enum/tenum.nim b/tests/enum/tenum.nim index 37383890c..a03019c5d 100644 --- a/tests/enum/tenum.nim +++ b/tests/enum/tenum.nim @@ -155,11 +155,113 @@ block nonzero: # bug #6959 C let slice = SomeEnum.low..SomeEnum.high -block size_one_byte: #issue 15752 +block size_one_byte: # bug #15752 type Flag = enum Disabled = 0x00 Enabled = 0xFF static: - assert 1 == sizeof(Flag) \ No newline at end of file + assert 1 == sizeof(Flag) + +block: # bug #12589 + when not defined(i386): + type + OGRwkbGeometryType {.size: sizeof(cuint).} = enum + wkbPoint25D = 0x80000001.cuint, wkbLineString25D = 0x80000002, + wkbPolygon25D = 0x80000003 + + proc typ(): OGRwkbGeometryType = + return wkbPoint25D + + when not defined(gcRefc): + doAssert $typ() == "wkbPoint25D" + + block: # bug #21280 + type + Test = enum + B = 19 + A = int64.high() + + doAssert ord(A) == int64.high() + +import std/enumutils +from std/sequtils import toSeq +import std/macros + +block: # unordered enum + block: + type + unordered_enum = enum + a = 1 + b = 0 + + doAssert (ord(a), ord(b)) == (1, 0) + doAssert unordered_enum.toSeq == @[a, b] + + block: + type + unordered_enum = enum + a = 1 + b = 0 + c + + doAssert (ord(a), ord(b), ord(c)) == (1, 0, 2) + + block: + type + unordered_enum = enum + a = 100 + b + c = 50 + d + + doAssert (ord(a), ord(b), ord(c), ord(d)) == (100, 101, 50, 51) + + block: + type + unordered_enum = enum + a = 7 + b = 6 + c = 5 + d + + doAssert (ord(a), ord(b), ord(c), ord(d)) == (7, 6, 5, 8) + doAssert unordered_enum.toSeq == @[a, b, c, d] + + block: + type + unordered_enum = enum + a = 100 + b + c = 500 + d + e + f = 50 + g + h + + doAssert (ord(a), ord(b), ord(c), ord(d), ord(e), ord(f), ord(g), ord(h)) == + (100, 101, 500, 501, 502, 50, 51, 52) + + block: + type + unordered_enum = enum + A + B + C = -1 + D + E + G = -999 + + doAssert (ord(A), ord(B), ord(C), ord(D), ord(E), ord(G)) == + (0, 1, -1, 2, 3, -999) + + block: + type + SomeEnum = enum + seA = 3 + seB = 2 + seC = "foo" + + doAssert (ord(seA), ord(seB), ord(seC)) == (3, 2, 4) diff --git a/tests/enum/tenum_duplicate.nim b/tests/enum/tenum_duplicate.nim new file mode 100644 index 000000000..4bcad7f6f --- /dev/null +++ b/tests/enum/tenum_duplicate.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "duplicate value in enum 'd'" +""" + +type + unordered_enum = enum + a = 1 + b = 0 + c + d = 2 diff --git a/tests/enum/tenum_invalid.nim b/tests/enum/tenum_invalid.nim new file mode 100644 index 000000000..8ae0a1057 --- /dev/null +++ b/tests/enum/tenum_invalid.nim @@ -0,0 +1,8 @@ +discard """ +cmd: "nim check $file" +""" + +type + Test = enum + A = 9.0 #[tt.Error + ^ ordinal type expected; given: float]# diff --git a/tests/enum/toverloadedname.nim b/tests/enum/toverloadedname.nim new file mode 100644 index 000000000..d11b0fb83 --- /dev/null +++ b/tests/enum/toverloadedname.nim @@ -0,0 +1,7 @@ +block: # issue #23998 + type + Enum {.pure.} = enum + a + Obj = object + a: Enum + proc test(a: Enum) = discard Obj(a: a) diff --git a/tests/enum/tpure_enums_conflict.nim b/tests/enum/tpure_enums_conflict.nim index 3c7528a72..3cf335440 100644 --- a/tests/enum/tpure_enums_conflict.nim +++ b/tests/enum/tpure_enums_conflict.nim @@ -1,6 +1,5 @@ discard """ - errormsg: "ambiguous identifier: 'amb'" - line: 19 + matrix: "-d:testsConciseTypeMismatch" """ # bug #8066 @@ -16,4 +15,13 @@ when true: echo valueA # MyEnum.valueA echo MyEnum.amb # OK. - echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb + echo amb #[tt.Error + ^ type mismatch +Expression: echo amb + [1] amb: MyEnum | OtherEnum + +Expected one of (first mismatch at [position]): +[1] proc echo(x: varargs[typed, `$$`]) + ambiguous identifier: 'amb' -- use one of the following: + MyEnum.amb: MyEnum + OtherEnum.amb: OtherEnum]# diff --git a/tests/enum/tpure_enums_conflict_legacy.nim b/tests/enum/tpure_enums_conflict_legacy.nim new file mode 100644 index 000000000..e592925bc --- /dev/null +++ b/tests/enum/tpure_enums_conflict_legacy.nim @@ -0,0 +1,25 @@ +# bug #8066 + +when true: + type + MyEnum {.pure.} = enum + valueA, valueB, valueC, valueD, amb + + OtherEnum {.pure.} = enum + valueX, valueY, valueZ, amb + + + echo valueA # MyEnum.valueA + echo MyEnum.amb # OK. + echo amb #[tt.Error + ^ type mismatch: got <MyEnum | OtherEnum> +but expected one of: +proc echo(x: varargs[typed, `$$`]) + first type mismatch at position: 1 + required type for x: varargs[typed] + but expression 'amb' is of type: None + ambiguous identifier: 'amb' -- use one of the following: + MyEnum.amb: MyEnum + OtherEnum.amb: OtherEnum + +expression: echo amb]# diff --git a/tests/enum/tredefinition.nim b/tests/enum/tredefinition.nim new file mode 100644 index 000000000..615ca6b1c --- /dev/null +++ b/tests/enum/tredefinition.nim @@ -0,0 +1,9 @@ +discard """ + cmd: '''nim check --hints:off $file''' + action: reject +nimout: ''' +tredefinition.nim(9, 25) Error: redefinition of 'Key_a'; previous declaration here: tredefinition.nim(9, 18) +''' +""" + +type Key* = enum Key_A, Key_a \ No newline at end of file diff --git a/tests/enum/ttypenameconflict.nim b/tests/enum/ttypenameconflict.nim new file mode 100644 index 000000000..b13bf00ce --- /dev/null +++ b/tests/enum/ttypenameconflict.nim @@ -0,0 +1,13 @@ +# issue #23689 + +type + MyEnum {.pure.} = enum + A, B, C, D + + B = object + field: int + +let x: MyEnum = B +doAssert $x == "B" +doAssert typeof(x) is MyEnum +doAssert x in {A, B} diff --git a/tests/errmsgs/mambparam1.nim b/tests/errmsgs/mambparam1.nim new file mode 100644 index 000000000..1a5133c3c --- /dev/null +++ b/tests/errmsgs/mambparam1.nim @@ -0,0 +1 @@ +const test* = "foo" diff --git a/tests/errmsgs/mambparam2.nim b/tests/errmsgs/mambparam2.nim new file mode 100644 index 000000000..073e3f8c8 --- /dev/null +++ b/tests/errmsgs/mambparam2.nim @@ -0,0 +1,2 @@ +import mambparam1 +export test diff --git a/tests/errmsgs/mambparam3.nim b/tests/errmsgs/mambparam3.nim new file mode 100644 index 000000000..5469244e2 --- /dev/null +++ b/tests/errmsgs/mambparam3.nim @@ -0,0 +1 @@ +const test* = "bar" diff --git a/tests/clearmsg/mb.nim b/tests/errmsgs/mb.nim index 2d21e2396..2d21e2396 100644 --- a/tests/clearmsg/mb.nim +++ b/tests/errmsgs/mb.nim diff --git a/tests/clearmsg/mc.nim b/tests/errmsgs/mc.nim index 79d7431df..79d7431df 100644 --- a/tests/clearmsg/mc.nim +++ b/tests/errmsgs/mc.nim diff --git a/tests/errmsgs/t10376.nim b/tests/errmsgs/t10376.nim index 2ce16d6a2..814c860dc 100644 --- a/tests/errmsgs/t10376.nim +++ b/tests/errmsgs/t10376.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:refc" errormsg: "finalizer must be a direct reference to a proc" - line: 29 + line: 30 """ type diff --git a/tests/errmsgs/t10489_a.nim b/tests/errmsgs/t10489_a.nim index 71a6cc3c4..c762ce876 100644 --- a/tests/errmsgs/t10489_a.nim +++ b/tests/errmsgs/t10489_a.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for let. Did you mean to call the macro with '()'?" +errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe.}' for let. Did you mean to call the macro with '()'?" line: 9 """ diff --git a/tests/errmsgs/t10489_b.nim b/tests/errmsgs/t10489_b.nim index 4b0b876e5..df05f0e6e 100644 --- a/tests/errmsgs/t10489_b.nim +++ b/tests/errmsgs/t10489_b.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe, locks: 0.}' for const. Did you mean to call the macro with '()'?" +errormsg: "invalid type: 'macro (body: untyped): untyped{.noSideEffect, gcsafe.}' for const. Did you mean to call the macro with '()'?" line: 9 """ diff --git a/tests/errmsgs/t10542.nim b/tests/errmsgs/t10542.nim new file mode 100644 index 000000000..b57dbf18b --- /dev/null +++ b/tests/errmsgs/t10542.nim @@ -0,0 +1,24 @@ +discard """ + matrix: "--hintaserror:ConvFromXtoItselfNotNeeded" +""" + +# bug #10542 + +proc f(args: varargs[string, string], length: int) = + doAssert args.len == length + +# main use case that requires type conversion (no warning here) +f("a", "b", 2) +f("a", 1) + + +proc m(args: varargs[cstring, cstring]) = + doAssert args.len == 2 + +# main use case that requires type conversion (no warning here) +m("a", "b") + +# if an argument already is cstring there's a warning +let x: cstring = "x" +m("a", x) +m(x, "a") \ No newline at end of file diff --git a/tests/errmsgs/t10735.nim b/tests/errmsgs/t10735.nim index 307acac2d..a39cd196e 100644 --- a/tests/errmsgs/t10735.nim +++ b/tests/errmsgs/t10735.nim @@ -1,36 +1,63 @@ discard """ cmd: "nim check $file" - errormsg: "selector must be of an ordinal type, float or string" + errormsg: "illformed AST: case buf[pos]" nimout: ''' -t10735.nim(38, 5) Error: 'let' symbol requires an initialization -t10735.nim(39, 10) Error: undeclared identifier: 'pos' -t10735.nim(39, 9) Error: type mismatch: got <cstring, > +t10735.nim(65, 5) Error: 'let' symbol requires an initialization +t10735.nim(66, 10) Error: undeclared identifier: 'pos' +t10735.nim(66, 10) Error: expression 'pos' has no type (or is ambiguous) +t10735.nim(66, 10) Error: expression 'pos' has no type (or is ambiguous) +t10735.nim(66, 9) Error: type mismatch: got <cstring, > but expected one of: proc `[]`(s: string; i: BackwardsIndex): char - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: string + but expression 'buf' is of type: cstring proc `[]`(s: var string; i: BackwardsIndex): var char - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: var string + but expression 'buf' is of type: cstring proc `[]`[I: Ordinal; T](a: T; i: I): T first type mismatch at position: 0 proc `[]`[Idx, T; U, V: Ordinal](a: array[Idx, T]; x: HSlice[U, V]): seq[T] - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for a: array[Idx, T] + but expression 'buf' is of type: cstring proc `[]`[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for a: array[Idx, T] + but expression 'buf' is of type: cstring proc `[]`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for a: var array[Idx, T] + but expression 'buf' is of type: cstring proc `[]`[T, U: Ordinal](s: string; x: HSlice[T, U]): string - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: string + but expression 'buf' is of type: cstring proc `[]`[T; U, V: Ordinal](s: openArray[T]; x: HSlice[U, V]): seq[T] - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: openArray[T] + but expression 'buf' is of type: cstring proc `[]`[T](s: openArray[T]; i: BackwardsIndex): T - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: openArray[T] + but expression 'buf' is of type: cstring proc `[]`[T](s: var openArray[T]; i: BackwardsIndex): var T - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: var openArray[T] + but expression 'buf' is of type: cstring +template `[]`(a: WideCStringObj; idx: int): Utf16Char + first type mismatch at position: 1 + required type for a: WideCStringObj + but expression 'buf' is of type: cstring template `[]`(s: string; i: int): char - first type mismatch at position: 0 + first type mismatch at position: 1 + required type for s: string + but expression 'buf' is of type: cstring -expression: `[]`(buf, pos) -t10735.nim(39, 9) Error: selector must be of an ordinal type, float or string +expression: buf[pos] +t10735.nim(66, 9) Error: expression '' has no type (or is ambiguous) +t10735.nim(68, 3) Error: illformed AST: case buf[pos] ''' joinable: false """ diff --git a/tests/errmsgs/t14444.nim b/tests/errmsgs/t14444.nim new file mode 100644 index 000000000..27365236e --- /dev/null +++ b/tests/errmsgs/t14444.nim @@ -0,0 +1,14 @@ +discard """ + matrix: "--hints:off" + exitcode: "1" + output: ''' +t14444.nim(13) t14444 +fatal.nim(53) sysFatal +Error: unhandled exception: index out of bounds, the container is empty [IndexDefect] +''' +""" + +when true: # bug #14444 + var i: string + i[10] = 'j' + echo i \ No newline at end of file diff --git a/tests/errmsgs/t16654.nim b/tests/errmsgs/t16654.nim new file mode 100644 index 000000000..b2b57619b --- /dev/null +++ b/tests/errmsgs/t16654.nim @@ -0,0 +1,12 @@ +discard """ + cmd: "nim check $options $file" + errormsg: "type mismatch: got <int literal(1), proc (r: GenericParam): auto>" +""" + +when true: # bug #16654 + func fn[T](a: T, op: proc(a: T): float) = discard + proc main() = + let v = 1 + proc bar(r: auto): auto = v + fn(1, bar) + main() diff --git a/tests/errmsgs/t17460.nim b/tests/errmsgs/t17460.nim index e377bc48a..bb8e21198 100644 --- a/tests/errmsgs/t17460.nim +++ b/tests/errmsgs/t17460.nim @@ -1,6 +1,6 @@ discard """ cmd: "nim check $options $file" - errormsg: "wrong number of variables" + errormsg: "tuple expected for tuple unpacking, but got 'array[0..2, int]'" """ iterator xclusters*[T](a: openArray[T]; s: static[int]): array[s, T] {.inline.} = @@ -16,4 +16,4 @@ proc m = for (i, j, k) in xclusters([1, 2, 3, 4, 5], 3): echo i, j, k -m() \ No newline at end of file +m() diff --git a/tests/errmsgs/t18886.nim b/tests/errmsgs/t18886.nim new file mode 100644 index 000000000..8ed160c64 --- /dev/null +++ b/tests/errmsgs/t18886.nim @@ -0,0 +1,18 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +t18886.nim(18, 24) Error: ambiguous identifier: 'bar' -- you need a helper proc to disambiguate the following: + t18886.bar: proc (i: ptr int){.noSideEffect, gcsafe.} + t18886.bar: proc (i: ptr char){.noSideEffect, gcsafe.} +''' +""" + +type Foo = (proc(_: pointer): void) + + +proc bar(i: ptr[int]) = discard +proc bar(i: ptr[char]) = discard + + +let fooBar = cast[Foo](bar) \ No newline at end of file diff --git a/tests/errmsgs/t19224.nim b/tests/errmsgs/t19224.nim new file mode 100644 index 000000000..7a9ecb2e7 --- /dev/null +++ b/tests/errmsgs/t19224.nim @@ -0,0 +1,12 @@ +discard """ +cmd: "nim check --hints:off $file" +errormsg: "" +nimout: ''' +t19224.nim(10, 10) Error: cannot infer element type of items([]) +t19224.nim(12, 10) Error: cannot infer element type of items(@[]) +''' +""" + +for _ in []: discard + +for _ in @[]: discard diff --git a/tests/errmsgs/t19882.nim b/tests/errmsgs/t19882.nim new file mode 100644 index 000000000..1f2f95ab7 --- /dev/null +++ b/tests/errmsgs/t19882.nim @@ -0,0 +1,10 @@ + +discard """ + errormsg: "cannot instantiate 'A[T, P]' inside of type definition: 'init'; Maybe generic arguments are missing?" +""" +type A[T,P] = object + b:T + c:P +proc init(): ref A = + new(result) +var a = init() diff --git a/tests/errmsgs/t19882_2.nim b/tests/errmsgs/t19882_2.nim new file mode 100644 index 000000000..7f3055a5d --- /dev/null +++ b/tests/errmsgs/t19882_2.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "cannot instantiate: 'A[T]'; the object's generic parameters cannot be inferred and must be explicitly given" +""" +type A[T] = object +var a = A() \ No newline at end of file diff --git a/tests/errmsgs/t21257.nim b/tests/errmsgs/t21257.nim new file mode 100644 index 000000000..eecdb1dfe --- /dev/null +++ b/tests/errmsgs/t21257.nim @@ -0,0 +1,20 @@ +discard """ + action: compile + cmd: "nim check $file" +""" + +type AC_WINCTRL_Fields* = distinct uint8 + +type AC_STATUSA_WSTATE0* {.pure.} = enum + ABOVE = 0x0, + INSIDE = 0x1, + BELOW = 0x2, + +type AC_WINCTRL_WINTSEL0* {.pure.} = enum + ABOVE = 0x0, + INSIDE = 0x1, + BELOW = 0x2, + OUTSIDE = 0x3, + +proc write*(WINTSEL0: AC_WINCTRL_WINTSEL0 = ABOVE) = + discard diff --git a/tests/errmsgs/t22097.nim b/tests/errmsgs/t22097.nim new file mode 100644 index 000000000..bb24ee8d3 --- /dev/null +++ b/tests/errmsgs/t22097.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "type mismatch: got <uint8>" +""" + +proc toUInt16(x: var uint16) = + discard + +var x = uint8(1) +toUInt16 x diff --git a/tests/errmsgs/t22284.nim b/tests/errmsgs/t22284.nim new file mode 100644 index 000000000..827155e6b --- /dev/null +++ b/tests/errmsgs/t22284.nim @@ -0,0 +1,25 @@ +discard """ + errormsg: "j(uRef, proc (config: F; sources: auto) {.raises: [].} = discard ) can raise an unlisted exception: Exception" +""" + +import std/macros + +macro h(): untyped = + result = newTree(nnkStmtList) + result.add quote do: + new int + +type F = object + +proc j[SecondarySources]( + uRef: ref SecondarySources, + u: proc (config: F, sources: ref SecondarySources)): F = + u(result, uRef) + +template programMain(body: untyped) = + proc main {.raises: [].} = body # doesn't SIGSEGV without this {.raises: [].} + main() + +programMain: + var uRef = h() + discard j(uRef, u = proc(config: F, sources: auto) {.raises: [].} = discard) \ No newline at end of file diff --git a/tests/errmsgs/t22753.nim b/tests/errmsgs/t22753.nim new file mode 100644 index 000000000..8a504109a --- /dev/null +++ b/tests/errmsgs/t22753.nim @@ -0,0 +1,52 @@ +discard """ +cmd: "nim check --hints:off $file" +errormsg: "type mismatch" +nimoutFull: true +nimout: ''' +t22753.nim(51, 13) Error: array expects two type parameters +t22753.nim(52, 1) Error: expression 'x' has no type (or is ambiguous) +t22753.nim(52, 1) Error: expression 'x' has no type (or is ambiguous) +t22753.nim(52, 2) Error: type mismatch: got <> +but expected one of: +proc `[]=`(s: var string; i: BackwardsIndex; x: char) + first type mismatch at position: 2 + required type for i: BackwardsIndex + but expression '0' is of type: int literal(0) +proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: sink S) + first type mismatch at position: 0 +proc `[]=`[Idx, T; U, V: Ordinal](a: var array[Idx, T]; x: HSlice[U, V]; + b: openArray[T]) + first type mismatch at position: 2 + required type for x: HSlice[[]=.U, []=.V] + but expression '0' is of type: int literal(0) +proc `[]=`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) + first type mismatch at position: 2 + required type for i: BackwardsIndex + but expression '0' is of type: int literal(0) +proc `[]=`[T, U: Ordinal](s: var string; x: HSlice[T, U]; b: string) + first type mismatch at position: 2 + required type for x: HSlice[[]=.T, []=.U] + but expression '0' is of type: int literal(0) +proc `[]=`[T; U, V: Ordinal](s: var seq[T]; x: HSlice[U, V]; b: openArray[T]) + first type mismatch at position: 2 + required type for x: HSlice[[]=.U, []=.V] + but expression '0' is of type: int literal(0) +proc `[]=`[T](s: var openArray[T]; i: BackwardsIndex; x: T) + first type mismatch at position: 2 + required type for i: BackwardsIndex + but expression '0' is of type: int literal(0) +template `[]=`(a: WideCStringObj; idx: int; val: Utf16Char) + first type mismatch at position: 3 + required type for val: Utf16Char + but expression '9' is of type: int literal(9) +template `[]=`(s: string; i: int; val: char) + first type mismatch at position: 3 + required type for val: char + but expression '9' is of type: int literal(9) + +expression: x[0] = 9 +''' +""" + +var x: array[3] # bug #22753 +x[0] = 9 diff --git a/tests/errmsgs/t22852.nim b/tests/errmsgs/t22852.nim new file mode 100644 index 000000000..7c352a49c --- /dev/null +++ b/tests/errmsgs/t22852.nim @@ -0,0 +1,9 @@ +discard """ + exitcode: 1 + outputsub: ''' +Error: unhandled exception: value out of range: -2 notin 0 .. 9223372036854775807 [RangeDefect] +''' +""" + +# bug #22852 +echo [0][2..^2] diff --git a/tests/errmsgs/t22996.nim b/tests/errmsgs/t22996.nim new file mode 100644 index 000000000..3a51fd8b0 --- /dev/null +++ b/tests/errmsgs/t22996.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "invalid type: 'typedesc[string]' for const" +""" + +# bug #22996 +type MyObject = ref object + _ = string diff --git a/tests/errmsgs/t23060.nim b/tests/errmsgs/t23060.nim new file mode 100644 index 000000000..abb79bcc3 --- /dev/null +++ b/tests/errmsgs/t23060.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "undeclared identifier: '♔♕♖♗♘♙'" +""" + +♔♕♖♗♘♙ = 1 \ No newline at end of file diff --git a/tests/errmsgs/t23419.nim b/tests/errmsgs/t23419.nim new file mode 100644 index 000000000..59a72f081 --- /dev/null +++ b/tests/errmsgs/t23419.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "invalid type: 'void' in this context: '(array[0..-1, void],)' for var" +""" + +var a: (array[0, void], ) diff --git a/tests/errmsgs/t23435.nim b/tests/errmsgs/t23435.nim new file mode 100644 index 000000000..5e2e4c82a --- /dev/null +++ b/tests/errmsgs/t23435.nim @@ -0,0 +1,12 @@ +discard """ + outputsub: "Error: unhandled exception: value out of range: -15 notin 0 .. 9223372036854775807 [RangeDefect]" + exitcode: "1" +""" + +# bug #23435 +proc foo() = + for _ in @[1, 3, 5]: + discard "abcde"[25..<10] + break + +foo() diff --git a/tests/errmsgs/t23536.nim b/tests/errmsgs/t23536.nim new file mode 100644 index 000000000..610a85bab --- /dev/null +++ b/tests/errmsgs/t23536.nim @@ -0,0 +1,26 @@ +discard """ + matrix: "--stackTrace:on --excessiveStackTrace:off" +""" + +const expected = """ +wrong trace: +t23536.nim(22) t23536 +t23536.nim(17) foo +assertions.nim(41) failedAssertImpl +assertions.nim(36) raiseAssert +fatal.nim(53) sysFatal +""" + + +try: + proc foo = # bug #23536 + doAssert false + + for i in 0 .. 1: + + + foo() +except AssertionDefect: + let e = getCurrentException() + let trace = e.getStackTrace + doAssert "wrong trace:\n" & trace == expected diff --git a/tests/errmsgs/t2614.nim b/tests/errmsgs/t2614.nim new file mode 100644 index 000000000..031ecb9d1 --- /dev/null +++ b/tests/errmsgs/t2614.nim @@ -0,0 +1,21 @@ +discard """ + cmd: "nim check $options --hints:off $file" + errormsg: "" + nimout: ''' +t2614.nim(19, 27) Error: type mismatch: got <array[0..1, proc ()]> but expected 'array[0..1, proc (){.closure.}]' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. +t2614.nim(21, 22) Error: type mismatch: got <seq[proc ()]> but expected 'seq[proc (){.closure.}]' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. +''' +""" + +proc g +proc f = + if false: g() +proc g = + if false: f() + +var a = [f, g] # This works +var b: array[2, proc()] = [f, g] # Error + +var c: seq[proc()] = @[f, g] \ No newline at end of file diff --git a/tests/errmsgs/t5167_4.nim b/tests/errmsgs/t5167_4.nim index 7a263622b..dafd7754d 100644 --- a/tests/errmsgs/t5167_4.nim +++ b/tests/errmsgs/t5167_4.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "type mismatch: got <proc [*missing parameters*](x: int) | proc (x: string){.gcsafe, locks: 0.}>" +errormsg: "type mismatch: got <proc [*missing parameters*](x: int) | proc (x: string){.gcsafe.}>" line: 19 """ diff --git a/tests/errmsgs/t5167_5.nim b/tests/errmsgs/t5167_5.nim index a9e260845..dea7e40b3 100644 --- a/tests/errmsgs/t5167_5.nim +++ b/tests/errmsgs/t5167_5.nim @@ -1,13 +1,9 @@ discard """ -cmd: "nim check $file" -errormsg: "'t' has unspecified generic parameters" -nimout: ''' -t5167_5.nim(10, 16) Error: expression 'system' has no type (or is ambiguous) -t5167_5.nim(21, 9) Error: 't' has unspecified generic parameters -''' +cmd: "nim check --mm:refc $file" """ # issue #11942 -discard newSeq[system]() +discard newSeq[system]() #[tt.Error + ^ expression 'system' has no type (or is ambiguous)]# # issue #5167 template t[B]() = @@ -18,8 +14,12 @@ macro m[T]: untyped = nil proc bar(x: proc (x: int)) = echo "bar" -let x = t -bar t +let x = t #[tt.Error + ^ 't' has unspecified generic parameters]# +bar t #[tt.Error +^ type mismatch: got <template [*missing parameters*]()>]# -let y = m -bar m +let y = m #[tt.Error + ^ 'm' has unspecified generic parameters]# +bar m #[tt.Error +^ type mismatch: got <macro [*missing parameters*](): untyped{.noSideEffect, gcsafe.}>]# diff --git a/tests/errmsgs/t6499.nim b/tests/errmsgs/t6499.nim new file mode 100644 index 000000000..25e78fdbb --- /dev/null +++ b/tests/errmsgs/t6499.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "'chr' is a built-in and cannot be used as a first-class procedure" +""" + +# bug #6499 +let x = (chr, 0) diff --git a/tests/errmsgs/t8064.nim b/tests/errmsgs/t8064.nim new file mode 100644 index 000000000..c35a3abcc --- /dev/null +++ b/tests/errmsgs/t8064.nim @@ -0,0 +1,9 @@ +import tables + +values + + +discard """ + # either this or "expression has no type": + errormsg: "ambiguous identifier: 'values' -- use one of the following:" +""" diff --git a/tests/errmsgs/t8794.nim b/tests/errmsgs/t8794.nim index 9db54a9c7..36f05dbad 100644 --- a/tests/errmsgs/t8794.nim +++ b/tests/errmsgs/t8794.nim @@ -1,33 +1,16 @@ discard """ cmd: "nim check $options $file" - errormsg: "" - nimout: ''' -t8794.nim(39, 27) Error: undeclared field: 'a3' for type m8794.Foo3 [type declared in m8794.nim(1, 6)] -''' """ - - - - - - - - - - - -## line 20 - ## issue #8794 import m8794 -when false: # pending https://github.com/nim-lang/Nim/pull/10091 add this - type Foo = object - a1: int +type Foo = object + a1: int - discard Foo().a2 +discard Foo().a2 #[tt.Error + ^ undeclared field: 'a2' for type t8794.Foo [type declared in t8794.nim(9, 6)]]# type Foo3b = Foo3 var x2: Foo3b @@ -36,4 +19,5 @@ proc getFun[T](): T = var a: T a -discard getFun[type(x2)]().a3 +discard getFun[type(x2)]().a3 #[tt.Error + ^ undeclared field: 'a3' for type m8794.Foo3 [type declared in m8794.nim(1, 6)]]# diff --git a/tests/errmsgs/t9768.nim b/tests/errmsgs/t9768.nim index b72a158c7..b5ff58367 100644 --- a/tests/errmsgs/t9768.nim +++ b/tests/errmsgs/t9768.nim @@ -1,13 +1,14 @@ discard """ - errormsg: "unhandled exception:" - file: "system/fatal.nim" + errormsg: "unhandled exception: t9768.nim(24, 3) `a < 4` [AssertionDefect]" + file: "std/assertions.nim" + matrix: "-d:nimPreviewSlimSystem" nimout: ''' stack trace: (most recent call last) -t9768.nim(28, 33) main -t9768.nim(23, 11) foo1 +t9768.nim(29, 33) main +t9768.nim(24, 11) foo1 ''' """ - +import std/assertions diff --git a/tests/errmsgs/t9908_01.nim b/tests/errmsgs/t9908_01.nim index b9d37b67b..99bc8237d 100644 --- a/tests/errmsgs/t9908_01.nim +++ b/tests/errmsgs/t9908_01.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "ordinal type expected" +errormsg: "ordinal type expected; given: string" line: 10 """ diff --git a/tests/errmsgs/t9908_02.nim b/tests/errmsgs/t9908_02.nim index 7ff3d1ff7..4fc60b3df 100644 --- a/tests/errmsgs/t9908_02.nim +++ b/tests/errmsgs/t9908_02.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "ordinal type expected" +errormsg: "ordinal type expected; given: float" line: 10 """ diff --git a/tests/clearmsg/ta.nim b/tests/errmsgs/ta.nim index 31baae773..31baae773 100644 --- a/tests/clearmsg/ta.nim +++ b/tests/errmsgs/ta.nim diff --git a/tests/errmsgs/tambparam.nim b/tests/errmsgs/tambparam.nim new file mode 100644 index 000000000..5b56a3fce --- /dev/null +++ b/tests/errmsgs/tambparam.nim @@ -0,0 +1,16 @@ +discard """ + matrix: "-d:testsConciseTypeMismatch" +""" + +import mambparam2, mambparam3 + +echo test #[tt.Error +^ type mismatch +Expression: echo test + [1] test: string | string + +Expected one of (first mismatch at [position]): +[1] proc echo(x: varargs[typed, `$$`]) + ambiguous identifier: 'test' -- use one of the following: + mambparam1.test: string + mambparam3.test: string]# diff --git a/tests/errmsgs/tambparam_legacy.nim b/tests/errmsgs/tambparam_legacy.nim new file mode 100644 index 000000000..bd99a3aac --- /dev/null +++ b/tests/errmsgs/tambparam_legacy.nim @@ -0,0 +1,14 @@ +import mambparam2, mambparam3 + +echo test #[tt.Error +^ type mismatch: got <string | string> +but expected one of: +proc echo(x: varargs[typed, `$$`]) + first type mismatch at position: 1 + required type for x: varargs[typed] + but expression 'test' is of type: None + ambiguous identifier: 'test' -- use one of the following: + mambparam1.test: string + mambparam3.test: string + +expression: echo test]# diff --git a/tests/errmsgs/tassignunpack.nim b/tests/errmsgs/tassignunpack.nim new file mode 100644 index 000000000..09d928a54 --- /dev/null +++ b/tests/errmsgs/tassignunpack.nim @@ -0,0 +1,3 @@ +var a, b = 0 +(a, b) = 1 #[tt.Error + ^ tuple expected for tuple unpacking, but got 'int literal(1)']# diff --git a/tests/errmsgs/tcall_with_default_arg.nim b/tests/errmsgs/tcall_with_default_arg.nim index 1cc86638f..44752f1ee 100644 --- a/tests/errmsgs/tcall_with_default_arg.nim +++ b/tests/errmsgs/tcall_with_default_arg.nim @@ -1,5 +1,5 @@ discard """ -outputsub: '''tcall_with_default_arg.nim(16) anotherFoo''' +outputsub: '''tcall_with_default_arg.nim(8) fail''' exitcode: 1 """ # issue: #5604 diff --git a/tests/errmsgs/tcase_stmt.nim b/tests/errmsgs/tcase_stmt.nim new file mode 100644 index 000000000..cf63b9c17 --- /dev/null +++ b/tests/errmsgs/tcase_stmt.nim @@ -0,0 +1,29 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +tcase_stmt.nim(22, 7) Error: selector must be of an ordinal type, float or string +tcase_stmt.nim(28, 6) Error: selector must be of an ordinal type, float or string + + + + + + + +''' +""" + + + +# bug #19682 +type A = object + +case A() +else: + discard + +# bug #20283 + +case @[] +else: discard diff --git a/tests/errmsgs/tconcisetypemismatch.nim b/tests/errmsgs/tconcisetypemismatch.nim new file mode 100644 index 000000000..3093cc24e --- /dev/null +++ b/tests/errmsgs/tconcisetypemismatch.nim @@ -0,0 +1,23 @@ +discard """ + cmd: "nim c --hints:off -d:testsConciseTypeMismatch $file" + errormsg: "type mismatch" + nimout: ''' +tconcisetypemismatch.nim(23, 47) Error: type mismatch +Expression: int(inNanoseconds(t2 - t1)) / 100.5 + [1] int(inNanoseconds(t2 - t1)): int + [2] 100.5: float64 + +Expected one of (first mismatch at [position]): +[1] proc `/`(x, y: float): float +[1] proc `/`(x, y: float32): float32 +[2] proc `/`(x, y: int): float +''' +""" + +import std/monotimes +from times import inNanoseconds + +let t1 = getMonotime() +let result = 1 + 2 +let t2 = getMonotime() +echo "Elapsed: ", (t2 - t1).inNanoseconds.int / 100.5 diff --git a/tests/errmsgs/tconstinfo.nim b/tests/errmsgs/tconstinfo.nim new file mode 100644 index 000000000..170972b9f --- /dev/null +++ b/tests/errmsgs/tconstinfo.nim @@ -0,0 +1,7 @@ +# https://forum.nim-lang.org/t/9762 + +const foo = "abc" +case 'a' +of foo: echo "should error" #[tt.Error + ^ type mismatch: got <string> but expected 'char']# +else: discard diff --git a/tests/clearmsg/tconsttypemismatch.nim b/tests/errmsgs/tconsttypemismatch.nim index 727bfbffb..727bfbffb 100644 --- a/tests/clearmsg/tconsttypemismatch.nim +++ b/tests/errmsgs/tconsttypemismatch.nim diff --git a/tests/errmsgs/tgcsafety.nim b/tests/errmsgs/tgcsafety.nim index 701adeebf..66496d364 100644 --- a/tests/errmsgs/tgcsafety.nim +++ b/tests/errmsgs/tgcsafety.nim @@ -1,8 +1,8 @@ discard """ cmd: "nim check $file" -errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>" +errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]>" nimout: ''' -tgcsafety.nim(31, 18) Error: type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}> +tgcsafety.nim(31, 18) Error: type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]> but expected one of: proc serve(server: AsyncHttpServer; port: Port; callback: proc (request: Request): Future[void] {.closure, gcsafe.}; @@ -10,7 +10,7 @@ proc serve(server: AsyncHttpServer; port: Port; Future[void]) first type mismatch at position: 3 required type for callback: proc (request: Request): Future[system.void]{.closure, gcsafe.} - but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.} + but expression 'cb' is of type: proc (req: Request): Future[system.void] This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information. expression: serve(server, Port(7898), cb) diff --git a/tests/errmsgs/tgenericmismatchsegfault.nim b/tests/errmsgs/tgenericmismatchsegfault.nim new file mode 100644 index 000000000..dbb783cb3 --- /dev/null +++ b/tests/errmsgs/tgenericmismatchsegfault.nim @@ -0,0 +1,13 @@ +discard """ + matrix: "-d:testsConciseTypeMismatch" +""" + +template v[T](c: SomeOrdinal): T = T(c) +discard v[int, char]('A') #[tt.Error + ^ type mismatch +Expression: v[int, char]('A') + [1] 'A': char + +Expected one of (first mismatch at [position]): +[2] template v[T](c: SomeOrdinal): T + generic parameter mismatch, expected SomeOrdinal but got 'char' of type: char]# diff --git a/tests/errmsgs/tgenericmismatchsegfault_legacy.nim b/tests/errmsgs/tgenericmismatchsegfault_legacy.nim new file mode 100644 index 000000000..1532611b9 --- /dev/null +++ b/tests/errmsgs/tgenericmismatchsegfault_legacy.nim @@ -0,0 +1,10 @@ +template v[T](c: SomeOrdinal): T = T(c) +discard v[int, char]('A') #[tt.Error + ^ type mismatch: got <char> +but expected one of: +template v[T](c: SomeOrdinal): T + first type mismatch at position: 2 in generic parameters + required type for SomeOrdinal: SomeOrdinal + but expression 'char' is of type: char + +expression: v[int, char]('A')]# diff --git a/tests/errmsgs/tinconsistentgensym.nim b/tests/errmsgs/tinconsistentgensym.nim new file mode 100644 index 000000000..8e4c85106 --- /dev/null +++ b/tests/errmsgs/tinconsistentgensym.nim @@ -0,0 +1,25 @@ +discard """ + cmd: "nim check --hints:off $file" +""" + +block: + template foo = + when false: + let x = 123 + else: + template x: untyped {.inject.} = 456 + echo x #[tt.Error + ^ undeclared identifier: 'x`gensym0'; if declared in a template, this identifier may be inconsistently marked inject or gensym]# + foo() + +block: + template foo(y: static bool) = + block: + when y: + let x {.gensym.} = 123 + else: + let x {.inject.} = 456 + echo x #[tt.Error + ^ undeclared identifier: 'x']# + foo(false) + foo(true) diff --git a/tests/clearmsg/tmacroerrorproc.nim b/tests/errmsgs/tmacroerrorproc.nim index 86726af72..86726af72 100644 --- a/tests/clearmsg/tmacroerrorproc.nim +++ b/tests/errmsgs/tmacroerrorproc.nim diff --git a/tests/errmsgs/tmetaobjectfields.nim b/tests/errmsgs/tmetaobjectfields.nim new file mode 100644 index 000000000..47d3acf18 --- /dev/null +++ b/tests/errmsgs/tmetaobjectfields.nim @@ -0,0 +1,75 @@ +discard """ + cmd: "nim check --hints:off $file" + action: "reject" + nimout: ''' +tmetaobjectfields.nim(26, 5) Error: 'array' is not a concrete type +tmetaobjectfields.nim(30, 5) Error: 'seq' is not a concrete type +tmetaobjectfields.nim(34, 5) Error: 'set' is not a concrete type +tmetaobjectfields.nim(37, 3) Error: 'sink' is not a concrete type +tmetaobjectfields.nim(39, 3) Error: 'lent' is not a concrete type +tmetaobjectfields.nim(56, 16) Error: 'seq' is not a concrete type +tmetaobjectfields.nim(60, 5) Error: 'ptr' is not a concrete type +tmetaobjectfields.nim(61, 5) Error: 'ref' is not a concrete type +tmetaobjectfields.nim(62, 5) Error: 'auto' is not a concrete type +tmetaobjectfields.nim(63, 5) Error: 'UncheckedArray' is not a concrete type +tmetaobjectfields.nim(68, 5) Error: 'object' is not a concrete type +tmetaobjectfields.nim(72, 5) Error: 'Type3011:ObjectType' is not a concrete type +''' +""" + + +# bug #6982 +# bug #19546 +# bug #23531 +type + ExampleObj1 = object + arr: array + +type + ExampleObj2 = object + arr: seq + +type + ExampleObj3 = object + arr: set + +type A = object + b: sink + # a: openarray + c: lent + +type PropertyKind = enum + tInt, + tFloat, + tBool, + tString, + tArray + +type + Property = ref PropertyObj + PropertyObj = object + case kind: PropertyKind + of tInt: intValue: int + of tFloat: floatValue: float + of tBool: boolValue: bool + of tString: stringValue: string + of tArray: arrayValue: seq + +type + RegressionTest = object + a: ptr + b: ref + c: auto + d: UncheckedArray + +# bug #3011 +type + Type3011 = ref object + context: ref object + +type + Value3011 = ref object + typ: Type3011 + +proc x3011(): Value3011 = + nil diff --git a/tests/misc/tnoop.nim b/tests/errmsgs/tnoop.nim index f55f2441a..f55f2441a 100644 --- a/tests/misc/tnoop.nim +++ b/tests/errmsgs/tnoop.nim diff --git a/tests/errmsgs/tproc_mismatch.nim b/tests/errmsgs/tproc_mismatch.nim index 4ddc7635e..16f319f3b 100644 --- a/tests/errmsgs/tproc_mismatch.nim +++ b/tests/errmsgs/tproc_mismatch.nim @@ -3,33 +3,36 @@ discard """ cmd: '''nim check --hints:off $options $file''' nimoutFull: true nimout: ''' -tproc_mismatch.nim(35, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}' +tproc_mismatch.nim(38, 52) Error: type mismatch: got <proc (a: int, c: float){.cdecl, noSideEffect, gcsafe.}> but expected 'proc (a: int, c: float){.closure, noSideEffect.}' Calling convention mismatch: got '{.cdecl.}', but expected '{.closure.}'. -tproc_mismatch.nim(39, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> +tproc_mismatch.nim(42, 6) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe.}> but expected one of: proc bar(a: proc ()) first type mismatch at position: 1 required type for a: proc (){.closure.} - but expression 'fn1' is of type: proc (){.inline, noSideEffect, gcsafe, locks: 0.} + but expression 'fn1' is of type: proc (){.inline, noSideEffect, gcsafe.} Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'. expression: bar(fn1) -tproc_mismatch.nim(43, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (){.closure.}' +tproc_mismatch.nim(46, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe.}> but expected 'proc (){.closure.}' Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'. -tproc_mismatch.nim(48, 8) Error: type mismatch: got <proc (){.locks: 0.}> but expected 'proc (){.closure, noSideEffect.}' +tproc_mismatch.nim(51, 8) Error: type mismatch: got <proc ()> but expected 'proc (){.closure, noSideEffect.}' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. Pragma mismatch: got '{..}', but expected '{.noSideEffect.}'. -tproc_mismatch.nim(52, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe, locks: 0.}> but expected 'proc (a: float){.closure.}' -tproc_mismatch.nim(61, 9) Error: type mismatch: got <proc (a: int){.locks: 0.}> but expected 'proc (a: int){.closure, gcsafe.}' +tproc_mismatch.nim(55, 8) Error: type mismatch: got <proc (a: int){.noSideEffect, gcsafe.}> but expected 'proc (a: float){.closure.}' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. +tproc_mismatch.nim(64, 9) Error: type mismatch: got <proc (a: int)> but expected 'proc (a: int){.closure, gcsafe.}' + Calling convention mismatch: got '{.nimcall.}', but expected '{.closure.}'. Pragma mismatch: got '{..}', but expected '{.gcsafe.}'. -tproc_mismatch.nim(69, 9) Error: type mismatch: got <proc (a: int): int{.nimcall.}> but expected 'proc (a: int): int{.cdecl.}' +tproc_mismatch.nim(72, 9) Error: type mismatch: got <proc (a: int): int{.nimcall.}> but expected 'proc (a: int): int{.cdecl.}' Calling convention mismatch: got '{.nimcall.}', but expected '{.cdecl.}'. -tproc_mismatch.nim(70, 9) Error: type mismatch: got <proc (a: int): int{.cdecl.}> but expected 'proc (a: int): int{.nimcall.}' +tproc_mismatch.nim(73, 9) Error: type mismatch: got <proc (a: int): int{.cdecl.}> but expected 'proc (a: int): int{.nimcall.}' Calling convention mismatch: got '{.cdecl.}', but expected '{.nimcall.}'. -tproc_mismatch.nim(74, 9) Error: type mismatch: got <proc (a: int){.closure, locks: 3.}> but expected 'proc (a: int){.closure, locks: 1.}' - Pragma mismatch: got '{.locks: 3.}', but expected '{.locks: 1.}'. -lock levels differ ''' """ + + + block: # CallConv mismatch func a(a: int, c: float) {.cdecl.} = discard var b: proc(a: int, c: float) {.noSideEffect.} = a @@ -68,7 +71,4 @@ block: # Indrection through pragmas var fn2: proc(a: int): int {.inl2, p2.} fn2 = fn1 fn1 = fn2 -block: # Lock levels differ - var fn1: proc(a: int){.locks: 3.} - var fn2: proc(a: int){.locks: 1.} - fn2 = fn1 + diff --git a/tests/errmsgs/tproper_stacktrace.nim b/tests/errmsgs/tproper_stacktrace.nim index 8617984fb..b0a008840 100644 --- a/tests/errmsgs/tproper_stacktrace.nim +++ b/tests/errmsgs/tproper_stacktrace.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--stackTrace:on --hint:all:off --warnings:off" output: '''ok''' """ import strscans, strutils @@ -76,10 +77,10 @@ when true: bar() const expectedStackTrace = """ - tproper_stacktrace.nim(86) tproper_stacktrace - tproper_stacktrace.nim(76) foo - tproper_stacktrace.nim(73) bar - tproper_stacktrace.nim(7) raiseTestException + tproper_stacktrace.nim(87) tproper_stacktrace + tproper_stacktrace.nim(77) foo + tproper_stacktrace.nim(74) bar + tproper_stacktrace.nim(8) raiseTestException """ verifyStackTrace expectedStackTrace: @@ -93,9 +94,9 @@ when true: bar(x) const expectedStackTrace = """ - tproper_stacktrace.nim(103) tproper_stacktrace - tproper_stacktrace.nim(90) bar - tproper_stacktrace.nim(7) raiseTestException + tproper_stacktrace.nim(104) tproper_stacktrace + tproper_stacktrace.nim(91) bar + tproper_stacktrace.nim(8) raiseTestException """ verifyStackTrace expectedStackTrace: @@ -110,10 +111,10 @@ when true: bar() const expectedStackTrace = """ - tproper_stacktrace.nim(120) tproper_stacktrace - tproper_stacktrace.nim(110) foo - tproper_stacktrace.nim(107) bar - tproper_stacktrace.nim(7) raiseTestException + tproper_stacktrace.nim(121) tproper_stacktrace + tproper_stacktrace.nim(111) foo + tproper_stacktrace.nim(108) bar + tproper_stacktrace.nim(8) raiseTestException """ verifyStackTrace expectedStackTrace: @@ -129,10 +130,10 @@ when true: bar() const expectedStackTrace = """ - tproper_stacktrace.nim(139) tproper_stacktrace - tproper_stacktrace.nim(129) foo - tproper_stacktrace.nim(125) baz - tproper_stacktrace.nim(7) raiseTestException + tproper_stacktrace.nim(140) tproper_stacktrace + tproper_stacktrace.nim(130) foo + tproper_stacktrace.nim(126) baz + tproper_stacktrace.nim(8) raiseTestException """ verifyStackTrace expectedStackTrace: diff --git a/tests/errmsgs/tproper_stacktrace2.nim b/tests/errmsgs/tproper_stacktrace2.nim index 44b208c87..5a6ca3fcb 100644 --- a/tests/errmsgs/tproper_stacktrace2.nim +++ b/tests/errmsgs/tproper_stacktrace2.nim @@ -1,5 +1,6 @@ discard """ - outputsub: '''tproper_stacktrace2.nim(20) main''' + matrix: "--stackTrace:on" + outputsub: '''tproper_stacktrace2.nim(21) main''' exitcode: 1 """ diff --git a/tests/errmsgs/tproper_stacktrace3.nim b/tests/errmsgs/tproper_stacktrace3.nim index c292fa092..97d63e6ec 100644 --- a/tests/errmsgs/tproper_stacktrace3.nim +++ b/tests/errmsgs/tproper_stacktrace3.nim @@ -1,5 +1,6 @@ discard """ - outputsub: '''tproper_stacktrace3.nim(21) main''' + matrix: "--stackTrace:on" + outputsub: '''tproper_stacktrace3.nim(22) main''' exitcode: 1 """ diff --git a/tests/errmsgs/tsigmatch.nim b/tests/errmsgs/tsigmatch.nim index 8f32ef9e6..85ed34169 100644 --- a/tests/errmsgs/tsigmatch.nim +++ b/tests/errmsgs/tsigmatch.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim check --showAllMismatches:on --hints:off $file" + cmd: "nim check --mm:refc --showAllMismatches:on --hints:off $file" nimout: ''' tsigmatch.nim(111, 4) Error: type mismatch: got <A, string> but expected one of: @@ -12,34 +12,34 @@ proc f(b: B) but expression 'A()' is of type: A expression: f(A(), "extra") -tsigmatch.nim(125, 6) Error: type mismatch: got <(string, proc (){.gcsafe, locks: 0.})> +tsigmatch.nim(125, 6) Error: type mismatch: got <(string, proc (){.gcsafe.})> but expected one of: proc foo(x: (string, proc ())) first type mismatch at position: 1 required type for x: (string, proc (){.closure.}) - but expression '("foobar", proc () = echo(["Hello!"]))' is of type: (string, proc (){.gcsafe, locks: 0.}) + but expression '("foobar", proc () = echo(["Hello!"]))' is of type: (string, proc (){.gcsafe.}) expression: foo(("foobar", proc () = echo(["Hello!"]))) -tsigmatch.nim(132, 11) Error: type mismatch: got <proc (s: string): string{.noSideEffect, gcsafe, locks: 0.}> +tsigmatch.nim(132, 11) Error: type mismatch: got <proc (s: string): string{.noSideEffect, gcsafe.}> but expected one of: proc foo[T, S](op: proc (x: T): S {.cdecl.}): auto first type mismatch at position: 1 required type for op: proc (x: T): S{.cdecl.} - but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.} + but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe.} proc foo[T, S](op: proc (x: T): S {.safecall.}): auto first type mismatch at position: 1 required type for op: proc (x: T): S{.safecall.} - but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe, locks: 0.} + but expression 'fun' is of type: proc (s: string): string{.noSideEffect, gcsafe.} expression: foo(fun) -tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcsafe, locks: 0.}]> +tsigmatch.nim(143, 13) Error: type mismatch: got <array[0..0, proc (x: int){.gcsafe.}]> but expected one of: -proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}]) +proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe.}]) first type mismatch at position: 1 - required type for fs: openArray[proc (x: int){.closure, gcsafe, locks: 0.}] - but expression '[proc (x: int) {.gcsafe, locks: 0.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe, locks: 0.}] + required type for fs: openArray[proc (x: int){.closure, gcsafe.}] + but expression '[proc (x: int) {.gcsafe.} = echo [x]]' is of type: array[0..0, proc (x: int){.gcsafe.}] -expression: takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo [x]]) +expression: takesFuncs([proc (x: int) {.gcsafe.} = echo [x]]) tsigmatch.nim(149, 4) Error: type mismatch: got <int literal(10), a0: int literal(5), string> but expected one of: proc f(a0: uint8; b: string) @@ -135,12 +135,12 @@ block: # bug #10285 Function signature don't match when inside seq/array/openArray # Note: the error message now shows `closure` which helps debugging the issue # out why it doesn't match - proc takesFunc(f: proc (x: int) {.gcsafe, locks: 0.}) = + proc takesFunc(f: proc (x: int) {.gcsafe.}) = echo "takes single Func" - proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe, locks: 0.}]) = + proc takesFuncs(fs: openArray[proc (x: int) {.gcsafe.}]) = echo "takes multiple Func" - takesFunc(proc (x: int) {.gcsafe, locks: 0.} = echo x) # works - takesFuncs([proc (x: int) {.gcsafe, locks: 0.} = echo x]) # fails + takesFunc(proc (x: int) {.gcsafe.} = echo x) # works + takesFuncs([proc (x: int) {.gcsafe.} = echo x]) # fails block: # bug https://github.com/nim-lang/Nim/issues/11061#issuecomment-508970465 diff --git a/tests/errmsgs/tsigmatch2.nim b/tests/errmsgs/tsigmatch2.nim index 4996634c9..31c966337 100644 --- a/tests/errmsgs/tsigmatch2.nim +++ b/tests/errmsgs/tsigmatch2.nim @@ -14,7 +14,7 @@ proc foo(i: Foo): string expression: foo(1.2) tsigmatch2.nim(40, 14) Error: expression '' has no type (or is ambiguous) -tsigmatch2.nim(46, 7) Error: type mismatch: got <int literal(1)> +tsigmatch2.nim(46, 3) Error: type mismatch: got <int literal(1)> but expected one of: proc foo(args: varargs[string, myproc]) first type mismatch at position: 1 @@ -44,4 +44,4 @@ block: let temp = 12.isNil proc foo(args: varargs[string, myproc]) = discard foo 1 -static: echo "done" \ No newline at end of file +static: echo "done" diff --git a/tests/misc/tsimtych.nim b/tests/errmsgs/tsimpletypecheck.nim index 74a6ad4c0..422437d3a 100644 --- a/tests/misc/tsimtych.nim +++ b/tests/errmsgs/tsimpletypecheck.nim @@ -1,6 +1,6 @@ discard """ errormsg: "type mismatch: got <bool> but expected \'string\'" - file: "tsimtych.nim" + file: "tsimpletypecheck.nim" line: 10 """ # Test 2 diff --git a/tests/errmsgs/tsubscriptmismatch.nim b/tests/errmsgs/tsubscriptmismatch.nim new file mode 100644 index 000000000..a2b297b68 --- /dev/null +++ b/tests/errmsgs/tsubscriptmismatch.nim @@ -0,0 +1,11 @@ +discard """ + matrix: "-d:testsConciseTypeMismatch" + nimout: ''' +[1] proc `[]`[T; U, V: Ordinal](s: openArray[T]; x: HSlice[U, V]): seq[T] +''' +""" + +type Foo = object +let x = Foo() +discard x[1] #[tt.Error + ^ type mismatch]# diff --git a/tests/errmsgs/tsubscriptmismatch_legacy.nim b/tests/errmsgs/tsubscriptmismatch_legacy.nim new file mode 100644 index 000000000..3e1f1eb71 --- /dev/null +++ b/tests/errmsgs/tsubscriptmismatch_legacy.nim @@ -0,0 +1,10 @@ +discard """ + nimout: ''' + but expression 'x' is of type: Foo +''' +""" + +type Foo = object +let x = Foo() +discard x[1] #[tt.Error + ^ type mismatch: got <Foo, int literal(1)>]# diff --git a/tests/errmsgs/ttupleindexoutofbounds.nim b/tests/errmsgs/ttupleindexoutofbounds.nim new file mode 100644 index 000000000..ae634dddb --- /dev/null +++ b/tests/errmsgs/ttupleindexoutofbounds.nim @@ -0,0 +1,2 @@ +let a = (1, 2)[4] #[tt.Error + ^ invalid index 4 in subscript for tuple of length 2]# diff --git a/tests/errmsgs/ttypeAllowed.nim b/tests/errmsgs/ttypeAllowed.nim index 516b616e0..fdb4c70b8 100644 --- a/tests/errmsgs/ttypeAllowed.nim +++ b/tests/errmsgs/ttypeAllowed.nim @@ -2,10 +2,10 @@ discard """ cmd: "nim check $file" errormsg: "" nimout: ''' -ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for let -ttypeAllowed.nim(17, 7) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for const -ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for var -ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe, locks: 0.}' for result +ttypeAllowed.nim(13, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for let +ttypeAllowed.nim(17, 7) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for const +ttypeAllowed.nim(21, 5) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for var +ttypeAllowed.nim(26, 10) Error: invalid type: 'iterator (a: int, b: int, step: Positive): int{.inline, noSideEffect, gcsafe.}' for result ''' """ diff --git a/tests/errmsgs/tundeclared_routine.nim b/tests/errmsgs/tundeclared_routine.nim index 2f1320fff..41b1d35f4 100644 --- a/tests/errmsgs/tundeclared_routine.nim +++ b/tests/errmsgs/tundeclared_routine.nim @@ -9,7 +9,7 @@ tundeclared_routine.nim(29, 28) Error: invalid pragma: myPragma tundeclared_routine.nim(36, 13) Error: undeclared field: 'bar3' for type tundeclared_routine.Foo [type declared in tundeclared_routine.nim(33, 8)] found tundeclared_routine.bar3() [iterator declared in tundeclared_routine.nim(35, 12)] tundeclared_routine.nim(41, 13) Error: undeclared field: 'bar4' for type tundeclared_routine.Foo [type declared in tundeclared_routine.nim(39, 8)] -tundeclared_routine.nim(44, 15) Error: attempting to call routine: 'bad5' +tundeclared_routine.nim(44, 11) Error: undeclared identifier: 'bad5' ''' """ diff --git a/tests/misc/tnoinst.nim b/tests/errmsgs/tunresolvedinnerproc.nim index 85db1e8e7..7655a5a41 100644 --- a/tests/misc/tnoinst.nim +++ b/tests/errmsgs/tunresolvedinnerproc.nim @@ -1,16 +1,10 @@ -discard """ - errormsg: "instantiate 'notConcrete' explicitly" - line: 12 - disabled: "true" -""" - proc wrap[T]() = proc notConcrete[T](x, y: int): int = var dummy: T result = x - y var x: proc (x, y: T): int - x = notConcrete - + x = notConcrete #[tt.Error + ^ 'notConcrete' doesn't have a concrete type, due to unspecified generic parameters.]# wrap[int]() diff --git a/tests/errmsgs/tuntypedoverload.nim b/tests/errmsgs/tuntypedoverload.nim new file mode 100644 index 000000000..1b1c2809c --- /dev/null +++ b/tests/errmsgs/tuntypedoverload.nim @@ -0,0 +1,37 @@ +discard """ + cmd: "nim check $file" +""" + +block: + template foo(x: var int, y: untyped) = discard + var a: float + foo(a, undeclared) #[tt.Error + ^ type mismatch: got <float, untyped>]# # `untyped` is arbitary + # previous error: undeclared identifier: 'undeclared' + +block: # issue #8697 + type + Fruit = enum + apple + banana + orange + macro hello(x, y: untyped) = discard + hello(apple, banana, orange) #[tt.Error + ^ type mismatch: got <Fruit, Fruit, Fruit>]# + +block: # issue #23265 + template declareFoo(fooName: untyped, value: uint16) = + const `fooName Value` {.inject.} = value + + declareFoo(FOO, 0xFFFF) + declareFoo(BAR, 0xFFFFF) #[tt.Error + ^ type mismatch: got <untyped, int literal(1048575)>]# + +block: # issue #9620 + template forLoop(index: untyped, length: int{lvalue}, body: untyped) = + for `index`{.inject.} in 0 ..< length: + body + var x = newSeq[int](10) + forLoop(i, x.len): #[tt.Error + ^ type mismatch: got <untyped, int, void>]# + x[i] = i diff --git a/tests/errmsgs/twrong_explicit_typeargs.nim b/tests/errmsgs/twrong_explicit_typeargs.nim new file mode 100644 index 000000000..5236e5f4f --- /dev/null +++ b/tests/errmsgs/twrong_explicit_typeargs.nim @@ -0,0 +1,26 @@ +discard """ + cmd: "nim c --hints:off -d:testsConciseTypeMismatch $file" + action: reject + nimout: ''' +twrong_explicit_typeargs.nim(26, 29) Error: type mismatch +Expression: newImage[string](320, 200) + [1] 320: int literal(320) + [2] 200: int literal(200) + +Expected one of (first mismatch at [position]): +[1] proc newImage[T: int32 | int64](w, h: int): ref Image[T] + generic parameter mismatch, expected int32 or int64 but got 'string' of type: string +''' +""" + +# bug #4084 +type + Image[T] = object + data: seq[T] + +proc newImage[T: int32|int64](w, h: int): ref Image[T] = + new(result) + result.data = newSeq[T](w * h) + +var correct = newImage[int32](320, 200) +var wrong = newImage[string](320, 200) diff --git a/tests/errmsgs/twrong_explicit_typeargs_legacy.nim b/tests/errmsgs/twrong_explicit_typeargs_legacy.nim new file mode 100644 index 000000000..cfa528c54 --- /dev/null +++ b/tests/errmsgs/twrong_explicit_typeargs_legacy.nim @@ -0,0 +1,25 @@ +discard """ + action: reject + nimout: ''' +twrong_explicit_typeargs_legacy.nim(25, 29) Error: type mismatch: got <int literal(320), int literal(200)> +but expected one of: +proc newImage[T: int32 | int64](w, h: int): ref Image[T] + first type mismatch at position: 1 in generic parameters + required type for T: int32 or int64 + but expression 'string' is of type: string + +expression: newImage[string](320, 200) +''' +""" + +# bug #4084 +type + Image[T] = object + data: seq[T] + +proc newImage[T: int32|int64](w, h: int): ref Image[T] = + new(result) + result.data = newSeq[T](w * h) + +var correct = newImage[int32](320, 200) +var wrong = newImage[string](320, 200) diff --git a/tests/exception/m21261.nim b/tests/exception/m21261.nim new file mode 100644 index 000000000..11b12fb5b --- /dev/null +++ b/tests/exception/m21261.nim @@ -0,0 +1 @@ +raise (ref Exception)(msg: "something") \ No newline at end of file diff --git a/tests/exception/m22469.nim b/tests/exception/m22469.nim new file mode 100644 index 000000000..201698701 --- /dev/null +++ b/tests/exception/m22469.nim @@ -0,0 +1,4 @@ +# ModuleB +echo "First top-level statement of ModuleB" +echo high(int) + 1 +echo "ModuleB last statement" \ No newline at end of file diff --git a/tests/exception/t13115.nim b/tests/exception/t13115.nim index ee1daed26..5db8f9107 100644 --- a/tests/exception/t13115.nim +++ b/tests/exception/t13115.nim @@ -13,13 +13,6 @@ else: const nim = getCurrentCompilerExe() const file = currentSourcePath for b in "c js cpp".split: - when defined(openbsd): - if b == "js": - # xxx bug: pending #13115 - # remove special case once nodejs updated >= 12.16.2 - # refs https://github.com/nim-lang/Nim/pull/16167#issuecomment-738270751 - continue - # save CI time by avoiding mostly redundant combinations as far as this bug is concerned var opts = case b of "c": @["", "-d:nim_t13115_static", "-d:danger", "-d:debug"] diff --git a/tests/exception/t20613.nim b/tests/exception/t20613.nim new file mode 100644 index 000000000..6edb69415 --- /dev/null +++ b/tests/exception/t20613.nim @@ -0,0 +1,8 @@ +discard """ + matrix: "; --panics:on" +""" + +func test = + if 0 > 10: + raiseAssert "hey" +test() diff --git a/tests/exception/t21261.nim b/tests/exception/t21261.nim new file mode 100644 index 000000000..84817d854 --- /dev/null +++ b/tests/exception/t21261.nim @@ -0,0 +1,9 @@ +discard """ + exitcode: 1 + outputsub: ''' +m21261.nim(1) m21261 +Error: unhandled exception: something [Exception] +''' +""" + +import m21261 \ No newline at end of file diff --git a/tests/exception/t22008.nim b/tests/exception/t22008.nim new file mode 100644 index 000000000..c0758e7b4 --- /dev/null +++ b/tests/exception/t22008.nim @@ -0,0 +1,8 @@ +template detect(v: untyped) = + doAssert typeof(v) is int + +detect: + try: + raise (ref ValueError)() + except ValueError: + 42 \ No newline at end of file diff --git a/tests/exception/t22469.nim b/tests/exception/t22469.nim new file mode 100644 index 000000000..a76c74967 --- /dev/null +++ b/tests/exception/t22469.nim @@ -0,0 +1,16 @@ +discard """ + exitcode: 1 + output: ''' +First top-level statement of ModuleB +m22469.nim(3) m22469 +fatal.nim(53) sysFatal +Error: unhandled exception: over- or underflow [OverflowDefect] +''' +""" + +# bug #22469 + +# ModuleA +import m22469 +echo "ModuleA about to have exception" +echo high(int) + 1 diff --git a/tests/exception/tcpp_imported_exc.nim b/tests/exception/tcpp_imported_exc.nim index 8ab7b8780..55a58440f 100644 --- a/tests/exception/tcpp_imported_exc.nim +++ b/tests/exception/tcpp_imported_exc.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" targets: "cpp" output: ''' caught as std::exception diff --git a/tests/exception/texceptionbreak.nim b/tests/exception/texceptionbreak.nim index 6548192c6..b8ce7eead 100644 --- a/tests/exception/texceptionbreak.nim +++ b/tests/exception/texceptionbreak.nim @@ -29,16 +29,16 @@ echo "2" try: raise newException(OSError, "Problem") except OSError: - block: - break + block label: + break label echo "3" # Fourth Variety -block: +block label: try: raise newException(OSError, "Problem") except OSError: - break + break label echo "4" diff --git a/tests/exprs/t22604.nim b/tests/exprs/t22604.nim new file mode 100644 index 000000000..c41cd3dfa --- /dev/null +++ b/tests/exprs/t22604.nim @@ -0,0 +1,36 @@ +# if +for i in 0..<1: + let x = + case false + of true: + 42 + of false: + if true: + continue + else: + raiseAssert "Won't get here" + +# nested case +for i in 0..<1: + let x = + case false + of true: + 42 + of false: + case true + of true: + continue + of false: + raiseAssert "Won't get here" + +# try except +for i in 0..<1: + let x = + case false + of true: + 42 + of false: + try: + continue + except: + raiseAssert "Won't get here" \ No newline at end of file diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim index 5bedca371..2bb61eb58 100644 --- a/tests/float/tfloat4.nim +++ b/tests/float/tfloat4.nim @@ -8,7 +8,7 @@ proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "<stdio.h>", vara proc floatToStr(f: float64): string = var buffer: array[128, char] - c_sprintf(addr buffer, "%.16e", f) + c_sprintf(cast[cstring](addr buffer), "%.16e", f) result = "" for ch in buffer: if ch == '\0': @@ -56,8 +56,14 @@ doAssert 0.9999999999999999 == ".9999999999999999".parseFloat # bug #18400 var s = [-13.888888'f32] -assert $s[0] == "-13.888888" +doAssert $s[0] == "-13.888888" var x = 1.23456789012345'f32 -assert $x == "1.2345679" +doAssert $x == "1.2345679" + +# bug #21847 +doAssert parseFloat"0e+42" == 0.0 +doAssert parseFloat"0e+42949672969" == 0.0 +doAssert parseFloat"0e+42949672970" == 0.0 +doAssert parseFloat"0e+42949623223346323563272970" == 0.0 echo("passed all tests.") diff --git a/tests/float/tfloats.nim b/tests/float/tfloats.nim index 480396e81..aaed2d615 100644 --- a/tests/float/tfloats.nim +++ b/tests/float/tfloats.nim @@ -41,8 +41,7 @@ template main = test ".1", 0.1 test "-.1", -0.1 test "-0", -0.0 - when false: # pending bug #18246 - test "-0", -0.0 + test "-0", -0'f # see #18246, -0 won't work test ".1e-1", 0.1e-1 test "0_1_2_3.0_1_2_3E+0_1_2", 123.0123e12 test "0_1_2.e-0", 12e0 @@ -157,9 +156,8 @@ template main = when nimvm: discard # xxx, refs #12884 else: - when not defined(js): - doAssert x == 1.2345679'f32 - doAssert $x == "1.2345679" + doAssert x == 1.2345679'f32 + doAssert $x == "1.2345679" static: main() main() diff --git a/tests/gc/closureleak.nim b/tests/gc/closureleak.nim index 0265431d0..e67beb513 100644 --- a/tests/gc/closureleak.nim +++ b/tests/gc/closureleak.nim @@ -11,9 +11,19 @@ var foo_counter = 0 var alive_foos = newseq[int](0) when defined(gcDestructors): - proc `=destroy`(some: var TFoo) = + proc `=destroy`(some: TFoo) = alive_foos.del alive_foos.find(some.id) - `=destroy`(some.fn) + # TODO: fixme: investigate why `=destroy` requires `some.fn` to be `gcsafe` + # the debugging info below came from `symPrototype` in the liftdestructors + # proc (){.closure, gcsafe.}, {tfThread, tfHasAsgn, tfCheckedForDestructor, tfExplicitCallConv} + # var proc (){.closure, gcsafe.}, {tfHasGCedMem} + # it worked by accident with var T destructors because in the sempass2 + # + # let argtype = skipTypes(a.typ, abstractInst) # !!! it does't skip `tyVar` + # if argtype.kind == tyProc and notGcSafe(argtype) and not tracked.inEnforcedGcSafe: + # localError(tracked.config, n.info, $n & " is not GC safe") + {.cast(gcsafe).}: + `=destroy`(some.fn) else: proc free*(some: ref TFoo) = diff --git a/tests/gc/tdisable_orc.nim b/tests/gc/tdisable_orc.nim new file mode 100644 index 000000000..b5f161c79 --- /dev/null +++ b/tests/gc/tdisable_orc.nim @@ -0,0 +1,9 @@ +discard """ + joinable: false +""" + +import std/asyncdispatch + +# bug #22256 +GC_disableMarkAndSweep() +waitFor sleepAsync(1000) diff --git a/tests/generics/m14509.nim b/tests/generics/m14509.nim new file mode 100644 index 000000000..cabc4f308 --- /dev/null +++ b/tests/generics/m14509.nim @@ -0,0 +1,16 @@ +import macros + +type float32x4 = array[4, float32] +type float32x8 = array[8, float32] + +{.experimental: "dynamicBindSym".} +macro dispatch(N: static int, T: type SomeNumber): untyped = + let BaseT = getTypeInst(T)[1] + result = bindSym($BaseT & "x" & $N) + +type + VecIntrin*[N: static int, T: SomeNumber] = dispatch(N, T) + +func `$`*[N, T](vec: VecIntrin[N, T]): string = + ## Display a vector + $cast[array[N, T]](vec) diff --git a/tests/generics/m22373a.nim b/tests/generics/m22373a.nim new file mode 100644 index 000000000..28e087ca6 --- /dev/null +++ b/tests/generics/m22373a.nim @@ -0,0 +1,7 @@ +# module a for t22373 + +# original: +type LightClientHeader* = object + +# simplified: +type TypeOrTemplate* = object diff --git a/tests/generics/m22373b.nim b/tests/generics/m22373b.nim new file mode 100644 index 000000000..67ee4211b --- /dev/null +++ b/tests/generics/m22373b.nim @@ -0,0 +1,18 @@ +# module b for t22373 + +import m22373a + +# original: +type + LightClientDataFork* {.pure.} = enum + None = 0, + Altair = 1 +template LightClientHeader*(kind: static LightClientDataFork): auto = + when kind == LightClientDataFork.Altair: + typedesc[m22373a.LightClientHeader] + else: + static: raiseAssert "Unreachable" + +# simplified: +template TypeOrTemplate*(num: int): untyped = + typedesc[m22373a.TypeOrTemplate] diff --git a/tests/generics/m3770.nim b/tests/generics/m3770.nim new file mode 100644 index 000000000..7f5714a2b --- /dev/null +++ b/tests/generics/m3770.nim @@ -0,0 +1,11 @@ +type + Noice* = object + hidden: int + +template jjj*: Noice = + Noice(hidden: 15) + +type Opt* = object + o: int + +template none*(O: type Opt): Opt = Opt(o: 0) diff --git a/tests/generics/mdotlookup.nim b/tests/generics/mdotlookup.nim index 3112c133f..090b97771 100644 --- a/tests/generics/mdotlookup.nim +++ b/tests/generics/mdotlookup.nim @@ -14,3 +14,15 @@ var intset = initHashSet[int]() proc fn*[T](a: T) = if a in intset: echo("true") else: echo("false") + +import strutils + +proc doStrip*[T](a: T): string = + result = ($a).strip() + +type Foo = int32 +proc baz2*[T](y: int): auto = + result = y.Foo + +proc set*(x: var int, a, b: string) = + x = a.len + b.len diff --git a/tests/friends/mfriends.nim b/tests/generics/mfriends.nim index 19672289e..19672289e 100644 --- a/tests/friends/mfriends.nim +++ b/tests/generics/mfriends.nim diff --git a/tests/generics/mopensymimport1.nim b/tests/generics/mopensymimport1.nim new file mode 100644 index 000000000..912db1302 --- /dev/null +++ b/tests/generics/mopensymimport1.nim @@ -0,0 +1,34 @@ +type + Result*[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + +template valueOr*[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def diff --git a/tests/generics/mopensymimport2.nim b/tests/generics/mopensymimport2.nim new file mode 100644 index 000000000..c17aafd00 --- /dev/null +++ b/tests/generics/mopensymimport2.nim @@ -0,0 +1,16 @@ +{.experimental: "openSym".} + +import mopensymimport1 + +type Xxx = enum + error + value + +proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + +proc g*(T: type): string = + let x = f().valueOr: + return $error + + "ok" diff --git a/tests/generics/mtypenodes.nim b/tests/generics/mtypenodes.nim new file mode 100644 index 000000000..e1132241b --- /dev/null +++ b/tests/generics/mtypenodes.nim @@ -0,0 +1,6 @@ +# issue #22699 + +type Private = distinct int + +proc chop*[T](x: int): int = + cast[int](cast[tuple[field: Private]](x)) diff --git a/tests/generics/muninstantiatedgenericcalls.nim b/tests/generics/muninstantiatedgenericcalls.nim new file mode 100644 index 000000000..caed07c98 --- /dev/null +++ b/tests/generics/muninstantiatedgenericcalls.nim @@ -0,0 +1,26 @@ +import std/bitops + +const + lengths = block: + var v: array[64, int8] + for i in 0..<64: + v[i] = int8((i + 7) div 7) + v + +type + Leb128* = object + +{.push checks: off.} +func len(T: type Leb128, x: SomeUnsignedInt): int8 = + if x == 0: 1 + else: lengths[fastLog2(x)] +{.pop.} + +# note private to test scoping issue: +func maxLen(T: type Leb128, I: type): int8 = + Leb128.len(I.high) + +type + Leb128Buf*[T: SomeUnsignedInt] = object + data*: array[maxLen(Leb128, T), byte] + len*: int8 diff --git a/tests/generics/t12938.nim b/tests/generics/t12938.nim new file mode 100644 index 000000000..e09d65c7a --- /dev/null +++ b/tests/generics/t12938.nim @@ -0,0 +1,9 @@ +type + ExampleArray[Size, T] = array[Size, T] + +var integerArray: ExampleArray[32, int] # Compiler crash! +doAssert integerArray.len == 32 + +const Size = 2 +var integerArray2: ExampleArray[Size, int] +doAssert integerArray2.len == 2 diff --git a/tests/generics/t14193.nim b/tests/generics/t14193.nim new file mode 100644 index 000000000..213b1a8e6 --- /dev/null +++ b/tests/generics/t14193.nim @@ -0,0 +1,6 @@ +type + Task*[N: int] = object + env*: array[N, byte] + +var task14193: Task[20] +doAssert task14193.env.len == 20 diff --git a/tests/generics/t14509.nim b/tests/generics/t14509.nim new file mode 100644 index 000000000..ef3143ee4 --- /dev/null +++ b/tests/generics/t14509.nim @@ -0,0 +1,4 @@ +import m14509 + +var v: VecIntrin[4, float32] +doAssert $v == "[0.0, 0.0, 0.0, 0.0]" diff --git a/tests/generics/t1500.nim b/tests/generics/t1500.nim new file mode 100644 index 000000000..6dd457d33 --- /dev/null +++ b/tests/generics/t1500.nim @@ -0,0 +1,8 @@ +#issue 1500 + +type + TFtpBase*[SockType] = object + job: TFTPJob[SockType] + PFtpBase*[SockType] = ref TFtpBase[SockType] + TFtpClient* = TFtpBase[string] + TFTPJob[T] = object \ No newline at end of file diff --git a/tests/generics/t17509.nim b/tests/generics/t17509.nim new file mode 100644 index 000000000..89f507577 --- /dev/null +++ b/tests/generics/t17509.nim @@ -0,0 +1,25 @@ +type List[O] = object + next: ptr List[O] + +proc initList[O](l: ptr List[O]) = + l[].next = l + +type + PolytopeVertex[R] = object + list: List[PolytopeVertex[R]] + + PolytopeEdge[R] = object + list: List[PolytopeEdge[R]] + + Polytope[R] = object + vertices: List[PolytopeVertex[R]] + edges: List[PolytopeEdge[R]] + +var pt: Polytope[float] + +static: + doAssert pt.vertices.next is (ptr List[PolytopeVertex[float]]) + doAssert pt.edges.next is (ptr List[PolytopeEdge[float]]) + +initList(addr pt.vertices) +initList(addr pt.edges) \ No newline at end of file diff --git a/tests/generics/t18823.nim b/tests/generics/t18823.nim new file mode 100644 index 000000000..94c79aebe --- /dev/null +++ b/tests/generics/t18823.nim @@ -0,0 +1,6 @@ +type BitsRange[T] = range[0..sizeof(T)*8-1] + +proc bar[T](a: T; b: BitsRange[T]) = + discard + +bar(1, 2.Natural) diff --git a/tests/generics/t19848.nim b/tests/generics/t19848.nim new file mode 100644 index 000000000..f80f0e298 --- /dev/null +++ b/tests/generics/t19848.nim @@ -0,0 +1,16 @@ +discard """ + output: ''' +todo +''' +""" + +type + Maybe[T] = object + List[T] = object + +proc dump[M: Maybe](a: List[M]) = + echo "todo" + +var a: List[Maybe[int]] + +dump(a) diff --git a/tests/generics/t20996.nim b/tests/generics/t20996.nim new file mode 100644 index 000000000..8aa83c4e2 --- /dev/null +++ b/tests/generics/t20996.nim @@ -0,0 +1,15 @@ +discard """ + action: compile +""" + +import std/macros + +macro matchMe(x: typed): untyped = + discard x.getTypeImpl + +type + ElementRT = object + Element[Z] = ElementRT # this version is needed, even though we don't use it + +let ar = ElementRT() +matchMe(ar) diff --git a/tests/generics/t21742.nim b/tests/generics/t21742.nim new file mode 100644 index 000000000..c49c8ee97 --- /dev/null +++ b/tests/generics/t21742.nim @@ -0,0 +1,10 @@ +type + Foo[T] = object + x:T + Bar[T,R] = Foo[T] + Baz = Bar[int,float] + +proc qux[T,R](x: Bar[T,R]) = discard + +var b:Baz +b.qux() \ No newline at end of file diff --git a/tests/generics/t21760.nim b/tests/generics/t21760.nim new file mode 100644 index 000000000..5343279bb --- /dev/null +++ b/tests/generics/t21760.nim @@ -0,0 +1,8 @@ +import std/tables + +type Url = object + +proc myInit(_: type[Url], params = default(Table[string, string])): Url = + discard + +discard myInit(Url) \ No newline at end of file diff --git a/tests/generics/t21958.nim b/tests/generics/t21958.nim new file mode 100644 index 000000000..f566b57cb --- /dev/null +++ b/tests/generics/t21958.nim @@ -0,0 +1,11 @@ +discard """ + action: compile +""" + +type + Ct*[T: SomeUnsignedInt] = distinct T + +template `shr`*[T: Ct](x: T, y: SomeInteger): T = T(T.T(x) shr y) + +var x: Ct[uint64] +let y {.used.} = x shr 2 \ No newline at end of file diff --git a/tests/generics/t22373.nim b/tests/generics/t22373.nim new file mode 100644 index 000000000..ecfaf0f1b --- /dev/null +++ b/tests/generics/t22373.nim @@ -0,0 +1,16 @@ +# issue #22373 + +import m22373a +import m22373b + +# original: +template lazy_header(name: untyped): untyped {.dirty.} = + var `name _ ptr`: ptr[data_fork.LightClientHeader] # this data_fork.Foo part seems required to reproduce +proc createLightClientUpdates(data_fork: static LightClientDataFork) = + lazy_header(attested_header) +createLightClientUpdates(LightClientDataFork.Altair) + +# simplified: +proc generic[T](abc: T) = + var x: abc.TypeOrTemplate +generic(123) diff --git a/tests/generics/t22826.nim b/tests/generics/t22826.nim new file mode 100644 index 000000000..914d4243a --- /dev/null +++ b/tests/generics/t22826.nim @@ -0,0 +1,8 @@ +import std/tables + +var a: Table[string, float] + +type Value*[T] = object + table: Table[string, Value[T]] + +discard toTable({"a": Value[float]()}) \ No newline at end of file diff --git a/tests/generics/t23186.nim b/tests/generics/t23186.nim new file mode 100644 index 000000000..76f38da6b --- /dev/null +++ b/tests/generics/t23186.nim @@ -0,0 +1,155 @@ +# issue #23186 + +block: # simplified + template typedTempl(x: int, body): untyped = + body + proc generic1[T]() = + discard + proc generic2[T]() = + typedTempl(1): + let x = generic1[T] + generic2[int]() + +import std/macros + +when not compiles(len((1, 2))): + import std/typetraits + + func len(x: tuple): int = + arity(type(x)) + +block: # full issue example + type FieldDescription = object + name: NimNode + func isTuple(t: NimNode): bool = + t.kind == nnkBracketExpr and t[0].kind == nnkSym and eqIdent(t[0], "tuple") + proc collectFieldsFromRecList(result: var seq[FieldDescription], + n: NimNode, + parentCaseField: NimNode = nil, + parentCaseBranch: NimNode = nil, + isDiscriminator = false) = + case n.kind + of nnkRecList: + for entry in n: + collectFieldsFromRecList result, entry, + parentCaseField, parentCaseBranch + of nnkIdentDefs: + for i in 0 ..< n.len - 2: + var field: FieldDescription + field.name = n[i] + if field.name.kind == nnkPragmaExpr: + field.name = field.name[0] + if field.name.kind == nnkPostfix: + field.name = field.name[1] + result.add field + of nnkNilLit, nnkDiscardStmt, nnkCommentStmt, nnkEmpty: + discard + else: + doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr + proc collectFieldsInHierarchy(result: var seq[FieldDescription], + objectType: NimNode) = + var objectType = objectType + if objectType.kind == nnkRefTy: + objectType = objectType[0] + let recList = objectType[2] + collectFieldsFromRecList result, recList + proc recordFields(typeImpl: NimNode): seq[FieldDescription] = + let objectType = case typeImpl.kind + of nnkObjectTy: typeImpl + of nnkTypeDef: typeImpl[2] + else: + macros.error("object type expected", typeImpl) + return + collectFieldsInHierarchy(result, objectType) + proc skipPragma(n: NimNode): NimNode = + if n.kind == nnkPragmaExpr: n[0] + else: n + func declval(T: type): T = + doAssert false, + "declval should be used only in `typeof` expressions and concepts" + default(ptr T)[] + macro enumAllSerializedFieldsImpl(T: type, body: untyped): untyped = + var typeAst = getType(T)[1] + var typeImpl: NimNode + let isSymbol = not typeAst.isTuple + if not isSymbol: + typeImpl = typeAst + else: + typeImpl = getImpl(typeAst) + result = newStmtList() + var i = 0 + for field in recordFields(typeImpl): + let + fieldIdent = field.name + realFieldName = newLit($fieldIdent.skipPragma) + fieldName = realFieldName + fieldIndex = newLit(i) + let fieldNameDefs = + if isSymbol: + quote: + const fieldName {.inject, used.} = `fieldName` + const realFieldName {.inject, used.} = `realFieldName` + else: + quote: + const fieldName {.inject, used.} = $`fieldIndex` + const realFieldName {.inject, used.} = $`fieldIndex` + # we can't access .Fieldn, so our helper knows + # to parseInt this + let field = + if isSymbol: + quote do: declval(`T`).`fieldIdent` + else: + quote do: declval(`T`)[`fieldIndex`] + result.add quote do: + block: + `fieldNameDefs` + type FieldType {.inject, used.} = type(`field`) + `body` + i += 1 + template enumAllSerializedFields(T: type, body): untyped = + when T is ref|ptr: + type TT = type(default(T)[]) + enumAllSerializedFieldsImpl(TT, body) + else: + enumAllSerializedFieldsImpl(T, body) + type + MemRange = object + startAddr: ptr byte + length: int + SszNavigator[T] = object + m: MemRange + func sszMount(data: openArray[byte], T: type): SszNavigator[T] = + let startAddr = unsafeAddr data[0] + SszNavigator[T](m: MemRange(startAddr: startAddr, length: data.len)) + func sszMount(data: openArray[char], T: type): SszNavigator[T] = + let startAddr = cast[ptr byte](unsafeAddr data[0]) + SszNavigator[T](m: MemRange(startAddr: startAddr, length: data.len)) + template sszMount(data: MemRange, T: type): SszNavigator[T] = + SszNavigator[T](m: data) + func navigateToField[T]( + n: SszNavigator[T], + FieldType: type): SszNavigator[FieldType] = + default(SszNavigator[FieldType]) + type + FieldInfo = ref object + navigator: proc (m: MemRange): MemRange {. + gcsafe, noSideEffect, raises: [IOError] .} + func fieldNavigatorImpl[RecordType; FieldType; fieldName: static string]( + m: MemRange): MemRange = + var typedNavigator = sszMount(m, RecordType) + discard navigateToField(typedNavigator, FieldType) + default(MemRange) + func genTypeInfo(T: type) = + when T is object: + enumAllSerializedFields(T): + discard FieldInfo(navigator: fieldNavigatorImpl[T, FieldType, fieldName]) + type + Foo = object + bar: Bar + BarList = seq[uint64] + Bar = object + b: BarList + baz: Baz + Baz = object + i: uint64 + genTypeInfo(Foo) diff --git a/tests/generics/t23790.nim b/tests/generics/t23790.nim new file mode 100644 index 000000000..9ac0df6a1 --- /dev/null +++ b/tests/generics/t23790.nim @@ -0,0 +1,14 @@ +# bug #23790 + +discard compiles($default(seq[seq[ref int]])) +discard compiles($default(seq[seq[ref uint]])) +discard compiles($default(seq[seq[ref int8]])) +discard compiles($default(seq[seq[ref uint8]])) +discard compiles($default(seq[seq[ref int16]])) +discard compiles($default(seq[seq[ref uint16]])) +discard compiles($default(seq[seq[ref int32]])) +discard compiles($default(seq[seq[ref uint32]])) +discard compiles($default(seq[seq[ref int64]])) +discard compiles($default(seq[seq[ref uint64]])) +proc s(_: int | string) = discard +s(0) diff --git a/tests/generics/t23853.nim b/tests/generics/t23853.nim new file mode 100644 index 000000000..bc9514a53 --- /dev/null +++ b/tests/generics/t23853.nim @@ -0,0 +1,91 @@ +# issue #23853 + +block simplified: + type QuadraticExt[F] = object + coords: array[2, F] + template Name(E: type QuadraticExt): int = 123 + template getBigInt(Name: static int): untyped = int + type Foo[GT] = object + a: getBigInt(GT.Name) + var x: Foo[QuadraticExt[int]] + +import std/macros + +type + Algebra* = enum + BN254_Snarks + BLS12_381 + + Fp*[Name: static Algebra] = object + limbs*: array[4, uint64] + + QuadraticExt*[F] = object + ## Quadratic Extension field + coords*: array[2, F] + + CubicExt*[F] = object + ## Cubic Extension field + coords*: array[3, F] + + ExtensionField*[F] = QuadraticExt[F] or CubicExt[F] + + Fp2*[Name: static Algebra] = + QuadraticExt[Fp[Name]] + + Fp4*[Name: static Algebra] = + QuadraticExt[Fp2[Name]] + + Fp6*[Name: static Algebra] = + CubicExt[Fp2[Name]] + + Fp12*[Name: static Algebra] = + CubicExt[Fp4[Name]] + # QuadraticExt[Fp6[Name]] + +template Name*(E: type ExtensionField): Algebra = + E.F.Name + +const BLS12_381_Order = [uint64 0x1, 0x2, 0x3, 0x4] +const BLS12_381_Modulus = [uint64 0x5, 0x6, 0x7, 0x8] + + +{.experimental: "dynamicBindSym".} + +macro baseFieldModulus*(Name: static Algebra): untyped = + result = bindSym($Name & "_Modulus") + +macro scalarFieldModulus*(Name: static Algebra): untyped = + result = bindSym($Name & "_Order") + +type FieldKind* = enum + kBaseField + kScalarField + +template getBigInt*(Name: static Algebra, kind: static FieldKind): untyped = + # Workaround: + # in `ptr UncheckedArray[BigInt[EC.getScalarField().bits()]] + # EC.getScalarField is not accepted by the compiler + # + # and `ptr UncheckedArray[BigInt[Fr[EC.F.Name].bits]]` gets undeclared field: 'Name' + # + # but `ptr UncheckedArray[getBigInt(EC.getName(), kScalarField)]` works fine + when kind == kBaseField: + Name.baseFieldModulus().typeof() + else: + Name.scalarFieldModulus().typeof() + +# ------------------------------------------------------------------------------ + +type BenchMultiexpContext*[GT] = object + elems: seq[GT] + exponents: seq[getBigInt(GT.Name, kScalarField)] + +proc createBenchMultiExpContext*(GT: typedesc, inputSizes: openArray[int]): BenchMultiexpContext[GT] = + discard + +# ------------------------------------------------------------------------------ + +proc main() = + let ctx = createBenchMultiExpContext(Fp12[BLS12_381], [2, 4, 8, 16]) + +main() diff --git a/tests/generics/t23854.nim b/tests/generics/t23854.nim new file mode 100644 index 000000000..f1175c8b2 --- /dev/null +++ b/tests/generics/t23854.nim @@ -0,0 +1,71 @@ +# issue #23854, not entirely fixed + +import std/bitops + +const WordBitWidth = sizeof(pointer) * 8 + +func wordsRequired*(bits: int): int {.inline.} = + const divShiftor = fastLog2(uint32(WordBitWidth)) + result = (bits + WordBitWidth - 1) shr divShiftor + +type + Algebra* = enum + BLS12_381 + + BigInt*[bits: static int] = object + limbs*: array[wordsRequired(bits), uint] + + Fr*[Name: static Algebra] = object + residue_form*: BigInt[255] + + Fp*[Name: static Algebra] = object + residue_form*: BigInt[381] + + FF*[Name: static Algebra] = Fp[Name] or Fr[Name] + +template getBigInt*[Name: static Algebra](T: type FF[Name]): untyped = + ## Get the underlying BigInt type. + typeof(default(T).residue_form) + +type + EC_ShortW_Aff*[F] = object + ## Elliptic curve point for a curve in Short Weierstrass form + ## y² = x³ + a x + b + ## + ## over a field F + x*, y*: F + +type FieldKind* = enum + kBaseField + kScalarField + +func bits*[Name: static Algebra](T: type FF[Name]): static int = + T.getBigInt().bits + +template getScalarField*(EC: type EC_ShortW_Aff): untyped = + Fr[EC.F.Name] + +# ------------------------------------------------------------------------------ + +type + ECFFT_Descriptor*[EC] = object + ## Metadata for FFT on Elliptic Curve + order*: int + rootsOfUnity1*: ptr UncheckedArray[BigInt[EC.getScalarField().bits()]] # Error: in expression 'EC.getScalarField()': identifier expected, but found 'EC.getScalarField' + rootsOfUnity2*: ptr UncheckedArray[BigInt[getScalarField(EC).bits()]] # Compiler SIGSEGV: Illegal Storage Access + +func new*(T: type ECFFT_Descriptor): T = + discard + +# ------------------------------------------------------------------------------ + +template getBits[bits: static int](x: ptr UncheckedArray[BigInt[bits]]): int = bits + +proc main() = + let ctx = ECFFT_Descriptor[EC_ShortW_Aff[Fp[BLS12_381]]].new() + doAssert getBits(ctx.rootsOfUnity1) == 255 + doAssert getBits(ctx.rootsOfUnity2) == 255 + doAssert ctx.rootsOfUnity1[0].limbs.len == wordsRequired(255) + doAssert ctx.rootsOfUnity2[0].limbs.len == wordsRequired(255) + +main() diff --git a/tests/generics/t23855.nim b/tests/generics/t23855.nim new file mode 100644 index 000000000..da8135a98 --- /dev/null +++ b/tests/generics/t23855.nim @@ -0,0 +1,61 @@ +# issue #23855, not entirely fixed + +import std/bitops + +const WordBitWidth = sizeof(pointer) * 8 + +func wordsRequired*(bits: int): int {.inline.} = + const divShiftor = fastLog2(uint32(WordBitWidth)) + result = (bits + WordBitWidth - 1) shr divShiftor + +type + Algebra* = enum + BLS12_381 + + BigInt*[bits: static int] = object + limbs*: array[wordsRequired(bits), uint] + + Fr*[Name: static Algebra] = object + residue_form*: BigInt[255] + + Fp*[Name: static Algebra] = object + residue_form*: BigInt[381] + + FF*[Name: static Algebra] = Fp[Name] or Fr[Name] + +template getBigInt*[Name: static Algebra](T: type FF[Name]): untyped = + ## Get the underlying BigInt type. + typeof(default(T).residue_form) + +type + EC_ShortW_Aff*[F] = object + ## Elliptic curve point for a curve in Short Weierstrass form + ## y² = x³ + a x + b + ## + ## over a field F + x*, y*: F + +func bits*[Name: static Algebra](T: type FF[Name]): static int = + T.getBigInt().bits + +# ------------------------------------------------------------------------------ + +type + ECFFT_Descriptor*[EC] = object + ## Metadata for FFT on Elliptic Curve + order*: int + rootsOfUnity*: ptr UncheckedArray[BigInt[Fr[EC.F.Name].bits()]] # Undeclared identifier `Name` + +func new*(T: type ECFFT_Descriptor): T = + discard + +# ------------------------------------------------------------------------------ + +template getBits[bits: static int](x: ptr UncheckedArray[BigInt[bits]]): int = bits + +proc main() = + let ctx = ECFFT_Descriptor[EC_ShortW_Aff[Fp[BLS12_381]]].new() + doAssert getBits(ctx.rootsOfUnity) == 255 + doAssert ctx.rootsOfUnity[0].limbs.len == wordsRequired(255) + +main() diff --git a/tests/generics/t3770.nim b/tests/generics/t3770.nim new file mode 100644 index 000000000..ffccbeeb5 --- /dev/null +++ b/tests/generics/t3770.nim @@ -0,0 +1,13 @@ +# bug #3770 +import m3770 + +doAssert $jjj() == "(hidden: 15)" # works + +proc someGeneric(_: type) = + doAssert $jjj() == "(hidden: 15)" # fails: "Error: the field 'hidden' is not accessible." + +someGeneric(int) + +# bug #20900 +proc c(y: int | int, w: Opt = Opt.none) = discard +c(0) diff --git a/tests/generics/t500.nim b/tests/generics/t500.nim new file mode 100644 index 000000000..2486359aa --- /dev/null +++ b/tests/generics/t500.nim @@ -0,0 +1,8 @@ +discard """ +action: compile +""" + +type + TTest = tuple[x: range[0..80], y: range[0..25]] + +let x: TTest = (2, 23) diff --git a/tests/generics/t6137.nim b/tests/generics/t6137.nim index 991f39dd1..fb7db22f8 100644 --- a/tests/generics/t6137.nim +++ b/tests/generics/t6137.nim @@ -1,6 +1,6 @@ discard """ - errormsg: "\'vectFunc\' doesn't have a concrete type, due to unspecified generic parameters." - line: 28 + errormsg: "cannot instantiate: 'T'" + line: 19 """ type diff --git a/tests/generics/t6637.nim b/tests/generics/t6637.nim new file mode 100644 index 000000000..dd4f339a2 --- /dev/null +++ b/tests/generics/t6637.nim @@ -0,0 +1,9 @@ + +type + Grid2D*[I: SomeInteger, w, h: static[I], T] = object + grid: array[w, array[h, T]] + Grid2DIns = Grid2D[int, 2, 3, uint8] + +let a = Grid2DIns() +doAssert a.grid.len == 2 +doAssert a.grid[0].len == 3 diff --git a/tests/generics/t7446.nim b/tests/generics/t7446.nim new file mode 100644 index 000000000..71aa8f0e8 --- /dev/null +++ b/tests/generics/t7446.nim @@ -0,0 +1,10 @@ +proc foo(x: Natural or SomeUnsignedInt):int = + when x is int: + result = 1 + else: + result = 2 +let a = 10 +doAssert foo(a) == 1 + +let b = 10'u8 +doAssert foo(b) == 2 \ No newline at end of file diff --git a/tests/generics/t7839.nim b/tests/generics/t7839.nim new file mode 100644 index 000000000..4d17b438b --- /dev/null +++ b/tests/generics/t7839.nim @@ -0,0 +1,9 @@ +type A[I: SomeOrdinal, E] = tuple # same for object + length: int + +doAssert A.sizeof == sizeof(int) # works without the following proc + +proc newA*[I: SomeOrdinal, E](): A[I, E] = # works without `SomeOrdinal` + discard + +discard newA[uint8, int]() diff --git a/tests/generics/taliashijack.nim b/tests/generics/taliashijack.nim new file mode 100644 index 000000000..fdebadded --- /dev/null +++ b/tests/generics/taliashijack.nim @@ -0,0 +1,8 @@ +# issue #23977 + +type Foo[T] = int + +proc foo(T: typedesc) = + var a: T + +foo(int) diff --git a/tests/generics/tbadcache.nim b/tests/generics/tbadcache.nim new file mode 100644 index 000000000..33e65be3a --- /dev/null +++ b/tests/generics/tbadcache.nim @@ -0,0 +1,26 @@ +# issue #16128 + +import std/[tables, hashes] + +type + NodeId*[L] = object + isSource: bool + index: Table[NodeId[L], seq[NodeId[L]]] + +func hash*[L](id: NodeId[L]): Hash = discard +func `==`[L](a, b: NodeId[L]): bool = discard + +proc makeIndex*[T, L](tree: T) = + var parent = NodeId[L]() + var tmp: Table[NodeId[L], seq[NodeId[L]]] + tmp[parent] = @[parent] + +proc simpleTreeDiff*[T, L](source, target: T) = + # Swapping these two lines makes error disappear + var m: Table[NodeId[L], NodeId[L]] + makeIndex[T, L](target) + +var tmp: Table[string, seq[string]] # removing this forward declaration also removes error + +proc diff(x1, x2: string): auto = + simpleTreeDiff[int, string](12, 12) diff --git a/tests/generics/tbaddeprecated.nim b/tests/generics/tbaddeprecated.nim new file mode 100644 index 000000000..335234a25 --- /dev/null +++ b/tests/generics/tbaddeprecated.nim @@ -0,0 +1,55 @@ +discard """ + output: ''' +not deprecated +not deprecated +not error +not error +''' +""" + +# issue #21724 + +block: # deprecated + {.push warningAsError[Deprecated]: on.} + type + SomeObj = object + hey: bool + proc hey() {.deprecated: "Shouldn't use this".} = echo "hey" + proc gen(o: auto) = + doAssert not compiles(o.hey()) + if o.hey: + echo "not deprecated" + gen(SomeObj(hey: true)) + doAssert not (compiles do: + proc hey(o: SomeObj) {.deprecated: "Shouldn't use this".} = echo "hey" + proc gen2(o: auto) = + if o.hey(): + echo "not deprecated" + gen2(SomeObj(hey: true))) + proc hey(o: SomeObj) {.deprecated: "Shouldn't use this".} = echo "hey" + proc gen3(o: auto) = + if o.hey: + echo "not deprecated" + gen3(SomeObj(hey: true)) + {.pop.} +block: # error + type + SomeObj = object + hey: bool + proc hey() {.error: "Shouldn't use this".} = echo "hey" + proc gen(o: auto) = + doAssert not compiles(o.hey()) + if o.hey: + echo "not error" + gen(SomeObj(hey: true)) + doAssert not (compiles do: + proc hey(o: SomeObj) {.error: "Shouldn't use this".} = echo "hey" + proc gen2(o: auto) = + if o.hey(): + echo "not error" + gen2(SomeObj(hey: true))) + proc hey(o: SomeObj) {.error: "Shouldn't use this".} = echo "hey" + proc gen3(o: auto) = + if o.hey: + echo "not error" + gen3(SomeObj(hey: true)) diff --git a/tests/generics/tbracketinstantiation.nim b/tests/generics/tbracketinstantiation.nim new file mode 100644 index 000000000..22a86af4c --- /dev/null +++ b/tests/generics/tbracketinstantiation.nim @@ -0,0 +1,86 @@ +discard """ + nimout: ''' +type + Bob = object +type + Another = object +''' +""" + +block: # issue #22645 + type + Opt[T] = object + FutureBase = ref object of RootObj + Future[T] = ref object of FutureBase ## Typed future. + internalValue: T ## Stored value + template err[T](E: type Opt[T]): E = E() + proc works(): Future[Opt[int]] {.stackTrace: off, gcsafe, raises: [].} = + var chronosInternalRetFuture: FutureBase + template result(): untyped {.used.} = + Future[Opt[int]](chronosInternalRetFuture).internalValue + result = err(type(result)) + proc breaks(): Future[Opt[int]] {.stackTrace: off, gcsafe, raises: [].} = + var chronosInternalRetFuture: FutureBase + template result(): untyped {.used.} = + cast[Future[Opt[int]]](chronosInternalRetFuture).internalValue + result = err(type(result)) + +import macros + +block: # issue #16118 + macro thing(name: static[string]) = + result = newStmtList( + nnkTypeSection.newTree( + nnkTypeDef.newTree( + ident(name), + newEmptyNode(), + nnkObjectTy.newTree( + newEmptyNode(), + newEmptyNode(), + nnkRecList.newTree())))) + template foo(name: string): untyped = + thing(name) + expandMacros: + foo("Bob") + block: + expandMacros: + foo("Another") + +block: # issue #19670 + type + Past[Z] = object + OpenObject = object + + macro rewriter(prc: untyped): untyped = + prc.body.add(nnkCall.newTree( + prc.params[0] + )) + prc + + macro macroAsync(name, restype: untyped): untyped = + quote do: + proc `name`(): Past[seq[`restype`]] {.rewriter.} = discard + + macroAsync(testMacro, OpenObject) + +import asyncdispatch + +block: # issue #11838 long + type + R[P] = object + updates: seq[P] + D[T, P] = ref object + ps: seq[P] + t: T + proc newD[T, P](ps: seq[P], t: T): D[T, P] = + D[T, P](ps: ps, t: t) + proc loop[T, P](d: D[T, P]) = + var results = newSeq[Future[R[P]]](10) + let d = newD[string, int](@[1], "") + d.loop() + +block: # issue #11838 minimal + type R[T] = object + proc loop[T]() = + discard newSeq[R[R[T]]]() + loop[int]() diff --git a/tests/generics/tcalltype.nim b/tests/generics/tcalltype.nim new file mode 100644 index 000000000..cba691f77 --- /dev/null +++ b/tests/generics/tcalltype.nim @@ -0,0 +1,26 @@ +discard """ + joinable: false # breaks everything because of #23977 +""" + +# issue #23406 + +template helper(_: untyped): untyped = + int + +type # Each of them should always be `int`. + GenA[T] = helper int + GenB[T] = helper(int) + GenC[T] = helper helper(int) + +block: + template helper(_: untyped): untyped = + float + + type + A = GenA[int] + B = GenB[int] + C = GenC[int] + + assert A is int # OK. + assert B is int # Fails; it is `float`! + assert C is int # OK. diff --git a/tests/constraints/tconstraints.nim b/tests/generics/tconstraints.nim index 3ca01cfd5..3ca01cfd5 100644 --- a/tests/constraints/tconstraints.nim +++ b/tests/generics/tconstraints.nim diff --git a/tests/friends/tfriends.nim b/tests/generics/tfriends.nim index 1e70d50a5..1e70d50a5 100644 --- a/tests/friends/tfriends.nim +++ b/tests/generics/tfriends.nim diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim index 44c34917d..16a148f7b 100644 --- a/tests/generics/tgeneric0.nim +++ b/tests/generics/tgeneric0.nim @@ -9,7 +9,7 @@ float32 """ -import tables +import std/tables block tgeneric0: @@ -153,3 +153,44 @@ proc unzip*[T,U](xs: List[tuple[t: T, u: U]]): (List[T], List[U]) = discard proc unzip2*[T,U](xs: List[(T,U)]): (List[T], List[U]) = discard +type + AtomicType = pointer|ptr|int + + Atomic[T: AtomicType] = distinct T + + Block[T: AtomicType] = object + + AtomicContainer[T: AtomicType] = object + b: Atomic[ptr Block[T]] + +# bug #8295 +var x = AtomicContainer[int]() +doAssert (ptr Block[int])(x.b) == nil + + +# bug #23233 +type + JsonObjectType*[T: string or uint64] = Table[string, JsonValueRef[T]] + + JsonValueRef*[T: string or uint64] = object + objVal*: JsonObjectType[T] + +proc scanValue[K](val: var K) = + var map: JsonObjectType[K.T] + var newVal: K + map["one"] = newVal + +block: + var a: JsonValueRef[uint64] + scanValue(a) + + var b: JsonValueRef[string] + scanValue(b) + +block: # bug #21347 + type K[T] = object + template s[T]() = discard + proc b1(n: bool | bool) = s[K[K[int]]]() + proc b2(n: bool) = s[K[K[int]]]() + b1(false) # Error: 's' has unspecified generic parameters + b2(false) # Builds, on its own diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim index 78183c7ca..29a73afc6 100644 --- a/tests/generics/tgeneric3.nim +++ b/tests/generics/tgeneric3.nim @@ -1,9 +1,9 @@ discard """ output: ''' 312 -1000000 -1000000 -500000 +1000 +1000 +500 0 ''' """ @@ -243,7 +243,7 @@ proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], Akey: T, Avalue: D) = of cLenCenter: setLen(APath.Nd.slots, cLen4) of cLen4: setLen(APath.Nd.slots, cLenMax) else: discard - for i in countdown(APath.Nd.count.int - 1, x + 1): shallowCopy(APath.Nd.slots[i], APath.Nd.slots[i - 1]) + for i in countdown(APath.Nd.count.int - 1, x + 1): APath.Nd.slots[i] = move APath.Nd.slots[i - 1] APath.Nd.slots[x] = setItem(Akey, Avalue, ANode) @@ -255,31 +255,39 @@ proc SplitPage[T,D](n, left: PNode[T,D], xi: int, Akey:var T, Avalue:var D): PNo result.slots.newSeq(cLenCenter) result.count = cCenter if x == cCenter: - for i in 0..cCenter-1: shallowCopy(it1[i], left.slots[i]) - for i in 0..cCenter-1: shallowCopy(result.slots[i], left.slots[cCenter + i]) + for i in 0..cCenter-1: + it1[i] = move left.slots[i] + for i in 0..cCenter-1: + result.slots[i] = move left.slots[cCenter + i] result.left = n else : if x < cCenter : - for i in 0..x-1: shallowCopy(it1[i], left.slots[i]) + for i in 0..x-1: + it1[i] = move left.slots[i] it1[x] = setItem(Akey, Avalue, n) - for i in x+1 .. cCenter-1: shallowCopy(it1[i], left.slots[i-1]) + for i in x+1 .. cCenter-1: + it1[i] = move left.slots[i-1] var w = left.slots[cCenter-1] Akey = w.key Avalue = w.value result.left = w.node - for i in 0..cCenter-1: shallowCopy(result.slots[i], left.slots[cCenter + i]) + for i in 0..cCenter-1: + result.slots[i] = move left.slots[cCenter + i] else : - for i in 0..cCenter-1: shallowCopy(it1[i], left.slots[i]) + for i in 0..cCenter-1: + it1[i] = move left.slots[i] x = x - (cCenter + 1) - for i in 0..x-1: shallowCopy(result.slots[i], left.slots[cCenter + i + 1]) + for i in 0..x-1: + result.slots[i] = move left.slots[cCenter + i + 1] result.slots[x] = setItem(Akey, Avalue, n) - for i in x+1 .. cCenter-1: shallowCopy(result.slots[i], left.slots[cCenter + i]) + for i in x+1 .. cCenter-1: + result.slots[i] = move left.slots[cCenter + i] var w = left.slots[cCenter] Akey = w.key Avalue = w.value result.left = w.node left.count = cCenter - shallowCopy(left.slots, it1) + left.slots = move it1 proc internalPut[T,D](ANode: ref TNode[T,D], Akey: T, Avalue: D, Oldvalue: var D): ref TNode[T,D] = @@ -437,7 +445,7 @@ proc test() = var it1 = internalFind(root, 312) echo it1.value - for i in 1..1_000_000: + for i in 1..1_000: root = internalPut(root, i, i, oldvalue) var cnt = 0 diff --git a/tests/generics/tgeneric_recursionlimit.nim b/tests/generics/tgeneric_recursionlimit.nim new file mode 100644 index 000000000..5fe9b43c6 --- /dev/null +++ b/tests/generics/tgeneric_recursionlimit.nim @@ -0,0 +1,123 @@ +discard """ + action: "compile" +""" + +# https://github.com/nim-lang/Nim/issues/20348 + +type + Payload[T] = object + payload: T + Carrier[T] = object + val: T + +type + Payload0*[T] = object + payload: Payload[T] + Payload1*[T] = object + payload: Payload[T] + Payload2*[T] = object + payload: Payload[T] + Payload3*[T] = object + payload: Payload[T] + Payload4*[T] = object + payload: Payload[T] + Payload5*[T] = object + payload: Payload[T] + Payload6*[T] = object + payload: Payload[T] + Payload7*[T] = object + payload: Payload[T] + Payload8*[T] = object + payload: Payload[T] + Payload9*[T] = object + payload: Payload[T] + Payload10*[T] = object + payload: Payload[T] + Payload11*[T] = object + payload: Payload[T] + Payload12*[T] = object + payload: Payload[T] + Payload13*[T] = object + payload: Payload[T] + Payload14*[T] = object + payload: Payload[T] + Payload15*[T] = object + payload: Payload[T] + Payload16*[T] = object + payload: Payload[T] + Payload17*[T] = object + payload: Payload[T] + Payload18*[T] = object + payload: Payload[T] + Payload19*[T] = object + payload: Payload[T] + Payload20*[T] = object + payload: Payload[T] + Payload21*[T] = object + payload: Payload[T] + Payload22*[T] = object + payload: Payload[T] + Payload23*[T] = object + payload: Payload[T] + Payload24*[T] = object + payload: Payload[T] + Payload25*[T] = object + payload: Payload[T] + Payload26*[T] = object + payload: Payload[T] + Payload27*[T] = object + payload: Payload[T] + Payload28*[T] = object + payload: Payload[T] + Payload29*[T] = object + payload: Payload[T] + Payload30*[T] = object + payload: Payload[T] + Payload31*[T] = object + payload: Payload[T] + Payload32*[T] = object + payload: Payload[T] + Payload33*[T] = object + payload: Payload[T] + +type + Carriers*[T] = object + c0*: Carrier[Payload0[T]] + c1*: Carrier[Payload1[T]] + c2*: Carrier[Payload2[T]] + c3*: Carrier[Payload3[T]] + c4*: Carrier[Payload4[T]] + c5*: Carrier[Payload5[T]] + c6*: Carrier[Payload6[T]] + c7*: Carrier[Payload7[T]] + c8*: Carrier[Payload8[T]] + c9*: Carrier[Payload9[T]] + c10*: Carrier[Payload10[T]] + c11*: Carrier[Payload11[T]] + c12*: Carrier[Payload12[T]] + c13*: Carrier[Payload13[T]] + c14*: Carrier[Payload14[T]] + c15*: Carrier[Payload15[T]] + c16*: Carrier[Payload16[T]] + c17*: Carrier[Payload17[T]] + c18*: Carrier[Payload18[T]] + c19*: Carrier[Payload19[T]] + c20*: Carrier[Payload20[T]] + c21*: Carrier[Payload21[T]] + c22*: Carrier[Payload22[T]] + c23*: Carrier[Payload23[T]] + c24*: Carrier[Payload24[T]] + c25*: Carrier[Payload25[T]] + c26*: Carrier[Payload26[T]] + c27*: Carrier[Payload27[T]] + c28*: Carrier[Payload28[T]] + c29*: Carrier[Payload29[T]] + c30*: Carrier[Payload30[T]] + c31*: Carrier[Payload31[T]] + c32*: Carrier[Payload32[T]] + c33*: Carrier[Payload33[T]] + +var carriers : Carriers[int] + +static: + assert $(typeof(carriers.c33.val)) == "Payload33[system.int]" diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim index db7a16569..3068a22f2 100644 --- a/tests/generics/tgenerics_issues.nim +++ b/tests/generics/tgenerics_issues.nim @@ -872,3 +872,23 @@ block: # Ensure no segfault from constraint a = Regex[int]() b = Regex[bool]() c = MyOtherType[seq[int]]() + +block: # https://github.com/nim-lang/Nim/issues/20416 + type + Item[T] = object + link:ptr Item[T] + data:T + + KVSeq[A,B] = seq[(A,B)] + + MyTable[A,B] = object + data: KVSeq[A,B] + + Container[T] = object + a: MyTable[int,ref Item[T]] + + proc p1(sg:Container) = discard # Make sure that a non parameterized 'Container' argument still compiles + + proc p2[T](sg:Container[T]) = discard + var v : Container[int] + p2(v) diff --git a/tests/generics/tgenerics_various.nim b/tests/generics/tgenerics_various.nim index 6c76502e1..53661236e 100644 --- a/tests/generics/tgenerics_various.nim +++ b/tests/generics/tgenerics_various.nim @@ -127,42 +127,6 @@ block trefs: -block tsharedcases: - proc typeNameLen(x: typedesc): int {.compileTime.} = - result = x.name.len - macro selectType(a, b: typedesc): typedesc = - result = a - - type - Foo[T] = object - data1: array[T.high, int] - data2: array[typeNameLen(T), float] - data3: array[0..T.typeNameLen, selectType(float, int)] - MyEnum = enum A, B, C, D - - var f1: Foo[MyEnum] - var f2: Foo[int8] - - doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2 - doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5 - - doAssert high(f2.data1) == 126 # 127 - 1 == 126 - doAssert high(f2.data2) == 3 # int8.len - 1 == 3 - - static: - doAssert high(f1.data1) == ord(C) - doAssert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high - - doAssert high(f2.data1) == 126 - doAssert high(f2.data2) == 3 - - doAssert high(f1.data3) == 6 # length of MyEnum - doAssert high(f2.data3) == 4 # length of int8 - - doAssert f2.data3[0] is float - - - block tmap_auto: let x = map(@[1, 2, 3], x => x+10) doAssert x == @[11, 12, 13] @@ -253,3 +217,38 @@ block: var x: Que[int] doAssert(x.x == 0) + + +# bug #4466 +proc identity[T](t: T): T = t + +proc doSomething[A, B](t: tuple[a: A, b: B]) = discard + +discard identity((c: 1, d: 2)) +doSomething(identity((1, 2))) + +# bug #6231 +proc myProc[T, U](x: T or U) = discard + +myProc[int, string](x = 2) + +block: # issue #8390 + proc x[T:SomeFloat](q: openarray[T], y: T = 1): string = + doAssert $q.type == $openarray[y.type] + $y.type + + doAssert x(@[1.0]) == $1.0.type + + +block: # issue #9381 + var evalCount {.compileTime.} = 0 + + macro test(t: typed): untyped = + inc evalCount + t + + type GenericObj[T] = object + f: test(T) + + var x: GenericObj[int] + static: doAssert evalCount == 1 diff --git a/tests/generics/tgenericwhen.nim b/tests/generics/tgenericwhen.nim new file mode 100644 index 000000000..87672a699 --- /dev/null +++ b/tests/generics/tgenericwhen.nim @@ -0,0 +1,58 @@ +discard """ + targets: "c js" +""" + +block: # issue #24041 + type ArrayBuf[N: static int, T = byte] = object + when sizeof(int) > sizeof(uint8): + when N <= int(uint8.high): + n: uint8 + else: + when sizeof(int) > sizeof(uint16): + when N <= int(uint16.high): + n: uint16 + else: + when sizeof(int) > sizeof(uint32): + when N <= int(uint32.high): + n: uint32 + else: + n: int + else: + n: int + else: + n: int + else: + n: int + + var x: ArrayBuf[8] + doAssert x.n is uint8 + when sizeof(int) > sizeof(uint32): + var y: ArrayBuf[int(uint32.high) * 8] + doAssert y.n is int + +block: # constant condition after dynamic one + type Foo[T] = object + when T is int: + a: int + elif true: + a: string + else: + a: bool + var x: Foo[string] + doAssert x.a is string + var y: Foo[int] + doAssert y.a is int + var z: Foo[float] + doAssert z.a is string + +block: # issue #4774, but not with threads + const hasThreadSupport = not defined(js) + when hasThreadSupport: + type Channel[T] = object + value: T + type + SomeObj[T] = object + when hasThreadSupport: + channel: ptr Channel[T] + var x: SomeObj[int] + doAssert compiles(x.channel) == hasThreadSupport diff --git a/tests/generics/tgensyminst.nim b/tests/generics/tgensyminst.nim new file mode 100644 index 000000000..3f30188d8 --- /dev/null +++ b/tests/generics/tgensyminst.nim @@ -0,0 +1,29 @@ +# issue #24048 + +import macros + +proc map(fn: proc(val: int): void) = fn(1) + +# This works fine, and is the exact same function call as what's +# generated by the macro `aBug`. +map proc(val: auto): void = + let variable = 123 + +macro aBug() = + # 1. let sym = ident("variable") + let sym = genSym(nskLet, "variable") + let letStmt = newLetStmt(sym, newLit(123)) + + let lambda = newProc( + params = @[ + ident("void"), + newIdentDefs(ident("val"), ident("auto")), + # 2. newIdentDefs(ident("val"), ident("int")), + ], + body = newStmtList(letStmt), + procType = nnkLambda + ) + + result = newCall(bindSym("map"), lambda) + +aBug() diff --git a/tests/generics/timpl_ast.nim b/tests/generics/timpl_ast.nim new file mode 100644 index 000000000..97fe128cd --- /dev/null +++ b/tests/generics/timpl_ast.nim @@ -0,0 +1,80 @@ +import std/macros +import std/assertions + +block: # issue #16639 + type Foo[T] = object + when true: + x: float + + type Bar = object + when true: + x: float + + macro test() = + let a = getImpl(bindSym"Foo")[^1] + let b = getImpl(bindSym"Bar")[^1] + doAssert treeRepr(a) == treeRepr(b) + + test() + +import strutils + +block: # issues #9899, ##14708 + macro implRepr(a: typed): string = + result = newLit(repr(a.getImpl)) + + type + Option[T] = object + when false: discard # issue #14708 + when false: x: int + when T is (ref | ptr): + val: T + else: + val: T + has: bool + + static: # check information is retained + let r = implRepr(Option) + doAssert "when T is" in r + doAssert r.count("val: T") == 2 + doAssert "has: bool" in r + + block: # try to compile the output + macro parse(s: static string) = + result = parseStmt(s) + parse("type " & implRepr(Option)) + +block: # issue #22639 + type + Spectrum[N: static int] = object + data: array[N, float] + AngleInterpolator = object + data: seq[Spectrum[60]] + proc initInterpolator(num: int): AngleInterpolator = + result = AngleInterpolator() + for i in 0 ..< num: + result.data.add Spectrum[60]() + macro genCompatibleTuple(t: typed): untyped = + let typ = t.getType[1].getTypeImpl[2] + result = nnkTupleTy.newTree() + for i, ch in typ: # is `nnkObjectTy` + result.add nnkIdentDefs.newTree(ident(ch[0].strVal), # ch is `nnkIdentDefs` + ch[1], + newEmptyNode()) + proc fullSize[T: object | tuple](x: T): int = + var tmp: genCompatibleTuple(T) + result = 0 + for field, val in fieldPairs(x): + result += sizeof(val) + doAssert result == sizeof(tmp) + + let reflectivity = initInterpolator(1) + for el in reflectivity.data: + doAssert fullSize(el) == sizeof(el) + doAssert fullSize(reflectivity.data[0]) == sizeof(reflectivity.data[0]) + doAssert genCompatibleTuple(Spectrum[60]) is tuple[data: array[60, float]] + doAssert genCompatibleTuple(Spectrum[120]) is tuple[data: array[120, float]] + type Foo[T] = object + data: T + doAssert genCompatibleTuple(Foo[int]) is tuple[data: int] + doAssert genCompatibleTuple(Foo[float]) is tuple[data: float] diff --git a/tests/generics/timplicit_and_explicit.nim b/tests/generics/timplicit_and_explicit.nim index ba24b79e9..7220b7429 100644 --- a/tests/generics/timplicit_and_explicit.nim +++ b/tests/generics/timplicit_and_explicit.nim @@ -3,8 +3,8 @@ block: # basic test proc doStuff[T](a: SomeInteger): T = discard proc doStuff[T;Y](a: SomeInteger, b: Y): Y = discard assert typeof(doStuff[int](100)) is int - assert typeof(doStuff[int](100, 1.0)) is float - assert typeof(doStuff[int](100, "Hello")) is string + assert typeof(doStuff[int, float](100, 1.0)) is float + assert typeof(doStuff[int, string](100, "Hello")) is string proc t[T](x: T; z: int | float): seq[T] = result.add(x & $z) @@ -34,7 +34,8 @@ block: #15622 proc test1[T](a: T, b: static[string] = "") = discard test1[int64](123) proc test2[T](a: T, b: static[string] = "") = discard - test2[int64, static[string]](123) + doAssert not (compiles do: + test2[int64, static[string]](123)) block: #4688 proc convertTo[T](v: int or float): T = (T)(v) @@ -42,4 +43,23 @@ block: #4688 block: #4164 proc printStr[T](s: static[string]): T = discard - discard printStr[int]("hello static") \ No newline at end of file + discard printStr[int]("hello static") + +import macros + +block: # issue #9040, statics with template, macro, symchoice explicit generics + block: # macro + macro fun[N: static int](): untyped = + newLit 1 + const a = fun[2]() + doAssert a == 1 + block: # template + template fun[N: static int](): untyped = + 1 + const a = fun[2]() + doAssert a == 1 + block: # symchoice + proc newSeq[x: static int](): int = 1 + template foo: int = + newSeq[2]() + doAssert foo() == 1 diff --git a/tests/generics/timports.nim b/tests/generics/timports.nim index 800ae7f88..e252ad194 100644 --- a/tests/generics/timports.nim +++ b/tests/generics/timports.nim @@ -7,7 +7,7 @@ false ''' """ -import mbind_bracket, mclosed_sym, mdotlookup, mmodule_same_as_proc +import mbind_bracket, mclosed_sym, mdotlookup, mmodule_same_as_proc, mtypenodes block tbind_bracket: @@ -31,15 +31,33 @@ block tclosed_sym: proc same(r:R, d:int) = echo "TEST1" doIt(Data[int](d:123), R()) +import strutils, unicode # ambiguous `strip` block tdotlookup: foo(7) # bug #1444 fn(4) - + doAssert doStrip(123) == "123" + # bug #14254 + doAssert baz2[float](1'i8) == 1 + # bug #21883 + proc abc[T: not not int](x: T): T = + var x = x + x.set("hello", "world") + result = x + doAssert abc(5) == 10 + block: # ensure normal call is consistent with dot call + proc T(x: int): float = x.float + proc foo[T](x: int) = + doAssert typeof(T(x)) is typeof(x.T) + foo[uint](123) block tmodule_same_as_proc: # bug #1965 proc test[T](t: T) = mmodule_same_as_proc"a" test(0) + +block ttypenodes: + # issue #22699 + doAssert chop[bool](42) == 42 diff --git a/tests/generics/tmacroinjectedsym.nim b/tests/generics/tmacroinjectedsym.nim new file mode 100644 index 000000000..985e415f2 --- /dev/null +++ b/tests/generics/tmacroinjectedsym.nim @@ -0,0 +1,186 @@ +{.experimental: "openSym".} + +block: # issue #22605, normal call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + proc g(T: type): string = + let x = valueOr 123: + return $error + + "ok" + + doAssert g(int) == "good" + + proc g2(T: type): string = + bind error # use the bad version on purpose + let x = valueOr 123: + return $error + + "ok" + + doAssert g2(int) == "bad" + +block: # issue #22605, method call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + proc g(T: type): string = + let x = 123.valueOr: + return $error + + "ok" + + doAssert g(int) == "good" + + proc g2(T: type): string = + bind error # use the bad version on purpose + let x = 123.valueOr: + return $error + + "ok" + + doAssert g2(int) == "bad" + +block: # issue #22605, original complex example + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + + proc g(T: type): string = + let x = f().valueOr: + return $error + + "ok" + + doAssert g(int) == "f" + + proc g2(T: type): string = + bind error # use the bad version on purpose + let x = f().valueOr: + return $error + + "ok" + + doAssert g2(int) == "error" + +block: # issue #23865 + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + func error[T, E](self: Result[T, E]): E = + ## Fetch error of result if set, or raise Defect + case self.oResultPrivate + of true: + when T isnot void: + raiseResultDefect("Trying to access error when value is set", self.vResultPrivate) + else: + raiseResultDefect("Trying to access error when value is set") + of false: + when E isnot void: + self.eResultPrivate + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + proc g(T: type): string = + let x = f().valueOr: + return $error + "ok" + doAssert g(int) == "f" + +import sequtils + +block: # issue #12283 + var b = 5 + type Foo[T] = object + h, w: int + proc bar[T](foos: seq[Foo[T]]): T = + let w = foldl(foos, a + b.w, 0) + w + let foos = @[Foo[int](h: 3, w: 5), Foo[int](h: 4, w: 6)] + doAssert bar(foos) == 11 diff --git a/tests/generics/tmacroinjectedsymwarning.nim b/tests/generics/tmacroinjectedsymwarning.nim new file mode 100644 index 000000000..77119004b --- /dev/null +++ b/tests/generics/tmacroinjectedsymwarning.nim @@ -0,0 +1,59 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj" +""" + +type Xxx = enum + error + value + +type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + +template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + +proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + +proc g(T: type): string = + let x = f().valueOr: + {.push warningAsError[IgnoredSymbolInjection]: on.} + # test spurious error + discard true + let _ = f + {.pop.} + return $error #[tt.Warning + ^ a new symbol 'error' has been injected during template or generic instantiation, however 'error' [enumField declared in tmacroinjectedsymwarning.nim(6, 3)] captured at the proc declaration will be used instead; either enable --experimental:openSym to use the injected symbol, or `bind` this captured symbol explicitly [IgnoredSymbolInjection]]# + + "ok" + +discard g(int) diff --git a/tests/generics/tnestedissues.nim b/tests/generics/tnestedissues.nim new file mode 100644 index 000000000..e96a1927e --- /dev/null +++ b/tests/generics/tnestedissues.nim @@ -0,0 +1,24 @@ +block: # issue #23568 + type G[T] = object + j: T + proc s[T](u: int) = discard + proc s[T]() = discard + proc c(e: int | int): G[G[G[int]]] = s[G[G[int]]]() + discard c(0) + +import std/options + +block: # issue #23310 + type + BID = string or uint64 + Future[T] = ref object of RootObj + internalValue: T + InternalRaisesFuture[T] = ref object of Future[T] + proc newInternalRaisesFutureImpl[T](): InternalRaisesFuture[T] = + let fut = InternalRaisesFuture[T]() + template newFuture[T](): auto = + newInternalRaisesFutureImpl[T]() + proc problematic(blockId: BID): Future[Option[seq[int]]] = + let resultFuture = newFuture[Option[seq[int]]]() + return resultFuture + let x = problematic("latest") diff --git a/tests/generics/tnestedtemplate.nim b/tests/generics/tnestedtemplate.nim new file mode 100644 index 000000000..22d0a2d3c --- /dev/null +++ b/tests/generics/tnestedtemplate.nim @@ -0,0 +1,9 @@ +block: # issue #13979 + var s: seq[int] + proc filterScanline[T](input: openArray[T]) = + template currPix: untyped = input[i] + for i in 0..<input.len: + s.add currPix + let pix = [1, 2, 3] + filterScanline(pix) + doAssert s == @[1, 2, 3] diff --git a/tests/generics/tobjecttyperel.nim b/tests/generics/tobjecttyperel.nim index 80fe23459..6f223c154 100644 --- a/tests/generics/tobjecttyperel.nim +++ b/tests/generics/tobjecttyperel.nim @@ -1,4 +1,5 @@ discard """ + matrix: "-d:nimInternalNonVtablesTesting" output: '''(peel: 0, color: 15) (color: 15) 17 diff --git a/tests/generics/topensymimport.nim b/tests/generics/topensymimport.nim new file mode 100644 index 000000000..a47496827 --- /dev/null +++ b/tests/generics/topensymimport.nim @@ -0,0 +1,5 @@ +# issue #23386 + +import mopensymimport2 + +doAssert g(int) == "f" diff --git a/tests/generics/toverloading_typedesc.nim b/tests/generics/toverloading_typedesc.nim index 5ab700828..4d748bfee 100644 --- a/tests/generics/toverloading_typedesc.nim +++ b/tests/generics/toverloading_typedesc.nim @@ -1,7 +1,3 @@ -discard """ - exitcode: 0 - disabled: '''true''' -""" import moverloading_typedesc import tables @@ -9,7 +5,6 @@ type LFoo = object LBar = object - when true: doAssert FBar.new() == 3 diff --git a/tests/generics/tparam_binding.nim b/tests/generics/tparam_binding.nim index cd0d58e02..fa7558613 100644 --- a/tests/generics/tparam_binding.nim +++ b/tests/generics/tparam_binding.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:arc; --mm:refc" errormsg: "got <ref Matrix[2, 2, system.float], ref Matrix[2, 1, system.float]>" - line: 27 + line: 28 """ type diff --git a/tests/generics/tprevent_double_bind.nim b/tests/generics/tprevent_double_bind.nim index 86e080ab6..d8fc6e5d3 100644 --- a/tests/generics/tprevent_double_bind.nim +++ b/tests/generics/tprevent_double_bind.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got <TT[seq[string]], proc (v: int){.gcsafe, locks: 0.}>" + errormsg: "type mismatch: got <TT[seq[string]], proc (v: int){.gcsafe.}>" line: 20 """ diff --git a/tests/generics/treentranttypes.nim b/tests/generics/treentranttypes.nim index 40ff1647b..801f0e444 100644 --- a/tests/generics/treentranttypes.nim +++ b/tests/generics/treentranttypes.nim @@ -101,3 +101,14 @@ echo @(b.arr[0].arr), @(b.arr[1].arr) let y = b echo @(y.arr[0].arr), @(y.arr[1].arr) +import macros + +block: # issue #5121 + type + A = object + AConst[X] = A + + macro dumpType(t: typedesc): untyped = + result = newTree(nnkTupleConstr, newLit $t.getType[1].typeKind, newLit t.getType[1].treeRepr) + + doAssert dumpType(A) == ("ntyObject", "Sym \"A\"") diff --git a/tests/generics/treturn_inference.nim b/tests/generics/treturn_inference.nim new file mode 100644 index 000000000..331a9d4db --- /dev/null +++ b/tests/generics/treturn_inference.nim @@ -0,0 +1,184 @@ + +{.experimental: "inferGenericTypes".} + +import std/tables + +block: + type + MyOption[T, Z] = object + x: T + y: Z + + proc none[T, Z](): MyOption[T, Z] = + when T is int: + result.x = 22 + when Z is float: + result.y = 12.0 + + proc myGenericProc[T, Z](): MyOption[T, Z] = + none() # implied by return type + + let a = myGenericProc[int, float]() + doAssert a.x == 22 + doAssert a.y == 12.0 + + let b: MyOption[int, float] = none() # implied by type of b + doAssert b.x == 22 + doAssert b.y == 12.0 + +# Simple template based result with inferred type for errors +block: + type + ResultKind {.pure.} = enum + Ok + Err + + Result[T] = object + case kind: ResultKind + of Ok: + data: T + of Err: + errmsg: cstring + + template err[T](msg: static cstring): Result[T] = + Result[T](kind : ResultKind.Err, errmsg : msg) + + proc testproc(): Result[int] = + err("Inferred error!") # implied by proc return + let r = testproc() + doAssert r.kind == ResultKind.Err + doAssert r.errmsg == "Inferred error!" + +# Builtin seq +block: + let x: seq[int] = newSeq(1) + doAssert x is seq[int] + doAssert x.len() == 1 + + type + MyType[T, Z] = object + x: T + y: Z + + let y: seq[MyType[int, float]] = newSeq(2) + doAssert y is seq[MyType[int, float]] + doAssert y.len() == 2 + + let z = MyType[seq[float], string]( + x : newSeq(3), + y : "test" + ) + doAssert z.x is seq[float] + doAssert z.x.len() == 3 + doAssert z.y is string + doAssert z.y == "test" + +# array +block: + proc giveArray[N, T](): array[N, T] = + for i in 0 .. N.high: + result[i] = i + var x: array[2, int] = giveArray() + doAssert x == [0, 1] + +# tuples +block: + proc giveTuple[T, Z]: (T, Z, T) = discard + let x: (int, float, int) = giveTuple() + doAssert x is (int, float, int) + doAssert x == (0, 0.0, 0) + + proc giveNamedTuple[T, Z]: tuple[a: T, b: Z] = discard + let y: tuple[a: int, b: float] = giveNamedTuple() + doAssert y is (int, float) + doAssert y is tuple[a: int, b: float] + doAssert y == (0, 0.0) + + proc giveNestedTuple[T, Z]: ((T, Z), Z) = discard + let z: ((int, float), float) = giveNestedTuple() + doAssert z is ((int, float), float) + doAssert z == ((0, 0.0), 0.0) + + # nesting inside a generic type + type MyType[T] = object + x: T + let a = MyType[(int, MyType[float])](x : giveNamedTuple()) + doAssert a.x is (int, MyType[float]) + + +# basic constructors +block: + type MyType[T] = object + x: T + + proc giveValue[T](): T = + when T is int: + 12 + else: + default(T) + + let x = MyType[int](x : giveValue()) + doAssert x.x is int + doAssert x.x == 12 + + let y = MyType[MyType[float]](x : MyType[float](x : giveValue())) + doAssert y.x is MyType[float] + doAssert y.x.x is float + doAssert y.x.x == 0.0 + + # 'MyType[float]' is bound to 'T' directly + # instead of mapping 'T' to 'float' + let z = MyType[MyType[float]](x : giveValue()) + doAssert z.x is MyType[float] + doAssert z.x.x == 0.0 + + type Foo = object + x: Table[int, float] + + let a = Foo(x: initTable()) + doAssert a.x is Table[int, float] + +# partial binding +block: + type + ResultKind = enum + Ok, Error + + Result[T, E] = object + case kind: ResultKind + of Ok: + okVal: T + of Error: + errVal: E + + proc err[T, E](myParam: E): Result[T, E] = + Result[T, E](kind : Error, errVal : myParam) + + proc doStuff(): Result[int, string] = + err("Error") + + let res = doStuff() + doAssert res.kind == Error + doAssert res.errVal == "Error" + +# ufcs +block: + proc getValue[T](_: string): T = + doAssert T is int + 44 + + proc `'test`[T](_: string): T = + 55 + + let a: int = getValue("") + let b: int = "".getValue() + let c: int = "".getValue + let d: int = getValue "" + let e: int = getValue"" + let f: int = 12345'test + doAssert a == 44 + doAssert b == 44 + doAssert c == 44 + doAssert d == 44 + doAssert e == 44 + doAssert f == 55 diff --git a/tests/generics/tstatic_constrained.nim b/tests/generics/tstatic_constrained.nim index 3c9201548..d356b9d1c 100644 --- a/tests/generics/tstatic_constrained.nim +++ b/tests/generics/tstatic_constrained.nim @@ -8,7 +8,7 @@ but expected: <T: float or string, Y> tstatic_constrained.nim(44, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)] got: <typedesc[int], int literal(10)> but expected: <T: float or string, Y> -tstatic_constrained.nim(44, 31) Error: object constructor needs an object type [proxy] +tstatic_constrained.nim(44, 31) Error: object constructor needs an object type [error] tstatic_constrained.nim(44, 31) Error: expression '' has no type (or is ambiguous) tstatic_constrained.nim(45, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)] got: <typedesc[byte], uint8> @@ -16,7 +16,7 @@ but expected: <T: float or string, Y> tstatic_constrained.nim(45, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)] got: <typedesc[byte], uint8> but expected: <T: float or string, Y> -tstatic_constrained.nim(45, 34) Error: object constructor needs an object type [proxy] +tstatic_constrained.nim(45, 34) Error: object constructor needs an object type [error] tstatic_constrained.nim(45, 34) Error: expression '' has no type (or is ambiguous) tstatic_constrained.nim(77, 14) Error: cannot instantiate MyType [type declared in tstatic_constrained.nim(71, 5)] got: <typedesc[float], float64> @@ -76,4 +76,4 @@ block: b: MyType[string, "hello"] c: MyType[float, 10d] d: MyOtherType[MyOtherConstraint[float],MyOtherConstraint[float]()] - e: MyOtherType[MyOtherConstraint[int], MyOtherConstraint[int]()] \ No newline at end of file + e: MyOtherType[MyOtherConstraint[int], MyOtherConstraint[int]()] diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim index 2af5a7615..300da56a6 100644 --- a/tests/generics/tthread_generic.nim +++ b/tests/generics/tthread_generic.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim $target --hints:on --threads:on $options $file" + matrix: "--mm:refc; --mm:orc" action: compile """ diff --git a/tests/generics/tuninstantiated_failure.nim b/tests/generics/tuninstantiated_failure.nim new file mode 100644 index 000000000..f3d5b34b8 --- /dev/null +++ b/tests/generics/tuninstantiated_failure.nim @@ -0,0 +1,16 @@ +discard """ +cmd: "nim check $file" +""" + +type + Test[T, K] = object + name: string + Something = Test[int] + +func `[]`[T, K](x: var Test[T, K], idx: int): var Test[T, K] = + x + +var b: Something +# Should give an error since Something isn't a valid Test +b[0].name = "Test" #[tt.Error + ^ expression '' has no type (or is ambiguous)]# diff --git a/tests/generics/tuninstantiatedgenericcalls.nim b/tests/generics/tuninstantiatedgenericcalls.nim new file mode 100644 index 000000000..f33fc8967 --- /dev/null +++ b/tests/generics/tuninstantiatedgenericcalls.nim @@ -0,0 +1,517 @@ +# Cases that used to only work due to weird workarounds in the compiler +# involving not instantiating calls in generic bodies which are removed +# due to breaking statics. +# The issue was that these calls are compiled as regular expressions at +# the generic declaration with unresolved generic parameter types, +# which are special cased in some places in the compiler, but sometimes +# treated like real types. + +block: + type Base10 = object + + func maxLen(T: typedesc[Base10], I: type): int8 = + when I is uint8: + 3 + elif I is uint16: + 5 + elif I is uint32: + 10 + elif I is uint64: + 20 + else: + when sizeof(uint) == 4: + 10 + else: + 20 + + type + Base10Buf[T: SomeUnsignedInt] = object + data: array[maxLen(Base10, T), byte] + len: int8 + + var x: Base10Buf[uint32] + doAssert x.data.len == 10 + var y: Base10Buf[uint16] + doAssert y.data.len == 5 + +import typetraits + +block thardcases: + proc typeNameLen(x: typedesc): int {.compileTime.} = + result = x.name.len + macro selectType(a, b: typedesc): typedesc = + result = a + + type + Foo[T] = object + data1: array[T.high, int] + data2: array[typeNameLen(T), float] + data3: array[0..T.typeNameLen, selectType(float, int)] + + type MyEnum = enum A, B, C, D + + var f1: Foo[MyEnum] + var f2: Foo[int8] + + doAssert high(f1.data1) == 2 # (D = 3) - 1 == 2 + doAssert high(f1.data2) == 5 # (MyEnum.len = 6) - 1 == 5 + + doAssert high(f2.data1) == 126 # 127 - 1 == 126 + doAssert high(f2.data2) == 3 # int8.len - 1 == 3 + + static: + doAssert high(f1.data1) == ord(C) + doAssert high(f1.data2) == 5 # length of MyEnum minus one, because we used T.high + + doAssert high(f2.data1) == 126 + doAssert high(f2.data2) == 3 + + doAssert high(f1.data3) == 6 # length of MyEnum + doAssert high(f2.data3) == 4 # length of int8 + + doAssert f2.data3[0] is float + +import muninstantiatedgenericcalls + +block: + var x: Leb128Buf[uint32] + doAssert x.data.len == 5 + var y: Leb128Buf[uint16] + doAssert y.data.len == 3 + +import macros + +block: # issue #12415 + macro isSomePointerImpl(t: typedesc): bool = + var impl = t.getTypeInst[1].getTypeImpl + if impl.kind == nnkDistinctTy: + impl = impl[0].getTypeImpl + if impl.kind in {nnkPtrTy,nnkRefTy}: + result = newLit(true) + elif impl.kind == nnkSym and impl.eqIdent("pointer"): + result = newLit(true) + else: + result = newLit(false) + + proc isSomePointer[T](t: typedesc[T]): bool {.compileTime.} = + isSomePointerImpl(t) + + type + Option[T] = object + ## An optional type that stores its value and state separately in a boolean. + when isSomePointer(typedesc(T)): + val: T + else: + val: T + has: bool + var x: Option[ref int] + doAssert not compiles(x.has) + var y: Option[int] + doAssert compiles(y.has) + +block: # issue #2002 + proc isNillable(T: typedesc): bool = + when compiles((let v: T = nil)): + return true + else: + return false + + type + Foo[T] = object + when isNillable(T): + nillable: float + else: + notnillable: int + + var val1: Foo[ref int] + doAssert compiles(val1.nillable) + doAssert not compiles(val1.notnillable) + var val2: Foo[int] + doAssert not compiles(val2.nillable) + doAssert compiles(val2.notnillable) + +block: # issue #1771 + type + Foo[X, T] = object + bar: array[X.low..X.high, T] + + proc test[X, T](f: Foo[X, T]): T = + f.bar[X.low] + + var a: Foo[range[0..2], float] + doAssert test(a) == 0.0 + +block: # issue #23730 + proc test(M: static[int]): array[1 shl M, int] = discard + doAssert len(test(3)) == 8 + doAssert len(test(5)) == 32 + +block: # issue #19819 + type + Example[N: static int] = distinct int + What[E: Example] = Example[E.N + E.N] + +block: # issue #23339 + type + A = object + B = object + template aToB(t: typedesc[A]): typedesc = B + type + Inner[I] = object + innerField: I + Outer[O] = object + outerField: Inner[O.aToB] + var x: Outer[A] + doAssert typeof(x.outerField.innerField) is B + +block: # deref syntax + type + Enqueueable = concept x + x is ptr + Foo[T: Enqueueable] = object + x: typeof(default(T)[]) + + proc p[T](f: Foo[T]) = + var bar: Foo[T] + discard + var foo: Foo[ptr int] + p(foo) + doAssert foo.x is int + foo.x = 123 + doAssert foo.x == 123 + inc foo.x + doAssert foo.x == 124 + +block: + type Generic[T] = object + field: T + macro foo(x: typed): untyped = x + macro bar[T](x: typedesc[Generic[T]]): untyped = x + type + Foo[T] = object + field: Generic[int].foo() + Foo2[T] = object + field: Generic[T].foo() + Bar[T] = object + field: Generic[int].bar() + Bar2[T] = object + field: Generic[T].bar() + var x: Foo[int] + var x2: Foo2[int] + var y: Bar[int] + var y2: Bar2[int] + +block: + macro pick(x: static int): untyped = + if x < 100: + result = bindSym"int" + else: + result = bindSym"float" + + type Foo[T: static int] = object + fixed1: pick(25) + fixed2: pick(125) + unknown: pick(T) + + var a: Foo[123] + doAssert a.fixed1 is int + doAssert a.fixed2 is float + doAssert a.unknown is float + var b: Foo[23] + doAssert b.fixed1 is int + doAssert b.fixed2 is float + doAssert b.unknown is int + +import std/sequtils + +block: # version of #23432 with `typed`, don't delay instantiation + type + Future[T] = object + InternalRaisesFuture[T, E] = object + macro Raising[T](F: typedesc[Future[T]], E: varargs[typed]): untyped = + let raises = nnkTupleConstr.newTree(E.mapIt(it)) + nnkBracketExpr.newTree( + ident "InternalRaisesFuture", + nnkDotExpr.newTree(F, ident"T"), + raises + ) + type X[E] = Future[void].Raising(E) + proc f(x: X) = discard + var v: Future[void].Raising([ValueError]) + f(v) + +block: # issue #22647 + proc c0(n: static int): int = 8 + proc c1(n: static int): int = n div 2 + proc c2(n: static int): int = n * 2 + proc c3(n: static int, n2: int): int = n * n2 + proc `**`(n: static int, n2: int): int = n * n2 + proc c4(n: int, n2: int): int = n * n2 + + type + a[N: static int] = object + f0 : array[N, int] + + b[N: static int] = object + f0 : a[c0(N)] # does not work + f1 : a[c1(N)] # does not work + f2 : a[c2(N)] # does not work + f3 : a[N * 2] # does not work + f4 : a[N] # works + f5: a[c3(N, 2)] + f6: a[N ** 2] + f7: a[2 * N] + f8: a[c4(N, 2)] + + proc p[N: static int](x : a[N]) = discard x.f0[0] + template check(x, s: untyped) = + p(x) + doAssert x is a[s] + doAssert x.N == s + doAssert typeof(x).N == s + doAssert x.f0 == default(array[s, int]) + doAssert x.f0.len == s + proc p2[N: static int](y : a[N]) {.gensym.} = + doAssert y is a[s] + doAssert y.N == s + doAssert typeof(y).N == s + doAssert y.f0 == default(array[s, int]) + doAssert y.f0.len == s + p2(x) + proc p3(z: typeof(x)) {.gensym.} = discard + p3(default(a[s])) + proc p[N: static int](x : b[N]) = + x.f0.check(8) + x.f1.check(2) + x.f2.check(8) + x.f3.check(8) + x.f4.check(4) + x.f5.check(8) + x.f6.check(8) + x.f7.check(8) + x.f8.check(8) + + var x: b[4] + x.p() + +block: # issue #1969 + type ZeroGenerator = object + proc next(g: ZeroGenerator): int = 0 + # This compiles. + type TripleOfInts = tuple + a, b, c: typeof(new(ZeroGenerator)[].next) + # This raises a compiler error before it's even instantiated. + # The `new` proc can't be resolved because `Generator` is not defined. + type TripleLike[Generator] = tuple + a, b, c: typeof(new(Generator)[].next) + +import std/atomics + +block: # issue #12720 + const CacheLineSize = 128 + type + Enqueueable = concept x, type T + x is ptr + x.next is Atomic[pointer] + MyChannel[T: Enqueueable] = object + pad: array[CacheLineSize - sizeof(default(T)[]), byte] + dummy: typeof(default(T)[]) + +block: # issue #12714 + type + Enqueueable = concept x, type T + x is ptr + x.next is Atomic[pointer] + MyChannel[T: Enqueueable] = object + dummy: type(default(T)[]) + +block: # issue #24044 + type ArrayBuf[N: static int, T = byte] = object + buf: array[N, T] + template maxLen(T: type): int = + sizeof(T) * 2 + type MyBuf[I] = ArrayBuf[maxLen(I)] + var v: MyBuf[int] + +block: # issue #15959 + proc my[T](a: T): typeof(a[0]) = discard + proc my2[T](a: T): array[sizeof(a[0]), T] = discard + proc byLent2[T](a: T): lent type(a[0]) = a[0] # Error: type mismatch: got <T, int literal(0)> + proc byLent3[T](a: T): lent typeof(a[0]) = a[0] # ditto + proc byLent4[T](a: T): lent[type(a[0])] = a[0] # Error: no generic parameters allowed for lent + var x = @[1, 2, 3] + doAssert my(x) is int + doAssert my2(x) is array[sizeof(int), seq[int]] + doAssert byLent2(x) == 1 + doAssert byLent2(x) is lent int + doAssert byLent3(x) == 1 + doAssert byLent3(x) is lent int + doAssert byLent4(x) == 1 + doAssert byLent4(x) is lent int + proc fn[U](a: U): auto = a + proc my3[T](a: T, b: typeof(fn(a))) = discard + my3(x, x) + doAssert not compiles(my3(x, x[0])) + +block: # issue #22342, type section version of #22607 + type GenAlias[isInt: static bool] = ( + when isInt: + int + else: + float + ) + doAssert GenAlias[true] is int + doAssert GenAlias[false] is float + proc foo(T: static bool): GenAlias[T] = discard + doAssert foo(true) is int + doAssert foo(false) is float + proc foo[T: static bool](v: var GenAlias[T]) = + v += 1 + var x: int + foo[true](x) + doAssert not compiles(foo[false](x)) + foo[true](x) + doAssert x == 2 + var y: float + foo[false](y) + doAssert not compiles(foo[true](y)) + foo[false](y) + doAssert y == 2 + +block: # `when`, test no constant semchecks + type Foo[T] = ( + when false: + {.error: "bad".} + elif defined(neverDefined): + {.error: "bad 2".} + else: + T + ) + var x: Foo[int] + type Bar[T] = ( + when true: + T + elif defined(js): + {.error: "bad".} + else: + {.error: "bad 2".} + ) + var y: Bar[int] + +block: # weird regression + type + Foo[T] = distinct int + Bar[T, U] = distinct int + proc foo[T, U](x: static Foo[T], y: static Bar[T, U]): Foo[T] = + # signature gives: + # Error: cannot instantiate Bar + # got: <typedesc[T], U> + # but expected: <T, U> + x + doAssert foo(Foo[int](1), Bar[int, int](2)).int == 1 + +block: # issue #24090 + type M[V] = object + template y[V](N: type M, v: V): M[V] = default(M[V]) + proc d(x: int | int, f: M[int] = M.y(0)) = discard + d(0, M.y(0)) + type Foo[T] = object + x: typeof(M.y(default(T))) + var a: Foo[int] + doAssert a.x is M[int] + var b: Foo[float] + doAssert b.x is M[float] + doAssert not (compiles do: + type Bar[T] = object + x: typeof(M()) # actually fails here immediately + var bar: Bar[int]) + doAssert not (compiles do: + type Bar[T] = object + x: typeof(default(M)) + var bar: Bar[int] + # gives "undeclared identifier x" because of #24091, + # normally it should fail in the line above + echo bar.x) + proc foo[T: M](x: T = default(T)) = discard x + foo[M[int]]() + doAssert not compiles(foo()) + +block: # above but encountered by sigmatch using replaceTypeVarsN + type Opt[T] = object + x: T + proc none[T](x: type Opt, y: typedesc[T]): Opt[T] = discard + proc foo[T](x: T, a = Opt.none(int)) = discard + foo(1, a = Opt.none(int)) + foo(1) + +block: # real version of above + type Opt[T] = object + x: T + template none(x: type Opt, T: type): Opt[T] = Opt[T]() + proc foo[T](x: T, a = Opt.none(int)) = discard + foo(1, a = Opt.none(int)) + foo(1) + +block: # issue #20880 + type + Child[n: static int] = object + data: array[n, int] + Parent[n: static int] = object + child: Child[3*n] + const n = 3 + doAssert $(typeof Parent[n*3]()) == "Parent[9]" + doAssert $(typeof Parent[1]().child) == "Child[3]" + doAssert Parent[1]().child.data.len == 3 + +{.experimental: "dynamicBindSym".} +block: # issue #16774 + type SecretWord = distinct uint64 + const WordBitWidth = 8 * sizeof(uint64) + func wordsRequired(bits: int): int {.compileTime.} = + ## Compute the number of limbs required + # from the **announced** bit length + (bits + WordBitWidth - 1) div WordBitWidth + type + Curve = enum BLS12_381 + BigInt[bits: static int] = object + limbs: array[bits.wordsRequired, SecretWord] + const BLS12_381_Modulus = default(BigInt[381]) + macro Mod(C: static Curve): untyped = + ## Get the Modulus associated to a curve + result = bindSym($C & "_Modulus") + macro getCurveBitwidth(C: static Curve): untyped = + result = nnkDotExpr.newTree( + getAST(Mod(C)), + ident"bits" + ) + type Fp[C: static Curve] = object + ## Finite Fields / Modular arithmetic + ## modulo the curve modulus + mres: BigInt[getCurveBitwidth(C)] + var x: Fp[BLS12_381] + doAssert x.mres.limbs.len == wordsRequired(getCurveBitWidth(BLS12_381)) + # minimized, as if we haven't tested it already: + macro makeIntLit(c: static int): untyped = + result = newLit(c) + type Test[T: static int] = object + myArray: array[makeIntLit(T), int] + var y: Test[2] + doAssert y.myArray.len == 2 + var z: Test[4] + doAssert z.myArray.len == 4 + +block: # issue #16175 + type + Thing[D: static uint] = object + when D == 0: + kid: char + else: + kid: Thing[D-1] + var t2 = Thing[3]() + doAssert t2.kid is Thing[2.uint] + doAssert t2.kid.kid is Thing[1.uint] + doAssert t2.kid.kid.kid is Thing[0.uint] + doAssert t2.kid.kid.kid.kid is char + var s = Thing[1]() + doAssert s.kid is Thing[0.uint] + doAssert s.kid.kid is char diff --git a/tests/generics/twrong_explicit_typeargs.nim b/tests/generics/twrong_explicit_typeargs.nim deleted file mode 100644 index e47b38e99..000000000 --- a/tests/generics/twrong_explicit_typeargs.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - errormsg: "cannot instantiate: 'newImage[string]'" - line: 16 -""" - -# bug #4084 -type - Image[T] = object - data: seq[T] - -proc newImage[T: int32|int64](w, h: int): ref Image[T] = - new(result) - result.data = newSeq[T](w * h) - -var correct = newImage[int32](320, 200) -var wrong = newImage[string](320, 200) diff --git a/tests/generics/twrong_generic_object.nim b/tests/generics/twrong_generic_object.nim index 442b89ea1..4951f735f 100644 --- a/tests/generics/twrong_generic_object.nim +++ b/tests/generics/twrong_generic_object.nim @@ -1,6 +1,6 @@ discard """ - errormsg: "cannot instantiate: 'GenericNodeObj[T]'; Maybe generic arguments are missing?" - line: 21 + errormsg: "'Node' is not a concrete type" + line: 11 """ # bug #2509 type diff --git a/tests/constr/a_module.nim b/tests/global/a_module.nim index 1d3f4848c..1d3f4848c 100644 --- a/tests/constr/a_module.nim +++ b/tests/global/a_module.nim diff --git a/tests/global/t15005.nim b/tests/global/t15005.nim new file mode 100644 index 000000000..6395b1dde --- /dev/null +++ b/tests/global/t15005.nim @@ -0,0 +1,18 @@ +type + T = ref object + data: string + +template foo(): T = + var a15005 {.global.}: T + once: + a15005 = T(data: "hi") + + a15005 + +proc test() = + var b15005 = foo() + + doAssert b15005.data == "hi" + +test() +test() diff --git a/tests/global/t21896.nim b/tests/global/t21896.nim new file mode 100644 index 000000000..c7765c4dd --- /dev/null +++ b/tests/global/t21896.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "cannot assign local to global variable" + line: 7 +""" + +proc example(a:int) = + let b {.global.} = a + +example(1) diff --git a/tests/global/t3505.nim b/tests/global/t3505.nim new file mode 100644 index 000000000..437a02ae6 --- /dev/null +++ b/tests/global/t3505.nim @@ -0,0 +1,41 @@ +discard """ +cmd: "nim check $options --hints:off $file" +action: "reject" +nimout: ''' +t3505.nim(22, 22) Error: cannot assign local to global variable +t3505.nim(31, 28) Error: cannot assign local to global variable +t3505.nim(39, 29) Error: cannot assign local to global variable + + + + +''' +""" + + + + + + +proc foo = + let a = 0 + var b {.global.} = a +foo() + +# issue #5132 +proc initX(it: float): int = 8 +proc initX2(it: int): int = it + +proc main() = + var f: float + var x {.global.} = initX2(initX(f)) + +main() + +# issue #20866 +proc foo2() = + iterator bar() {.closure.} = + discard + var g {.global.} = rawProc(bar) + +foo2() \ No newline at end of file diff --git a/tests/global/tglobal2.nim b/tests/global/tglobal2.nim new file mode 100644 index 000000000..73a575bbd --- /dev/null +++ b/tests/global/tglobal2.nim @@ -0,0 +1,9 @@ +# b.nim +import a_module +doAssert foo() == 0 + +proc hello(x: type) = + var s {.global.} = default(x) + doAssert s == 0 + +hello(int) diff --git a/tests/ic/config.nims b/tests/ic/config.nims index 76b29a6aa..a622ec309 100644 --- a/tests/ic/config.nims +++ b/tests/ic/config.nims @@ -1,2 +1 @@ -when defined(windows): - --threads:off +--mm:refc diff --git a/tests/ic/tgenericinst.nim b/tests/ic/tgenericinst.nim new file mode 100644 index 000000000..3346764f5 --- /dev/null +++ b/tests/ic/tgenericinst.nim @@ -0,0 +1,11 @@ +discard """ + cmd: "nim cpp --incremental:on $file" +""" + +{.emit:"""/*TYPESECTION*/ +#include <iostream> + struct Foo { }; +""".} + +type Foo {.importcpp.} = object +echo $Foo() #Notice the generic is instantiate in the this module if not, it wouldnt find Foo \ No newline at end of file diff --git a/tests/implicit/timplicit.nim b/tests/implicit/timplicit.nim deleted file mode 100644 index bb701249c..000000000 --- a/tests/implicit/timplicit.nim +++ /dev/null @@ -1,49 +0,0 @@ -discard """ - output: ''' -1 -2 -3 -4 -2 -88 -timplicit done -''' -""" - - -for x in [1, 2, 3, 4]: - echo x - - -type - TValue* {.pure, final.} = object of RootObj - a: int - PValue = ref TValue - PPValue = ptr PValue - - -var x: PValue -new x -var sp: PPValue = addr x - -sp.a = 2 -if sp.a == 2: echo 2 # with sp[].a the error is gone - -# Test the new auto-deref a little - -{.experimental.} - -proc p(x: var int; y: int) = x += y - -block: - var x: ref int - new(x) - - x.p(44) - - var indirect = p - x.indirect(44) - - echo x[] - - echo "timplicit done" diff --git a/tests/import/buzz/m21496.nim b/tests/import/buzz/m21496.nim new file mode 100644 index 000000000..677324000 --- /dev/null +++ b/tests/import/buzz/m21496.nim @@ -0,0 +1 @@ +proc fb*: string = "buzz!" \ No newline at end of file diff --git a/tests/import/fizz/m21496.nim b/tests/import/fizz/m21496.nim new file mode 100644 index 000000000..525b653d6 --- /dev/null +++ b/tests/import/fizz/m21496.nim @@ -0,0 +1 @@ +proc fb*: string = "fizz!" \ No newline at end of file diff --git a/tests/import/t21496.nim b/tests/import/t21496.nim new file mode 100644 index 000000000..1a4907b12 --- /dev/null +++ b/tests/import/t21496.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "ambiguous identifier: 'm21496'" +""" + +import fizz/m21496, buzz/m21496 + +# bug #21496 + +discard m21496.fb() diff --git a/tests/import/t22065.nim b/tests/import/t22065.nim new file mode 100644 index 000000000..dfd87a107 --- /dev/null +++ b/tests/import/t22065.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "cannot open file: ./sugar" +""" + +import ./sugar \ No newline at end of file diff --git a/tests/import/t22208.nim b/tests/import/t22208.nim new file mode 100644 index 000000000..b935d751c --- /dev/null +++ b/tests/import/t22208.nim @@ -0,0 +1,6 @@ +import fizz/m21496 as alas +import buzz/m21496 + +# bug #21496 + +doAssert m21496.fb() == "buzz!" diff --git a/tests/import/t23167.nim b/tests/import/t23167.nim new file mode 100644 index 000000000..0891ee2af --- /dev/null +++ b/tests/import/t23167.nim @@ -0,0 +1,5 @@ +# bug #23167 +template sharedImport() = + import std / os + +sharedImport() diff --git a/tests/importalls/m4.nim b/tests/importalls/m4.nim index b682b766a..77ec65c61 100644 --- a/tests/importalls/m4.nim +++ b/tests/importalls/m4.nim @@ -1,4 +1,3 @@ -{.warning[UnusedImport]: off.} # xxx bug: this shouldn't be needed since we have `export m3` import ./m3 {.all.} import ./m3 as m3b export m3b diff --git a/tests/init/tcompiles.nim b/tests/init/tcompiles.nim new file mode 100644 index 000000000..67e17b241 --- /dev/null +++ b/tests/init/tcompiles.nim @@ -0,0 +1,101 @@ +discard """ + matrix: "--warningAsError:ProveInit --warningAsError:Uninit" +""" + +{.experimental: "strictdefs".} + +type Test = object + id: int + +proc foo {.noreturn.} = discard + +block: + proc test(x: bool): Test = + if x: + foo() + else: + foo() + +block: + proc test(x: bool): Test = + if x: + result = Test() + else: + foo() + + discard test(true) + +block: + proc test(x: bool): Test = + if x: + result = Test() + else: + return Test() + + discard test(true) + +block: + proc test(x: bool): Test = + if x: + return Test() + else: + return Test() + + discard test(true) + +block: + proc test(x: bool): Test = + if x: + result = Test() + else: + result = Test() + return + + discard test(true) + +block: + proc test(x: bool): Test = + if x: + result = Test() + return + else: + raise newException(ValueError, "unreachable") + + discard test(true) + +# bug #21615 +# bug #16735 + +block: + type Test {.requiresInit.} = object + id: int + + proc bar(): int = + raise newException(CatchableError, "error") + + proc test(): Test = + raise newException(CatchableError, "") + + template catchError(body) = + var done = false + try: + body + except CatchableError: + done = true + doAssert done + + catchError: + echo test() + + catchError: + echo bar() + +block: + proc foo(x: ptr int) = + discard + + proc main = + var s: int + foo(addr s) + + main() diff --git a/tests/init/tinitchecks_v2.nim b/tests/init/tinitchecks_v2.nim new file mode 100644 index 000000000..f7716bcca --- /dev/null +++ b/tests/init/tinitchecks_v2.nim @@ -0,0 +1,83 @@ +discard """ +cmd: "nim check $file" +action: "compile" +""" + +{.experimental: "strictDefs".} + +proc myopen(f: out File; s: string): bool = + f = default(File) + result = false + +proc main = + var f: File + if myopen(f, "aarg"): + f.close + +proc invalid = + var s: seq[string] + s.add "abc" #[tt.Warning + ^ use explicit initialization of 's' for clarity [Uninit] ]# + +proc valid = + var s: seq[string] = @[] + s.add "abc" # valid! + +main() +invalid() +valid() + +proc branchy(cond: bool) = + var s: seq[string] + if cond: + s = @["y"] + else: + s = @[] + s.add "abc" # valid! + +branchy true + +proc p(x: out int; y: out string; cond: bool) = #[tt.Warning + ^ Cannot prove that 'y' is initialized. This will become a compile time error in the future. [ProveInit] ]# + x = 4 + if cond: + y = "abc" + # error: not every path initializes 'y' + +var gl: int +var gs: string +p gl, gs, false + +proc canRaise(x: int): int = + result = x + raise newException(ValueError, "wrong") + +proc currentlyValid(x: out int; y: out string; cond: bool) = + x = canRaise(45) + y = "abc" # <-- error: not every path initializes 'y' + +currentlyValid gl, gs, false + +block: # previously effects/toutparam + proc gah[T](x: out T) = + x = 3 + + proc arr1 = + var a: array[2, int] + var x: int + gah(x) + a[0] = 3 + a[x] = 3 + echo x + + arr1() + + proc arr2 = + var a: array[2, int] + var x: int + a[0] = 3 + a[x] = 3 #[tt.Warning + ^ use explicit initialization of 'x' for clarity [Uninit] ]# + echo x + + arr2() diff --git a/tests/init/tlet.nim b/tests/init/tlet.nim new file mode 100644 index 000000000..e32bedb18 --- /dev/null +++ b/tests/init/tlet.nim @@ -0,0 +1,55 @@ +{.experimental: "strictDefs".} + +proc bar(x: out string) = + x = "abc" + +template moe = # bug #21043 + try: + discard + except ValueError as e: + echo(e.msg) + +template moe0 {.dirty.} = # bug #21043 + try: + discard + except ValueError as e: + echo(e.msg) + +proc foo() = + block: + let x: string + if true: + x = "abc" + else: + x = "def" + doAssert x == "abc" + block: + let y: string + bar(y) + doAssert y == "abc" + block: + let x: string + if true: + x = "abc" + discard "abc" + else: + x = "def" + discard "def" + doAssert x == "abc" + block: # + let x {.used.} : int + block: # + let x: float + x = 1.234 + doAssert x == 1.234 + + block: + try: + discard + except ValueError as e: + echo(e.msg) + moe() + moe0() + +static: foo() +foo() diff --git a/tests/init/tlet_uninit2.nim b/tests/init/tlet_uninit2.nim new file mode 100644 index 000000000..174aa28f7 --- /dev/null +++ b/tests/init/tlet_uninit2.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "'let' symbol requires an initialization" +""" + +let x: int \ No newline at end of file diff --git a/tests/init/tlet_uninit3.nim b/tests/init/tlet_uninit3.nim new file mode 100644 index 000000000..cb786f8c8 --- /dev/null +++ b/tests/init/tlet_uninit3.nim @@ -0,0 +1,24 @@ +discard """ + cmd: "nim check $file" + action: "reject" + nimout: ''' +tlet_uninit3.nim(13, 5) Error: 'let' symbol requires an initialization +tlet_uninit3.nim(19, 5) Error: 'x' cannot be assigned to +tlet_uninit3.nim(23, 11) Error: 'let' symbol requires an initialization +''' +""" + +{.experimental: "strictDefs".} + +let global {.used.}: int + +proc foo() = + block: + let x: int + x = 13 + x = 14 + + block: + let x: int + doAssert x == 0 +foo() diff --git a/tests/init/tlet_uninit4.nim b/tests/init/tlet_uninit4.nim new file mode 100644 index 000000000..c57d15ff8 --- /dev/null +++ b/tests/init/tlet_uninit4.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "type mismatch: got <string>" +""" + +{.experimental: "strictDefs".} + +proc foo(x: var string) = + echo x + +proc bar() = + let x: string + foo(x) diff --git a/tests/init/toutparam_subtype.nim b/tests/init/toutparam_subtype.nim new file mode 100644 index 000000000..3597f1459 --- /dev/null +++ b/tests/init/toutparam_subtype.nim @@ -0,0 +1,24 @@ +discard """ +cmd: "nim check $file" +action: "compile" +errormsg: "type mismatch: got <Subclass[system.int]>" +line: 21 +""" + +{.experimental: "strictDefs".} + +type + Superclass[T] = object of RootObj + a: T + Subclass[T] = object of Superclass[T] + s: string + +proc init[T](x: out Superclass[T]) = + x = Superclass(a: 8) + +proc subtypeCheck = + var v: Subclass[int] + init(v) + echo v.s # the 's' field was never initialized! + +subtypeCheck() diff --git a/tests/init/toutparams.nim b/tests/init/toutparams.nim new file mode 100644 index 000000000..590768599 --- /dev/null +++ b/tests/init/toutparams.nim @@ -0,0 +1,14 @@ +discard """ + matrix: "--warningAsError:ProveInit" +""" + +{.experimental: "strictdefs".} + +proc foo(x: out int) = + x = 1 + +proc bar(x: out int) = + foo(x) + +var s: int +bar(s) diff --git a/tests/misc/tproveinit.nim b/tests/init/tproveinit.nim index c9f688309..c9f688309 100644 --- a/tests/misc/tproveinit.nim +++ b/tests/init/tproveinit.nim diff --git a/tests/init/treturns.nim b/tests/init/treturns.nim new file mode 100644 index 000000000..18cebe0b1 --- /dev/null +++ b/tests/init/treturns.nim @@ -0,0 +1,106 @@ +{.experimental: "strictdefs".} + +type Test = object + id: int + +proc foo {.noreturn.} = discard + +proc test1(): Test = + if true: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return Test() + else: + return + +proc test0(): Test = + if true: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return + else: + foo() + +proc test2(): Test = + if true: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return + else: + return + +proc test3(): Test = + if true: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return + else: + return Test() + +proc test4(): Test = + if true: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return + else: + result = Test() + return + +proc test5(x: bool): Test = + case x: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + of true: + return + else: + return Test() + +proc test6(x: bool): Test = + case x: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + of true: + return + else: + return + +proc test7(x: bool): Test = + case x: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + of true: + return + else: + discard + +proc test8(x: bool): Test = + case x: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + of true: + discard + else: + raise + +proc hasImportStmt(): bool = + if false: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return true + else: + discard + +discard hasImportStmt() + +block: + proc hasImportStmt(): bool = + if false: #[tt.Warning + ^ Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit]]# + return true + else: + return + + discard hasImportStmt() + +block: + block: + proc foo(x: var int) = + discard + + proc main = + var s: int + foo(s)#[tt.Warning + ^ use explicit initialization of 's' for clarity [Uninit]]# + + main() + diff --git a/tests/init/tuninit1.nim b/tests/init/tuninit1.nim index 9a4161a30..ac3007e8d 100644 --- a/tests/init/tuninit1.nim +++ b/tests/init/tuninit1.nim @@ -4,7 +4,7 @@ discard """ """ import strutils - +{.experimental: "strictDefs".} {.warning[Uninit]:on.} proc p = diff --git a/tests/int/t1.nim b/tests/int/t1.nim new file mode 100644 index 000000000..6e5cdc8d4 --- /dev/null +++ b/tests/int/t1.nim @@ -0,0 +1,61 @@ +discard """ + targets: "c cpp" +""" + +doAssert typeOf(1.int64 + 1.int) is int64 +doAssert typeOf(1.uint64 + 1.uint) is uint64 +doAssert int64 is SomeNumber +doAssert int64 is (SomeNumber and not(uint32|uint64|uint|int)) +doAssert int64 is (not(uint32|uint64|uint|int)) +doAssert int isnot int64 +doAssert int64 isnot int +var myInt16 = 5i16 +var myInt: int +doAssert typeOf(myInt16 + 34) is int16 # of type `int16` +doAssert typeOf(myInt16 + myInt) is int # of type `int` +doAssert typeOf(myInt16 + 2i32) is int32 # of type `int32` +doAssert int32 isnot int64 +doAssert int32 isnot int + +block: # bug #23947 + template foo = + let test_u64 : uint64 = 0xFF07.uint64 + let test_u8 : uint8 = test_u64.uint8 + # Error: illegal conversion from '65287' to '[0..255]' + doAssert test_u8 == 7 + + static: foo() + foo() + +block: + # bug #22085 + const + x = uint32(uint64.high) # vm error + u = uint64.high + v = uint32(u) # vm error + + let + z = uint64.high + y = uint32(z) # runtime ok + + let + w = uint32(uint64.high) # semfold error + + doAssert x == w + doAssert v == y + + # bug #14522 + doAssert 0xFF000000_00000000.uint64 == 18374686479671623680'u64 + +block: # bug #23954 + let testRT_u8 : uint8 = 0x107.uint8 + doAssert testRT_u8 == 7 + const testCT_u8 : uint8 = 0x107.uint8 + doAssert testCT_u8 == 7 + +block: # issue #24104 + type P = distinct uint # uint, uint8, uint16, uint32, uint64 + let v = 0.P + case v + of 0.P: discard + else: discard diff --git a/tests/arithm/tarithm.nim b/tests/int/tarithm.nim index d0943d225..d0943d225 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/int/tarithm.nim diff --git a/tests/arithm/tashr.nim b/tests/int/tashr.nim index aeb3b6843..aeb3b6843 100644 --- a/tests/arithm/tashr.nim +++ b/tests/int/tashr.nim diff --git a/tests/arithm/tdiv.nim b/tests/int/tdiv.nim index 5d8eed84d..5d8eed84d 100644 --- a/tests/arithm/tdiv.nim +++ b/tests/int/tdiv.nim diff --git a/tests/misc/tints.nim b/tests/int/tints.nim index d24cbd4ac..773e8ccad 100644 --- a/tests/misc/tints.nim +++ b/tests/int/tints.nim @@ -1,4 +1,5 @@ discard """ + matrix: "; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" output: ''' 0 0 0 0 @@ -6,6 +7,9 @@ Success''' """ # Test the different integer operations + +import std/private/jsutils + var testNumber = 0 template test(opr, a, b, c: untyped): untyped = @@ -23,28 +27,37 @@ template test(opr, a, b, c: untyped): untyped = test(`+`, 12'i8, -13'i16, -1'i16) test(`shl`, 0b11, 0b100, 0b110000) +whenJsNoBigInt64: discard +do: + test(`shl`, 0b11'i64, 0b100'i64, 0b110000'i64) when not defined(js): + # mixed type shr needlessly complicates codegen with bigint + # and thus is not yet supported in JS for 64 bit ints test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64) test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32) test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16) test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16) -when not defined(js): +whenJsNoBigInt64: discard +do: test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64) test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16) test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8) -when not defined(js): +whenJsNoBigInt64: discard +do: test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64) test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32) -when not defined(js): +whenJsNoBigInt64: discard +do: test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64) test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16) test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8) -when not defined(js): +whenJsNoBigInt64: discard +do: test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64) test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32) @@ -80,6 +93,58 @@ block: # Casts to uint # issue #7174 let c = 1'u let val = c > 0 -doAssert val +doAssert val + +block: # bug #6752 + when not defined(js) or (defined(js) and compileOption("jsbigint64")): + let x = 711127'i64 + doAssert x * 86400'i64 == 61441372800'i64 + +block: # bug #17604 + let a = 2147483648'u + doAssert (a and a) == a + doAssert (a or 0) == a + +block: # bitwise not + let + z8 = 0'u8 + z16 = 0'u16 + z32 = 0'u32 + z64 = 0'u64 + doAssert (not z8) == uint8.high + doAssert (not z16) == uint16.high + doAssert (not z32) == uint32.high + when not defined(js) or (defined(js) and compileOption("jsbigint64")): + doAssert (not z64) == uint64.high + +block: # shl + let i8 = int8.high + let i16 = int16.high + let i32 = int32.high + let i64 = int64.high + doAssert i8 shl 1 == -2 + doAssert i8 shl 2 == -4 + doAssert i16 shl 1 == -2 + doAssert i16 shl 2 == -4 + doAssert i32 shl 1 == -2 + doAssert i32 shl 2 == -4 + when not defined(js) or (defined(js) and compileOption("jsbigint64")): + doAssert i64 shl 1 == -2 + doAssert i64 shl 2 == -4 + + let u8 = uint8.high + let u16 = uint16.high + let u32 = uint32.high + let u64 = uint64.high + doAssert u8 shl 1 == u8 - 1 + doAssert u16 shl 1 == u16 - 1 + doAssert u32 shl 1 == u32 - 1 + when not defined(js) or (defined(js) and compileOption("jsbigint64")): + doAssert u64 shl 1 == u64 - 1 + +block: # bug #23378 + var neg = -1 # prevent compile-time evaluation + let n = abs BiggestInt neg + doAssert n == 1 echo("Success") #OUT Success diff --git a/tests/misc/tunsigned64mod.nim b/tests/int/tunsigned64mod.nim index ca3286df3..ca3286df3 100644 --- a/tests/misc/tunsigned64mod.nim +++ b/tests/int/tunsigned64mod.nim diff --git a/tests/misc/tunsignedcmp.nim b/tests/int/tunsignedcmp.nim index 11b67ac5f..11b67ac5f 100644 --- a/tests/misc/tunsignedcmp.nim +++ b/tests/int/tunsignedcmp.nim diff --git a/tests/misc/tunsignedcomp.nim b/tests/int/tunsignedcomp.nim index 970c4ae9d..970c4ae9d 100644 --- a/tests/misc/tunsignedcomp.nim +++ b/tests/int/tunsignedcomp.nim diff --git a/tests/misc/tunsignedconv.nim b/tests/int/tunsignedconv.nim index 0acb39106..6c73521d3 100644 --- a/tests/misc/tunsignedconv.nim +++ b/tests/int/tunsignedconv.nim @@ -1,15 +1,19 @@ +discard """ + targets: "c cpp js" +""" + # Tests unsigned literals and implicit conversion between uints and ints -var h8:uint8 = 128 -var h16:uint16 = 32768 -var h32:uint32 = 2147483648'u32 -var h64:uint64 = 9223372036854775808'u64 -var foobar:uint64 = 9223372036854775813'u64 # Issue 728 +var h8: uint8 = 128 +var h16: uint16 = 32768 +var h32: uint32 = 2147483648'u32 +var h64: uint64 = 9223372036854775808'u64 +var foobar: uint64 = 9223372036854775813'u64 # Issue 728 -var v8:uint8 = 10 -var v16:uint16 = 10 -var v32:uint32 = 10 -var v64:uint64 = 10 +var v8: uint8 = 10 +var v16: uint16 = 10 +var v32: uint32 = 10 +var v64: uint64 = 10 # u8 + literal produces u8: var a8: uint8 = v8 + 10 @@ -57,8 +61,8 @@ const x1 = cast[uint](-1) discard $(x1,) # bug #13698 -let n: csize = 1 # xxx should that be csize_t or is that essential here? -doAssert $n.int32 == "1" +let n2: csize_t = 1 +doAssert $n2.int32 == "1" # bug #14616 @@ -66,8 +70,8 @@ let limit = 1'u64 let rangeVar = 0'u64 ..< limit -doAssert repr(rangeVar) == """[a = 0, -b = 0]""" +when not defined(gcRefc): + doAssert repr(rangeVar) == """0 .. 0""", repr(rangeVar) # bug #15210 @@ -95,3 +99,17 @@ template main() = static: main() main() + +block: + let a = uint64.high + let b = uint32.high + + doAssert a.uint64 == a + doAssert a.uint32 == uint32.high + doAssert a.uint16 == uint16.high + doAssert a.uint8 == uint8.high + + doAssert b.uint64 == b + doAssert b.uint32 == b + doAssert b.uint16 == uint16.high + doAssert b.uint8 == uint8.high diff --git a/tests/misc/tunsignedinc.nim b/tests/int/tunsignedinc.nim index 9d1a4bbb4..9392f1b74 100644 --- a/tests/misc/tunsignedinc.nim +++ b/tests/int/tunsignedinc.nim @@ -32,3 +32,9 @@ block t4175: const j = 0u - 1u doAssert i == j doAssert j + 1u == 0u + +block: # https://forum.nim-lang.org/t/12465#76998 + var a: int = 1 + var x: uint8 = 1 + a.inc(x) # Error: type mismatch + doAssert a == 2 diff --git a/tests/misc/tunsignedmisc.nim b/tests/int/tunsignedmisc.nim index b2a3849cf..b2a3849cf 100644 --- a/tests/misc/tunsignedmisc.nim +++ b/tests/int/tunsignedmisc.nim diff --git a/tests/int/twrongexplicitvarconv.nim b/tests/int/twrongexplicitvarconv.nim new file mode 100644 index 000000000..79f770e8e --- /dev/null +++ b/tests/int/twrongexplicitvarconv.nim @@ -0,0 +1,16 @@ +discard """ + action: reject + nimout: ''' + but expression 'int(a)' is immutable, not 'var' +''' +""" + +proc `++`(n: var int) = + n += 1 + +var a: int32 = 15 + +++int(a) #[tt.Error +^ type mismatch: got <int>]# + +echo a diff --git a/tests/int/twrongvarconv.nim b/tests/int/twrongvarconv.nim new file mode 100644 index 000000000..db6ac2c53 --- /dev/null +++ b/tests/int/twrongvarconv.nim @@ -0,0 +1,9 @@ +proc `++`(n: var int) = + n += 1 + +var a: int32 = 15 + +++a #[tt.Error +^ type mismatch: got <int32>]# + +echo a diff --git a/tests/isolate/tisolated_lock.nim b/tests/isolate/tisolated_lock.nim new file mode 100644 index 000000000..312abf0f6 --- /dev/null +++ b/tests/isolate/tisolated_lock.nim @@ -0,0 +1,67 @@ +discard """ + cmd: "nim $target --threads:on $options $file" + action: "compile" +""" + +import std / [os, locks, atomics, isolation] + +type + MyList {.acyclic.} = ref object + data: string + next: Isolated[MyList] + +template withMyLock*(a: Lock, body: untyped) = + acquire(a) + {.gcsafe.}: + try: + body + finally: + release(a) + +var head: Isolated[MyList] +var headL: Lock + +var shouldStop: Atomic[bool] + +initLock headL + +proc send(x: sink string) = + withMyLock headL: + head = isolate MyList(data: x, next: move head) + +proc worker() {.thread.} = + var workItem = MyList(nil) + var echoed = 0 + while true: + withMyLock headL: + var h = extract head + if h != nil: + workItem = h + # workitem is now isolated: + head = move h.next + else: + workItem = nil + # workItem is isolated, so we can access it outside + # the lock: + if workItem.isNil: + if shouldStop.load: + break + else: + # give producer time to breath: + os.sleep 30 + else: + if echoed < 100: + echo workItem.data + inc echoed + +var thr: Thread[void] +createThread(thr, worker) + +send "abc" +send "def" +for i in 0 ..< 10_000: + send "xzy" + send "zzz" +shouldStop.store true + +joinThread(thr) diff --git a/tests/iter/t1550.nim b/tests/iter/t1550.nim index 8ad96f0da..c971943ee 100644 --- a/tests/iter/t1550.nim +++ b/tests/iter/t1550.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + type A[T] = iterator(x: T): T {.gcsafe, closure.} diff --git a/tests/iter/t20891.nim b/tests/iter/t20891.nim new file mode 100644 index 000000000..34deec41b --- /dev/null +++ b/tests/iter/t20891.nim @@ -0,0 +1,28 @@ +import macros, tables + +var mapping {.compileTime.}: Table[string, NimNode] + +macro register(a: static[string], b: typed): untyped = + mapping[a] = b + +macro getPtr(a: static[string]): untyped = + result = mapping[a] + +proc foo() = + iterator it() {.closure.} = + discard + proc getIterPtr(): pointer {.nimcall.} = + rawProc(it) + register("foo", getIterPtr()) + discard getIterPtr() # Comment either this to make it work +foo() # or this + +proc bar() = + iterator it() {.closure.} = + discard getPtr("foo") # Or this + discard + proc getIterPtr(): pointer {.nimcall.} = + rawProc(it) + register("bar", getIterPtr()) + discard getIterPtr() +bar() diff --git a/tests/iter/t21306.nim b/tests/iter/t21306.nim new file mode 100644 index 000000000..4d0396294 --- /dev/null +++ b/tests/iter/t21306.nim @@ -0,0 +1,118 @@ +discard """ + targets: "c js" +""" + +# bug #21306 +type + FutureState {.pure.} = enum + Pending, Finished, Cancelled, Failed + + FutureBase = ref object of RootObj + state: FutureState + error: ref CatchableError + id: uint + + Future[T] = ref object of FutureBase + closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.} + value: T + +template setupFutureBase() = + new(result) + result.state = FutureState.Pending + +proc newFutureImpl[T](): Future[T] = + setupFutureBase() + +template newFuture[T](fromProc: static[string] = ""): Future[T] = + newFutureImpl[T]() + +proc internalRead[T](fut: Future[T]): T = + when T isnot void: + return fut.value + +template await[T](f: Future[T]): untyped = + when declared(chronosInternalRetFuture): + when not declaredInScope(chronosInternalTmpFuture): + var chronosInternalTmpFuture {.inject.}: FutureBase = f + else: + chronosInternalTmpFuture = f + + yield chronosInternalTmpFuture + + when T isnot void: + cast[type(f)](chronosInternalTmpFuture).internalRead() + +type + VerifierError {.pure.} = enum + Invalid + MissingParent + UnviableFork + Duplicate + ProcessingCallback = proc() {.gcsafe, raises: [Defect].} + BlockVerifier = + proc(signedBlock: int): + Future[VerifierError] {.gcsafe, raises: [Defect].} + + SyncQueueKind {.pure.} = enum + Forward, Backward + + SyncRequest[T] = object + kind: SyncQueueKind + index: uint64 + slot: uint64 + count: uint64 + item: T + + SyncResult[T] = object + request: SyncRequest[T] + data: seq[ref int] + + SyncQueue[T] = ref object + kind: SyncQueueKind + readyQueue: seq[SyncResult[T]] + blockVerifier: BlockVerifier + +iterator blocks[T](sq: SyncQueue[T], + sr: SyncResult[T]): ref int = + case sq.kind + of SyncQueueKind.Forward: + for i in countup(0, len(sr.data) - 1): + yield sr.data[i] + of SyncQueueKind.Backward: + for i in countdown(len(sr.data) - 1, 0): + yield sr.data[i] + +proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int]; + processingCb: ProcessingCallback = nil): Future[void] {. + stackTrace: off, gcsafe.} = + iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {. + closure, gcsafe, raises: [Defect, CatchableError, Exception].} = + block: + template result(): auto {.used.} = + {.fatal: "You should not reference the `result` variable inside" & + " a void async proc".} + + let item = default(SyncResult[T]) + for blk in sq.blocks(item): + let res = await sq.blockVerifier(blk[]) + + var resultFuture = newFuture[void]("push") + resultFuture.closure = push_436208182 + return resultFuture + +type + SomeTPeer = ref object + score: int + +proc getSlice(): seq[ref int] = + discard + +template smokeTest(kkind: SyncQueueKind, start, finish: uint64, + chunkSize: uint64) = + var queue: SyncQueue[SomeTPeer] + var request: SyncRequest[SomeTPeer] + discard queue.push(request, getSlice()) + +for k in {SyncQueueKind.Forward}: + for item in [(uint64(1181), uint64(1399), 41'u64)]: + smokeTest(k, item[0], item[1], item[2]) \ No newline at end of file diff --git a/tests/iter/t21737.nim b/tests/iter/t21737.nim new file mode 100644 index 000000000..da06faea7 --- /dev/null +++ b/tests/iter/t21737.nim @@ -0,0 +1,22 @@ +discard """ + action: compile +""" + +template mytoSeq*(iter: untyped): untyped = + var result: seq[typeof(iter)]# = @[] + for x in iter: + result.add(x) + result + +iterator test(dir:int): int = + yield 1234 + +iterator walkGlobKinds (): int = + let dir2 = 123 + let it = mytoSeq(test(dir2)) + +proc main()= + let it = iterator(): int= + for path in walkGlobKinds(): + yield path +main() diff --git a/tests/iter/t22148.nim b/tests/iter/t22148.nim new file mode 100644 index 000000000..9954eed87 --- /dev/null +++ b/tests/iter/t22148.nim @@ -0,0 +1,15 @@ +discard """ + action: compile +""" + +import std/memfiles + +# bug #22148 +proc make*(input: string) = + var inp = memfiles.open(input) + for line in memSlices(inp): + let lineF = MemFile(mem: line.data, size: line.size) + for word in memSlices(lineF, ','): + discard + +make("") # Must call to trigger diff --git a/tests/iter/t22548.nim b/tests/iter/t22548.nim new file mode 100644 index 000000000..b9abb75d0 --- /dev/null +++ b/tests/iter/t22548.nim @@ -0,0 +1,21 @@ +discard """ + action: compile +""" + +type Xxx[T] = object + +iterator x(v: string): char = + var v2: Xxx[int] + + var y: v2.T + + echo y + +proc bbb(vv: string): proc () = + proc xxx() = + for c in x(vv): + echo c + + return xxx + +bbb("test")() diff --git a/tests/iter/t22619.nim b/tests/iter/t22619.nim new file mode 100644 index 000000000..6a98391f3 --- /dev/null +++ b/tests/iter/t22619.nim @@ -0,0 +1,83 @@ +# bug #22619 + +when false: # todo fixme + block: + type + Resource = object + value: int + + Object = object + r {.cursor.}: Resource + s {.cursor.}: seq[Resource] + + var numDestroy = 0 + + proc `=copy`(x: var Resource, y: Resource) {.error.} # disallow full copies + proc `=destroy`(x: Resource) = + inc numDestroy + + proc test() = + # perform the test in procedure so that globals aren't used (their different + # semantics with regards to destruction would interfere) + var + r = Resource(value: 1) # initialize a resource + s = @[Resource(value: 2)] + + # make sure no copy is required in the initializer expression: + var o = Object(r: r, s: s) + + # copying the object doesn't perform a full copy of the cursor fields: + var o2 = o + discard addr(o2) # prevent `o2` from being turned into a cursor + + # check that the fields were shallow-copied: + doAssert o2.r.value == 1 + doAssert o2.s[0].value == 2 + + # make sure no copy is required with normal field assignments: + o.r = r + o.s = s + + + # when `o` and `o2` are destroyed, their destructor must not be called on + # their fields + + test() + + # one call for the `r` local and one for the object in `s` + doAssert numDestroy == 2 + +block: + type Value = distinct int + + var numDestroy = 0 + + when defined(gcRefc): + proc `=destroy`(x: var Value) = + inc numDestroy + else: + proc `=destroy`(x: Value) = + inc numDestroy + + iterator iter(s: seq[Value]): int {.closure.} = + # because it is used across yields, `s2` is lifted into the iterator's + # environment. Since non-ref cursors in object didn't have their hooks + # disabled inside the environments lifted hooks, this led to double + # frees + var s2 {.cursor.} = s + var i = 0 + let L = s2.len + while i < L: + yield s2[i].int + inc i + + proc test() = + var s = @[Value(1), Value(2)] + let cl = iter + # make sure resuming the iterator works: + doAssert cl(s) == 1 + doAssert cl(s) == 2 + doAssert cl(s) == 0 + + test() + doAssert numDestroy == 2 diff --git a/tests/iter/t2771.nim b/tests/iter/t2771.nim index 49befb0a9..71a8a9dcd 100644 --- a/tests/iter/t2771.nim +++ b/tests/iter/t2771.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + template t1(i: int): int= i+1 template t2(i: int): int= diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim index 9f0d0a74b..fee16497f 100644 --- a/tests/iter/tanoniter1.nim +++ b/tests/iter/tanoniter1.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: '''1 2 3 diff --git a/tests/iter/tclosureiters.nim b/tests/iter/tclosureiters.nim index 85611373c..4a2639852 100644 --- a/tests/iter/tclosureiters.nim +++ b/tests/iter/tclosureiters.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: '''0 1 2 @@ -152,15 +153,18 @@ iterator filesIt(path: string): auto {.closure.} = yield prefix / f # bug #13815 -var love = iterator: int {.closure.} = - yield cast[type( - block: - var a = 0 - yield a - a)](0) - -for i in love(): - echo i +when not defined(js): + var love = iterator: int {.closure.} = + yield cast[type( + block: + var a = 0 + yield a + a)](0) + + for i in love(): + echo i +else: + echo 0 # bug #18474 iterator pairs(): (int, int) {.closure.} = diff --git a/tests/iter/tgeniteratorinblock.nim b/tests/iter/tgeniteratorinblock.nim new file mode 100644 index 000000000..2ab903996 --- /dev/null +++ b/tests/iter/tgeniteratorinblock.nim @@ -0,0 +1,54 @@ +discard """ + output: '''30 +60 +90 +150 +180 +210 +240 +60 +180 +240 +[60, 180, 240] +[60, 180]''' +""" +import std/enumerate + +template map[T; Y](i: iterable[T], fn: proc(x: T): Y): untyped = + iterator internal(): Y {.gensym.} = + for it in i: + yield fn(it) + internal() + +template filter[T](i: iterable[T], fn: proc(x: T): bool): untyped = + iterator internal(): T {.gensym.} = + for it in i: + if fn(it): + yield it + internal() + +template group[T](i: iterable[T], amount: static int): untyped = + iterator internal(): array[amount, T] {.gensym.} = + var val: array[amount, T] + for ind, it in enumerate i: + val[ind mod amount] = it + if ind mod amount == amount - 1: + yield val + internal() + +var a = [10, 20, 30, 50, 60, 70, 80] + +proc mapFn(x: int): int = x * 3 +proc filterFn(x: int): bool = x mod 20 == 0 + +for x in a.items.map(mapFn): + echo x + +for y in a.items.map(mapFn).filter(filterFn): + echo y + +for y in a.items.map(mapFn).filter(filterFn).group(3): + echo y + +for y in a.items.map(mapFn).filter(filterFn).group(2): + echo y diff --git a/tests/iter/titer.nim b/tests/iter/titer.nim index 3a2450ae3..b03d43f36 100644 --- a/tests/iter/titer.nim +++ b/tests/iter/titer.nim @@ -112,3 +112,36 @@ let res = collect: fn2(v2) doAssert res == @[42, 43, 43, 44] + +block: # bug #21110 + iterator p(): int = + when nimvm: + yield 0 + else: + yield 0 + + template foo = + for k in p(): + let m = "" + proc e() = discard m & "" + e() + static: foo() + foo() + + +# bug #15924 +iterator walk(): (int, int) {.closure.} = + yield (10,11) + +for (i,j) in walk(): + doAssert i == 10 + +proc main123() = + let x = false + iterator it(): (bool, bool) {.closure.} = # normally {.closure.} here makes #21476 work + discard x + + for (_, _) in it(): + discard + +main123() diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim index 2b39c74f7..153b3c29a 100644 --- a/tests/iter/titer11.nim +++ b/tests/iter/titer11.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' [ 1 diff --git a/tests/iter/titer12.nim b/tests/iter/titer12.nim index f7fc64da4..f264a0e82 100644 --- a/tests/iter/titer12.nim +++ b/tests/iter/titer12.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' Selecting 2 1.0 diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim index 9c7a5eab0..c82b3902d 100644 --- a/tests/iter/titer_issues.nim +++ b/tests/iter/titer_issues.nim @@ -1,4 +1,5 @@ discard """ + target: "c js" output: ''' 0 1 @@ -38,6 +39,10 @@ nested finally outer finally nested finally outer finally +In defer +trying +exception caught +finally block ''' """ @@ -362,3 +367,45 @@ block: for _ in p4(): discard + +# bug #18824 +iterator poc_iterator: int {.closure.} = + block bug18824: + try: + break bug18824 + finally: + echo "In defer" + +for _ in poc_iterator(): + discard + +# bug #20624 +iterator tryFinally() {.closure.} = + block route: + try: + echo "trying" + raise + except: + echo "exception caught" + break route + finally: + echo "finally block" + +var x = tryFinally +x() + +block: # bug #24033 + type Query = ref object + + iterator pairs(query: Query): (int, (string, float32)) = + var output: (int, (string, float32)) = (0, ("foo", 3.14)) + for id in @[0, 1, 2]: + output[0] = id + yield output + + var collections: seq[(int, string, string)] + + for id, (str, num) in Query(): + collections.add (id, str, $num) + + doAssert collections[1] == (1, "foo", "3.14") diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim index ad1192bd8..b2fe71ceb 100644 --- a/tests/iter/titervaropenarray.nim +++ b/tests/iter/titervaropenarray.nim @@ -1,6 +1,6 @@ discard """ output: "123" - targets: "c" + targets: "c cpp" """ # Try to break the transformation pass: iterator iterAndZero(a: var openArray[int]): int = diff --git a/tests/iter/tshallowcopy_closures.nim b/tests/iter/tshallowcopy_closures.nim index 279e7d950..06b04a788 100644 --- a/tests/iter/tshallowcopy_closures.nim +++ b/tests/iter/tshallowcopy_closures.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" ccodecheck: "!@('{' \\s* 'NI HEX3Astate;' \\s* '}')" output: ''' a1 10 diff --git a/tests/iter/tyieldintry.nim b/tests/iter/tyieldintry.nim index 9df201dd4..e51ab7f0d 100644 --- a/tests/iter/tyieldintry.nim +++ b/tests/iter/tyieldintry.nim @@ -1,4 +1,5 @@ discard """ + matrix: "; --experimental:strictdefs; -d:nimOptIters" targets: "c cpp" """ @@ -503,3 +504,26 @@ block: # void iterator except: discard var a = it + +if defined(nimOptIters): # Locals present in only 1 state should be on the stack + proc checkOnStack(a: pointer, shouldBeOnStack: bool) = + # Quick and dirty way to check if a points to stack + var dummy = 0 + let dummyAddr = addr dummy + let distance = abs(cast[int](dummyAddr) - cast[int](a)) + const requiredDistance = 300 + if shouldBeOnStack: + doAssert(distance <= requiredDistance, "a is not on stack, but should") + else: + doAssert(distance > requiredDistance, "a is on stack, but should not") + + iterator it(): int {.closure.} = + var a = 1 + var b = 2 + var c {.liftLocals.} = 3 + checkOnStack(addr a, true) + checkOnStack(addr b, false) + checkOnStack(addr c, false) + yield a + yield b + test(it, 1, 2) diff --git a/tests/js/t20233.nim b/tests/js/t20233.nim new file mode 100644 index 000000000..401d14122 --- /dev/null +++ b/tests/js/t20233.nim @@ -0,0 +1,7 @@ +discard """ + output: "yes" +""" +case 1.0 +of 1.0..2.0, 4.0: echo "yes" +of 3.0: discard +else: echo "no" \ No newline at end of file diff --git a/tests/js/t20235.nim b/tests/js/t20235.nim new file mode 100644 index 000000000..3a69c2bd6 --- /dev/null +++ b/tests/js/t20235.nim @@ -0,0 +1,11 @@ +discard """ + action: "run" + output: "0 4" +""" + +proc main = + var s = "" + s.setLen(4) + echo s[0].ord, " ", s.len + +main() diff --git a/tests/js/t21209.nim b/tests/js/t21209.nim new file mode 100644 index 000000000..4de34f035 --- /dev/null +++ b/tests/js/t21209.nim @@ -0,0 +1,6 @@ +discard """ + action: "compile" + cmd: "nim check --warning[UnusedImport]:off $file" +""" + +import std/times diff --git a/tests/js/t21209.nims b/tests/js/t21209.nims new file mode 100644 index 000000000..318e28f97 --- /dev/null +++ b/tests/js/t21209.nims @@ -0,0 +1 @@ +--b:js \ No newline at end of file diff --git a/tests/js/t21247.nim b/tests/js/t21247.nim new file mode 100644 index 000000000..5b38787b3 --- /dev/null +++ b/tests/js/t21247.nim @@ -0,0 +1,15 @@ +import std/typetraits + +type + QueryParams* = distinct seq[(string, string)] + +converter toBase*(params: var QueryParams): var seq[(string, string)] = + params.distinctBase + +proc foo(): QueryParams = + # Issue was that the implicit converter call didn't say that it took the + # address of the parameter it was converting. This led to the parameter not being + # passed as a fat pointer which toBase expected + result.add(("hello", "world")) + +assert foo().distinctBase() == @[("hello", "world")] diff --git a/tests/js/t21439.nim b/tests/js/t21439.nim new file mode 100644 index 000000000..3caeb090a --- /dev/null +++ b/tests/js/t21439.nim @@ -0,0 +1,11 @@ +proc test(a: openArray[string]): proc = + let a = @a + result = proc = + for i in a: + discard i + + +const a = ["t1", "t2"] + +discard test(a) + diff --git a/tests/js/t7109.nim b/tests/js/t7109.nim index 0d071dbbf..a1a3b718e 100644 --- a/tests/js/t7109.nim +++ b/tests/js/t7109.nim @@ -1,8 +1,8 @@ -discard """ - errormsg: "Closure iterators are not supported by JS backend!" -""" - iterator iter*(): int {.closure.} = yield 3 var x = iter +doAssert x() == 3 + +let fIt = iterator(): int = yield 70 +doAssert fIt() == 70 diff --git a/tests/js/t8821.nim b/tests/js/t8821.nim index 43cf3f6f2..38c88efa8 100644 --- a/tests/js/t8821.nim +++ b/tests/js/t8821.nim @@ -1,6 +1,3 @@ -discard """ - errormsg: "Your case statement contains too many branches, consider using if/else instead!" -""" proc isInt32(i: int): bool = case i @@ -9,4 +6,4 @@ proc isInt32(i: int): bool = else: return false -discard isInt32(1) \ No newline at end of file +doAssert isInt32(1) == true \ No newline at end of file diff --git a/tests/js/tasyncjs.nim b/tests/js/tasyncjs.nim index 00753a16c..f3b273c44 100644 --- a/tests/js/tasyncjs.nim +++ b/tests/js/tasyncjs.nim @@ -94,4 +94,14 @@ proc main() {.async.} = doAssert "foobar: 7" in $reason.message echo "done" # justified here to make sure we're running this, since it's inside `async` +block asyncPragmaInType: + type Handler = proc () {.async.} + proc foo() {.async.} = discard + var x: Handler = foo + +block: # 13341 + proc f {.async.} = + proc g: int = + result = 123 + discard main() diff --git a/tests/js/tcodegendeclproc.nim b/tests/js/tcodegendeclproc.nim index 3acf0bc13..33064bdf1 100644 --- a/tests/js/tcodegendeclproc.nim +++ b/tests/js/tcodegendeclproc.nim @@ -3,7 +3,7 @@ discard """ -1 8 ''' - ccodecheck: "'console.log(-1); function fac_' \\d+ '(n_' \\d+ ')'" + ccodecheck: "'console.log(-1); function fac__tcodegendeclproc_u1(n_p0)'" """ proc fac(n: int): int {.codegenDecl: "console.log(-1); function $2($3)".} = return n diff --git a/tests/js/tdanger.nim b/tests/js/tdanger.nim new file mode 100644 index 000000000..9088859a8 --- /dev/null +++ b/tests/js/tdanger.nim @@ -0,0 +1,17 @@ +discard """ + matrix: ";--d:danger" +""" + +block: + proc foo() = + var name = int64(12) + var x = uint32(name) + var m = x + 12 + + var y = int32(name) + var n = y + 1 + + doAssert m == uint32(n + 11) + + + foo() diff --git a/tests/js/tjsffi.nim b/tests/js/tjsffi.nim index 06a30c44d..f27ea5546 100644 --- a/tests/js/tjsffi.nim +++ b/tests/js/tjsffi.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--legacy:jsnolambdalifting;" output: ''' 3 2 @@ -180,7 +181,7 @@ block: # Test lit block: # Test bindMethod type TestObject = object a: int - onWhatever: proc(e: int): int + onWhatever: proc(e: int): int {.nimcall.} proc handleWhatever(this: TestObject, e: int): int = e + this.a block: @@ -217,7 +218,7 @@ block: on("click") do (e: Event): console.log e - jslib.on("reloaded") do: + jslib.on("reloaded") do (): console.log jsarguments[0] # this test case is different from the above, because @@ -265,3 +266,9 @@ block: # test ** doAssert to(`**`(a + a, b), int) == 2 doAssert to(`**`(toJs(1) + toJs(1), toJs(2)), int) == 4 + +block: # issue #21208 + type MyEnum = enum baz + var obj: JsObject + {.emit: "`obj` = {bar: {baz: 123}};".} + discard obj.bar.baz diff --git a/tests/js/tjsffi_old.nim b/tests/js/tjsffi_old.nim index 078d208c5..378003f4e 100644 --- a/tests/js/tjsffi_old.nim +++ b/tests/js/tjsffi_old.nim @@ -279,8 +279,8 @@ block: block: type TestObject = object a: int - onWhatever: proc(e: int): int - proc handleWhatever(this: TestObject, e: int): int = + onWhatever: proc(e: int): int {.nimcall.} + proc handleWhatever(this: TestObject, e: int): int {.nimcall.} = e + this.a proc test(): bool = let obj = TestObject(a: 9, onWhatever: bindMethod(handleWhatever)) @@ -321,7 +321,7 @@ block: on("click") do (e: Event): console.log e - jslib.on("reloaded") do: + jslib.on("reloaded") do (): console.log jsarguments[0] # this test case is different from the above, because diff --git a/tests/js/tjsnimscombined.nim b/tests/js/tjsnimscombined.nim new file mode 100644 index 000000000..4d3e6c453 --- /dev/null +++ b/tests/js/tjsnimscombined.nim @@ -0,0 +1 @@ +import std/jsffi diff --git a/tests/js/tjsnimscombined.nims b/tests/js/tjsnimscombined.nims new file mode 100644 index 000000000..01b93d3fa --- /dev/null +++ b/tests/js/tjsnimscombined.nims @@ -0,0 +1 @@ +# test the condition where both `js` and `nimscript` are defined (nimscript receives priority) diff --git a/tests/js/tnativeexc.nim b/tests/js/tnativeexc.nim index ea371c1cd..8b2b43e8f 100644 --- a/tests/js/tnativeexc.nim +++ b/tests/js/tnativeexc.nim @@ -18,7 +18,7 @@ try: except JsEvalError: doAssert false except JsSyntaxError as se: - doAssert se.message == "Unexpected token ; in JSON at position 0" + doAssert se.message == "Unexpected token ';', \";;\" is not valid JSON" except JsError as e: doAssert false diff --git a/tests/js/tneginthash.nim b/tests/js/tneginthash.nim new file mode 100644 index 000000000..c082405c9 --- /dev/null +++ b/tests/js/tneginthash.nim @@ -0,0 +1,21 @@ +# issue #19929 + +import std/[tables, hashes] + +type Foo = object + a: int + +proc hash(f: Foo): Hash = + var h: Hash = 0 + h = h !& hash(f.a) + result = !$h + +proc transpose[T, S](data: array[T, S]): Table[S, T] = + for i, x in data: + result[x] = i + +const xs = [Foo(a: 5), Foo(a: -5)] +const x = transpose(xs) + +doAssert x[Foo(a: -5)] == 1 +doAssert x[Foo(a: 5)] == 0 diff --git a/tests/js/tos.nim b/tests/js/tos.nim index bfe3cd9b4..40fb52bcf 100644 --- a/tests/js/tos.nim +++ b/tests/js/tos.nim @@ -13,11 +13,9 @@ block: doAssert not "foo".isAbsolute doAssert relativePath("", "bar") == "" doAssert normalizedPath(".///foo//./") == "foo" - let cwd = getCurrentDir() - let isWindows = '\\' in cwd - # defined(windows) doesn't work with -d:nodejs but should - # these actually break because of that (see https://github.com/nim-lang/Nim/issues/13469) - if not isWindows: + when nimvm: discard + else: + let cwd = getCurrentDir() doAssert cwd.isAbsolute - doAssert relativePath(getCurrentDir() / "foo", "bar") == "../foo" + doAssert relativePath(getCurrentDir() / "foo", "bar") == ".." / "foo" diff --git a/tests/js/trepr.nim b/tests/js/trepr.nim index c63b64d3a..a562ad63b 100644 --- a/tests/js/trepr.nim +++ b/tests/js/trepr.nim @@ -283,7 +283,7 @@ block bunch: result[] = b var - aa: A + aa = default(A) bb: B = B(a: "inner", b: @['o', 'b', 'j']) cc: A = A(a: 12, b: 1, c: 1.2, d: '\0', e: eC, f: "hello", g: {'A'}, h: {2'i16}, @@ -303,7 +303,7 @@ g = {}, h = {}, i = ["", "", ""], j = @[], -k = 0, +k = -12, l = [a = "", b = @[]], m = nil, diff --git a/tests/js/tsourcemap.nim b/tests/js/tsourcemap.nim new file mode 100644 index 000000000..d358e4a57 --- /dev/null +++ b/tests/js/tsourcemap.nim @@ -0,0 +1,96 @@ +discard """ + action: "run" + targets: "js" + cmd: "nim js -r -d:nodejs $options --sourceMap:on $file" +""" +import std/[os, json, strutils, sequtils, algorithm, assertions, paths, compilesettings] + +# Implements a very basic sourcemap parser and then runs it on itself. +# Allows to check for basic problems such as bad counts and lines missing (e.g. issue #21052) + +type + SourceMap = object + version: int + sources: seq[string] + names: seq[string] + mappings: string + file: string + + Line = object + line, column: int + file: string + +const + flag = 1 shl 5 + signBit = 0b1 + fourBits = 0b1111 + fiveBits = 0b11111 + mask = (1 shl 5) - 1 + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + +var b64Table: seq[int] = 0.repeat(max(alphabet.mapIt(it.ord)) + 1) +for i, b in alphabet.pairs: + b64Table[b.ord] = i + +# From https://github.com/juancarlospaco/nodejs/blob/main/src/nodejs/jsfs.nim +proc importFs*() {.importjs: "var fs = require(\"fs\");".} +proc readFileSync*(path: cstring): cstring {.importjs: "(fs.$1(#).toString())".} +importFS() +# Read in needed files +let + jsFileName = string(querySetting(outDir).Path / "tsourcemap.js".Path) + mapFileName = jsFileName & ".map" + + data = parseJson($mapFileName.cstring.readFileSync()).to(SourceMap) + jsFile = $readFileSync(jsFileName.cstring) + +proc decodeVLQ(inp: string): seq[int] = + var + shift, value: int + for v in inp.mapIt(b64Table[it.ord]): + value += (v and mask) shl shift + if (v and flag) > 0: + shift += 5 + continue + result &= (value shr 1) * (if (value and 1) > 0: -1 else: 1) + shift = 0 + value = 0 + + +# Keep track of state +var + line = 0 + source = 0 + name = 0 + column = 0 + jsLine = 1 + lines: seq[Line] + +for gline in data.mappings.split(';'): + jsLine += 1 + var jsColumn = 0 + for item in gline.strip().split(','): + let value = item.decodeVLQ() + doAssert value.len in [0, 1, 4, 5] + if value.len == 0: + continue + jsColumn += value[0] + if value.len >= 4: + source += value[1] + line += value[2] + column += value[3] + lines &= Line(line: line, column: column, file: data.sources[source]) + +let jsLines = jsFile.splitLines().len +# There needs to be a mapping for every line in the JS +# If there isn't then the JS lines wont match up with Nim lines. +# Except we don't care about the final line since that doesn't need to line up +doAssert data.mappings.count(';') == jsLines - 1 + +# Check we can find this file somewhere in the source map +var foundSelf = false +for line in lines: + if "tsourcemap.nim" in line.file: + foundSelf = true + doAssert line.line in 0..<jsLines, "Lines is out of bounds for file" +doAssert foundSelf, "Couldn't find tsourcemap.nim in source map" diff --git a/tests/js/tstdlib_imports.nim b/tests/js/tstdlib_imports.nim index 30aca7561..db851ba28 100644 --- a/tests/js/tstdlib_imports.nim +++ b/tests/js/tstdlib_imports.nim @@ -4,6 +4,11 @@ discard """ {.warning[UnusedImport]: off.} +when defined(nimPreviewSlimSystem): + import std/[ + syncio, assertions, formatfloat, objectdollar, widestrs + ] + import std/[ # Core: bitops, typetraits, lenientops, macros, volatile, typeinfo, @@ -20,7 +25,7 @@ import std/[ # Strings: cstrutils, editdistance, wordwrap, parseutils, ropes, - pegs, punycode, strformat, strmisc, strscans, strtabs, + pegs, strformat, strmisc, strscans, strtabs, strutils, unicode, unidecode, # fails due to FFI: encodings @@ -40,7 +45,7 @@ import std/[ # Internet protocols: cookies, httpcore, mimetypes, uri, # fails due to FFI: asyncdispatch, asyncfile, asyncftpclient, asynchttpserver, - # asyncnet, cgi, httpclient, nativesockets, net, selectors, smtp + # asyncnet, cgi, httpclient, nativesockets, net, selectors # works but no need to test: asyncstreams, asyncfutures # Threading: @@ -57,7 +62,7 @@ import std/[ htmlgen, # Hashing: - base64, hashes, md5, + base64, hashes, # fails due to cstring cast/endians import: oids # fails due to copyMem/endians import: sha1 diff --git a/tests/js/tstdlib_various.nim b/tests/js/tstdlib_various.nim index 4b5ce1de8..1e584f735 100644 --- a/tests/js/tstdlib_various.nim +++ b/tests/js/tstdlib_various.nim @@ -150,12 +150,7 @@ block tsplit2: s.add("#") s.add(w) - var errored = false - try: - discard "hello".split("") - except AssertionDefect: - errored = true - doAssert errored + doAssert "true".split("") == @["true"] block txmlgen: var nim = "Nim" diff --git a/tests/js/ttypedarray.nim b/tests/js/ttypedarray.nim index 222f66569..4807cb103 100644 --- a/tests/js/ttypedarray.nim +++ b/tests/js/ttypedarray.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--jsbigint64:off -d:nimStringHash2; --jsbigint64:on" +""" + import std/private/jsutils proc main()= @@ -5,9 +9,10 @@ proc main()= doAssert fn(array[2, int8].default) == "Int8Array" doAssert fn(array[2, uint8].default) == "Uint8Array" doAssert fn(array[2, byte].default) == "Uint8Array" - # doAssert fn(array[2, char].default) == "Uint8Array" # xxx fails; bug? - doAssert fn(array[2, uint64].default) == "Array" - # pending https://github.com/nim-lang/RFCs/issues/187 maybe use `BigUint64Array` + doAssert fn(array[2, char].default) == "Uint8Array" + whenJsNoBigInt64: discard + do: + doAssert fn(array[2, uint64].default) == "BigUint64Array" doAssert fn([1'u8]) == "Uint8Array" doAssert fn([1'u16]) == "Uint16Array" doAssert fn([byte(1)]) == "Uint8Array" diff --git a/tests/lent/t16898.nim b/tests/lent/t16898.nim index ea7c934ef..a69c6d244 100644 --- a/tests/lent/t16898.nim +++ b/tests/lent/t16898.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "invalid type: 'lent QuadraticExt' in this context: 'proc (r: var QuadraticExt, a: lent QuadraticExt, b: lent QuadraticExt){.noSideEffect, gcsafe, locks: 0.}' for proc" + errormsg: "invalid type: 'lent QuadraticExt' in this context: 'proc (r: var QuadraticExt, a: lent QuadraticExt, b: lent QuadraticExt){.noSideEffect, gcsafe.}' for proc" """ # bug #16898 diff --git a/tests/lent/tbasic_lent_check.nim b/tests/lent/tbasic_lent_check.nim index 92d731451..ce9b89adf 100644 --- a/tests/lent/tbasic_lent_check.nim +++ b/tests/lent/tbasic_lent_check.nim @@ -28,7 +28,7 @@ template main2 = # bug #15958 doAssert byLent(a) == [11,12] doAssert sameAddress(byLent(a), a) doAssert byLent(b) == @[21,23] - # pending bug #16073 + # bug #16073 doAssert sameAddress(byLent(b), b) doAssert byLent(ss) == {1, 2, 3, 5} doAssert sameAddress(byLent(ss), ss) diff --git a/tests/lent/tlent_from_var.nim b/tests/lent/tlent_from_var.nim index 912390dc1..1fb3d0c17 100644 --- a/tests/lent/tlent_from_var.nim +++ b/tests/lent/tlent_from_var.nim @@ -30,3 +30,78 @@ let x2 = x.byLentVar let xs2 = xs.byLentVar echo xs2 + +# bug #22138 + +type Xxx = object + +type + Opt[T] = object + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + +func value*[T: not void](self: Opt[T]): lent T {.inline.} = + self.vResultPrivate +template get*[T: not void](self: Opt[T]): T = self.value() + +method connect*( + self: Opt[(int, int)]) = + discard self.get()[0] + +block: # bug #23454 + type + Letter = enum + A + + LetterPairs = object + values: seq[(Letter, string)] + + iterator items(list: var LetterPairs): lent (Letter, string) = + for item in list.values: + yield item + + var instance = LetterPairs(values: @[(A, "foo")]) + + for (a, _) in instance: + case a + of A: discard + +block: # bug #23454 + type + Letter = enum + A + + LetterPairs = object + values: seq[(Letter, string)] + + iterator items(list: var LetterPairs): var (Letter, string) = + for item in list.values.mItems: + yield item + + var instance = LetterPairs(values: @[(A, "foo")]) + + for (a, _) in instance: + case a + of A: discard + +block: # bug #24034 + type T = object + v: array[100, byte] + + + iterator pairs(t: T): (int, lent array[100, byte]) = + yield (0, t.v) + + + block: + for a, b in default(T): + doAssert a == 0 + doAssert b.len == 100 + + block: + for (a, b) in pairs(default(T)): + doAssert a == 0 + doAssert b.len == 100 diff --git a/tests/lent/tvm.nim b/tests/lent/tvm.nim new file mode 100644 index 000000000..5df1d1270 --- /dev/null +++ b/tests/lent/tvm.nim @@ -0,0 +1,21 @@ +block: # issue #17527 + iterator items2[IX, T](a: array[IX, T]): lent T {.inline.} = + var i = low(IX) + if i <= high(IX): + while true: + yield a[i] + if i >= high(IX): break + inc(i) + + proc main() = + var s: seq[string] = @[] + for i in 0..<3: + for (key, val) in items2([("any", "bar")]): + s.add $(i, key, val) + doAssert s == @[ + "(0, \"any\", \"bar\")", + "(1, \"any\", \"bar\")", + "(2, \"any\", \"bar\")" + ] + + static: main() diff --git a/tests/lexer/nim.cfg b/tests/lexer/nim.cfg deleted file mode 100644 index f7a301a10..000000000 --- a/tests/lexer/nim.cfg +++ /dev/null @@ -1 +0,0 @@ ---experimental:unicodeOperators diff --git a/tests/lexer/tcustom_numeric_literals.nim b/tests/lexer/tcustom_numeric_literals.nim index 9c49d0c08..35b4803d3 100644 --- a/tests/lexer/tcustom_numeric_literals.nim +++ b/tests/lexer/tcustom_numeric_literals.nim @@ -134,17 +134,14 @@ template main = block: # bug 1 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 macro deb1(a): untyped = newLit a.repr - macro deb2(a): untyped = newLit a.lispRepr + macro deb2(a): untyped = + a[1] = ident($a[1]) + newLit a.lispRepr doAssert deb1(-12'wrap) == "-12'wrap" doAssert deb1(-12'nonexistent) == "-12'nonexistent" doAssert deb2(-12'nonexistent) == """(DotExpr (RStrLit "-12") (Ident "\'nonexistent"))""" - when false: # xxx bug: - # this holds: - doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Sym "wrap2"))""" - doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Sym "\'wrap"))""" - # but instead this should hold: - doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Ident "wrap2"))""" - doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Ident "\'wrap"))""" + doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Ident "wrap2"))""" + doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Ident "\'wrap"))""" block: # bug 2 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 template toSuf(`'suf`): untyped = @@ -165,21 +162,16 @@ template main = doAssert fn2() == "[[-12]]" doAssert fn3() == "[[-12]]" - when false: # xxx this fails; bug 9 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 - #[ - possible workaround: use `genAst` (https://github.com/nim-lang/Nim/pull/17426) and this: - let a3 = `'wrap3`("-128") - ]# - block: - macro metawrap(): untyped = - func wrap1(a: string): string = "{" & a & "}" - func `'wrap3`(a: string): string = "{" & a & "}" - result = quote do: - let a1 = wrap1"-128" - let a2 = -128'wrap3 - metawrap() - doAssert a1 == "{-128}" - doAssert a2 == "{-128}" + block: # bug 9 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 + macro metawrap(): untyped = + func wrap1(a: string): string = "{" & a & "}" + func `'wrap3`(a: string): string = "{" & a & "}" + result = quote do: + let a1 {.inject.} = wrap1"-128" + let a2 {.inject.} = -128'wrap3 + metawrap() + doAssert a1 == "{-128}" + doAssert a2 == "{-128}" static: main() main() diff --git a/tests/lexer/tlexerspaces.nim b/tests/lexer/tlexerspaces.nim new file mode 100644 index 000000000..14b16111d --- /dev/null +++ b/tests/lexer/tlexerspaces.nim @@ -0,0 +1,2 @@ +discard 12 + 5 +discard 12 + 5 diff --git a/tests/misc/trawstr.nim b/tests/lexer/trawstr.nim index aa41071d5..aa41071d5 100644 --- a/tests/misc/trawstr.nim +++ b/tests/lexer/trawstr.nim diff --git a/tests/lexer/tunary_minus.nim b/tests/lexer/tunary_minus.nim index 1641e918c..5ec2b5c70 100644 --- a/tests/lexer/tunary_minus.nim +++ b/tests/lexer/tunary_minus.nim @@ -5,6 +5,7 @@ discard """ # Test numeric literals and handling of minus symbol import std/[macros, strutils] +import std/private/jsutils import mlexerutils @@ -60,7 +61,8 @@ template main = doAssert -2147483648'i32 == int32.low when int.sizeof > 4: doAssert -9223372036854775808 == int.low - when not defined(js): + whenJsNoBigInt64: discard + do: doAssert -9223372036854775808 == int64.low block: # check when a minus (-) is an unary op diff --git a/tests/lookups/issue_23032/deep_scope.nim b/tests/lookups/issue_23032/deep_scope.nim new file mode 100644 index 000000000..3e25809a7 --- /dev/null +++ b/tests/lookups/issue_23032/deep_scope.nim @@ -0,0 +1,2 @@ +type A*[T] = object +proc foo*(a: A[int]): bool = false diff --git a/tests/lookups/issue_23172/m23172.nim b/tests/lookups/issue_23172/m23172.nim new file mode 100644 index 000000000..36af48761 --- /dev/null +++ b/tests/lookups/issue_23172/m23172.nim @@ -0,0 +1,6 @@ +type + Foo* = object + Bar* = object + +func `$`*(x: Foo | Bar): string = + "X" diff --git a/tests/ambsym/mambsym1.nim b/tests/lookups/mambsym1.nim index c4902b1b4..c4902b1b4 100644 --- a/tests/ambsym/mambsym1.nim +++ b/tests/lookups/mambsym1.nim diff --git a/tests/ambsym/mambsym2.nim b/tests/lookups/mambsym2.nim index 21d980073..21d980073 100644 --- a/tests/ambsym/mambsym2.nim +++ b/tests/lookups/mambsym2.nim diff --git a/tests/lookups/mambsym3.nim b/tests/lookups/mambsym3.nim new file mode 100644 index 000000000..946a5ff29 --- /dev/null +++ b/tests/lookups/mambsym3.nim @@ -0,0 +1,4 @@ +# Module A +var x*: string +proc foo*(a: string) = + echo "A: ", a diff --git a/tests/lookups/mambsym4.nim b/tests/lookups/mambsym4.nim new file mode 100644 index 000000000..ed66cc16d --- /dev/null +++ b/tests/lookups/mambsym4.nim @@ -0,0 +1,4 @@ +# Module B +var x*: int +proc foo*(b: int) = + echo "B: ", b diff --git a/tests/ambsym/mambsys1.nim b/tests/lookups/mambsys1.nim index 22e54cb94..22e54cb94 100644 --- a/tests/ambsym/mambsys1.nim +++ b/tests/lookups/mambsys1.nim diff --git a/tests/ambsym/mambsys2.nim b/tests/lookups/mambsys2.nim index ef63e4f7e..ef63e4f7e 100644 --- a/tests/ambsym/mambsys2.nim +++ b/tests/lookups/mambsys2.nim diff --git a/tests/lookups/mambtype1.nim b/tests/lookups/mambtype1.nim new file mode 100644 index 000000000..47046142e --- /dev/null +++ b/tests/lookups/mambtype1.nim @@ -0,0 +1 @@ +type K* = object diff --git a/tests/lookups/mambtype2.nim b/tests/lookups/mambtype2.nim new file mode 100644 index 000000000..cf622466b --- /dev/null +++ b/tests/lookups/mambtype2.nim @@ -0,0 +1,4 @@ +import ./mambtype1 +export mambtype1 +template K*(kind: static int): auto = typedesc[mambtype1.K] +template B*(kind: static int): auto = typedesc[mambtype1.K] diff --git a/tests/bind/mbind3.nim b/tests/lookups/mbind3.nim index 1a7d3b63b..1a7d3b63b 100644 --- a/tests/bind/mbind3.nim +++ b/tests/lookups/mbind3.nim diff --git a/tests/lookups/mdisambsym1.nim b/tests/lookups/mdisambsym1.nim new file mode 100644 index 000000000..b8beca035 --- /dev/null +++ b/tests/lookups/mdisambsym1.nim @@ -0,0 +1,2 @@ +proc count*(s: string): int = + s.len diff --git a/tests/lookups/mdisambsym2.nim b/tests/lookups/mdisambsym2.nim new file mode 100644 index 000000000..1e056311d --- /dev/null +++ b/tests/lookups/mdisambsym2.nim @@ -0,0 +1 @@ +var count*: int = 10 diff --git a/tests/lookups/mdisambsym3.nim b/tests/lookups/mdisambsym3.nim new file mode 100644 index 000000000..95bd19702 --- /dev/null +++ b/tests/lookups/mdisambsym3.nim @@ -0,0 +1 @@ +const count* = 3.142 diff --git a/tests/lookups/mmacroamb.nim b/tests/lookups/mmacroamb.nim new file mode 100644 index 000000000..107e51055 --- /dev/null +++ b/tests/lookups/mmacroamb.nim @@ -0,0 +1,10 @@ +# issue #12732 + +import std/macros +const getPrivate3_tmp* = 0 +const foobar1* = 0 # comment this or make private and it'll compile fine +macro foobar4*(): untyped = + newLit "abc" +template currentPkgDir2*: string = foobar4() +macro currentPkgDir2*(dir: string): untyped = + newLit "abc2" diff --git a/tests/lookups/t23032.nim b/tests/lookups/t23032.nim new file mode 100644 index 000000000..144abcb05 --- /dev/null +++ b/tests/lookups/t23032.nim @@ -0,0 +1,13 @@ +discard """ +action: "run" +outputsub: "proc (a: A[system.float]): bool{.noSideEffect, gcsafe.}" +""" + +import issue_23032/deep_scope + +proc foo(a: A[float]):bool = true + +let p: proc = foo +echo p.typeof +doAssert p(A[float]()) == true +doAssert compiles(doAssert p(A[int]()) == true) == false diff --git a/tests/lookups/t23172.nim b/tests/lookups/t23172.nim new file mode 100644 index 000000000..9edf9905a --- /dev/null +++ b/tests/lookups/t23172.nim @@ -0,0 +1,9 @@ +import issue_23172/m23172 + +type FooX = distinct Foo + +func `$`*(x: FooX): string = + $m23172.Foo(x) + +var a: FooX +doAssert $a == "X" diff --git a/tests/lookups/t23749.nim b/tests/lookups/t23749.nim new file mode 100644 index 000000000..650f04ea4 --- /dev/null +++ b/tests/lookups/t23749.nim @@ -0,0 +1,37 @@ +discard """ + action: compile +""" + +{.pragma: callback, gcsafe, raises: [].} + +type + DataProc* = proc(val: openArray[byte]) {.callback.} + GetProc = proc (db: RootRef, key: openArray[byte], onData: DataProc): bool {.nimcall, callback.} + KvStoreRef* = ref object + obj: RootRef + getProc: GetProc + +template get(dbParam: KvStoreRef, key: openArray[byte], onData: untyped): bool = + let db = dbParam + db.getProc(db.obj, key, onData) + +func decode(input: openArray[byte], maxSize = 128): seq[byte] = + @[] + +proc getSnappySSZ(db: KvStoreRef, key: openArray[byte]): string = + var status = "not found" + proc decode(data: openArray[byte]) = + status = + if true: "found" + else: "corrupted" + discard db.get(key, decode) + status + + +var ksr: KvStoreRef +var k = [byte(1), 2, 3, 4, 5] + +proc foo(): string = + getSnappySSZ(ksr, toOpenArray(k, 1, 3)) + +echo foo() diff --git a/tests/lookups/tambiguousemit.nim b/tests/lookups/tambiguousemit.nim new file mode 100644 index 000000000..4f4bacce4 --- /dev/null +++ b/tests/lookups/tambiguousemit.nim @@ -0,0 +1,12 @@ +discard """ + cmd: "nim check $options $file" # use check to assure error is pre-codegen + matrix: "; --backend:js" # backend shouldn't matter but at least check js +""" + +proc foo(x: int) = discard +proc foo(x: float) = discard + +{.emit: ["// ", foo].} #[tt.Error + ^ ambiguous identifier: 'foo' -- use one of the following: + tambiguousemit.foo: proc (x: int){.noSideEffect, gcsafe.} + tambiguousemit.foo: proc (x: float){.noSideEffect, gcsafe.}]# diff --git a/tests/lookups/tambprocvar.nim b/tests/lookups/tambprocvar.nim new file mode 100644 index 000000000..f5c3fde4f --- /dev/null +++ b/tests/lookups/tambprocvar.nim @@ -0,0 +1,19 @@ +discard """ + action: reject + cmd: "nim check $file" + nimout: ''' +tambprocvar.nim(15, 11) Error: ambiguous identifier: 'foo' -- use one of the following: + tambprocvar.foo: proc (x: int){.noSideEffect, gcsafe.} + tambprocvar.foo: proc (x: float){.noSideEffect, gcsafe.} +''' +""" + +block: + proc foo(x: int) = discard + proc foo(x: float) = discard + + let x = foo + +block: + let x = `+` #[tt.Error + ^ ambiguous identifier: '+' -- use one of the following:]# diff --git a/tests/ambsym/tambsym.nim b/tests/lookups/tambsym.nim index bd0f41717..bd0f41717 100644 --- a/tests/ambsym/tambsym.nim +++ b/tests/lookups/tambsym.nim diff --git a/tests/ambsym/tambsym2.nim b/tests/lookups/tambsym2.nim index 747f1a086..747f1a086 100644 --- a/tests/ambsym/tambsym2.nim +++ b/tests/lookups/tambsym2.nim diff --git a/tests/ambsym/tambsym3.nim b/tests/lookups/tambsym3.nim index 0558517bd..6bbebca10 100644 --- a/tests/ambsym/tambsym3.nim +++ b/tests/lookups/tambsym3.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "ambiguous identifier" + errormsg: "ambiguous identifier: 'mDec' -- use one of the following:" file: "tambsym3.nim" line: 11 """ diff --git a/tests/lookups/tambsymmanual.nim b/tests/lookups/tambsymmanual.nim new file mode 100644 index 000000000..3ad91b8cc --- /dev/null +++ b/tests/lookups/tambsymmanual.nim @@ -0,0 +1,25 @@ +discard """ + output: ''' +A: abc +B: 123 +A: def +4 +''' +""" +# Module C +import mambsym3, mambsym4 + +foo("abc") # A: abc +foo(123) # B: 123 +let inferred: proc (x: string) = foo +foo("def") # A: def + +doAssert not compiles(write(stdout, x)) # error: x is ambiguous +write(stdout, mambsym3.x) # no error: qualifier used + +proc bar(a: int): int = a + 1 +doAssert bar(x) == x + 1 # no error: only A.x of type int matches + +var x = 4 +write(stdout, x) # not ambiguous: uses the module C's x +echo() # for test output diff --git a/tests/ambsym/tambsys.nim b/tests/lookups/tambsys.nim index aa740c38f..aa740c38f 100644 --- a/tests/ambsym/tambsys.nim +++ b/tests/lookups/tambsys.nim diff --git a/tests/lookups/tambtype.nim b/tests/lookups/tambtype.nim new file mode 100644 index 000000000..a292db83a --- /dev/null +++ b/tests/lookups/tambtype.nim @@ -0,0 +1,20 @@ +import ./mambtype2 + +block: # issue #23893 + discard default(K(0)) # works + discard default(mambtype2.B(0)) # works + discard default(mambtype2.K(0)) # doesn't work + +block: # issue #23898, in template + template r() = + discard default(B(0)) # compiles + discard default(mambtype2.B(0)) # compiles + discard default(K(0)) # does not compile + r() + +block: # in generics + proc foo[T]() = + discard default(B(0)) # compiles + discard default(mambtype2.B(0)) # compiles + discard default(K(0)) # does not compile + foo[int]() diff --git a/tests/bind/tbind.nim b/tests/lookups/tbind.nim index f3fb952e3..f3fb952e3 100644 --- a/tests/bind/tbind.nim +++ b/tests/lookups/tbind.nim diff --git a/tests/lookups/tdisambsym.nim b/tests/lookups/tdisambsym.nim new file mode 100644 index 000000000..678528ad6 --- /dev/null +++ b/tests/lookups/tdisambsym.nim @@ -0,0 +1,8 @@ +# issue #15247 + +import mdisambsym1, mdisambsym2, mdisambsym3 + +proc twice(n: int): int = + n*2 + +doAssert twice(count) == 20 diff --git a/tests/lookups/tenumlocalsym.nim b/tests/lookups/tenumlocalsym.nim new file mode 100644 index 000000000..575227c07 --- /dev/null +++ b/tests/lookups/tenumlocalsym.nim @@ -0,0 +1,22 @@ +block: + type Enum = enum a, b + + block: + let a = b + let x: Enum = a + doAssert x == b + +block: + type + Enum = enum + a = 2 + b = 10 + + iterator items2(): Enum = + for a in [a, b]: + yield a + + var s = newSeq[Enum]() + for i in items2(): + s.add i + doAssert s == @[a, b] diff --git a/tests/gensym/tgensym.nim b/tests/lookups/tgensym.nim index e33a2783f..e33a2783f 100644 --- a/tests/gensym/tgensym.nim +++ b/tests/lookups/tgensym.nim diff --git a/tests/gensym/tgensymgeneric.nim b/tests/lookups/tgensymgeneric.nim index c17a0715f..6e1df4842 100644 --- a/tests/gensym/tgensymgeneric.nim +++ b/tests/lookups/tgensymgeneric.nim @@ -21,7 +21,7 @@ template genImpl() = gensymed.x = "abc" else: gensymed.x = 123 - shallowCopy(result, gensymed) + result = move gensymed proc gen[T](x: T): T = genImpl() diff --git a/tests/bind/tinvalidbindtypedesc.nim b/tests/lookups/tinvalidbindtypedesc.nim index 1c71c8daf..1c71c8daf 100644 --- a/tests/bind/tinvalidbindtypedesc.nim +++ b/tests/lookups/tinvalidbindtypedesc.nim diff --git a/tests/lookups/tmacroamb.nim b/tests/lookups/tmacroamb.nim new file mode 100644 index 000000000..854017e72 --- /dev/null +++ b/tests/lookups/tmacroamb.nim @@ -0,0 +1,5 @@ +# issue #12732 + +import mmacroamb +const s0 = currentPkgDir2 #[tt.Error + ^ ambiguous identifier: 'currentPkgDir2' -- use one of the following:]# diff --git a/tests/lookups/tmoduleclash1.nim b/tests/lookups/tmoduleclash1.nim new file mode 100644 index 000000000..7058f691e --- /dev/null +++ b/tests/lookups/tmoduleclash1.nim @@ -0,0 +1,13 @@ +# issue #23596 + +import std/heapqueue +type Algo = enum heapqueue, quick +when false: + let x = heapqueue +let y: Algo = heapqueue +proc bar*(algo=quick) = + var x: HeapQueue[int] + case algo + of heapqueue: echo 1 # `Algo.heapqueue` works on devel + of quick: echo 2 + echo x.len diff --git a/tests/lookups/tmoduleclash2.nim b/tests/lookups/tmoduleclash2.nim new file mode 100644 index 000000000..958da2299 --- /dev/null +++ b/tests/lookups/tmoduleclash2.nim @@ -0,0 +1,6 @@ +import std/heapqueue +proc heapqueue(x: int) = discard +let x: proc (x: int) = heapqueue +let y: proc = heapqueue +when false: + let z = heapqueue diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/lookups/tnicerrorforsymchoice.nim index 684b83239..6001b6b09 100644 --- a/tests/bind/tnicerrorforsymchoice.nim +++ b/tests/lookups/tnicerrorforsymchoice.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}>" + errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe.}>" line: 23 """ diff --git a/tests/bind/told_bind_expr.nim b/tests/lookups/told_bind_expr.nim index 56389eaf6..56389eaf6 100644 --- a/tests/bind/told_bind_expr.nim +++ b/tests/lookups/told_bind_expr.nim diff --git a/tests/lookups/tundeclaredmixin.nim b/tests/lookups/tundeclaredmixin.nim new file mode 100644 index 000000000..74d16cdde --- /dev/null +++ b/tests/lookups/tundeclaredmixin.nim @@ -0,0 +1,17 @@ +discard """ + nimout: ''' + mixin nothing, add +''' +""" + +# issue #22012 + +import macros + +expandMacros: + proc foo[T](): int = + # `nothing` is undeclared, `add` is declared + mixin nothing, add + 123 + + doAssert foo[int]() == 123 diff --git a/tests/macros/t14329.nim b/tests/macros/t14329.nim new file mode 100644 index 000000000..b5606424a --- /dev/null +++ b/tests/macros/t14329.nim @@ -0,0 +1,4 @@ +import macros + +macro myMacro(n) = + let x = if true: newLit"test" else: error "error", n diff --git a/tests/macros/t15691.nim b/tests/macros/t15691.nim new file mode 100644 index 000000000..c1e8a8648 --- /dev/null +++ b/tests/macros/t15691.nim @@ -0,0 +1,22 @@ +discard """ + action: compile +""" + +import std/macros + +macro simplifiedExpandMacros(body: typed): untyped = + result = body + +simplifiedExpandMacros: + proc testProc() = discard + +simplifiedExpandMacros: + template testTemplate(): untyped = discard + +# Error: illformed AST: macro testMacro(): untyped = +simplifiedExpandMacros: + macro testMacro(): untyped = discard + +# Error: illformed AST: converter testConverter(x: int): float = +simplifiedExpandMacros: + converter testConverter(x: int): float = discard diff --git a/tests/macros/t15751.nim b/tests/macros/t15751.nim new file mode 100644 index 000000000..fcabb2f9e --- /dev/null +++ b/tests/macros/t15751.nim @@ -0,0 +1,11 @@ +discard """ + cmd: "nim c --hints:off $file" + nimout: "out" +""" + +# bug #15751 +macro print(n: untyped): untyped = + echo n.repr + +print: + out diff --git a/tests/macros/t16758.nim b/tests/macros/t16758.nim new file mode 100644 index 000000000..66b6d42c5 --- /dev/null +++ b/tests/macros/t16758.nim @@ -0,0 +1,38 @@ +discard """ +errormsg: "'blk.p(a)' has nil child at index 1" +action: reject +""" +import macros + +type BlockLiteral[T] = object + p: T + +proc p[T](a:int) = echo 1 +proc p[T](a:string) = echo "a" + +iterator arguments(formalParams: NimNode): NimNode = + var iParam = 0 + for i in 1 ..< formalParams.len: + let pp = formalParams[i] + for j in 0 .. pp.len - 3: + yield pp[j] + inc iParam + +macro implementInvoke(T: typedesc): untyped = + let t = getTypeImpl(T)[1] + + let call = newCall(newDotExpr(ident"blk", ident"p")) + let params = copyNimTree(t[0]) + result = newProc(ident"invoke", body = call) + # result[2] = newTree(nnkGenericParams,T) + for n in arguments(params): + call.add(n) + + params.insert(1, newIdentDefs(ident"blk", newTree(nnkBracketExpr, bindSym"BlockLiteral", T))) + result.params = params + +proc getInvoke(T: typedesc) = + implementInvoke(T) + + +getInvoke(proc(a: int)) diff --git a/tests/macros/t19766_20114.nim b/tests/macros/t19766_20114.nim new file mode 100644 index 000000000..ac336f150 --- /dev/null +++ b/tests/macros/t19766_20114.nim @@ -0,0 +1,16 @@ +discard """ + action: compile + nimout: ''' +const + foo {.strdefine.} = "abc" +let hey {.tddd.} = 5 +''' +""" + +import macros + +template tddd {.pragma.} + +expandMacros: + const foo {.strdefine.} = "abc" + let hey {.tddd.} = 5 diff --git a/tests/macros/t20435.nim b/tests/macros/t20435.nim new file mode 100644 index 000000000..824282198 --- /dev/null +++ b/tests/macros/t20435.nim @@ -0,0 +1,30 @@ + +#[ + A better test requires matching, so the use of @ working can be showcased + For example: + + proc regularCase[T]() = + case [(1, 3), (3, 4)]: + of [(1, @a), (_, @b)]: + echo a, b + else: discard +]# + +{.experimental: "caseStmtMacros".} + +import macros + +type Foo = object + +macro `case`(obj: Foo) = quote do: discard + +proc notGeneric() = + case Foo() + of a b c d: discard + +proc generic[T]() = + case Foo() + of a b c d: discard + +notGeneric() +generic[int]() diff --git a/tests/macros/t21593.nim b/tests/macros/t21593.nim new file mode 100644 index 000000000..b0b7ebe75 --- /dev/null +++ b/tests/macros/t21593.nim @@ -0,0 +1,13 @@ +discard """ +nimout: ''' +StmtList + UIntLit 18446744073709551615 + IntLit -1''' +""" + +import macros + +dumpTree: + 0xFFFFFFFF_FFFFFFFF'u + 0xFFFFFFFF_FFFFFFFF + diff --git a/tests/macros/t23032_1.nim b/tests/macros/t23032_1.nim new file mode 100644 index 000000000..4e1707414 --- /dev/null +++ b/tests/macros/t23032_1.nim @@ -0,0 +1,19 @@ +import std/macros + +type A[T, H] = object + +proc `%*`(a: A): bool = true +proc `%*`[T](a: A[int, T]): bool = false + +macro collapse(s: untyped) = + result = newStmtList() + result.add quote do: + doAssert(`s`(A[float, int]()) == true) + +macro startHere(n: untyped): untyped = + result = newStmtList() + let s = n[0] + result.add quote do: + `s`.collapse() + +startHere(`a` %* `b`) diff --git a/tests/macros/t23032_2.nim b/tests/macros/t23032_2.nim new file mode 100644 index 000000000..8dde29e10 --- /dev/null +++ b/tests/macros/t23032_2.nim @@ -0,0 +1,20 @@ +discard """ + action: "reject" + errormsg: "ambiguous identifier: '%*'" +""" +import std/macros + +type A[T, H] = object + +proc `%*`[T](a: A) = discard +proc `%*`[T](a: A[int, T]) = discard + +macro collapse(s: typed) = discard + +macro startHere(n: untyped): untyped = + result = newStmtList() + let s = n[0] + result.add quote do: + collapse(`s`.typeof()) + +startHere(`a` %* `b`) diff --git a/tests/macros/t23547.nim b/tests/macros/t23547.nim new file mode 100644 index 000000000..9a2bff9ff --- /dev/null +++ b/tests/macros/t23547.nim @@ -0,0 +1,23 @@ +# https://github.com/nim-lang/Nim/issues/23547 + +type + A[T] = object + x: T + +proc mulCheckSparse[F](dummy: var A[F], xmulchecksparse: static A[F]) = + static: + echo "mulCheckSparse: ", typeof(dummy), ", ", typeof(xmulchecksparse) # when generic params not specified: A[system.int], A + +template sumImpl(xsumimpl: typed) = + static: + echo "sumImpl: ", typeof(xsumimpl) # A + var a = A[int](x: 55) + mulCheckSparse(a, xsumimpl) # fails here + +proc sum[T](xsum: static T) = + static: + echo "sum: ", typeof(xsum) # A[system.int] + sumImpl(xsum) + +const constA = A[int](x : 100) +sum[A[int]](constA) diff --git a/tests/macros/t23784.nim b/tests/macros/t23784.nim new file mode 100644 index 000000000..31b4544c6 --- /dev/null +++ b/tests/macros/t23784.nim @@ -0,0 +1,157 @@ +discard """ + joinable: false +""" + + +# debug ICE: genCheckedRecordField +# apparently after https://github.com/nim-lang/Nim/pull/23477 + +# bug #23784 + +import std/bitops, std/macros + +# -------------------------------------------------------------- + +type Algebra = enum + BN254_Snarks + +type SecretWord* = distinct uint64 +const WordBitWidth* = sizeof(SecretWord) * 8 + +func wordsRequired*(bits: int): int {.inline.} = + const divShiftor = fastLog2(WordBitWidth) + result = (bits + WordBitWidth - 1) shr divShiftor + +type + BigInt*[bits: static int] = object + limbs*: array[bits.wordsRequired, SecretWord] # <--- crash points to here + +# -------------------------------------------------------------- + +const CurveBitWidth = [ + BN254_Snarks: 254 +] + +const BN254_Snarks_Modulus = BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x2, SecretWord 0x3, SecretWord 0x4]) +const BN254_Snarks_Order = BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x1, SecretWord 0x2, SecretWord 0x2]) + +func montyOne*(M: BigInt[254]): BigInt[254] = + ## Returns "1 (mod M)" in the Montgomery domain. + ## This is equivalent to R (mod M) in the natural domain + BigInt[254](limbs: [SecretWord 0x1, SecretWord 0x1, SecretWord 0x1, SecretWord 0x1]) + + +{.experimental: "dynamicBindSym".} + +type + DerivedConstantMode* = enum + kModulus + kOrder + +macro genDerivedConstants*(mode: static DerivedConstantMode): untyped = + ## Generate constants derived from the main constants + ## + ## For example + ## - the Montgomery magic constant "R^2 mod N" in ROM + ## For each curve under the private symbol "MyCurve_R2modP" + ## - the Montgomery magic constant -1/P mod 2^Wordbitwidth + ## For each curve under the private symbol "MyCurve_NegInvModWord + ## - ... + + # Now typedesc are NimNode and there is no way to translate + # NimNode -> typedesc easily so we can't + # "for curve in low(Curve) .. high(Curve):" + # As an ugly workaround, we count + # The item at position 0 is a pragma + result = newStmtList() + + template used(name: string): NimNode = + nnkPragmaExpr.newTree( + ident(name), + nnkPragma.newTree(ident"used") + ) + + let ff = if mode == kModulus: "_Fp" else: "_Fr" + + for curveSym in low(Algebra) .. high(Algebra): + let curve = $curveSym + let M = if mode == kModulus: bindSym(curve & "_Modulus") + else: bindSym(curve & "_Order") + + # const MyCurve_montyOne = montyOne(MyCurve_Modulus) + result.add newConstStmt( + used(curve & ff & "_MontyOne"), newCall( + bindSym"montyOne", + M + ) + ) + +# -------------------------------------------------------------- + +{.experimental: "dynamicBindSym".} + +genDerivedConstants(kModulus) +genDerivedConstants(kOrder) + +proc bindConstant(ff: NimNode, property: string): NimNode = + # Need to workaround https://github.com/nim-lang/Nim/issues/14021 + # which prevents checking if a type FF[Name] = Fp[Name] or Fr[Name] + # was instantiated with Fp or Fr. + # getTypeInst only returns FF and sameType doesn't work. + # so quote do + when checks. + let T = getTypeInst(ff) + T.expectKind(nnkBracketExpr) + doAssert T[0].eqIdent("typedesc") + + let curve = + if T[1].kind == nnkBracketExpr: # typedesc[Fp[BLS12_381]] as used internally + # doAssert T[1][0].eqIdent"Fp" or T[1][0].eqIdent"Fr", "Found ident: '" & $T[1][0] & "' instead of 'Fp' or 'Fr'" + T[1][1].expectKind(nnkIntLit) # static enum are ints in the VM + $Algebra(T[1][1].intVal) + else: # typedesc[bls12381_fp] alias as used for C exports + let T1 = getTypeInst(T[1].getImpl()[2]) + if T1.kind != nnkBracketExpr or + T1[1].kind != nnkIntLit: + echo T.repr() + echo T1.repr() + echo getTypeInst(T1).treerepr() + error "getTypeInst didn't return the full instantiation." & + " Dealing with types in macros is hard, complain at https://github.com/nim-lang/RFCs/issues/44" + $Algebra(T1[1].intVal) + + let curve_fp = bindSym(curve & "_Fp_" & property) + let curve_fr = bindSym(curve & "_Fr_" & property) + result = quote do: + when `ff` is Fp: + `curve_fp` + elif `ff` is Fr: + `curve_fr` + else: + {.error: "Unreachable, received type: " & $`ff`.} + +# -------------------------------------------------------------- + +template matchingBigInt*(Name: static Algebra): untyped = + ## BigInt type necessary to store the prime field Fp + # Workaround: https://github.com/nim-lang/Nim/issues/16774 + # as we cannot do array accesses in type section. + # Due to generic sandwiches, it must be exported. + BigInt[CurveBitWidth[Name]] + +type + Fp*[Name: static Algebra] = object + mres*: matchingBigInt(Name) + +macro getMontyOne*(ff: type Fp): untyped = + ## Get one in Montgomery representation (i.e. R mod P) + result = bindConstant(ff, "MontyOne") + +func getOne*(T: type Fp): T {.noInit, inline.} = + result = cast[ptr T](unsafeAddr getMontyOne(T))[] + +# -------------------------------------------------------------- +proc foo(T: Fp) = + discard T + +let a = Fp[BN254_Snarks].getOne() +foo(a) # oops this was a leftover that broke the bisect. diff --git a/tests/macros/tastrepr.nim b/tests/macros/tastrepr.nim index 759ca55b5..96a37c7a2 100644 --- a/tests/macros/tastrepr.nim +++ b/tests/macros/tastrepr.nim @@ -8,7 +8,11 @@ for i, d in pairs(data): discard for i, (x, y) in pairs(data): discard -var (a, b) = (1, 2) +var + a = 1 + b = 2 +type + A* = object var data = @[(1, "one"), (2, "two")] for (i, d) in pairs(data): @@ -18,6 +22,11 @@ for i, d in pairs(data): for i, (x, y) in pairs(data): discard var (a, b) = (1, 2) +type + A* = object + +var t04 = 1.0'f128 +t04 = 2.0'f128 ''' """ @@ -42,3 +51,8 @@ echoTypedAndUntypedRepr: for i, (x,y) in pairs(data): discard var (a,b) = (1,2) + type A* = object # issue #22933 + +echoUntypedRepr: + var t04 = 1'f128 + t04 = 2'f128 diff --git a/tests/macros/tfail_parse.nim b/tests/macros/tfail_parse.nim new file mode 100644 index 000000000..1925f2b69 --- /dev/null +++ b/tests/macros/tfail_parse.nim @@ -0,0 +1,15 @@ +discard """ +action: "reject" +cmd: "nim check $file" +errormsg: "expected expression, but got multiple statements [ValueError]" +file: "macros.nim" +""" + +import macros +static: + discard parseStmt("'") + discard parseExpr("'") + discard parseExpr(""" +proc foo() +proc foo() = discard +""") diff --git a/tests/macros/tgetimpl.nim b/tests/macros/tgetimpl.nim index de132f253..ab33131b0 100644 --- a/tests/macros/tgetimpl.nim +++ b/tests/macros/tgetimpl.nim @@ -1,5 +1,5 @@ discard """ - nimout: '''"muhaha" + nimout: '''foo = "muhaha" proc poo(x, y: int) = let y = x echo ["poo"]''' @@ -44,10 +44,11 @@ static: doAssert checkOwner(poo, 2) == "nskProc" doAssert checkOwner(poo, 3) == "nskModule" doAssert isSameOwner(foo, poo) - doAssert isSameOwner(foo, echo) == false - doAssert isSameOwner(poo, len) == false - -#--------------------------------------------------------------- + proc wrappedScope() = + proc dummyproc() = discard + doAssert isSameOwner(foo, dummyproc) == false + doAssert isSameOwner(poo, dummyproc) == false + wrappedScope() macro check_gen_proc(ex: typed): (bool, bool) = let lenChoice = bindsym"len" @@ -72,7 +73,9 @@ assert: check_gen_proc(len(a)) == (false, true) macro check(x: type): untyped = let z = getType(x) let y = getImpl(z[1]) - let sym = if y[0].kind == nnkSym: y[0] else: y[0][0] + var sym = y[0] + if sym.kind == nnkPragmaExpr: sym = sym[0] + if sym.kind == nnkPostfix: sym = sym[1] expectKind(z[1], nnkSym) expectKind(sym, nnkSym) expectKind(y[2], nnkObjectTy) diff --git a/tests/macros/tgettypeinst7737.nim b/tests/macros/tgettypeinst7737.nim new file mode 100644 index 000000000..e49f82562 --- /dev/null +++ b/tests/macros/tgettypeinst7737.nim @@ -0,0 +1,61 @@ +discard """ + nimout: ''' +seq[int] +CustomSeq[int] +''' +""" + +import macros, typetraits, sequtils + +block: # issue #7737 original + type + CustomSeq[T] = object + data: seq[T] + + proc getSubType(T: NimNode): NimNode = + echo getTypeInst(T).repr + result = getTypeInst(T)[1] + + macro typed_helper(x: varargs[typed]): untyped = + let foo = getSubType(x[0]) + result = quote do: discard + + macro untyped_heavylifting(x: varargs[untyped]): untyped = + var containers = nnkArgList.newTree() + for arg in x: + case arg.kind: + of nnkInfix: + if eqIdent(arg[0], "in"): + containers.add arg[2] + else: + discard + result = quote do: + typed_helper(`containers`) + var a, b, c: seq[int] + untyped_heavylifting z in c, x in a, y in b: + discard + ## The following gives me CustomSeq instead + ## of CustomSeq[int] in getTypeInst + var u, v, w: CustomSeq[int] + untyped_heavylifting z in u, x in v, y in w: + discard + +block: # issue #7737 comment + type + CustomSeq[T] = object + data: seq[T] + # when using just one argument, `foo` and `bar` should be exactly + # identical. + macro foo(arg: typed): string = + result = newLit(arg.getTypeInst.repr) + macro bar(args: varargs[typed]): untyped = + result = newTree(nnkBracket) + for arg in args: + result.add newLit(arg.getTypeInst.repr) + var + a: seq[int] + b: CustomSeq[int] + doAssert foo(a) == "seq[int]" + doAssert bar(a) == ["seq[int]"] + doAssert foo(b) == "CustomSeq[int]" + doAssert bar(b) == ["CustomSeq[int]"] diff --git a/tests/macros/tmacros_various.nim b/tests/macros/tmacros_various.nim index d702db56a..e351b4527 100644 --- a/tests/macros/tmacros_various.nim +++ b/tests/macros/tmacros_various.nim @@ -91,7 +91,7 @@ block tlexerex: -block tlineinfo: +block tcopylineinfo: # issue #5617, feature request type Test = object @@ -103,6 +103,27 @@ block tlineinfo: var z = mixer(Test) doAssert z +block tsetgetlineinfo: + # issue #21098, feature request + type Test = object + + macro mixer1(n: typed): untyped = + let x = newIdentNode("echo") + var lineInfo = n.lineInfoObj + x.setLineInfo lineInfo + result = newLit(x.lineInfo == n.lineInfo) + + macro mixer2(n: typed): untyped = + let x = newIdentNode("echo") + var lineInfo = n.lineInfoObj + lineInfo.line += 1 + x.setLineInfo lineInfo + result = newLit(x.lineInfo != n.lineInfo) + + doAssert mixer1(Test) + + doAssert mixer2(Test) + block tdebugstmt: @@ -247,6 +268,37 @@ xbenchmark: discard inputtest fastSHA("hey") +block: # issue #4547 + macro lazy(stmtList : typed) : untyped = + let decl = stmtList[0] + decl.expectKind nnkLetSection + let name = decl[0][0].strVal + let call = decl[0][2].copy + call.expectKind nnkCall + let ident = newIdentNode("get" & name) + result = quote do: + var value : type(`call`) + proc `ident`() : type(`call`) = + if value.isNil: + value = `call` + value + type MyObject = object + a,b: int + # this part, the macro call and it's result (written in the comment below) is important + lazy: + let y = new(MyObject) + #[ + var value: type(new(MyObject)) + proc gety(): type(new(MyObject)) = + if value.isNil: + value = new(MyObject) + value + ]# + doAssert gety().a == 0 # works and should work + doAssert gety().b == 0 # works and should work + doAssert not declared(y) + doAssert not compiles(y.a) # identifier y should not exist anymore + doAssert not compiles(y.b) # identifier y should not exist anymore block: # bug #13511 type @@ -330,3 +382,10 @@ block: # bug #15118 block: flop("b") + +static: + block: + const containsTable = CacheTable"containsTable" + doAssert "foo" notin containsTable + containsTable["foo"] = newLit 42 + doAssert "foo" in containsTable diff --git a/tests/macros/tmacrostmt.nim b/tests/macros/tmacrostmt.nim index 79be5f764..817bc8352 100644 --- a/tests/macros/tmacrostmt.nim +++ b/tests/macros/tmacrostmt.nim @@ -124,7 +124,7 @@ static: let fn4s = "proc fn4(x: int): int =\n if x mod 2 == 0:\n return x + 2\n else:\n return 0\n" let fn5s = "proc fn5(a, b: float): float =\n result = -a * a / (b * b)\n" let fn6s = "proc fn6() =\n var a = @[1.0, 2.0]\n let z = a{0, 1}\n a{2} = 5.0\n" - let fnAddr = "proc fn_unsafeaddr(x: int): int =\n result = cast[int](unsafeAddr(x))\n" + let fnAddr = "proc fn_unsafeaddr(x: int): int =\n result = cast[int](addr(x))\n" doAssert fn1.repr_to_string == fn1s doAssert fn2.repr_to_string == fn2s diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim index 43819c81d..13b421303 100644 --- a/tests/macros/tmacrotypes.nim +++ b/tests/macros/tmacrotypes.nim @@ -1,9 +1,9 @@ discard """ - nimout: '''intProc; ntyProc; proc[int, int, float]; proc (a: int; b: float): int + nimout: '''intProc; ntyProc; proc[int, int, float]; proc (a: int; b: float): int {.nimcall.} void; ntyVoid; void; void int; ntyInt; int; int -proc (); ntyProc; proc[void]; proc () -voidProc; ntyProc; proc[void]; proc () +proc () {.nimcall.}; ntyProc; proc[void]; proc () {.nimcall.} +voidProc; ntyProc; proc[void]; proc () {.nimcall.} listing fields for ObjType a: string b: int diff --git a/tests/macros/tprocgettype.nim b/tests/macros/tprocgettype.nim new file mode 100644 index 000000000..0c1cc4270 --- /dev/null +++ b/tests/macros/tprocgettype.nim @@ -0,0 +1,28 @@ +discard """ + nimout: ''' +var x: proc () {.cdecl.} = foo +var x: iterator (): int {.closure.} = bar +''' +""" + +# issue #19010 + +import macros + +macro createVar(x: typed): untyped = + result = nnkVarSection.newTree: + newIdentDefs(ident"x", getTypeInst(x), copy(x)) + + echo repr result + +block: + proc foo() {.cdecl.} = discard + + createVar(foo) + x() + +block: + iterator bar(): int {.closure.} = discard + + createVar(bar) + for a in x(): discard diff --git a/tests/macros/tstaticparamsmacro.nim b/tests/macros/tstaticparamsmacro.nim index 8bd653920..2632ca730 100644 --- a/tests/macros/tstaticparamsmacro.nim +++ b/tests/macros/tstaticparamsmacro.nim @@ -7,9 +7,9 @@ numbers 11 22 AST a -[(11, 22), (33, 44)] +@[(c: 11, d: 22), (c: 33, d: 44)] AST b -([55, 66], [77, 88]) +(e: @[55, 66], f: @[77, 88]) 55 10 20Test diff --git a/tests/macros/tstructuredlogging.nim b/tests/macros/tstructuredlogging.nim index 5e4fdea3f..649c6c0bd 100644 --- a/tests/macros/tstructuredlogging.nim +++ b/tests/macros/tstructuredlogging.nim @@ -1,7 +1,7 @@ discard """ output: ''' main started: a=10, b=inner-b, c=10, d=some-d, x=16, z=20 -exiting: a=12, b=overriden-b, c=100, msg=bye bye, x=16 +exiting: a=12, b=overridden-b, c=100, msg=bye bye, x=16 ''' """ @@ -134,7 +134,7 @@ scope: scope: x = 16 - b = "overriden-b" + b = "overridden-b" scope: c = 100 diff --git a/tests/macros/ttemplatesymbols.nim b/tests/macros/ttemplatesymbols.nim index 280b34ff1..3182de79d 100644 --- a/tests/macros/ttemplatesymbols.nim +++ b/tests/macros/ttemplatesymbols.nim @@ -148,8 +148,6 @@ proc overloadedProc[T](x: T) = echo x """ - # XXX: There seems to be a repr rendering problem above. - # Notice that `echo [x]` inspectSymbol overloadedProc[float], """ proc overloadedProc(x: T) = diff --git a/tests/macros/ttryparseexpr.nim b/tests/macros/ttryparseexpr.nim index fc0ee61d0..e6e9e9880 100644 --- a/tests/macros/ttryparseexpr.nim +++ b/tests/macros/ttryparseexpr.nim @@ -18,3 +18,7 @@ const c = test("\"") # bug #2504 echo a, " ", b + +static: + # Issue #9918 + discard parseStmt("echo(1+1);") diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim index e2c1b0a04..0ad57167b 100644 --- a/tests/manyloc/argument_parser/argument_parser.nim +++ b/tests/manyloc/argument_parser/argument_parser.nim @@ -168,14 +168,14 @@ template new_parsed_parameter*(tkind: Tparam_kind, expr): Tparsed_parameter = ## initialised with. The template figures out at compile time what field to ## assign the variable to, and thus you reduce code clutter and may use this ## to initialise single assignments variables in `let` blocks. Example: - ## - ## .. code-block:: nim + ## ```nim ## let ## parsed_param1 = new_parsed_parameter(PK_FLOAT, 3.41) ## parsed_param2 = new_parsed_parameter(PK_BIGGEST_INT, 2358123 * 23123) ## # The following line doesn't compile due to ## # type mismatch: got <string> but expected 'int' ## #parsed_param3 = new_parsed_parameter(PK_INT, "231") + ## ``` var result {.gensym.}: Tparsed_parameter result.kind = tkind when tkind == PK_EMPTY: discard diff --git a/tests/manyloc/keineschweine/dependencies/nake/nake.nim b/tests/manyloc/keineschweine/dependencies/nake/nake.nim index e466ee5e1..36538097e 100644 --- a/tests/manyloc/keineschweine/dependencies/nake/nake.nim +++ b/tests/manyloc/keineschweine/dependencies/nake/nake.nim @@ -69,7 +69,7 @@ else: var task: string printTaskList: bool - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdLongOption, cmdShortOption: case key.tolower diff --git a/tests/manyloc/keineschweine/enet_server/enet_server.nim b/tests/manyloc/keineschweine/enet_server/enet_server.nim index 794e1c843..86d0ab360 100644 --- a/tests/manyloc/keineschweine/enet_server/enet_server.nim +++ b/tests/manyloc/keineschweine/enet_server/enet_server.nim @@ -113,7 +113,7 @@ when true: block: var zoneCfgFile = "./server_settings.json" - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdShortOption, cmdLongOption: case key diff --git a/tests/manyloc/keineschweine/enet_server/server_utils.nim b/tests/manyloc/keineschweine/enet_server/server_utils.nim index 1fb8326ed..3940dcf01 100644 --- a/tests/manyloc/keineschweine/enet_server/server_utils.nim +++ b/tests/manyloc/keineschweine/enet_server/server_utils.nim @@ -1,4 +1,6 @@ -import enet, sg_packets, estreams, md5, zlib_helpers, client_helpers, strutils, +import ../../../../dist/checksums/src/checksums/md5 + +import enet, sg_packets, estreams, zlib_helpers, client_helpers, strutils, idgen, sg_assets, tables, os type PClient* = ref object diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index cde31bd18..123a4aebb 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -691,7 +691,7 @@ when true: block: var bPlayOffline = false - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdArgument: if key == "offline": bPlayOffline = true diff --git a/tests/manyloc/keineschweine/keineschweine.nim.cfg b/tests/manyloc/keineschweine/keineschweine.nim.cfg index ca6c75f6e..a670e2b77 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim.cfg +++ b/tests/manyloc/keineschweine/keineschweine.nim.cfg @@ -7,3 +7,4 @@ path = "dependencies/genpacket" path = "enet_server" debugger = off warning[SmallLshouldNotBeUsed] = off +mm = refc diff --git a/tests/manyloc/keineschweine/lib/client_helpers.nim b/tests/manyloc/keineschweine/lib/client_helpers.nim index b535225dc..b21e67cf7 100644 --- a/tests/manyloc/keineschweine/lib/client_helpers.nim +++ b/tests/manyloc/keineschweine/lib/client_helpers.nim @@ -1,6 +1,8 @@ +import ../../../../dist/checksums/src/checksums/md5 + import tables, sg_packets, enet, estreams, sg_gui, sfml, - zlib_helpers, md5, sg_assets, os + zlib_helpers, sg_assets, os type PServer* = ptr TServer TServer* = object diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim index 5ab029b52..c5e45e0e7 100644 --- a/tests/manyloc/keineschweine/lib/estreams.nim +++ b/tests/manyloc/keineschweine/lib/estreams.nim @@ -78,9 +78,9 @@ proc write*(buffer: PBuffer; val: var string) = setLen buffer.data, buffer.pos + length.int copyMem(addr buffer.data[buffer.pos], addr val[0], length.int) inc buffer.pos, length.int -proc write*[T: SomeNumber|bool|char|byte](buffer: PBuffer; val: T) = +proc write*[T: SomeNumber|bool|char|byte](buffer: PBuffer; val: sink T) = var v: T - shallowCopy v, val + v = val writeBE buffer, v proc readInt8*(buffer: PBuffer): int8 = diff --git a/tests/manyloc/keineschweine/lib/sg_assets.nim b/tests/manyloc/keineschweine/lib/sg_assets.nim index 5929add43..96c962dc3 100644 --- a/tests/manyloc/keineschweine/lib/sg_assets.nim +++ b/tests/manyloc/keineschweine/lib/sg_assets.nim @@ -1,6 +1,8 @@ +import ../../../../dist/checksums/src/checksums/md5 + import re, json, strutils, tables, math, os, math_helpers, - sg_packets, md5, zlib_helpers + sg_packets, zlib_helpers when defined(NoSFML): import server_utils diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim index 0727c699a..797a60706 100644 --- a/tests/manyloc/keineschweine/lib/sg_packets.nim +++ b/tests/manyloc/keineschweine/lib/sg_packets.nim @@ -1,4 +1,6 @@ -import genpacket_enet, nativesockets, net, md5, enet +import ../../../../dist/checksums/src/checksums/md5 + +import genpacket_enet, nativesockets, net, enet defPacketImports() type diff --git a/tests/manyloc/keineschweine/server/old_dirserver.nim b/tests/manyloc/keineschweine/server/old_dirserver.nim index cd2b60b26..a63829691 100644 --- a/tests/manyloc/keineschweine/server/old_dirserver.nim +++ b/tests/manyloc/keineschweine/server/old_dirserver.nim @@ -1,9 +1,9 @@ ## directory server ## handles client authorization and assets - +import ../../../dist/checksums/src/checksums/md5 import sockets, times, streams, streams_enh, tables, json, os, - sg_packets, sg_assets, md5, server_utils, map_filter + sg_packets, sg_assets, server_utils, map_filter type THandler = proc(client: PCLient; stream: PStream) var @@ -159,7 +159,7 @@ proc poll*(timeout: int = 250) = when true: import parseopt, strutils var cfgFile = "dirserver_settings.json" - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdShortOption, cmdLongOption: case key diff --git a/tests/manyloc/keineschweine/server/old_server_utils.nim b/tests/manyloc/keineschweine/server/old_server_utils.nim index 3da6e078c..f389c0836 100644 --- a/tests/manyloc/keineschweine/server/old_server_utils.nim +++ b/tests/manyloc/keineschweine/server/old_server_utils.nim @@ -1,5 +1,7 @@ +import ../../../dist/checksums/src/checksums/md5 + import - streams, md5, sockets, + streams, sockets, sg_packets, zlib_helpers, idgen type TClientType* = enum diff --git a/tests/manyloc/keineschweine/server/old_sg_server.nim b/tests/manyloc/keineschweine/server/old_sg_server.nim index 8bd44017e..d6fbbe99e 100644 --- a/tests/manyloc/keineschweine/server/old_sg_server.nim +++ b/tests/manyloc/keineschweine/server/old_sg_server.nim @@ -144,7 +144,7 @@ proc poll*(timeout: int = 250) = when true: import parseopt, strutils var zoneCfgFile = "./server_settings.json" - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdShortOption, cmdLongOption: case key diff --git a/tests/manyloc/keineschweine/server/sg_lobby.nim b/tests/manyloc/keineschweine/server/sg_lobby.nim index d7e01e6e6..04ce10f08 100644 --- a/tests/manyloc/keineschweine/server/sg_lobby.nim +++ b/tests/manyloc/keineschweine/server/sg_lobby.nim @@ -1,6 +1,7 @@ +import ../../../dist/checksums/src/checksums/md5 import - sockets, streams, tables, times, math, strutils, json, os, md5, + sockets, streams, tables, times, math, strutils, json, os, sfml, sfml_vector, sfml_colors, streams_enh, input_helpers, zlib_helpers, client_helpers, sg_packets, sg_assets, sg_gui type diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim index ce7faab5c..5d3173a20 100644 --- a/tests/manyloc/nake/nake.nim +++ b/tests/manyloc/nake/nake.nim @@ -65,7 +65,7 @@ else: var task: string printTaskList: bool - for kind, key, val in getOpt(): + for kind, key, val in getopt(): case kind of cmdLongOption, cmdShortOption: case key.tolowerAscii diff --git a/tests/metatype/tcompositetypeclasses.nim b/tests/metatype/tcompositetypeclasses.nim index d125b119b..43b6a57e4 100644 --- a/tests/metatype/tcompositetypeclasses.nim +++ b/tests/metatype/tcompositetypeclasses.nim @@ -30,7 +30,7 @@ accept bar(vbar) accept baz(vbar) accept baz(vbaz) -#reject baz(vnotbaz) # XXX this really shouldn't compile +reject baz(vnotbaz) reject bar(vfoo) # https://github.com/Araq/Nim/issues/517 diff --git a/tests/metatype/tmetatype_issues.nim b/tests/metatype/tmetatype_issues.nim index 21c5c02f1..d33d8dd31 100644 --- a/tests/metatype/tmetatype_issues.nim +++ b/tests/metatype/tmetatype_issues.nim @@ -157,3 +157,12 @@ block t3338: var t2 = Bar[int32]() t2.add() doAssert t2.x == 5 + +block: # issue #24203 + proc b(G: typedesc) = + type U = G + template s(h: untyped) = h + s(b(typeof (0, 0))) + b(seq[int]) + b((int, int)) + b(typeof (0, 0)) diff --git a/tests/metatype/tmetatype_various.nim b/tests/metatype/tmetatype_various.nim index 30169aa1e..45c74432d 100644 --- a/tests/metatype/tmetatype_various.nim +++ b/tests/metatype/tmetatype_various.nim @@ -66,3 +66,8 @@ var x: array[8, CTBool[Ct[uint32]]] x[0] = (CTBool[Ct[uint32]])(1) echo x.repr, " ", typeof(x[0]) +block: # bug #23139 + type Foo = enum a, b + + var x: range[a..b] + doAssert (repr x) == "a" diff --git a/tests/metatype/tstatic_generic_typeclass.nim b/tests/metatype/tstatic_generic_typeclass.nim new file mode 100644 index 000000000..0e9256a62 --- /dev/null +++ b/tests/metatype/tstatic_generic_typeclass.nim @@ -0,0 +1,30 @@ +type MyThing[T: static int] = object + when T == 300: + a: int + +var a = MyThing[300]() +proc doThing(myThing: MyThing): string = $myThing +proc doOtherThing[T](myThing: MyThing[T]): string = $myThing +assert doThing(a) == $a +assert doThing(MyThing[0]()) == $MyThing[0]() +assert doOtherThing(a) == "(a: 0)" + +type + Backend* = enum + Cpu, + Cuda + + Tensor*[B: static[Backend]; T] = object + shape: seq[int] + strides: seq[int] + offset: int + when B == Backend.Cpu: + data: seq[T] + else: + data_ptr: ptr T + +template shape*(t: Tensor): seq[int] = + t.shape + + +assert Tensor[Cpu, int]().shape == @[] diff --git a/tests/metatype/tstaticparammacro.nim b/tests/metatype/tstaticparammacro.nim index 16a6e56b8..bcf28d331 100644 --- a/tests/metatype/tstaticparammacro.nim +++ b/tests/metatype/tstaticparammacro.nim @@ -6,9 +6,9 @@ numbers 11 22 AST a -[(11, 22), (33, 44)] +@[(c: 11, d: 22), (c: 33, d: 44)] AST b -([55, 66], [77, 88]) +(e: @[55, 66], f: @[77, 88]) 55 10 20Test diff --git a/tests/metatype/tstaticvector.nim b/tests/metatype/tstaticvector.nim index ca16518fe..85a66974b 100644 --- a/tests/metatype/tstaticvector.nim +++ b/tests/metatype/tstaticvector.nim @@ -1,9 +1,10 @@ discard """ + matrix: "--mm:orc" output: '''0 0 2 100 -30.0 [data = [2.0]] +30.0 TVec[1, system.float32](data: [2.0]) ''' """ diff --git a/tests/metatype/ttypedescnotnimnode.nim b/tests/metatype/ttypedescnotnimnode.nim new file mode 100644 index 000000000..52a04815b --- /dev/null +++ b/tests/metatype/ttypedescnotnimnode.nim @@ -0,0 +1,21 @@ +discard """ + errormsg: "type mismatch: got <NimNode> but expected 'typedesc'" + line: 14 +""" + +import macros + +# This is the same example as ttypeselectors but using a proc instead of a macro +# Instead of type mismatch for macro, proc just failed with internal error: getTypeDescAux(tyNone) +# https://github.com/nim-lang/Nim/issues/7231 + +proc getBase2*(bits: static[int]): typedesc = + if bits == 128: + result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint64")) + else: + result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint32")) + +type + MpUint2*[bits: static[int]] = getbase2(bits) +# technically shouldn't error until instantiation, so instantiate it +var x: MpUint2[123] diff --git a/tests/metatype/ttypeselectors.nim b/tests/metatype/ttypeselectors.nim index 5385a1be9..d0843511d 100644 --- a/tests/metatype/ttypeselectors.nim +++ b/tests/metatype/ttypeselectors.nim @@ -98,16 +98,3 @@ var c: Bar[32] echo sizeof(a) echo sizeof(b) echo sizeof(c) - -# This is the same example but using a proc instead of a macro -# Instead of type mismatch for macro, proc just failed with internal error: getTypeDescAux(tyNone) -# https://github.com/nim-lang/Nim/issues/7231 - -proc getBase2*(bits: static[int]): typedesc = - if bits == 128: - result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint64")) - else: - result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint32")) - -type - MpUint2*[bits: static[int]] = getbase2(bits) diff --git a/tests/metatype/ttypetraits.nim b/tests/metatype/ttypetraits.nim index bfaa23057..0523390a7 100644 --- a/tests/metatype/ttypetraits.nim +++ b/tests/metatype/ttypetraits.nim @@ -144,6 +144,32 @@ block distinctBase: doAssert($distinctBase(typeof(b2)) == "string") doAssert($distinctBase(typeof(c2)) == "int") +block: # rangeBase + {.push warningAsError[EnumConv]: on.} + proc foo[T: not range](x: T): string = + $T & "(" & $x & ")" + proc foo[T: range](x: T): string = + "ranged(" & $low(T) & ".." & $high(T) & " of " & $rangeBase(T) & ") " & foo(rangeBase(x)) + doAssert foo(123) == "int(123)" + type IntRange = range[0..3] + let x: IntRange = 2 + doAssert foo(x) == "ranged(0..3 of int) int(2)" + type E = enum a, b, c, d, e, f + type EnumRange = range[c..e] + let y: EnumRange = d + doAssert foo(y) == "ranged(c..e of E) E(d)" + let z: range['a'..'z'] = 'g' + doAssert foo(z) == "ranged(a..z of char) char(g)" + {.pop.} + + # works only with #24037: + var toChange: range[0..3] = 1 + proc bar[T: int and not range](y: var T) = + inc y + doAssert not compiles(bar(toChange)) + bar(rangeBase(toChange)) + doAssert toChange == 2 + block: # tupleLen doAssert not compiles(tupleLen(int)) @@ -365,3 +391,14 @@ block: # enum.len doAssert MyEnum.enumLen == 4 doAssert OtherEnum.enumLen == 3 doAssert MyFlag.enumLen == 4 + +when true: # Odd bug where alias can seep inside of `distinctBase` + import std/unittest + + type + AdtChild* = concept t + distinctBase(t) + + proc `$`*[T: AdtChild](adtChild: T): string = "" + + check 10 is int diff --git a/tests/metatype/twrong_same_type.nim b/tests/metatype/twrong_same_type.nim new file mode 100644 index 000000000..ea903b7a3 --- /dev/null +++ b/tests/metatype/twrong_same_type.nim @@ -0,0 +1,28 @@ +# bug #23418 + +template mapIt*(x: untyped): untyped = + type OutType {.gensym.} = typeof(x) #typeof(x, typeOfProc) + newSeq[OutType](5) + +type F[E] = object + +proc start(v: int): F[(ValueError,)] = discard +proc stop(v: int): F[tuple[]] = discard + +assert $typeof(mapIt(start(9))) == "seq[F[(ValueError,)]]" +assert $typeof(mapIt(stop(9))) == "seq[F[tuple[]]]" + +# bug #23445 + +type F2[T; I: static int] = distinct int + +proc start2(v: int): F2[void, 22] = discard +proc stop2(v: int): F2[void, 33] = discard + +var a = mapIt(start2(5)) + +assert $type(a) == "seq[F2[system.void, 22]]", $type(a) + +var b = mapIt(stop2(5)) + +assert $type(b) == "seq[F2[system.void, 33]]", $type(b) diff --git a/tests/method/nim.cfg b/tests/method/nim.cfg deleted file mode 100644 index 57698b028..000000000 --- a/tests/method/nim.cfg +++ /dev/null @@ -1 +0,0 @@ -multimethods:on diff --git a/tests/method/t20515.nim b/tests/method/t20515.nim new file mode 100644 index 000000000..1921f2e46 --- /dev/null +++ b/tests/method/t20515.nim @@ -0,0 +1,20 @@ +discard """ + errormsg: "Base method 'zzz' requires explicit '{.gcsafe.}' to be GC-safe" + line: 10 +""" + +type + A = ref object of RootObj + B = ref object of A + +method zzz(a: A) {.base.} = + discard + +var s: seq[int] +method zzz(a: B) = + echo s + +proc xxx(someObj: A) {.gcsafe.} = + someObj.zzz() + +xxx(B()) diff --git a/tests/method/t22673.nim b/tests/method/t22673.nim new file mode 100644 index 000000000..1689e9d42 --- /dev/null +++ b/tests/method/t22673.nim @@ -0,0 +1,21 @@ +discard """ + matrix: "--warningAsError:UseBase" +""" + +# bug #22673 +type RefEntry = ref object of RootObj + +type RefFile = ref object of RefEntry + filename*: string + data*: string + +type RefDir = ref object of RefEntry + dirname*: string + files*: seq[RefFile] + +method name*(e: RefEntry): lent string {.base.} = + raiseAssert "Don't call the base method" + +method name*(e: RefFile): lent string = e.filename + +method name*(e: RefDir): lent string = e.dirname \ No newline at end of file diff --git a/tests/method/tcompilegenerics.nim b/tests/method/tcompilegenerics.nim new file mode 100644 index 000000000..d0732895b --- /dev/null +++ b/tests/method/tcompilegenerics.nim @@ -0,0 +1,24 @@ +discard """ + matrix: "--mm:arc; --mm:refc" + output: ''' +newDNode base +''' +""" + +type + SNodeAny = ref object of RootObj + SNode[T] = ref object of SNodeAny + m: T + DNode[T] = ref object + +method getStr(s: SNode[float]): string {.base.} = "blahblah" + +method newDNode(s: SNodeAny) {.base.} = + echo "newDNode base" + +method newDNode[T](s: SNode[T]) = + echo "newDNode generic" + +let m = SNode[float]() +let s = SNodeAny(m) +newDnode(s) \ No newline at end of file diff --git a/tests/method/tgeneric_methods.nim b/tests/method/tgeneric_methods.nim index ab92c66d8..f8d068cc5 100644 --- a/tests/method/tgeneric_methods.nim +++ b/tests/method/tgeneric_methods.nim @@ -1,42 +1,42 @@ -discard """ - matrix: "--mm:arc; --mm:refc" - output: '''wow2 -X 1 -X 3''' -""" -type - First[T] = ref object of RootObj - value: T - - Second[T] = ref object of First[T] - value2: T - -method wow[T](y: int; x: First[T]) {.base.} = - echo "wow1" - -method wow[T](y: int; x: Second[T]) = - echo "wow2" - -var - x: Second[int] -new(x) - -proc takeFirst(x: First[int]) = - wow(2, x) - -takeFirst(x) - - -# bug #5479 -type - Base[T: static[int]] = ref object of RootObj - -method test[T](t: Base[T]) {.base.} = - echo "X ", t.T - -let ab = Base[1]() - -ab.test() - -let ac = Base[3]() -ac.test() +discard """ + matrix: "--mm:arc --multimethods:on -d:nimInternalNonVtablesTesting; --mm:refc --multimethods:on -d:nimInternalNonVtablesTesting" + output: '''wow2 +X 1 +X 3''' +""" +type + First[T] = ref object of RootObj + value: T + + Second[T] = ref object of First[T] + value2: T + +method wow[T](y: int; x: First[T]) {.base.} = + echo "wow1" + +method wow[T](y: int; x: Second[T]) = + echo "wow2" + +var + x: Second[int] +new(x) + +proc takeFirst(x: First[int]) = + wow(2, x) + +takeFirst(x) + + +# bug #5479 +type + Base[T: static[int]] = ref object of RootObj + +method test[T](t: Base[T]) {.base.} = + echo "X ", t.T + +let ab = Base[1]() + +ab.test() + +let ac = Base[3]() +ac.test() diff --git a/tests/method/tmethod_issues.nim b/tests/method/tmethod_issues.nim index 07d4635f6..daaa46522 100644 --- a/tests/method/tmethod_issues.nim +++ b/tests/method/tmethod_issues.nim @@ -160,3 +160,11 @@ proc main() = main() +block: # bug #20391 + type Container[T] = ref object of RootRef + item: T + + let a = Container[int]() + + doAssert a of Container[int] + doAssert not (a of Container[string]) diff --git a/tests/method/tmethod_various.nim b/tests/method/tmethod_various.nim index c41d04983..3b64aea8d 100644 --- a/tests/method/tmethod_various.nim +++ b/tests/method/tmethod_various.nim @@ -1,15 +1,12 @@ discard """ matrix: "--mm:arc; --mm:refc" output: ''' -do nothing HELLO WORLD! ''' """ -# tmethods1 -method somethin(obj: RootObj) {.base.} = - echo "do nothing" + type TNode* {.inheritable.} = object @@ -23,8 +20,6 @@ type method foo(a: PNode, b: PSomethingElse) {.base.} = discard method foo(a: PNodeFoo, b: PSomethingElse) = discard -var o: RootObj -o.somethin() diff --git a/tests/method/tmethods_old.nim b/tests/method/tmethods_old.nim new file mode 100644 index 000000000..d24eb0cc7 --- /dev/null +++ b/tests/method/tmethods_old.nim @@ -0,0 +1,12 @@ +discard """ + matrix: "--mm:arc -d:nimInternalNonVtablesTesting" + output: ''' +do nothing +''' +""" + +# tmethods1 +method somethin(obj: RootObj) {.base.} = + echo "do nothing" +var o: RootObj +o.somethin() diff --git a/tests/method/tmultim.nim b/tests/method/tmultim.nim index 126eb7526..bba4d8c5c 100644 --- a/tests/method/tmultim.nim +++ b/tests/method/tmultim.nim @@ -1,96 +1,97 @@ -discard """ - output: ''' -collide: unit, thing -collide: unit, thing -collide: thing, unit -collide: thing, thing -collide: unit, thing | -collide: unit, thing | -collide: thing, unit | -do nothing -''' - joinable: false - disabled: true -""" - - -# tmultim2 -type - TThing {.inheritable.} = object - TUnit = object of TThing - x: int - TParticle = object of TThing - a, b: int - -method collide(a, b: TThing) {.base, inline.} = - echo "collide: thing, thing" - -method collide(a: TThing, b: TUnit) {.inline.} = - echo "collide: thing, unit" - -method collide(a: TUnit, b: TThing) {.inline.} = - echo "collide: unit, thing" - -proc test(a, b: TThing) {.inline.} = - collide(a, b) - -proc staticCollide(a, b: TThing) {.inline.} = - procCall collide(a, b) - -var - a: TThing - b, c: TUnit -collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing! -test(b, c) -collide(a, b) -staticCollide(a, b) - - - -# tmultim6 -type - Thing {.inheritable.} = object - Unit[T] = object of Thing - x: T - Particle = object of Thing - a, b: int - -method collide(a, b: Thing) {.base, inline.} = - quit "to override!" - -method collide[T](a: Thing, b: Unit[T]) {.inline.} = - echo "collide: thing, unit |" - -method collide[T](a: Unit[T], b: Thing) {.inline.} = - echo "collide: unit, thing |" - -proc test(a, b: Thing) {.inline.} = - collide(a, b) - -var - aaa: Thing - bbb, ccc: Unit[string] -collide(bbb, Thing(ccc)) -test(bbb, ccc) -collide(aaa, bbb) - - - -# tmethods1 -method somethin(obj: RootObj) {.base.} = - echo "do nothing" - -type - TNode* {.inheritable.} = object - PNode* = ref TNode - - PNodeFoo* = ref object of TNode - - TSomethingElse = object - PSomethingElse = ref TSomethingElse - -method foo(a: PNode, b: PSomethingElse) {.base.} = discard -method foo(a: PNodeFoo, b: PSomethingElse) = discard - -var o: RootObj -o.somethin() +discard """ + matrix: "--multimethods:on" + output: ''' +collide: unit, thing +collide: unit, thing +collide: thing, unit +collide: thing, thing +collide: unit, thing | +collide: unit, thing | +collide: thing, unit | +do nothing +''' + joinable: false + disabled: true +""" + + +# tmultim2 +type + TThing {.inheritable.} = object + TUnit = object of TThing + x: int + TParticle = object of TThing + a, b: int + +method collide(a, b: TThing) {.base, inline.} = + echo "collide: thing, thing" + +method collide(a: TThing, b: TUnit) {.inline.} = + echo "collide: thing, unit" + +method collide(a: TUnit, b: TThing) {.inline.} = + echo "collide: unit, thing" + +proc test(a, b: TThing) {.inline.} = + collide(a, b) + +proc staticCollide(a, b: TThing) {.inline.} = + procCall collide(a, b) + +var + a: TThing + b, c: TUnit +collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing! +test(b, c) +collide(a, b) +staticCollide(a, b) + + + +# tmultim6 +type + Thing {.inheritable.} = object + Unit[T] = object of Thing + x: T + Particle = object of Thing + a, b: int + +method collide(a, b: Thing) {.base, inline.} = + quit "to override!" + +method collide[T](a: Thing, b: Unit[T]) {.inline.} = + echo "collide: thing, unit |" + +method collide[T](a: Unit[T], b: Thing) {.inline.} = + echo "collide: unit, thing |" + +proc test(a, b: Thing) {.inline.} = + collide(a, b) + +var + aaa: Thing + bbb, ccc: Unit[string] +collide(bbb, Thing(ccc)) +test(bbb, ccc) +collide(aaa, bbb) + + + +# tmethods1 +method somethin(obj: RootObj) {.base.} = + echo "do nothing" + +type + TNode* {.inheritable.} = object + PNode* = ref TNode + + PNodeFoo* = ref object of TNode + + TSomethingElse = object + PSomethingElse = ref TSomethingElse + +method foo(a: PNode, b: PSomethingElse) {.base.} = discard +method foo(a: PNodeFoo, b: PSomethingElse) = discard + +var o: RootObj +o.somethin() diff --git a/tests/method/tvtable.nim b/tests/method/tvtable.nim new file mode 100644 index 000000000..a1b33d6b7 --- /dev/null +++ b/tests/method/tvtable.nim @@ -0,0 +1,24 @@ +discard """ + targets: "c cpp" +""" + +type FooBase = ref object of RootObj + dummy: int +type Foo = ref object of FooBase + value : float32 +type Foo2 = ref object of Foo + change : float32 +method bar(x: FooBase, a: float32) {.base.} = + discard +method bar(x: Foo, a: float32) = + x.value += a +method bar(x: Foo2, a: float32) = + x.value += a + + +proc test() = + var x = new Foo2 + x.bar(2.3) + doAssert x.value <= 2.3 + +test() \ No newline at end of file diff --git a/tests/misc/m15955.nim b/tests/misc/m15955.nim new file mode 100644 index 000000000..22da345db --- /dev/null +++ b/tests/misc/m15955.nim @@ -0,0 +1,4 @@ +proc add*(a, b: int): int {.cdecl, exportc.} = + a + b +proc sub*(a, b: int): int {.cdecl, exportc.} = + a - b \ No newline at end of file diff --git a/tests/misc/m15955_main.nim b/tests/misc/m15955_main.nim new file mode 100644 index 000000000..a71af8121 --- /dev/null +++ b/tests/misc/m15955_main.nim @@ -0,0 +1,11 @@ +import stdtest/specialpaths +import std/os + +const buildLib = buildDir / "libD20220923T19380" + +{.passL: buildLib.} +proc add*(a, b: int):int {.cdecl, importc.} +proc sub*(a, b: int):int {.cdecl, importc.} + +echo add(10, 5) +echo sub(10, 5) diff --git a/tests/misc/m20456.nims b/tests/misc/m20456.nims new file mode 100644 index 000000000..8a9313129 --- /dev/null +++ b/tests/misc/m20456.nims @@ -0,0 +1 @@ +echo 123 \ No newline at end of file diff --git a/tests/misc/mjsondoc.nim b/tests/misc/mjsondoc.nim index e4642f0b4..016c8522d 100644 --- a/tests/misc/mjsondoc.nim +++ b/tests/misc/mjsondoc.nim @@ -9,3 +9,6 @@ const type MyEnum* = enum foo, bar + +proc foo2*[T: int, M: string, U](x: T, y: U, z: M) = + echo 1 diff --git a/tests/misc/t11634.nim b/tests/misc/t11634.nim new file mode 100644 index 000000000..390af40f4 --- /dev/null +++ b/tests/misc/t11634.nim @@ -0,0 +1,17 @@ +discard """ + action: reject +""" + +type Foo = ref object + val: int + +proc divmod(a, b: Foo): (Foo, Foo) = + ( + Foo(val: a.val div b.val), + Foo(val: a.val mod b.val) + ) + +block: + let a {.compileTime.} = Foo(val: 2) + let b {.compileTime.} = Foo(val: 3) + let (c11634 {.compileTime.}, d11634 {.compileTime.}) = divmod(a, b) diff --git a/tests/misc/t12869.nim b/tests/misc/t12869.nim new file mode 100644 index 000000000..054e28a03 --- /dev/null +++ b/tests/misc/t12869.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: "type mismatch: got <openArray[int], proc (x: GenericParam, y: GenericParam): auto, SortOrder>" + line: 12 +""" + +import sugar +from algorithm import sorted, SortOrder + +let a = 5 + +proc sorted*[T](a: openArray[T], key: proc(v: T): int, order = SortOrder.Ascending): seq[T] = + sorted(a, (x, y) => key(x) < key(y), order) + +echo sorted(@[9, 1, 8, 2, 6, 4, 5, 0], (x) => (a - x).abs) diff --git a/tests/misc/t14667.nim b/tests/misc/t14667.nim new file mode 100644 index 000000000..3034e2841 --- /dev/null +++ b/tests/misc/t14667.nim @@ -0,0 +1,12 @@ +discard """ + matrix: "--cc:vcc" + disabled: "linux" + disabled: "bsd" + disabled: "osx" + disabled: "unix" + disabled: "posix" +""" + +type A = tuple +discard () +discard default(A) diff --git a/tests/misc/t15351.nim b/tests/misc/t15351.nim new file mode 100644 index 000000000..c31e604a2 --- /dev/null +++ b/tests/misc/t15351.nim @@ -0,0 +1,5 @@ +discard """ + action: "compile" +""" +var + ## TODO: broken diff --git a/tests/misc/t15955.nim b/tests/misc/t15955.nim new file mode 100644 index 000000000..7441e5398 --- /dev/null +++ b/tests/misc/t15955.nim @@ -0,0 +1,22 @@ +discard """ +joinable: false +""" + +import stdtest/specialpaths +import std/[osproc, strformat, os] + +const + nim = getCurrentCompilerExe() + buildLib = buildDir / "libD20220923T19380" + currentDir = splitFile(currentSourcePath).dir + file = currentDir / "m15955.nim" + main = currentDir / "m15955_main.nim" + + +proc runCmd(cmd: string) = + let (msg, code) = execCmdEx(cmd) + doAssert code == 0, msg + + +runCmd fmt"{nim} c -o:{buildLib} --nomain --nimMainPrefix:libA -f --app:staticlib {file}" +runCmd fmt"{nim} c -r {main}" diff --git a/tests/misc/t16244.nim b/tests/misc/t16244.nim new file mode 100644 index 000000000..5e8128736 --- /dev/null +++ b/tests/misc/t16244.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "type mismatch: got <int, float64>" + line: 9 +""" + +proc g(): auto = 1 +proc h(): auto = 1.0 + +var a = g() + h() diff --git a/tests/misc/t16264.nim b/tests/misc/t16264.nim new file mode 100644 index 000000000..afe319e6c --- /dev/null +++ b/tests/misc/t16264.nim @@ -0,0 +1,2 @@ +import times +doAssert low(Time) == fromUnix(0) \ No newline at end of file diff --git a/tests/misc/t16541.nim b/tests/misc/t16541.nim new file mode 100644 index 000000000..452327e8f --- /dev/null +++ b/tests/misc/t16541.nim @@ -0,0 +1,12 @@ +discard """ + action: "reject" + +""" + +import strutils, sugar, nre + +proc my_replace*(s: string, r: Regex, by: string | (proc (match: string): string)): string = + nre.replace(s, r, by) + +discard my_replace("abcde", re"[bcd]", match => match.to_upper) == "aBCDe" +discard my_replace("abcde", re"[bcd]", (match: string) => match.to_upper) == "aBCDe" diff --git a/tests/misc/t18079.nim b/tests/misc/t18079.nim new file mode 100644 index 000000000..ae64bbff9 --- /dev/null +++ b/tests/misc/t18079.nim @@ -0,0 +1,15 @@ +discard """ + matrix: "--mm:orc" +""" + +type + Foo = object + y: int + + Bar = object + x: Foo + +proc baz(state: var Bar):int = + state.x.y = 2 + state.x.y +doAssert baz((ref Bar)(x: (new Foo)[])[]) == 2 diff --git a/tests/misc/t20253.nim b/tests/misc/t20253.nim new file mode 100644 index 000000000..d47c36c55 --- /dev/null +++ b/tests/misc/t20253.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "'result' requires explicit initialization" + line: 10 +""" + +type Meow {.requiresInit.} = object + init: bool + +proc initMeow(): Meow = + discard diff --git a/tests/misc/t20289.nim b/tests/misc/t20289.nim new file mode 100644 index 000000000..5a0a269f0 --- /dev/null +++ b/tests/misc/t20289.nim @@ -0,0 +1,15 @@ +discard """ + action: reject +""" + +type E[T] = object + v: T + +template j[T](R: type E[T], x: untyped): R = R(v: x) +template d[T](O: type E, v: T): E[T] = E[T].j(v) + +proc w[T](): E[T] = + template r(k: int): auto = default(T) + E.d r + +discard w[int]() diff --git a/tests/misc/t20456_2.nim b/tests/misc/t20456_2.nim new file mode 100644 index 000000000..37e52c452 --- /dev/null +++ b/tests/misc/t20456_2.nim @@ -0,0 +1,14 @@ +discard """ + joinable: false +""" + +import std/[osproc, os, strformat] +from stdtest/specialpaths import testsDir + +when defined(nimPreviewSlimSystem): + import std/assertions + +const + nim = getCurrentCompilerExe() + file = testsDir / "misc" / "m20456.nims" +doAssert execCmd(fmt"{nim} check {file}") == 0 diff --git a/tests/misc/t20883.nim b/tests/misc/t20883.nim new file mode 100644 index 000000000..92e7929f4 --- /dev/null +++ b/tests/misc/t20883.nim @@ -0,0 +1,13 @@ +discard """ + action: reject +nimout: ''' +t20883.nim(13, 4) template/generic instantiation of `foo` from here +t20883.nim(9, 11) Error: cannot instantiate: 'U' +''' +""" + +proc foo*[U](x: U = U(1e-6)) = + echo x + +foo[float]() +foo() diff --git a/tests/misc/t21109.nim b/tests/misc/t21109.nim new file mode 100644 index 000000000..0f7980896 --- /dev/null +++ b/tests/misc/t21109.nim @@ -0,0 +1,13 @@ +discard """ + action: reject + errormsg: "type expected" + file: "iterators.nim" +""" + + +template b(j: untyped) = j +template m() = discard + +b: + for t, f in @[]: + m() diff --git a/tests/misc/t21443.nim b/tests/misc/t21443.nim new file mode 100644 index 000000000..70413c5b3 --- /dev/null +++ b/tests/misc/t21443.nim @@ -0,0 +1,6 @@ +import std/envvars + +# bug #19292 +putEnv("NimPutEnvTest", "test") +# bug #21122 +doAssert getEnv("NimPutEnvTest") == "test" diff --git a/tests/misc/t23240.nim b/tests/misc/t23240.nim new file mode 100644 index 000000000..d5edcefe8 --- /dev/null +++ b/tests/misc/t23240.nim @@ -0,0 +1,6 @@ +discard """ + cmd: "nim c foo/bar.nim" + action: "reject" + errormsg: "cannot open 'foo/'" + file: "" +""" diff --git a/tests/misc/t3907.nim b/tests/misc/t3907.nim new file mode 100644 index 000000000..45fc75e81 --- /dev/null +++ b/tests/misc/t3907.nim @@ -0,0 +1,10 @@ +import std/assertions + +let a = 0 +let b = if false: -1 else: a +doAssert b == 0 + +let c: range[0..high(int)] = 0 +let d = if false: -1 else: c + +doAssert d == 0 diff --git a/tests/misc/t6549.nim b/tests/misc/t6549.nim new file mode 100644 index 000000000..1d7393318 --- /dev/null +++ b/tests/misc/t6549.nim @@ -0,0 +1,4 @@ + +const l = $(range[low(uint64) .. high(uint64)]) +const r = "range 0..18446744073709551615(uint64)" +doAssert l == r diff --git a/tests/misc/t8545.nim b/tests/misc/t8545.nim index 89957e1d3..48b886cb8 100644 --- a/tests/misc/t8545.nim +++ b/tests/misc/t8545.nim @@ -1,5 +1,6 @@ discard """ - targets: "c cpp js" + # just tests that this doesn't crash the compiler + errormsg: "cannot instantiate: 'a:type'" """ # bug #8545 diff --git a/tests/misc/taddr.nim b/tests/misc/taddr.nim index 631c9f265..64f95c7e3 100644 --- a/tests/misc/taddr.nim +++ b/tests/misc/taddr.nim @@ -32,6 +32,10 @@ doAssert objDeref.x == 42 # String tests obj.s = "lorem ipsum dolor sit amet" +when defined(gcArc) or defined(gcOrc): + prepareMutation(obj.s) + + var indexAddr = addr(obj.s[2]) doAssert indexAddr[] == 'r' @@ -232,8 +236,17 @@ block: # bug #15939 const bar = proc2(foo) doAssert bar == "foo" +template prepareMutationForOrc(x: string) = + when defined(gcArc) or defined(gcOrc): + when nimvm: + discard + else: + prepareMutation(x) + proc test15939() = # bug #15939 (v2) template fn(a) = + when typeof(a) is string: + prepareMutationForOrc(a) let pa = a[0].addr doAssert pa != nil doAssert pa[] == 'a' @@ -253,12 +266,23 @@ proc test15939() = # bug #15939 (v2) # mycstring[ind].addr template cstringTest = var a2 = "abc" + prepareMutationForOrc(a2) var b2 = a2.cstring fn(b2) when nimvm: cstringTest() else: # can't take address of cstring element in js when not defined(js): cstringTest() +block: # bug #23499 + template volatileStore[T](dest: ptr T, val: T) = + dest[] = val + + proc foo = + var ctr = 0 + volatileStore(addr ctr, 0) + + foo() + template main = # xxx wrap all other tests here like that so they're also tested in VM test14420() diff --git a/tests/misc/tcast.nim b/tests/misc/tcast.nim index 6d67b1c52..73196e76c 100644 --- a/tests/misc/tcast.nim +++ b/tests/misc/tcast.nim @@ -1,6 +1,7 @@ discard """ output: ''' Hello World +Hello World Hello World''' joinable: false """ @@ -8,7 +9,7 @@ type MyProc = proc() {.cdecl.} type MyProc2 = proc() {.nimcall.} type MyProc3 = proc() #{.closure.} is implicit -proc testProc() = echo "Hello World" +proc testProc() {.exportc:"foo".} = echo "Hello World" template reject(x) = doAssert(not compiles(x)) @@ -23,6 +24,10 @@ proc callPointer(p: pointer) = ffunc0() ffunc1() + # bug #5901 + proc foo() {.importc.} + (cast[proc(a: int) {.cdecl.}](foo))(5) + callPointer(cast[pointer](testProc)) reject: discard cast[enum](0) diff --git a/tests/misc/tconv.nim b/tests/misc/tconv.nim index 5e8eac729..90fae868b 100644 --- a/tests/misc/tconv.nim +++ b/tests/misc/tconv.nim @@ -2,6 +2,9 @@ discard """ matrix: "--warningAsError:EnumConv --warningAsError:CStringConv" """ +from std/enumutils import items # missing from the example code +from std/sequtils import toSeq + template reject(x) = static: doAssert(not compiles(x)) template accept(x) = @@ -85,6 +88,13 @@ block: # https://github.com/nim-lang/RFCs/issues/294 reject: Goo(k2) reject: k2.Goo + type KooRange = range[k2..k2] + accept: KooRange(k2) + accept: k2.KooRange + let k2ranged: KooRange = k2 + accept: Koo(k2ranged) + accept: k2ranged.Koo + reject: # bug #18550 proc f(c: char): cstring = @@ -117,4 +127,17 @@ reject: var va = 2 var vb = va.Hole +block: # bug #22844 + type + A = enum + a0 = 2 + a1 = 4 + a2 + B[T] = enum + b0 = 2 + b1 = 4 + + doAssert A.toSeq == [a0, a1, a2] + doAssert B[float].toSeq == [B[float].b0, B[float].b1] + {.pop.} diff --git a/tests/misc/tcsharpusingstatement.nim b/tests/misc/tcsharpusingstatement.nim index dd4cf589d..1ce553895 100644 --- a/tests/misc/tcsharpusingstatement.nim +++ b/tests/misc/tcsharpusingstatement.nim @@ -49,25 +49,13 @@ macro autoClose(args: varargs[untyped]): untyped = var finallyBlock = newNimNode(nnkStmtList) finallyBlock.add(closingCalls) - # XXX: Use a template here once getAst is working properly - var targetAst = parseStmt"""block: - var - x = foo() - y = bar() - - try: - body() - - finally: - close x - close y - """ - - targetAst[0][1][0] = varSection - targetAst[0][1][1][0] = body - targetAst[0][1][1][1][0] = finallyBlock - - result = targetAst + result = quote do: + block: + `varSection` + try: + `body` + finally: + `finallyBlock` type TResource* = object diff --git a/tests/misc/tdefine.nim b/tests/misc/tdefine.nim index c4d11c941..f3fa4711f 100644 --- a/tests/misc/tdefine.nim +++ b/tests/misc/tdefine.nim @@ -1,12 +1,23 @@ discard """ joinable: false -cmd: "nim c -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -d:namespaced.define=false -d:double.namespaced.define -r $file" +cmd: "nim c $options -d:booldef -d:booldef2=false -d:intdef=2 -d:strdef=foobar -d:namespaced.define=false -d:double.namespaced.define -r $file" +matrix: "; -d:useGenericDefine" """ -const booldef {.booldefine.} = false -const booldef2 {.booldefine.} = true -const intdef {.intdefine.} = 0 -const strdef {.strdefine.} = "" +when defined(useGenericDefine): + {.pragma: booldefine2, define.} + {.pragma: intdefine2, define.} + {.pragma: strdefine2, define.} +else: + + {.pragma: booldefine2, booldefine.} + {.pragma: intdefine2, intdefine.} + {.pragma: strdefine2, strdefine.} + +const booldef {.booldefine2.} = false +const booldef2 {.booldefine2.} = true +const intdef {.intdefine2.} = 0 +const strdef {.strdefine2.} = "" doAssert defined(booldef) doAssert defined(booldef2) @@ -17,17 +28,28 @@ doAssert not booldef2 doAssert intdef == 2 doAssert strdef == "foobar" +when defined(useGenericDefine): + block: + const uintdef {.define: "intdef".}: uint = 17 + doAssert intdef == int(uintdef) + const cstrdef {.define: "strdef".}: cstring = "not strdef" + doAssert $cstrdef == strdef + type FooBar = enum foo, bar, foobar + const enumdef {.define: "strdef".} = foo + doAssert $enumdef == strdef + doAssert enumdef == foobar + # Intentionally not defined from command line -const booldef3 {.booldefine.} = true -const intdef2 {.intdefine.} = 1 -const strdef2 {.strdefine.} = "abc" +const booldef3 {.booldefine2.} = true +const intdef2 {.intdefine2.} = 1 +const strdef2 {.strdefine2.} = "abc" type T = object - when booldef3: - field1: int - when intdef2 == 1: - field2: int - when strdef2 == "abc": - field3: int + when booldef3: + field1: int + when intdef2 == 1: + field2: int + when strdef2 == "abc": + field3: int doAssert not defined(booldef3) doAssert not defined(intdef2) @@ -35,11 +57,21 @@ doAssert not defined(strdef2) discard T(field1: 1, field2: 2, field3: 3) doAssert defined(namespaced.define) -const `namespaced.define` {.booldefine.} = true +const `namespaced.define` {.booldefine2.} = true doAssert not `namespaced.define` +when defined(useGenericDefine): + const aliasToNamespacedDefine {.define: "namespaced.define".} = not `namespaced.define` +else: + const aliasToNamespacedDefine {.booldefine: "namespaced.define".} = not `namespaced.define` +doAssert aliasToNamespacedDefine == `namespaced.define` doAssert defined(double.namespaced.define) -const `double.namespaced.define` {.booldefine.} = false +const `double.namespaced.define` {.booldefine2.} = false doAssert `double.namespaced.define` +when defined(useGenericDefine): + const aliasToDoubleNamespacedDefine {.define: "double.namespaced.define".} = not `double.namespaced.define` +else: + const aliasToDoubleNamespacedDefine {.booldefine: "double.namespaced.define".} = not `double.namespaced.define` +doAssert aliasToDoubleNamespacedDefine == `double.namespaced.define` doAssert not defined(namespaced.butnotdefined) diff --git a/tests/misc/tgenconstraints.nim b/tests/misc/tgenconstraints.nim deleted file mode 100644 index 829da5173..000000000 --- a/tests/misc/tgenconstraints.nim +++ /dev/null @@ -1,31 +0,0 @@ -discard """ - errormsg: "cannot instantiate T2" - file: "tgenconstraints.nim" - line: 25 - disabled: true -""" - -type - T1[T: int|string] = object - x: T - - T2[T: Ordinal] = object - x: T - -var x1: T1[int] -var x2: T1[string] -var x3: T2[int] - -proc foo[T](x: T): T2[T] {.discardable.} = - var o: T1[T] - -foo(10) - -# XXX: allow type intersections in situation like this -proc bar(x: int|TNumber): T1[type(x)] {.discardable.} = - when type(x) is TNumber: - var o: T2[type(x)] - -bar "test" -bar 100 -bar 1.1 diff --git a/tests/misc/tradix.nim b/tests/misc/tradix.nim index 1773a9609..f4fb56849 100644 --- a/tests/misc/tradix.nim +++ b/tests/misc/tradix.nim @@ -40,8 +40,8 @@ type TRadixNode {.pure, inheritable.} = object kind: TRadixNodeKind TRadixNodeLinear = object of TRadixNode - len: int8 - keys: array[0..31, int8] + len: uint8 + keys: array[0..31, uint8] vals: array[0..31, PRadixNode] TRadixNodeFull = object of TRadixNode @@ -49,8 +49,8 @@ type TRadixNodeLeafBits = object of TRadixNode b: array[0..7, int] TRadixNodeLeafLinear = object of TRadixNode - len: int8 - keys: array[0..31, int8] + len: uint8 + keys: array[0..31, uint8] var root: PRadixNode @@ -59,8 +59,8 @@ proc searchInner(r: PRadixNode, a: int): PRadixNode = case r.kind of rnLinear: var x = cast[ptr TRadixNodeLinear](r) - for i in 0..ze(x.len)-1: - if ze(x.keys[i]) == a: return x.vals[i] + for i in 0..int(x.len)-1: + if int(x.keys[i]) == a: return x.vals[i] of rnFull: var x = cast[ptr TRadixNodeFull](r) return x.b[a] @@ -87,8 +87,8 @@ proc searchLeaf(r: PRadixNode, a: int): bool = return testBit(x.b[a /% BitsPerUnit], a) of rnLeafLinear: var x = cast[ptr TRadixNodeLeafLinear](r) - for i in 0..ze(x.len)-1: - if ze(x.keys[i]) == a: return true + for i in 0..int(x.len)-1: + if int(x.keys[i]) == a: return true else: assert(false) proc exclLeaf(r: PRadixNode, a: int) = @@ -98,9 +98,9 @@ proc exclLeaf(r: PRadixNode, a: int) = resetBit(x.b[a /% BitsPerUnit], a) of rnLeafLinear: var x = cast[ptr TRadixNodeLeafLinear](r) - var L = ze(x.len) + var L = int(x.len) for i in 0..L-1: - if ze(x.keys[i]) == a: + if int(x.keys[i]) == a: x.keys[i] = x.keys[L-1] dec(x.len) return @@ -131,8 +131,8 @@ proc addLeaf(r: var PRadixNode, a: int): bool = # a linear node: var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear))) x.kind = rnLeafLinear - x.len = 1'i8 - x.keys[0] = toU8(a) + x.len = 1'u8 + x.keys[0] = uint8(a) r = x return false # not already in set case r.kind @@ -141,18 +141,18 @@ proc addLeaf(r: var PRadixNode, a: int): bool = return testOrSetBit(x.b[a /% BitsPerUnit], a) of rnLeafLinear: var x = cast[ptr TRadixNodeLeafLinear](r) - var L = ze(x.len) + var L = int(x.len) for i in 0..L-1: - if ze(x.keys[i]) == a: return true + if int(x.keys[i]) == a: return true if L <= high(x.keys): - x.keys[L] = toU8(a) + x.keys[L] = uint8(a) inc(x.len) else: # transform into a full node: var y = cast[ptr TRadixNodeLeafBits](alloc0(sizeof(TRadixNodeLeafBits))) y.kind = rnLeafBits - for i in 0..ze(x.len)-1: - var u = ze(x.keys[i]) + for i in 0..int(x.len)-1: + var u = int(x.keys[i]) setBit(y.b[u /% BitsPerUnit], u) setBit(y.b[a /% BitsPerUnit], a) dealloc(r) @@ -167,26 +167,26 @@ proc addInner(r: var PRadixNode, a: int, d: int): bool = # a linear node: var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear))) x.kind = rnLinear - x.len = 1'i8 - x.keys[0] = toU8(k) + x.len = 1'u8 + x.keys[0] = uint8(k) r = x return addInner(x.vals[0], a, d-8) case r.kind of rnLinear: var x = cast[ptr TRadixNodeLinear](r) - var L = ze(x.len) + var L = int(x.len) for i in 0..L-1: - if ze(x.keys[i]) == k: # already exists + if int(x.keys[i]) == k: # already exists return addInner(x.vals[i], a, d-8) if L <= high(x.keys): - x.keys[L] = toU8(k) + x.keys[L] = uint8(k) inc(x.len) return addInner(x.vals[L], a, d-8) else: # transform into a full node: var y = cast[ptr TRadixNodeFull](alloc0(sizeof(TRadixNodeFull))) y.kind = rnFull - for i in 0..L-1: y.b[ze(x.keys[i])] = x.vals[i] + for i in 0..L-1: y.b[int(x.keys[i])] = x.vals[i] dealloc(r) r = y return addInner(y.b[k], a, d-8) @@ -211,8 +211,8 @@ iterator innerElements(r: PRadixNode): tuple[prefix: int, n: PRadixNode] = yield (i, r.b[i]) of rnLinear: var r = cast[ptr TRadixNodeLinear](r) - for i in 0..ze(r.len)-1: - yield (ze(r.keys[i]), r.vals[i]) + for i in 0..int(r.len)-1: + yield (int(r.keys[i]), r.vals[i]) else: assert(false) iterator leafElements(r: PRadixNode): int = @@ -228,8 +228,8 @@ iterator leafElements(r: PRadixNode): int = yield i*BitsPerUnit+j of rnLeafLinear: var r = cast[ptr TRadixNodeLeafLinear](r) - for i in 0..ze(r.len)-1: - yield ze(r.keys[i]) + for i in 0..int(r.len)-1: + yield int(r.keys[i]) else: assert(false) iterator elements*(r: PRadixNode): ByteAddress {.inline.} = diff --git a/tests/misc/trfc405.nim b/tests/misc/trfc405.nim index 8c967eb77..0828879ee 100644 --- a/tests/misc/trfc405.nim +++ b/tests/misc/trfc405.nim @@ -79,6 +79,34 @@ template main = foobar3 foobar4 doAssert a2 == (1, 20, "\nfoobar1\nfoobar2", "\nfoobar3\nfoobar4") + + block: # issue #19015 + template hi(a: untyped, b: varargs[untyped]): untyped = + a + + var worked = false + hi: + worked = true + doAssert worked + worked = false + hi(doAssert(not worked)): + doesntCompile + hi(doAssert(not worked), doesntCompile, againDoesntCompile): + definitelyDoesntCompile + + template hi2(a: bool, b: untyped, c: varargs[untyped]): untyped = + b + doAssert a + + hi2 worked: + worked = true + doAssert worked + hi2 worked, doAssert(worked): + doesntCompile + hi2 worked, doAssert(worked), doesntCompile, againDoesntCompile: + definitelyDoesntCompile + hi2 worked, doAssert(worked), againDoesntCompile: + definitelyDoesntCompile static: main() main() diff --git a/tests/misc/trunner.nim b/tests/misc/trunner.nim index add92cbfd..6e5487d1b 100644 --- a/tests/misc/trunner.nim +++ b/tests/misc/trunner.nim @@ -64,7 +64,7 @@ when defined(nimTrunnerFfi): hello world stderr hi stderr """ - let output = runNimCmdChk("vm/mevalffi.nim", fmt"{opt} --experimental:compiletimeFFI") + let output = runNimCmdChk("vm/mevalffi.nim", fmt"{opt} --warnings:off --experimental:compiletimeFFI") doAssert output == fmt""" {prefix}foo foo:100 @@ -224,13 +224,15 @@ sub/mmain.idx""", context doAssert exitCode == 0, msg let data = parseJson(readFile(output))["entries"] - doAssert data.len == 4 + doAssert data.len == 5 let doSomething = data[0] doAssert doSomething["name"].getStr == "doSomething" doAssert doSomething["type"].getStr == "skProc" doAssert doSomething["line"].getInt == 1 doAssert doSomething["col"].getInt == 0 doAssert doSomething["code"].getStr == "proc doSomething(x, y: int): int {.raises: [], tags: [], forbids: [].}" + let foo2 = data[4] + doAssert $foo2["signature"] == """{"arguments":[{"name":"x","type":"T"},{"name":"y","type":"U"},{"name":"z","type":"M"}],"genericParams":[{"name":"T","types":"int"},{"name":"M","types":"string"},{"name":"U"}]}""" block: # nim jsondoc # bug #11953 let file = testsDir / "misc/mjsondoc.nim" @@ -241,7 +243,7 @@ sub/mmain.idx""", context doAssert exitCode == 0, msg let data = parseJson(readFile(destDir / "mjsondoc.json"))["entries"] - doAssert data.len == 4 + doAssert data.len == 5 let doSomething = data[0] doAssert doSomething["name"].getStr == "doSomething" doAssert doSomething["type"].getStr == "skProc" @@ -271,10 +273,13 @@ sub/mmain.idx""", context check execCmdEx(cmd) == ("12\n", 0) block: # bug #15316 - let file = testsDir / "misc/m15316.nim" - let cmd = fmt"{nim} check --hints:off --nimcache:{nimcache} {file}" - check execCmdEx(cmd) == ("m15316.nim(1, 15) Error: expression expected, but found \')\'\nm15316.nim(2, 1) Error: expected: \':\', but got: \'[EOF]\'\nm15316.nim(2, 1) Error: expression expected, but found \'[EOF]\'\nm15316.nim(2, 1) " & - "Error: expected: \')\', but got: \'[EOF]\'\nError: illformed AST: \n", 1) + when not defined(windows): + # This never worked reliably on Windows. Needs further investigation but it is hard to reproduce. + # Looks like a mild stack corruption when bailing out of nested exception handling. + let file = testsDir / "misc/m15316.nim" + let cmd = fmt"{nim} check --hints:off --nimcache:{nimcache} {file}" + check execCmdEx(cmd) == ("m15316.nim(1, 15) Error: expression expected, but found \')\'\nm15316.nim(2, 1) Error: expected: \':\', but got: \'[EOF]\'\nm15316.nim(2, 1) Error: expression expected, but found \'[EOF]\'\nm15316.nim(2, 1) " & + "Error: expected: \')\', but got: \'[EOF]\'\nError: illformed AST: \n", 1) block: # config.nims, nim.cfg, hintConf, bug #16557 @@ -342,8 +347,8 @@ tests/newconfig/bar/mfoo.nims""".splitLines when not defined(windows): check3 lines.len == 5 check3 lines[0].isDots - check3 lines[1].dup(removePrefix(">>> ")) == "3" # prompt depends on `nimUseLinenoise` - check3 lines[2].isDots + # check3 lines[1].isDots # todo nim secret might use parsing pipeline + check3 lines[2].dup(removePrefix(">>> ")) == "3" # prompt depends on `nimUseLinenoise` check3 lines[3] == "ab" check3 lines[4] == "" else: @@ -404,7 +409,7 @@ running: v2 block: # UnusedImport proc fn(opt: string, expected: string) = - let output = runNimCmdChk("pragmas/mused3.nim", fmt"--warning:all:off --warning:UnusedImport --hint:DuplicateModuleImport {opt}") + let output = runNimCmdChk("msgs/mused3.nim", fmt"--warning:all:off --warning:UnusedImport --hint:DuplicateModuleImport {opt}") doAssert output == expected, opt & "\noutput:\n" & output & "expected:\n" & expected fn("-d:case1"): """ mused3.nim(13, 8) Warning: imported and not used: 'mused3b' [UnusedImport] @@ -434,7 +439,6 @@ mused3.nim(75, 10) Hint: duplicate import of 'mused3a'; previous import here: mu fn("-d:case2 --gc:refc"): """mfield_defect.nim(25, 15) field 'f2' is not accessible for type 'Foo' [discriminant declared in mfield_defect.nim(14, 8)] using 'kind = k3'""" fn("-d:case1 -b:js"): """mfield_defect.nim(25, 15) Error: field 'f2' is not accessible for type 'Foo' [discriminant declared in mfield_defect.nim(14, 8)] using 'kind = k3'""" fn("-d:case2 -b:js"): """field 'f2' is not accessible for type 'Foo' [discriminant declared in mfield_defect.nim(14, 8)] using 'kind = k3'""" - # 3 instead of k3, because of lack of RTTI - fn("-d:case2 --gc:arc"): """mfield_defect.nim(25, 15) field 'f2' is not accessible for type 'Foo' [discriminant declared in mfield_defect.nim(14, 8)] using 'kind = 3'""" + fn("-d:case2 --gc:arc"): """mfield_defect.nim(25, 15) field 'f2' is not accessible for type 'Foo' [discriminant declared in mfield_defect.nim(14, 8)] using 'kind = k3'""" else: discard # only during debugging, tests added here will run with `-d:nimTestsTrunnerDebugging` enabled diff --git a/tests/misc/trunner_special.nim b/tests/misc/trunner_special.nim index 47ba44a29..e08b419b0 100644 --- a/tests/misc/trunner_special.nim +++ b/tests/misc/trunner_special.nim @@ -1,6 +1,7 @@ discard """ targets: "c cpp" joinable: false + disabled: osx """ #[ @@ -13,6 +14,10 @@ xxx test all tests/untestable/* here, possibly with adjustments to make running import std/[strformat,os,unittest,compilesettings] import stdtest/specialpaths + +from stdtest/testutils import disableSSLTesting + + const nim = getCurrentCompilerExe() mode = querySetting(backend) @@ -26,6 +31,7 @@ proc main = block: # SSL nimDisableCertificateValidation integration tests runCmd fmt"{nim} r {options} -d:nimDisableCertificateValidation -d:ssl {testsDir}/untestable/thttpclient_ssl_disabled.nim" block: # SSL certificate check integration tests - runCmd fmt"{nim} r {options} -d:ssl --threads:on {testsDir}/untestable/thttpclient_ssl_remotenetwork.nim" + runCmd fmt"{nim} r {options} -d:ssl --threads:on --mm:refc {testsDir}/untestable/thttpclient_ssl_remotenetwork.nim" -main() +when not disableSSLTesting(): + main() diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim index 0d96a5e04..ce5334664 100644 --- a/tests/misc/tsizeof.nim +++ b/tests/misc/tsizeof.nim @@ -732,3 +732,11 @@ type doAssert sizeof(PackedUnion) == 11 doAssert alignof(PackedUnion) == 1 + +# bug #22553 +type + ChunkObj = object + data: UncheckedArray[byte] + +doAssert sizeof(ChunkObj) == 1 +doAssert offsetOf(ChunkObj, data) == 1 diff --git a/tests/misc/tsizeof3.nim b/tests/misc/tsizeof3.nim index 1215b4bcd..f0ba8c4d0 100644 --- a/tests/misc/tsizeof3.nim +++ b/tests/misc/tsizeof3.nim @@ -27,3 +27,32 @@ type static: doAssert(compiles(offsetOf(Payload, vals))) + + +type + GoodboySave* {.bycopy.} = object + saveCount: uint8 + savePoint: uint16 + shards: uint32 + friendCount: uint8 + friendCards: set[0..255] + locationsKnown: set[0..127] + locationsUnlocked: set[0..127] + pickupsObtained: set[0..127] + pickupsUsed: set[0..127] + pickupCount: uint8 + +block: # bug #20914 + block: + proc csizeof[T](a: T): int {.importc:"sizeof", nodecl.} + + var s: GoodboySave + doAssert sizeof(s) == 108 + doAssert csizeof(s) == static(sizeof(s)) + + block: + proc calignof[T](a: T): int {.importc:"alignof", header: "<stdalign.h>".} + + var s: set[0..256] + doAssert alignof(s) == 1 + doAssert calignof(s) == static(alignof(s)) diff --git a/tests/misc/tspellsuggest.nim b/tests/misc/tspellsuggest.nim deleted file mode 100644 index 033ed0afc..000000000 --- a/tests/misc/tspellsuggest.nim +++ /dev/null @@ -1,45 +0,0 @@ -discard """ - # pending bug #16521 (bug 12) use `matrix` - cmd: "nim c --spellsuggest:15 --hints:off $file" - action: "reject" - nimout: ''' -tspellsuggest.nim(45, 13) Error: undeclared identifier: 'fooBar' -candidates (edit distance, scope distance); see '--spellSuggest': - (1, 0): 'fooBar8' [var declared in tspellsuggest.nim(43, 9)] - (1, 1): 'fooBar7' [var declared in tspellsuggest.nim(41, 7)] - (1, 3): 'fooBar1' [var declared in tspellsuggest.nim(33, 5)] - (1, 3): 'fooBar2' [let declared in tspellsuggest.nim(34, 5)] - (1, 3): 'fooBar3' [const declared in tspellsuggest.nim(35, 7)] - (1, 3): 'fooBar4' [proc declared in tspellsuggest.nim(36, 6)] - (1, 3): 'fooBar5' [template declared in tspellsuggest.nim(37, 10)] - (1, 3): 'fooBar6' [macro declared in tspellsuggest.nim(38, 7)] - (1, 5): 'FooBar' [type declared in mspellsuggest.nim(5, 6)] - (1, 5): 'fooBar4' [proc declared in mspellsuggest.nim(1, 6)] - (1, 5): 'fooBar9' [var declared in mspellsuggest.nim(2, 5)] - (1, 5): 'fooCar' [var declared in mspellsuggest.nim(4, 5)] - (2, 5): 'FooCar' [type declared in mspellsuggest.nim(6, 6)] - (2, 5): 'GooBa' [type declared in mspellsuggest.nim(7, 6)] - (3, 0): 'fooBarBaz' [const declared in tspellsuggest.nim(44, 11)] -''' -""" - -# tests `--spellsuggest:num` - - - -# line 30 -import ./mspellsuggest - -var fooBar1 = 0 -let fooBar2 = 0 -const fooBar3 = 0 -proc fooBar4() = discard -template fooBar5() = discard -macro fooBar6() = discard - -proc main = - var fooBar7 = 0 - block: - var fooBar8 = 0 - const fooBarBaz = 0 - let x = fooBar diff --git a/tests/misc/tspellsuggest2.nim b/tests/misc/tspellsuggest2.nim deleted file mode 100644 index 78504c513..000000000 --- a/tests/misc/tspellsuggest2.nim +++ /dev/null @@ -1,45 +0,0 @@ -discard """ - # pending bug #16521 (bug 12) use `matrix` - cmd: "nim c --spellsuggest --hints:off $file" - action: "reject" - nimout: ''' -tspellsuggest2.nim(45, 13) Error: undeclared identifier: 'fooBar' -candidates (edit distance, scope distance); see '--spellSuggest': - (1, 0): 'fooBar8' [var declared in tspellsuggest2.nim(43, 9)] - (1, 1): 'fooBar7' [var declared in tspellsuggest2.nim(41, 7)] - (1, 3): 'fooBar1' [var declared in tspellsuggest2.nim(33, 5)] - (1, 3): 'fooBar2' [let declared in tspellsuggest2.nim(34, 5)] - (1, 3): 'fooBar3' [const declared in tspellsuggest2.nim(35, 7)] - (1, 3): 'fooBar4' [proc declared in tspellsuggest2.nim(36, 6)] - (1, 3): 'fooBar5' [template declared in tspellsuggest2.nim(37, 10)] - (1, 3): 'fooBar6' [macro declared in tspellsuggest2.nim(38, 7)] - (1, 5): 'FooBar' [type declared in mspellsuggest.nim(5, 6)] - (1, 5): 'fooBar4' [proc declared in mspellsuggest.nim(1, 6)] - (1, 5): 'fooBar9' [var declared in mspellsuggest.nim(2, 5)] - (1, 5): 'fooCar' [var declared in mspellsuggest.nim(4, 5)] -''' -""" - -# tests `--spellsuggest` - - - - - - -# line 30 -import ./mspellsuggest - -var fooBar1 = 0 -let fooBar2 = 0 -const fooBar3 = 0 -proc fooBar4() = discard -template fooBar5() = discard -macro fooBar6() = discard - -proc main = - var fooBar7 = 0 - block: - var fooBar8 = 0 - const fooBarBaz = 0 - let x = fooBar diff --git a/tests/misc/tstrtabs.nim b/tests/misc/tstrtabs.nim deleted file mode 100644 index 2f7eda9f7..000000000 --- a/tests/misc/tstrtabs.nim +++ /dev/null @@ -1,20 +0,0 @@ -discard """ - targets: "c cpp js" -""" - -import std/strtabs - -proc fun()= - let ret = newStringTable(modeCaseSensitive) - ret["foo"] = "bar" - - doAssert $ret == "{foo: bar}" - - let b = ret["foo"] - doAssert b == "bar" - -proc main()= - static: fun() - fun() - -main() diff --git a/tests/misc/ttlsemulation.nim b/tests/misc/ttlsemulation.nim index 47c5934e6..767a9bd4e 100644 --- a/tests/misc/ttlsemulation.nim +++ b/tests/misc/ttlsemulation.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 matrix: "-d:nimTtlsemulationCase1 --threads --tlsEmulation:on; -d:nimTtlsemulationCase2 --threads --tlsEmulation:off; -d:nimTtlsemulationCase3 --threads" targets: "c cpp" """ diff --git a/tests/misc/tvarnums.nim b/tests/misc/tvarnums.nim index 2aef242e1..498099c49 100644 --- a/tests/misc/tvarnums.nim +++ b/tests/misc/tvarnums.nim @@ -7,7 +7,7 @@ import strutils type - TBuffer = array[0..10, int8] + TBuffer = array[0..10, uint8] proc toVarNum(x: int32, b: var TBuffer) = # encoding: first bit indicates end of number (0 if at end) @@ -21,11 +21,11 @@ proc toVarNum(x: int32, b: var TBuffer) = # anyway a = abs(x) # first 6 bits: - b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63)) + b[0] = uint8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63)) a = (a shr 6'i32) and 0x03ffffff # skip first 6 bits var i = 1 while a != 0'i32: - b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127)) + b[i] = uint8(ord(a >% 127'i32) shl 7 or (int(a) and 127)) inc(i) a = a shr 7'i32 @@ -41,40 +41,40 @@ proc toVarNum64(x: int64, b: var TBuffer) = # anyway a = abs(x) # first 6 bits: - b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63)) + b[0] = uint8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63)) a = (a shr 6) and 0x03ffffffffffffff # skip first 6 bits var i = 1 while a != 0'i64: - b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127)) + b[i] = uint8(ord(a >% 127'i64) shl 7 or int(a and 127)) inc(i) a = a shr 7 proc toNum64(b: TBuffer): int64 = # treat first byte different: - result = ze64(b[0]) and 63 + result = int64(b[0]) and 63 var i = 0 Shift = 6'i64 - while (ze(b[i]) and 128) != 0: + while (int(b[i]) and 128) != 0: inc(i) - result = result or ((ze64(b[i]) and 127) shl Shift) + result = result or ((int64(b[i]) and 127) shl Shift) inc(Shift, 7) - if (ze(b[0]) and 64) != 0: # sign bit set? + if (int(b[0]) and 64) != 0: # sign bit set? result = not result +% 1 # this is the same as ``- result`` # but gives no overflow error for low(int) proc toNum(b: TBuffer): int32 = # treat first byte different: - result = int32 ze(b[0]) and 63 + result = int32(b[0]) and 63 var i = 0 Shift = 6'i32 - while (ze(b[i]) and 128) != 0: + while (int(b[i]) and 128) != 0: inc(i) - result = result or ((int32(ze(b[i])) and 127'i32) shl Shift) + result = result or ((int32(b[i]) and 127'i32) shl Shift) Shift = Shift + 7'i32 - if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set? + if (int(b[0]) and (1 shl 6)) != 0: # sign bit set? result = (not result) +% 1'i32 # this is the same as ``- result`` # but gives no overflow error for low(int) diff --git a/tests/misc/tvcc.nim b/tests/misc/tvcc.nim new file mode 100644 index 000000000..10533729c --- /dev/null +++ b/tests/misc/tvcc.nim @@ -0,0 +1,9 @@ +discard """ + matrix: "--cc:vcc" + disabled: "linux" + disabled: "bsd" + disabled: "osx" + disabled: "unix" + disabled: "posix" +""" +doAssert true diff --git a/tests/modules/mincludeprefix.nim b/tests/modules/mincludeprefix.nim new file mode 100644 index 000000000..6d557a430 --- /dev/null +++ b/tests/modules/mincludeprefix.nim @@ -0,0 +1 @@ +const bar = 456 diff --git a/tests/modules/mincludetemplate.nim b/tests/modules/mincludetemplate.nim new file mode 100644 index 000000000..febe9bfcf --- /dev/null +++ b/tests/modules/mincludetemplate.nim @@ -0,0 +1 @@ +const foo = 123 diff --git a/tests/modules/timportas.nim b/tests/modules/timportas.nim index 2f7bf7f6a..179613c6b 100644 --- a/tests/modules/timportas.nim +++ b/tests/modules/timportas.nim @@ -2,15 +2,20 @@ discard """ action: run """ -import .. / modules / [definitions as foo] -import .. / modules / definitions as foo +import .. / modules / [mexporta as a1, definitions as foo1] +import .. / modules / definitions as foo2 +import ./[mexporta as a2, definitions as foo3] import std / times as bar from times as bar2 import nil import times as bar3 except convert import definitions as baz -discard foo.v +discard foo1.v +discard foo2.v +discard foo3.v discard bar.now() discard bar2.now() discard bar3.now() discard baz.v +discard a1.xyz +discard a2.xyz diff --git a/tests/modules/tincludeprefix.nim b/tests/modules/tincludeprefix.nim new file mode 100644 index 000000000..d45a6eff3 --- /dev/null +++ b/tests/modules/tincludeprefix.nim @@ -0,0 +1,3 @@ +include ./[mincludeprefix, mincludetemplate] +doAssert foo == 123 +doAssert bar == 456 diff --git a/tests/modules/tincludetemplate.nim b/tests/modules/tincludetemplate.nim new file mode 100644 index 000000000..77e409ee5 --- /dev/null +++ b/tests/modules/tincludetemplate.nim @@ -0,0 +1,5 @@ +# issue #12539 + +template includePath(n: untyped) = include ../modules/n # But `include n` works +includePath(mincludetemplate) +doAssert foo == 123 diff --git a/tests/modules/tmodule_name_clashes.nim b/tests/modules/tmodule_name_clashes.nim index 73b166c77..814d5d152 100644 --- a/tests/modules/tmodule_name_clashes.nim +++ b/tests/modules/tmodule_name_clashes.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" targets: "c" ccodecheck: "\\i @('atmaatsmodule_name_clashesdotnim_DatInit000')" ccodecheck: "\\i @('atmbatsmodule_name_clashesdotnim_DatInit000')" diff --git a/tests/modules/tmodulesymtype.nim b/tests/modules/tmodulesymtype.nim new file mode 100644 index 000000000..d17c4cca4 --- /dev/null +++ b/tests/modules/tmodulesymtype.nim @@ -0,0 +1,22 @@ +discard """ +cmd: "nim check $file" +""" + +# bug #19225 +import std/sequtils +sequtils #[tt.Error +^ expression has no type: sequtils]# +proc foo() = + block: #[tt.Error + ^ expression has no type: block: + sequtils]# + sequtils + +foo() + +# issue #23399 +when isMainModule: + sequtils #[tt.Error + ^ expression has no type: sequtils]# + +discard diff --git a/tests/modules/treorder.nim b/tests/modules/treorder.nim index c81715cd8..ff0b2e071 100644 --- a/tests/modules/treorder.nim +++ b/tests/modules/treorder.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim -d:testdef $target $file" + matrix: "-d:testdef" output: '''works 34 34 defined @@ -8,6 +8,8 @@ defined {.experimental: "codeReordering".} +{.push callconv: stdcall.} + proc bar(x: T) proc foo() = @@ -41,3 +43,5 @@ using my, omy: int goo(3, 4) + +{.pop.} diff --git a/tests/deprecated/importme.nim b/tests/msgs/mdeprecated3.nim index 0a9c6e37d..0a9c6e37d 100644 --- a/tests/deprecated/importme.nim +++ b/tests/msgs/mdeprecated3.nim diff --git a/tests/misc/mspellsuggest.nim b/tests/msgs/mspellsuggest.nim index ad449554f..ad449554f 100644 --- a/tests/misc/mspellsuggest.nim +++ b/tests/msgs/mspellsuggest.nim diff --git a/tests/pragmas/mused2a.nim b/tests/msgs/mused2a.nim index d9b2bb9bf..d9b2bb9bf 100644 --- a/tests/pragmas/mused2a.nim +++ b/tests/msgs/mused2a.nim diff --git a/tests/pragmas/mused2b.nim b/tests/msgs/mused2b.nim index 39c92b964..39c92b964 100644 --- a/tests/pragmas/mused2b.nim +++ b/tests/msgs/mused2b.nim diff --git a/tests/pragmas/mused2c.nim b/tests/msgs/mused2c.nim index a374e634e..a374e634e 100644 --- a/tests/pragmas/mused2c.nim +++ b/tests/msgs/mused2c.nim diff --git a/tests/pragmas/mused3.nim b/tests/msgs/mused3.nim index 0beec1d44..0beec1d44 100644 --- a/tests/pragmas/mused3.nim +++ b/tests/msgs/mused3.nim diff --git a/tests/pragmas/mused3a.nim b/tests/msgs/mused3a.nim index c33d1ecb3..c33d1ecb3 100644 --- a/tests/pragmas/mused3a.nim +++ b/tests/msgs/mused3a.nim diff --git a/tests/pragmas/mused3b.nim b/tests/msgs/mused3b.nim index de288bb08..de288bb08 100644 --- a/tests/pragmas/mused3b.nim +++ b/tests/msgs/mused3b.nim diff --git a/tests/msgs/tdeprecated1.nim b/tests/msgs/tdeprecated1.nim new file mode 100644 index 000000000..f4e85da0b --- /dev/null +++ b/tests/msgs/tdeprecated1.nim @@ -0,0 +1,15 @@ +let foo* {.deprecated: "abcd".} = 42 +var foo1* {.deprecated: "efgh".} = 42 +foo1 = foo #[tt.Warning +^ efgh; foo1 is deprecated [Deprecated]; tt.Warning + ^ abcd; foo is deprecated [Deprecated]]# + +proc hello[T](a: T) {.deprecated: "Deprecated since v1.2.0, use 'HelloZ'".} = + discard + +hello[int](12) #[tt.Warning +^ Deprecated since v1.2.0, use 'HelloZ'; hello is deprecated [Deprecated]]# + +const foo2* {.deprecated: "abcd".} = 42 +discard foo2 #[tt.Warning + ^ abcd; foo2 is deprecated [Deprecated]]# diff --git a/tests/deprecated/tdeprecated.nim b/tests/msgs/tdeprecated2.nim index ba8d579ad..71d20081e 100644 --- a/tests/deprecated/tdeprecated.nim +++ b/tests/msgs/tdeprecated2.nim @@ -1,8 +1,8 @@ discard """ nimout: ''' -tdeprecated.nim(23, 3) Warning: a is deprecated [Deprecated] -tdeprecated.nim(30, 11) Warning: asdf; enum 'Foo' which contains field 'a' is deprecated [Deprecated] -tdeprecated.nim(40, 16) Warning: use fooX instead; fooA is deprecated [Deprecated] +tdeprecated2.nim(23, 3) Warning: a is deprecated [Deprecated] +tdeprecated2.nim(30, 11) Warning: asdf; enum 'Foo' which contains field 'a' is deprecated [Deprecated] +tdeprecated2.nim(40, 16) Warning: use fooX instead; fooA is deprecated [Deprecated] end ''' """ @@ -35,7 +35,7 @@ block: # issue #8063 Foo = enum fooX - {.deprecated: [fooA: fooX].} + const fooA {.deprecated: "use fooX instead".} = fooX let foo: Foo = fooA echo foo diff --git a/tests/msgs/tdeprecated3.nim b/tests/msgs/tdeprecated3.nim new file mode 100644 index 000000000..0c1b7deff --- /dev/null +++ b/tests/msgs/tdeprecated3.nim @@ -0,0 +1,33 @@ +discard """ + matrix: "--hint:all:off" + nimoutFull: true + nimout: ''' +tdeprecated3.nim(21, 8) Warning: goodbye; mdeprecated3 is deprecated [Deprecated] +tdeprecated3.nim(24, 10) Warning: Ty is deprecated [Deprecated] +tdeprecated3.nim(27, 10) Warning: hello; Ty1 is deprecated [Deprecated] +tdeprecated3.nim(30, 8) Warning: aVar is deprecated [Deprecated] +tdeprecated3.nim(32, 3) Warning: aProc is deprecated [Deprecated] +tdeprecated3.nim(33, 3) Warning: hello; aProc1 is deprecated [Deprecated] +''' +""" + + + + + + + +# line 20 +import mdeprecated3 + +block: + var z: Ty + z = 0 +block: + var z: Ty1 + z = 0 +block: + echo aVar +block: + aProc() + aProc1() diff --git a/tests/msgs/tdeprecatedequalhook.nim b/tests/msgs/tdeprecatedequalhook.nim new file mode 100644 index 000000000..79ee835f8 --- /dev/null +++ b/tests/msgs/tdeprecatedequalhook.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "Overriding `=` hook is deprecated; Override `=copy` hook instead" + matrix: "--warningAsError[Deprecated]:on" +""" + +type + SharedString = object + data: string + +proc `=`(x: var SharedString, y: SharedString) = + discard \ No newline at end of file diff --git a/tests/compilerfeatures/texpandmacro.nim b/tests/msgs/texpandmacro.nim index fea8b571f..fea8b571f 100644 --- a/tests/compilerfeatures/texpandmacro.nim +++ b/tests/msgs/texpandmacro.nim diff --git a/tests/misc/thints_off.nim b/tests/msgs/thints_off.nim index 5a4cadad6..5a4cadad6 100644 --- a/tests/misc/thints_off.nim +++ b/tests/msgs/thints_off.nim diff --git a/tests/msgs/tspellsuggest.nim b/tests/msgs/tspellsuggest.nim new file mode 100644 index 000000000..ea0a98cd3 --- /dev/null +++ b/tests/msgs/tspellsuggest.nim @@ -0,0 +1,45 @@ +discard """ + matrix: "--spellsuggest:15 --hints:off" + action: "reject" + nimout: ''' +tspellsuggest.nim(45, 13) Error: undeclared identifier: 'fooBar' +candidates (edit distance, scope distance); see '--spellSuggest': + (1, 0): 'fooBar8' + (1, 1): 'fooBar7' + (1, 3): 'fooBar1' + (1, 3): 'fooBar2' + (1, 3): 'fooBar3' + (1, 3): 'fooBar4' + (1, 3): 'fooBar5' + (1, 3): 'fooBar6' + (1, 5): 'FooBar' + (1, 5): 'fooBar4' + (1, 5): 'fooBar9' + (1, 5): 'fooCar' + (2, 5): 'FooCar' + (2, 5): 'GooBa' + (3, 0): 'fooBarBaz' +''' +""" + +# tests `--spellsuggest:num` + + + + +# line 30 +import ./mspellsuggest + +var fooBar1 = 0 +let fooBar2 = 0 +const fooBar3 = 0 +proc fooBar4() = discard +template fooBar5() = discard +macro fooBar6() = discard + +proc main = + var fooBar7 = 0 + block: + var fooBar8 = 0 + const fooBarBaz = 0 + let x = fooBar diff --git a/tests/msgs/tspellsuggest2.nim b/tests/msgs/tspellsuggest2.nim new file mode 100644 index 000000000..4bf05799e --- /dev/null +++ b/tests/msgs/tspellsuggest2.nim @@ -0,0 +1,45 @@ +discard """ + matrix: "--spellsuggest:12 --hints:off" + action: "reject" + nimout: ''' +tspellsuggest2.nim(45, 13) Error: undeclared identifier: 'fooBar' +candidates (edit distance, scope distance); see '--spellSuggest': + (1, 0): 'fooBar8' + (1, 1): 'fooBar7' + (1, 3): 'fooBar1' + (1, 3): 'fooBar2' + (1, 3): 'fooBar3' + (1, 3): 'fooBar4' + (1, 3): 'fooBar5' + (1, 3): 'fooBar6' + (1, 5): 'FooBar' + (1, 5): 'fooBar4' + (1, 5): 'fooBar9' + (1, 5): 'fooCar' +''' +""" + +# tests `--spellsuggest` + + + + + + + +# line 30 +import ./mspellsuggest + +var fooBar1 = 0 +let fooBar2 = 0 +const fooBar3 = 0 +proc fooBar4() = discard +template fooBar5() = discard +macro fooBar6() = discard + +proc main = + var fooBar7 = 0 + block: + var fooBar8 = 0 + const fooBarBaz = 0 + let x = fooBar diff --git a/tests/msgs/tspellsuggest3.nim b/tests/msgs/tspellsuggest3.nim new file mode 100644 index 000000000..bd4d5256f --- /dev/null +++ b/tests/msgs/tspellsuggest3.nim @@ -0,0 +1,21 @@ +discard """ + matrix: "--spellsuggest:4 --hints:off" + action: "reject" + nimout: ''' +tspellsuggest3.nim(21, 1) Error: undeclared identifier: 'fooBar' +candidates (edit distance, scope distance); see '--spellSuggest': + (1, 2): 'FooBar' + (1, 2): 'fooBar4' + (1, 2): 'fooBar9' + (1, 2): 'fooCar' +''' +""" + + +import ./mspellsuggest +import ./mspellsuggest +import ./mspellsuggest +import ./mspellsuggest + + +fooBar diff --git a/tests/pragmas/tused2.nim b/tests/msgs/tused2.nim index f80c198d8..5ccda7737 100644 --- a/tests/pragmas/tused2.nim +++ b/tests/msgs/tused2.nim @@ -7,12 +7,12 @@ mused2a.nim(12, 6) Hint: 'fn1' is declared but not used [XDeclaredButNotUsed] mused2a.nim(16, 5) Hint: 'fn4' is declared but not used [XDeclaredButNotUsed] mused2a.nim(20, 7) Hint: 'fn7' is declared but not used [XDeclaredButNotUsed] mused2a.nim(23, 6) Hint: 'T1' is declared but not used [XDeclaredButNotUsed] -mused2a.nim(1, 11) Warning: imported and not used: 'strutils' [UnusedImport] -mused2a.nim(3, 9) Warning: imported and not used: 'os' [UnusedImport] +mused2a.nim(1, 12) Warning: imported and not used: 'strutils' [UnusedImport] +mused2a.nim(3, 10) Warning: imported and not used: 'os' [UnusedImport] mused2a.nim(5, 23) Warning: imported and not used: 'typetraits2' [UnusedImport] -mused2a.nim(6, 9) Warning: imported and not used: 'setutils' [UnusedImport] +mused2a.nim(6, 10) Warning: imported and not used: 'setutils' [UnusedImport] tused2.nim(42, 8) Warning: imported and not used: 'mused2a' [UnusedImport] -tused2.nim(45, 11) Warning: imported and not used: 'strutils' [UnusedImport] +tused2.nim(45, 12) Warning: imported and not used: 'strutils' [UnusedImport] ''' """ diff --git a/tests/misc/twarningaserror.nim b/tests/msgs/twarningaserror.nim index 6f7b76095..6f7b76095 100644 --- a/tests/misc/twarningaserror.nim +++ b/tests/msgs/twarningaserror.nim diff --git a/tests/navigator/tincludefile.nim b/tests/navigator/tincludefile.nim index f35ab2ec9..a913d0736 100644 --- a/tests/navigator/tincludefile.nim +++ b/tests/navigator/tincludefile.nim @@ -1,4 +1,5 @@ discard """ + disabled: true cmd: "nim check $options --defusages:$file,12,7 $file" nimout: '''def tincludefile_temp.nim(11, 10) usage tincludefile_temp.nim(12, 8) @@ -7,7 +8,6 @@ usage tincludefile_temp.nim(12, 8) - proc foo(x: int) = echo x diff --git a/tests/navigator/tnav1.nim b/tests/navigator/tnav1.nim index b6bbdbf19..e76c921f3 100644 --- a/tests/navigator/tnav1.nim +++ b/tests/navigator/tnav1.nim @@ -1,11 +1,11 @@ discard """ + disabled: true cmd: "nim check $options --defusages:$file,12,7 $file" nimout: '''def tnav1_temp.nim(11, 10) usage tnav1_temp.nim(12, 8) ''' """ - import std / [times] proc foo(x: int) = diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims index 0cb950227..f22caaacd 100644 --- a/tests/newconfig/tfoo.nims +++ b/tests/newconfig/tfoo.nims @@ -6,7 +6,7 @@ exec "gcc -v" --define:release --forceBuild ---path: "../friends" +--path: "../generics" warning("uninit", off) diff --git a/tests/nimdoc/m13129.nim b/tests/nimdoc/m13129.nim index 145cae39c..34e118381 100644 --- a/tests/nimdoc/m13129.nim +++ b/tests/nimdoc/m13129.nim @@ -4,6 +4,7 @@ when defined(cpp): {.push header: "<vector>".} type Vector[T] {.importcpp: "std::vector".} = object + {.pop.} elif defined(js): proc endsWith*(s, suffix: cstring): bool {.noSideEffect,importjs: "#.endsWith(#)".} elif defined(c): diff --git a/tests/nimdoc/trunnableexamples.nim b/tests/nimdoc/trunnableexamples.nim index ac7a0e26f..57e725b2e 100644 --- a/tests/nimdoc/trunnableexamples.nim +++ b/tests/nimdoc/trunnableexamples.nim @@ -1,5 +1,5 @@ discard """ -cmd: "nim doc --doccmd:--hints:off --hints:off $file" +cmd: '''nim doc --doccmd:"-d:testFooExternal --hints:off" --hints:off $file''' action: "compile" nimoutFull: true nimout: ''' @@ -7,7 +7,6 @@ foo1 foo2 foo3 foo5 -foo6 foo7 in examplesInTemplate1 doc in outer @@ -15,16 +14,11 @@ doc in inner1 doc in inner2 foo8 foo9 +foo6 ''' joinable: false """ -#[ -pending bug #18077, use instead: -cmd: "nim doc --doccmd:'-d:testFooExternal --hints:off' --hints:off $file" -and merge trunnableexamples2 back here -]# -{.define(testFooExternal).} proc fun*() = runnableExamples: @@ -43,7 +37,7 @@ proc fun*() = proc fun*()=echo "foo5" fun() - runnableExamples: + runnableExamples("--experimental:codeReordering --warnings:off"): # `codeReordering` only allowed at top level {.experimental: "codeReordering".} proc fun1() = fun2() @@ -65,7 +59,7 @@ when true: # issue #12746 runnableExamples: try: discard - except: + except CatchableError: # just the general except will work discard @@ -196,6 +190,10 @@ runnableExamples: proc fun*()=echo "foo9" fun() +# import std/assertions by default +runnableExamples("-d:nimPreviewSlimSystem"): + doAssert true + # note: there are yet other examples where putting runnableExamples at module # scope is needed, for example when using an `include` before an `import`, etc. @@ -208,3 +206,8 @@ snippet: doAssert defined(testFooExternal) ]## + +when true: # runnableExamples with rdoccmd + runnableExamples "-d:testFoo -d:testBar": + doAssert defined(testFoo) and defined(testBar) + doAssert defined(testFooExternal) diff --git a/tests/nimdoc/trunnableexamples2.nim b/tests/nimdoc/trunnableexamples2.nim deleted file mode 100644 index 5a437744e..000000000 --- a/tests/nimdoc/trunnableexamples2.nim +++ /dev/null @@ -1,11 +0,0 @@ -discard """ -cmd: "nim doc --doccmd:-d:testFooExternal --hints:off $file" -action: "compile" -joinable: false -""" - -# pending bug #18077, merge back inside trunnableexamples.nim -when true: # runnableExamples with rdoccmd - runnableExamples "-d:testFoo -d:testBar": - doAssert defined(testFoo) and defined(testBar) - doAssert defined(testFooExternal) diff --git a/tests/niminaction/Chapter3/various3.nim b/tests/niminaction/Chapter3/various3.nim index 4e028a048..c7cdf7db4 100644 --- a/tests/niminaction/Chapter3/various3.nim +++ b/tests/niminaction/Chapter3/various3.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" output: ''' Future is no longer empty, 42 ''' diff --git a/tests/niminaction/Chapter7/Tweeter/src/createDatabase.nim b/tests/niminaction/Chapter7/Tweeter/src/createDatabase.nim index a7d4ebe00..67d9323f2 100644 --- a/tests/niminaction/Chapter7/Tweeter/src/createDatabase.nim +++ b/tests/niminaction/Chapter7/Tweeter/src/createDatabase.nim @@ -1,4 +1,5 @@ discard """ +disabled: true output: "Database created successfully!" """ diff --git a/tests/niminaction/Chapter7/Tweeter/src/tweeter.nim b/tests/niminaction/Chapter7/Tweeter/src/tweeter.nim index 2fac949b9..1b521521c 100644 --- a/tests/niminaction/Chapter7/Tweeter/src/tweeter.nim +++ b/tests/niminaction/Chapter7/Tweeter/src/tweeter.nim @@ -1,4 +1,5 @@ discard """ +disabled: true action: compile matrix: "--threads:off" """ diff --git a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim index a3cab4cba..c8beb4a30 100644 --- a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim +++ b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim @@ -1,4 +1,5 @@ discard """ +disabled: true outputsub: "All tests finished successfully!" """ diff --git a/tests/niminaction/Chapter8/sdl/sdl_test.nim b/tests/niminaction/Chapter8/sdl/sdl_test.nim index 1c4d258fb..db1700e0d 100644 --- a/tests/niminaction/Chapter8/sdl/sdl_test.nim +++ b/tests/niminaction/Chapter8/sdl/sdl_test.nim @@ -18,7 +18,7 @@ renderer.setDrawColor 29, 64, 153, 255 renderer.clear renderer.setDrawColor 255, 255, 255, 255 -when defined(c): +when false: # no long work with gcc 14! # just to ensure code from NimInAction still works, but # the `else` branch would work as well in C mode var points = [ diff --git a/tests/notnil/tparse.nim b/tests/notnil/tparse.nim new file mode 100644 index 000000000..5c938ff04 --- /dev/null +++ b/tests/notnil/tparse.nim @@ -0,0 +1,18 @@ +# issue #16324 + +{.push experimental: "notnil".} + +block: + type Foo = ref object + value: int + + proc newFoo1(): Foo not nil = # This compiles + return Foo(value: 1) + + proc newFoo2(): Foo not nil {.inline.} = # This does not + return Foo(value: 1) + + doAssert newFoo1().value == 1 + doAssert newFoo2().value == 1 + +{.pop.} diff --git a/tests/objects/mobject_default_value.nim b/tests/objects/mobject_default_value.nim new file mode 100644 index 000000000..224549501 --- /dev/null +++ b/tests/objects/mobject_default_value.nim @@ -0,0 +1,15 @@ +type + Clean = object + mem: int + Default* = object + poi: int = 12 + clc: Clean + se*: range[0'i32 .. high(int32)] + + NonDefault* = object + poi: int + + PrellDeque*[T] = object + pendingTasks*: range[0'i32 .. high(int32)] + head: T + tail: T diff --git a/tests/objects/t20972.nim b/tests/objects/t20972.nim new file mode 100644 index 000000000..6383dc9b1 --- /dev/null +++ b/tests/objects/t20972.nim @@ -0,0 +1,15 @@ +discard """ + matrix: "--mm:refc -d:release; --mm:orc -d:release" +""" + +{.passC: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -Wall -Wextra -pedantic -flto".} +{.passL: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -flto".} + +# bug #20972 +type ForkedEpochInfo = object + case kind: bool + of true, false: discard +var info = ForkedEpochInfo(kind: true) +doAssert info.kind +info.kind = false +doAssert not info.kind diff --git a/tests/objects/t22301.nim b/tests/objects/t22301.nim new file mode 100644 index 000000000..8746bf584 --- /dev/null +++ b/tests/objects/t22301.nim @@ -0,0 +1,17 @@ +discard """ + errormsg: "branch initialization with a runtime discriminator is not supported for a branch whose fields have default values." +""" + +# bug #22301 +type + Enum = enum A, B + Object = object + case a: Enum + of A: + integer: int = 200 + of B: + time: string + +let x = A +let s = Object(a: x) +echo s \ No newline at end of file diff --git a/tests/objects/t4318.nim b/tests/objects/t4318.nim index 34ff722f5..beadd6909 100644 --- a/tests/objects/t4318.nim +++ b/tests/objects/t4318.nim @@ -1,3 +1,8 @@ +discard """ + matrix: "--mm:refc" +""" + + type A = object of RootObj B = object of A diff --git a/tests/objects/tdefaultfieldscheck.nim b/tests/objects/tdefaultfieldscheck.nim new file mode 100644 index 000000000..8a05439d9 --- /dev/null +++ b/tests/objects/tdefaultfieldscheck.nim @@ -0,0 +1,16 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: +''' +tdefaultfieldscheck.nim(14, 17) Error: type mismatch: got <string> but expected 'int' +''' +""" + + +type + Date* = object + goal: float = 7 + name: int = "string" + +echo default(Date) diff --git a/tests/objects/tdefaultrangetypescheck.nim b/tests/objects/tdefaultrangetypescheck.nim new file mode 100644 index 000000000..71e7ac59b --- /dev/null +++ b/tests/objects/tdefaultrangetypescheck.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "cannot convert 0 to range 1..5(int)" + line: 9 +""" + +type + Point = object + y: int + x: range[1..5] = 0 + +echo default(Point) diff --git a/tests/objects/tillegal_recursion.nim b/tests/objects/tillegal_recursion.nim index 222139101..428c2e445 100644 --- a/tests/objects/tillegal_recursion.nim +++ b/tests/objects/tillegal_recursion.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "inheritance only works with non-final objects" + errormsg: "Cannot inherit from: 'Foo:ObjectType'" line: 7 """ # bug #1691 diff --git a/tests/objects/tillegal_recursion2.nim b/tests/objects/tillegal_recursion2.nim new file mode 100644 index 000000000..ce2279f04 --- /dev/null +++ b/tests/objects/tillegal_recursion2.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "Cannot inherit from: 'Foo'" + line: 6 +""" +type + Foo = object of Foo diff --git a/tests/objects/tillegal_recursion3.nim b/tests/objects/tillegal_recursion3.nim new file mode 100644 index 000000000..c80f29e28 --- /dev/null +++ b/tests/objects/tillegal_recursion3.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "Cannot inherit from: 'Foo'" + line: 6 +""" +type + Foo = object of ref Foo diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim index 2e36b65a3..ce67c4490 100644 --- a/tests/objects/tobj_asgn_dont_slice.nim +++ b/tests/objects/tobj_asgn_dont_slice.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" outputsub: '''ObjectAssignmentDefect''' exitcode: "1" """ diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim index 1e4d89d68..ee5a5b221 100644 --- a/tests/objects/tobjconstr.nim +++ b/tests/objects/tobjconstr.nim @@ -50,27 +50,30 @@ type BS = object of B C = object of BS z*: int -# inherited fields are ignored, so no fields are set -when true: - var - o: B - o = B(x: 123) - echo o - o = B(y: 678, x: 123) - echo o -# inherited fields are ignored -echo C(x: 128, z: 89) # (y: 0, x: 0) -echo B(y: 678, x: 123) # (y: 678, x: 0) -echo B(x: 123, y: 678) # (y: 678, x: 0) +proc main2 = + # inherited fields are ignored, so no fields are set + when true: + var + o: B + o = B(x: 123) + echo o + o = B(y: 678, x: 123) + echo o -when true: - # correct, both with `var` and `let`; - var b=B(x: 123) - echo b # (y: 0, x: 123) - b=B(y: 678, x: 123) - echo b # (y: 678, x: 123) - b=B(y: b.x, x: b.y) - echo b # (y: 123, x: 678) + # inherited fields are ignored + echo C(x: 128, z: 89) # (y: 0, x: 0) + echo B(y: 678, x: 123) # (y: 678, x: 0) + echo B(x: 123, y: 678) # (y: 678, x: 0) + when true: + # correct, both with `var` and `let`; + var b=B(x: 123) + echo b # (y: 0, x: 123) + b=B(y: 678, x: 123) + echo b # (y: 678, x: 123) + b=B(y: b.x, x: b.y) + echo b # (y: 123, x: 678) + +main2() GC_fullCollect() diff --git a/tests/objects/tobject.nim b/tests/objects/tobject.nim index 543a86376..a185bebcb 100644 --- a/tests/objects/tobject.nim +++ b/tests/objects/tobject.nim @@ -1,4 +1,3 @@ -import unittest type Obj = object foo: int @@ -10,9 +9,9 @@ block: # object basic methods block: # it should convert an object to a string var obj = makeObj(1) # Should be "obj: (foo: 1)" or similar. - check($obj == "(foo: 1)") + doAssert($obj == "(foo: 1)") block: # it should test equality based on fields - check(makeObj(1) == makeObj(1)) + doAssert(makeObj(1) == makeObj(1)) # bug #10203 @@ -58,3 +57,18 @@ block: # bug #14698 x1: int x3: seq[int] doAssert t[].sizeof == Foo1.sizeof + +# bug #147 +type + TValue* {.pure, final.} = object of RootObj + a: int + PValue = ref TValue + PPValue = ptr PValue + + +var x: PValue +new x +var sp: PPValue = addr x + +sp.a = 2 +doAssert sp.a == 2 diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim new file mode 100644 index 000000000..0cd05e4f3 --- /dev/null +++ b/tests/objects/tobject_default_value.nim @@ -0,0 +1,780 @@ +discard """ + matrix: "-d:nimPreviewRangeDefault --mm:refc; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc" + targets: "c cpp js" +""" + +import std/[times, macros, tables] + +type + Guess = object + poi: DateTime + + GuessDistinct = distinct Guess + +block: + var x: Guess + discard Guess() + + var y: GuessDistinct + + discard y + + discard GuessDistinct(x) + + +import mobject_default_value + +block: + let x = Default() + doAssert x.se == 0'i32 + +block: + let x = default(Default) + doAssert x.se == 0'i32 +# echo Default(poi: 12) +# echo Default(poi: 17) + +# echo NonDefault(poi: 77) + +block: + var x: Default + doAssert x.se == 0'i32 + +type + ObjectBase = object of RootObj + value = 12 + + ObjectBaseDistinct = distinct ObjectBase + + DinstinctInObject = object + data: ObjectBaseDistinct + + Object = object of ObjectBase + time: float = 1.2 + date: int + scale: range[1..10] + + Object2 = object + name: Object + + Object3 = object + obj: Object2 + + ObjectTuple = tuple + base: ObjectBase + typ: int + obj: Object + + TupleInObject = object + size = 777 + data: ObjectTuple + + Ref = ref object of ObjectBase + + RefInt = ref object of Ref + data = 73 + + Ref2 = ref object of ObjectBase + + RefInt2 = ref object of Ref + data = 73 + +var t {.threadvar.}: Default +# var m1, m2 {.threadvar.}: Default + +block: + doAssert t.se == 0'i32 + +block: # ARC/ORC cannot bind destructors twice, so it cannot + # be moved into main + block: + var x: Ref + new(x) + doAssert x.value == 12, "Ref.value = " & $x.value + + var y: RefInt + new(y) + doAssert y.value == 12 + doAssert y.data == 73 + + block: + var x: Ref2 + new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref") + doAssert x.value == 12, "Ref.value = " & $x.value + + proc call(x: RefInt2) = + discard "call RefInt" + + var y: RefInt2 + new(y, call) + doAssert y.value == 12 + doAssert y.data == 73 + +template main {.dirty.} = + block: # bug #16744 + type + R = range[1..10] + Obj = object + r: R + + var + rVal: R = default(R) # Works fine + objVal = default(Obj) + + doAssert rVal == 1 + doAssert objVal.r == 1 + + block: # bug #16744 + type + R = range[1..10] + Obj = object + r: R + + var + rVal: R = default(R) # Works fine + objVal = Obj() + + doAssert rVal == 1 # it should be 1 + doAssert objVal.r == 1 + + block: # bug #3608 + type + abc = ref object + w: range[2..100] + + proc createABC(): abc = + new(result) + result.w = 20 + + doAssert createABC().w == 20 + + block: + var x = new ObjectBase + doAssert x.value == 12 + + proc hello(): ref ObjectBase = + new result + + let z = hello() + doAssert z.value == 12 + + block: + var base = ObjectBase() + var x: ObjectBaseDistinct = ObjectBaseDistinct(base) + doAssert ObjectBase(x).value == 12 + let y = ObjectBaseDistinct(default(ObjectBase)) + doAssert ObjectBase(y).value == 12 + + let m = ObjectBaseDistinct(ObjectBase()) + doAssert ObjectBase(m).value == 12 + + proc hello(): ObjectBaseDistinct = + result = ObjectBaseDistinct(default(ObjectBase)) + + let z = hello() + doAssert ObjectBase(z).value == 12 + + block: + var x: DinstinctInObject + x.data = ObjectBaseDistinct(default(ObjectBase)) + + doAssert ObjectBase(x.data).value == 12 + + block: + var x = Object() + doAssert x.value == 12 + doAssert x.time == 1.2 + doAssert x.scale == 1 + + let y = default(Object) + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + var x1, x2, x3 = default(Object) + doAssert x1.value == 12 + doAssert x1.time == 1.2 + doAssert x1.scale == 1 + doAssert x2.value == 12 + doAssert x2.time == 1.2 + doAssert x2.scale == 1 + doAssert x3.value == 12 + doAssert x3.time == 1.2 + doAssert x3.scale == 1 + + block: + var x = new Object + doAssert x[] == default(Object) + + block: + var x = default(Object2) + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + + block: + let x = Object2() + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + + block: + var x: ref Object2 + new x + doAssert x[] == default(Object2) + + block: + var x = default(Object3) + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + + block: + var x = Object3() + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + + when nimvm: + # todo + discard "fixme" + else: + when defined(gcArc) or defined(gcOrc): + block: #seq + var x = newSeq[Object](10) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: seq[Object] + setLen(x, 5) + let y = x[^1] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var my = @[1, 2, 3, 4, 5] + my.setLen(0) + my.setLen(5) + doAssert my == @[0, 0, 0, 0, 0] + + block: + var my = "hello" + my.setLen(0) + my.setLen(5) + doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']""" + + block: # array + var x: array[10, Object] = default(array[10, Object]) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: # array + var x {.noinit.}: array[10, Object] + discard x + + block: # tuple + var x = default(ObjectTuple) + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x = default(TupleInObject) + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 + + type + ObjectArray = object + data: array[10, Object] + + block: + var x = default(ObjectArray) + let y = x.data[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: PrellDeque[int] + doAssert x.pendingTasks == 0 + + type + Color = enum + Red, Blue, Yellow + + ObjectVarint = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + ObjectVarint1 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + + block: + var x = ObjectVarint(kind: Red) + doAssert x.kind == Red + doAssert x.data == 10 + + block: + var x = ObjectVarint(kind: Blue) + doAssert x.kind == Blue + doAssert x.fill == "123" + + block: + var x = ObjectVarint(kind: Yellow) + doAssert x.kind == Yellow + doAssert typeof(x.time) is float32 + + block: + var x = default(ObjectVarint1) + doAssert x.kind == Blue + doAssert x.fill2 == "123" + x.cry = 326 + + type + ObjectVarint2 = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + block: + var x = ObjectVarint2(kind: Blue) + doAssert x.fill == "123" + + block: + type + Color = enum + Red, Blue, Yellow + + type + ObjectVarint3 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + case name: Color = Blue + of Blue: + go = 12 + else: + temp = 66 + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + + block: + var x = default(ObjectVarint3) + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + + block: + var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) + doAssert x.kind == Blue + doAssert x.name == Red + doAssert x.temp == 99 + + block: + type + Default = tuple + id: int = 1 + obj: ObjectBase + name: string + + Class = object + def: Default + + Member = object + def: Default = (id: 777, obj: ObjectBase(), name: "fine") + + block: + var x = default(Default) + doAssert x.id == 1 + doAssert x.obj == default(ObjectBase) + doAssert x.name == "" + + block: + var x = default(Class) + doAssert x.def == default(Default) + doAssert x.def.id == 1 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "" + + block: + var x = default(Member) + doAssert x.def.id == 777 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "fine" + + block: + var x {.noinit.} = 12 + doAssert x == 12 + + type + Pure = object + id: int = 12 + + var y {.noinit.}: Pure + doAssert y.id == 0 + + var z {.noinit.}: Pure = Pure(id: 77) + doAssert z.id == 77 + + block: # bug #20681 + type A = object + d: DateTime = DateTime() + + let x = default(A) + doAssert $x == "(d: Uninitialized DateTime)" + + block: # bug #20715 + block: + type + Foo = enum + A + B + + Bar = object + case foo: Foo + of A: + t: range[-1..2] + else: discard + + var d = default(Bar) + doAssert d.t == -1 + + block: + type + Foo = enum + A + B + + Bar = object + case foo: Foo + of A: + t: range[0..2] + else: discard + + var d = default(Bar) + doAssert d.t == 0 + + block: # bug #20740 + block: + proc foo(x: static DateTime = Datetime()) = + discard + + foo() + + block: + macro foo(x: static DateTime) = + discard x + + macro foo2: untyped = + var x = DateTime() + + result = quote do: + foo(`x`) + + foo2() + + + block: # issue #20699 + type + Either[A,B] = object + case kind:bool + of false: + b: B + of true: + a: A + O = object of RootRef + + proc oToEither(o:O):Either[O,void] = + Either[O,void](kind:true,a: o) + + discard oToEither(O()) + + block: # bug #20695 + type + Default = object + tabs: Table[string, int] = initTable[string, int]() + + let d = default(Default) + doAssert d.tabs.len == 0 + + block: + type + Default = object + tabs: Table[string, int] = Table[string, int]() + + let d = default(Default) + doAssert d.tabs.len == 0 + + + block: + type DjangoDateTime = distinct DateTime + + type Default = object + data: DjangoDateTime = DjangoDateTime(DateTime()) + + let x = default(Default) + doAssert x.data is DjangoDateTime + + block: + type DjangoDateTime = distinct DateTime + + type Default = object + data = DjangoDateTime(DateTime()) + + let x = default(Default) + doAssert x.data is DjangoDateTime + + block: + type + Result2 = object + case o: bool + of false: + e: float + of true: + v {.requiresInit.} : int = 1 + + proc startSessionSync(): Result2 = + return Result2(o: true) + + proc mainSync = + let ff = startSessionSync() + doAssert ff.v == 1 + + mainSync() + + block: + type + Result2 = object + v {.requiresInit.} : int = 1 + + proc startSessionSync(): Result2 = + return Result2() + + proc mainSync = + let ff = startSessionSync() + doAssert ff.v == 1 + + mainSync() + + block: # bug #21801 + func evaluate(i: int): float = + 0.0 + + func evaluate(): float = + 0.0 + + type SearchOptions = object + evaluation: proc(): float = evaluate + + block: + func evaluate(): float = + 0.0 + + type SearchOptions = object + evaluation: proc(): float = evaluate + + block: + func evaluate(i: int): float = + 0.0 + + type SearchOptions = object + evaluation = evaluate + block: + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + + template `?`[T, E](self: Result[T, E]): auto = + let v = (self) + if not v.oResultPrivate: + when compiles(`assignResult?`(default(typeof(result)))): + when typeof(result) is typeof(v): + `assignResult?`(v) + elif E is void: + `assignResult?`(err(typeof(result))) + else: + `assignResult?`(err(typeof(result), v.eResultPrivate)) + return + else: + return + when typeof(result) is typeof(v): + v + elif E is void: + err(typeof(result)) + else: + err(typeof(result), v.eResultPrivate) + + when not(T is void): + v.vResultPrivate + + type R = Result[int, string] + + proc testAssignResult() = + var assigned: bool + template `assignResult?`(v: Result) = + assigned = true + result = v + + proc failed(): Result[int, string] = + discard + + proc calling(): Result[int, string] = + let _ = ? failed() + doAssert false + + let r = calling() + doAssert assigned + + when nimvm: + when not defined(js): + testAssignResult() + else: + testAssignResult() + + block: # bug #22123 + type Thing = object + x: float32 = 1 + + type ThingWithArray = object + arr: array[256, float32] + n: float32 = 1 + + type Container = ref object + thing: array[5, Thing] + thing_with_array: array[5, ThingWithArray] + + var foo = new Container + doAssert int(foo.thing[0].x) == 1 + + block: # bug #22613 + type + K = enum + A = "a" + B = "b" + T = object + case kind: K = B + of A: + a: int + of B: + b: float + + doAssert T().kind == B + + block: # bug #22926 + type + Direction = enum + North + South + East + West + + ArrayObj1 = object + list: array[Direction, int] + + ArrayObj2 = object + list: array[Direction, int] = [1, 2, 3, 4] + + block: + var a: ArrayObj1 + doAssert a.list[West] == 0 + var b = default ArrayObj1 + doAssert b.list[North] == 0 + + + block: + var a: ArrayObj2 + doAssert a.list[West] == 0 + var b = default ArrayObj2 + doAssert b.list[North] == 1 + + block: + type limited_float = range[1.2..20.0] + doAssert default(limited_float) == 1.2 + + + block: + type + range1 = range[1..10] + range2 = range[-1..10] + + proc foo = + doAssert default(range1) == 1 + doAssert default(range2) == -1 + + let s = default(array[5, range1]) + doAssert s == [range1 1, 1, 1, 1, 1] + + foo() + + block: + type + Object = object + id: range[1.2..29.3] + + var s = default(Object) + doAssert s.id == 1.2 + + block: # bug #23943 + type limited_int = range[1..20] + var d: limited_int; + doAssert d == 1 + +static: main() +main() diff --git a/tests/objects/tobjects_various.nim b/tests/objects/tobjects_various.nim index 8ec090f42..55db9312e 100644 --- a/tests/objects/tobjects_various.nim +++ b/tests/objects/tobjects_various.nim @@ -105,3 +105,16 @@ block t7244: proc test(foo: var Foo) = discard proc test(bar: var Bar) = test(Foo(bar)) + + +import std/macros + +#bug #20856 +macro ensureImplWorksOnConstr(t: typed): untyped = + expectKind(t, nnkObjConstr) + doAssert t[0].getTypeInst.getImpl.repr == "A = object" + doAssert t[0].getImpl.repr == "A = object" + +type A = object + +ensureImplWorksOnConstr(A()) diff --git a/tests/objects/trequireinit.nim b/tests/objects/trequireinit.nim new file mode 100644 index 000000000..202667b02 --- /dev/null +++ b/tests/objects/trequireinit.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "The MPlayerObj type doesn't have a default value. The following fields must be initialized: foo." +""" + +type + MPlayerObj* {.requiresInit.} = object + foo: range[5..10] = 5 + +var a: MPlayerObj +echo a.foo \ No newline at end of file diff --git a/tests/objects/tunsafenew.nim b/tests/objects/tunsafenew.nim new file mode 100644 index 000000000..6c1b33cd9 --- /dev/null +++ b/tests/objects/tunsafenew.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "conversion from int literal(-1) to Natural is invalid" +""" + +type + Obj = object + case b: bool + else: discard +var o: ref Obj +unsafeNew(o, -1) \ No newline at end of file diff --git a/tests/objects/tunsafenew2.nim b/tests/objects/tunsafenew2.nim new file mode 100644 index 000000000..83112bcfc --- /dev/null +++ b/tests/objects/tunsafenew2.nim @@ -0,0 +1,15 @@ +discard """ +valgrind: "leaks" +matrix: "-d:useMalloc" +targets: "c cpp" +""" + +type + Obj = object + case b: bool + else: discard + a: UncheckedArray[byte] + +var o: ref Obj +unsafeNew(o, sizeof(Obj) + 512) +zeroMem(addr o.a, 512) diff --git a/tests/objects/twhen1.nim b/tests/objects/twhen1.nim index 5b8eea3f4..fe072a46b 100644 --- a/tests/objects/twhen1.nim +++ b/tests/objects/twhen1.nim @@ -55,3 +55,35 @@ type x: int when (NimMajor, NimMinor) >= (1, 1): y: int +discard MyObject(x: 100, y: 200) + +block: # Ensure when evaluates properly in objects + type X[bits: static int] = object #22474 + when bits >= 256: + data32: byte + else: + data16: byte + + static: + discard X[255]().data16 + discard X[256]().data32 + + + type ComplexExprObject[S: static string, I: static int, Y: static auto] = object + when 'h' in S and I < 10 and Y isnot float: + a: int + elif I > 30: + b: int + elif typeof(Y) is float: + c: int + else: + d: int + + static: + discard ComplexExprObject["hello", 9, 300i32]().a + discard ComplexExprObject["", 40, 30f]().b + discard ComplexExprObject["", 20, float 30]().c + discard ComplexExprObject["", 20, ""]().d + + + diff --git a/tests/objvariant/tconstobjvariant.nim b/tests/objvariant/tconstobjvariant.nim new file mode 100644 index 000000000..45a647707 --- /dev/null +++ b/tests/objvariant/tconstobjvariant.nim @@ -0,0 +1,18 @@ +# This is a sample code, the first echo statement prints out the error +type + A = object + case w: uint8 + of 1: + n: int + else: + other: string + +const + a = A(w: 1, n: 5) + +proc foo = + + let c = [a] + doAssert c[0].n == 5 + +foo() \ No newline at end of file diff --git a/tests/openarray/topenarray.nim b/tests/openarray/topenarray.nim index aec5a4cbf..25b983651 100644 --- a/tests/openarray/topenarray.nim +++ b/tests/openarray/topenarray.nim @@ -48,6 +48,41 @@ proc main = doAssert testing(mySeq) == mySeq doAssert testing(mySeq[2..^2]) == mySeq[2..^2] + block: # bug #23321 + block: + proc foo(x: openArray[int]) = + doAssert x[0] == 0 + + var d = new array[1, int] + foo d[].toOpenArray(0, 0) + + block: + proc foo(x: openArray[int]) = + doAssert x[0] == 0 + + proc task(x: var array[1, int]): var array[1, int] = + result = x + var d: array[1, int] + foo task(d).toOpenArray(0, 0) + + block: + proc foo(x: openArray[int]) = + doAssert x[0] == 0 + + proc task(x: var array[1, int]): lent array[1, int] = + result = x + var d: array[1, int] + foo task(d).toOpenArray(0, 0) + + block: + proc foo(x: openArray[int]) = + doAssert x[0] == 0 + + proc task(x: var array[1, int]): ptr array[1, int] = + result = addr x + var d: array[1, int] + foo task(d)[].toOpenArray(0, 0) + main() -# static: main() # xxx bug #15952: Error: cannot generate code for: mSlice +static: main() diff --git a/tests/openarray/tuncheckedarray.nim b/tests/openarray/tuncheckedarray.nim new file mode 100644 index 000000000..c8ca9d2d4 --- /dev/null +++ b/tests/openarray/tuncheckedarray.nim @@ -0,0 +1,19 @@ +discard """ + exitcode: 0 + targets: "c cpp" +""" + +proc main = + block: # issue 19171 + var a = ['A'] + proc mutB(x: var openArray[char]) = + x[0] = 'B' + mutB(toOpenArray(cast[ptr UncheckedArray[char]](addr a), 0, 0)) + doAssert a[0] == 'B' + proc mutC(x: var openArray[char]; c: char) = + x[0] = c + let p = cast[ptr UncheckedArray[char]](addr a) + mutC(toOpenArray(p, 0, 0), 'C') + doAssert p[0] == 'C' + +main() diff --git a/tests/options/tnimbasepattern.nim b/tests/options/tnimbasepattern.nim new file mode 100644 index 000000000..1237af5c5 --- /dev/null +++ b/tests/options/tnimbasepattern.nim @@ -0,0 +1,26 @@ +discard """ + cmd: "nim cpp --nimbasepattern:test.h --cincludes:./tests/options $file " + output:''' +(a: 1) +''' +""" +const header = """ +#pragma once +#include "nimbase.h" +struct Foo { + int a; +}; +""" + +import os +static: + const dir = "./tests/options/" + createDir(dir) + writeFile(dir / "test.h", header) + +type + Foo {.importc.} = object + a: int32 = 1 + + +echo $Foo() \ No newline at end of file diff --git a/tests/osproc/tnoexe.nim b/tests/osproc/tnoexe.nim new file mode 100644 index 000000000..19a3cca67 --- /dev/null +++ b/tests/osproc/tnoexe.nim @@ -0,0 +1,27 @@ +discard """ + output: '''true +true''' +""" + +import std/osproc + +const command = "lsaaa -lah" + +try: + let process = startProcess(command, options = {poUsePath}) + discard process.waitForExit() +except OSError as e: + echo e.errorCode != 0 + +# `poEvalCommand`, invokes the system shell to run the specified command +try: + let process = startProcess(command, options = {poUsePath, poEvalCommand}) + # linux + let exitCode = process.waitForExit() + echo exitCode != 0 +except OSError as e: + # Because the implementation of `poEvalCommand` on different platforms is inconsistent, + # Linux will not throw an exception, but Windows will throw an exception + + # windows + echo e.errorCode != 0 diff --git a/tests/osproc/twaitforexit.nim b/tests/osproc/twaitforexit.nim new file mode 100644 index 000000000..535faca63 --- /dev/null +++ b/tests/osproc/twaitforexit.nim @@ -0,0 +1,38 @@ +import std/[osproc, os, times] + +block: # bug #5091 + when defined(linux): + const filename = "false" + var p = startProcess(filename, options = {poStdErrToStdOut, poUsePath}) + os.sleep(1000) # make sure process has exited already + + let atStart = getTime() + const msWait = 2000 + + try: + discard waitForExit(p, msWait) + except OSError: + discard + + # check that we don't have to wait msWait milliseconds + doAssert(getTime() < atStart + milliseconds(msWait)) + +block: # bug #23825 + + # the sleep command might not be available in all Windows installations + + when defined(linux): + + var thr: array[0..99, Thread[int]] + + proc threadFunc(i: int) {.thread.} = + let sleepTime = float(i) / float(thr.len + 1) + doAssert sleepTime < 1.0 + let p = startProcess("sleep", workingDir = "", args = @[$sleepTime], options = {poUsePath, poParentStreams}) + # timeout = 1_000_000 seconds ~= 278 hours ~= 11.5 days + doAssert p.waitForExit(timeout=1_000_000_000) == 0 + + for i in low(thr)..high(thr): + createThread(thr[i], threadFunc, i) + + joinThreads(thr) diff --git a/tests/overflw/tdistinct_range.nim b/tests/overflow/tdistinct_range.nim index f53515d45..f53515d45 100644 --- a/tests/overflw/tdistinct_range.nim +++ b/tests/overflow/tdistinct_range.nim diff --git a/tests/overflow/toverflow.nim b/tests/overflow/toverflow.nim new file mode 100644 index 000000000..972f929c6 --- /dev/null +++ b/tests/overflow/toverflow.nim @@ -0,0 +1,82 @@ +discard """ + output: "ok" + matrix: "--overflowChecks:off; --overflowChecks:off --b:js" +""" +# Tests nim's ability to detect overflows + +{.push overflowChecks: on.} + +var + a = high(int) + b = -2 + overflowDetected = false + +try: + echo(b - a) +except OverflowDefect: + overflowDetected = true + +{.pop.} # overflow check + +doAssert(overflowDetected) + +block: # Overflow checks in a proc + var + a = high(int) + b = -2 + overflowDetected = false + + {.push overflowChecks: on.} + proc foo() = + let c = b - a + {.pop.} + + try: + foo() + except OverflowDefect: + overflowDetected = true + + doAssert(overflowDetected) + +block: # Overflow checks in a forward declared proc + var + a = high(int) + b = -2 + overflowDetected = false + + proc foo() + + {.push overflowChecks: on.} + proc foo() = + let c = b - a + {.pop.} + + try: + foo() + except OverflowDefect: + overflowDetected = true + + doAssert(overflowDetected) + +block: # Overflow checks doesn't affect fwd declaration + var + a = high(int) + b = -2 + overflowDetected = false + + {.push overflowChecks: on.} + proc foo() + {.pop.} + + proc foo() = + let c = b - a + + try: + foo() + except OverflowDefect: + overflowDetected = true + + doAssert(not overflowDetected) + + +echo "ok" diff --git a/tests/overflw/toverflw2.nim b/tests/overflow/toverflow2.nim index c06b35c6d..c06b35c6d 100644 --- a/tests/overflw/toverflw2.nim +++ b/tests/overflow/toverflow2.nim diff --git a/tests/overflw/toverflw.nim b/tests/overflow/toverflow_reorder.nim index 164e16e5c..fcf7b0c82 100644 --- a/tests/overflw/toverflw.nim +++ b/tests/overflow/toverflow_reorder.nim @@ -1,3 +1,5 @@ +{.experimental: "codeReordering".} + discard """ output: "ok" cmd: "nim $target --overflowChecks:off $options $file" @@ -12,7 +14,7 @@ var overflowDetected = false try: - writeLine(stdout, b - a) + echo b - a except OverflowDefect: overflowDetected = true diff --git a/tests/overflw/tovfint.nim b/tests/overflow/tovfint.nim index 5c440a540..5c440a540 100644 --- a/tests/overflw/tovfint.nim +++ b/tests/overflow/tovfint.nim diff --git a/tests/misc/trangechecks.nim b/tests/overflow/trangechecks.nim index e48b1272b..e48b1272b 100644 --- a/tests/misc/trangechecks.nim +++ b/tests/overflow/trangechecks.nim diff --git a/tests/overflow/twronginference.nim b/tests/overflow/twronginference.nim new file mode 100644 index 000000000..34a982976 --- /dev/null +++ b/tests/overflow/twronginference.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "cannot convert 256 to int8" + line: 9 +""" + +# issue #23177 + +var x: int8 +x = 256 +echo x # 0 diff --git a/tests/overload/issue22142/tfail_implicit_ambiguous.nim b/tests/overload/issue22142/tfail_implicit_ambiguous.nim new file mode 100644 index 000000000..2586e0877 --- /dev/null +++ b/tests/overload/issue22142/tfail_implicit_ambiguous.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "ambiguous call" +""" +type + A[T] = object + C = object + +proc test[T: A](param: T): bool = false +proc test(param: A): bool = true +doAssert test(A[C]()) == true # previously would pass diff --git a/tests/overload/issue22142/tfail_nested_pointers.nim b/tests/overload/issue22142/tfail_nested_pointers.nim new file mode 100644 index 000000000..1603d98cb --- /dev/null +++ b/tests/overload/issue22142/tfail_nested_pointers.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "ambiguous call" +""" + +type + A[T] = object + C = object + x:int +proc p[T: A[ptr]](x:ptr[T]):bool = false +proc p(x: ptr[A[ptr]]):bool = true +var a: A[ptr[C]] +doAssert p(a.addr) == true diff --git a/tests/overload/issue22142/tfail_object_is_generic.nim b/tests/overload/issue22142/tfail_object_is_generic.nim new file mode 100644 index 000000000..b46795bd5 --- /dev/null +++ b/tests/overload/issue22142/tfail_object_is_generic.nim @@ -0,0 +1,16 @@ +discard """ + errormsg: "ambiguous call" +""" + +#[ +As of the time of writing `object` needs some special +treament in order to be considered "generic" in the right +context when used implicitly +]# + +type + C = object + +proc test[T: object](param: T): bool = false +proc test(param: object): bool = true +doAssert test(C()) == true # previously would pass diff --git a/tests/overload/issue22142/tfail_typeclass_var_invar.nim b/tests/overload/issue22142/tfail_typeclass_var_invar.nim new file mode 100644 index 000000000..07db65fef --- /dev/null +++ b/tests/overload/issue22142/tfail_typeclass_var_invar.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "ambiguous call" +""" + +type C = object +proc test[T: ptr](param: var T): bool = false +proc test(param: var ptr): bool = true +var d: ptr[C] +doAssert test(d) == true # previously would pass diff --git a/tests/overload/issue22142/tissue22142_shouldpass.nim b/tests/overload/issue22142/tissue22142_shouldpass.nim new file mode 100644 index 000000000..90d4efe51 --- /dev/null +++ b/tests/overload/issue22142/tissue22142_shouldpass.nim @@ -0,0 +1,68 @@ +type + A[T] = object of RootObj + B[T] = object + C = object + x:int + +# change (previously true) +block: + proc test[J;H: A[J];T: B[H]](param: T): bool = false + proc test[T](param: B[T]): bool = true + doAssert test(B[A[int]]()) == false +block: # object is more specific then `T` + proc p[H:object;T:ptr[H]](param:T):bool = false + proc p[T](param:ptr[T]):bool= true + var l: ptr[C] + doAssert p(l) == false +block: + proc p[T:A[object]](param:T):bool = false + proc p[T](param: A[T]):bool= true + doAssert p(A[C]()) == false +block: + proc test[H;T: A[H]](param: T): bool = false + proc test(param: A): bool = true + doAssert test(A[C]()) == false + +# change (previously ambiguous) +block: + proc p[T](a: A[T]): bool = false + proc p[T: object](a: T): bool = true + doAssert p(A[int]()) == false +block: # A is more specific than `object` + proc test[T: A](param: T): bool = false + proc test[T: object](param: T): bool = true + doAssert test(A[int]()) == false +block: + proc test[T: A](param: T): bool = false + proc test(param: object): bool = true + doAssert test(A[int]()) == false +block: + proc test[H;T: A[H]](param: T): bool = false + proc test(param: object): bool = true + doAssert test(A[C]()) == false +block: + proc test[H;T: A[B[H]]](param: T): bool = false + proc test[T: object](param: T): bool = true + doAssert test(A[B[int]]()) == false +block: + #[ + This was referenced in the nim compiler source (`sumGeneric`) as a case + that was supposed to not be ambiguous, yet it was + ]# + proc test[J;H:A[J]; T: A[H]](param: T): bool = false + proc test[H;T: A[H]](param: T): bool = true + doAssert test(A[A[C]]()) == false +block: + proc test[J;T:A[J]](param: A[T]): bool = false + proc test[T](param: A[T]): bool = true + doAssert test(A[A[C]]()) == false +block: + proc test[T](param: A[T]): bool = false + proc test[T: object](param: A[T]): bool = true + doAssert test(A[C]()) == true + + +block: #anti-regression (object is more specific then `T`) + proc test[J;T:A[J]](param: A[T]): bool = false + proc test(param: A[A[object]]): bool = true + doAssert test(A[A[C]]()) == true \ No newline at end of file diff --git a/tests/overload/m19737.nim b/tests/overload/m19737.nim new file mode 100644 index 000000000..7f7ac98e2 --- /dev/null +++ b/tests/overload/m19737.nim @@ -0,0 +1,10 @@ +type + UInt128* = object + lo, hi: uint64 + +func `<`*(x, y: UInt128): bool = + (x.hi < y.hi) or ((x.hi == y.hi) and (x.lo < y.lo)) + +when not defined(works): + func `>`*(x, y: UInt128): bool = + (x.hi > y.hi) or ((x.hi == y.hi) and (x.lo > y.lo)) diff --git a/tests/overload/mvaruintconv.nim b/tests/overload/mvaruintconv.nim new file mode 100644 index 000000000..b889c90cf --- /dev/null +++ b/tests/overload/mvaruintconv.nim @@ -0,0 +1,145 @@ +import + std/[macros, tables, hashes] + +export + macros + +type + FieldDescription* = object + name*: NimNode + isPublic*: bool + isDiscriminator*: bool + typ*: NimNode + pragmas*: NimNode + caseField*: NimNode + caseBranch*: NimNode + +{.push raises: [].} + +func isTuple*(t: NimNode): bool = + t.kind == nnkBracketExpr and t[0].kind == nnkSym and eqIdent(t[0], "tuple") + +macro isTuple*(T: type): untyped = + newLit(isTuple(getType(T)[1])) + +proc collectFieldsFromRecList(result: var seq[FieldDescription], + n: NimNode, + parentCaseField: NimNode = nil, + parentCaseBranch: NimNode = nil, + isDiscriminator = false) = + case n.kind + of nnkRecList: + for entry in n: + collectFieldsFromRecList result, entry, + parentCaseField, parentCaseBranch + of nnkRecWhen: + for branch in n: + case branch.kind: + of nnkElifBranch: + collectFieldsFromRecList result, branch[1], + parentCaseField, parentCaseBranch + of nnkElse: + collectFieldsFromRecList result, branch[0], + parentCaseField, parentCaseBranch + else: + doAssert false + + of nnkRecCase: + collectFieldsFromRecList result, n[0], + parentCaseField, + parentCaseBranch, + isDiscriminator = true + + for i in 1 ..< n.len: + let branch = n[i] + case branch.kind + of nnkOfBranch: + collectFieldsFromRecList result, branch[^1], n[0], branch + of nnkElse: + collectFieldsFromRecList result, branch[0], n[0], branch + else: + doAssert false + + of nnkIdentDefs: + let fieldType = n[^2] + for i in 0 ..< n.len - 2: + var field: FieldDescription + field.name = n[i] + field.typ = fieldType + field.caseField = parentCaseField + field.caseBranch = parentCaseBranch + field.isDiscriminator = isDiscriminator + + if field.name.kind == nnkPragmaExpr: + field.pragmas = field.name[1] + field.name = field.name[0] + + if field.name.kind == nnkPostfix: + field.isPublic = true + field.name = field.name[1] + + result.add field + + of nnkSym: + result.add FieldDescription( + name: n, + typ: getType(n), + caseField: parentCaseField, + caseBranch: parentCaseBranch, + isDiscriminator: isDiscriminator) + + of nnkNilLit, nnkDiscardStmt, nnkCommentStmt, nnkEmpty: + discard + + else: + doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr + +proc collectFieldsInHierarchy(result: var seq[FieldDescription], + objectType: NimNode) = + var objectType = objectType + + objectType.expectKind {nnkObjectTy, nnkRefTy} + + if objectType.kind == nnkRefTy: + objectType = objectType[0] + + objectType.expectKind nnkObjectTy + + var baseType = objectType[1] + if baseType.kind != nnkEmpty: + baseType.expectKind nnkOfInherit + baseType = baseType[0] + baseType.expectKind nnkSym + baseType = getImpl(baseType) + baseType.expectKind nnkTypeDef + baseType = baseType[2] + baseType.expectKind {nnkObjectTy, nnkRefTy} + collectFieldsInHierarchy result, baseType + + let recList = objectType[2] + collectFieldsFromRecList result, recList + +proc recordFields*(typeImpl: NimNode): seq[FieldDescription] = + if typeImpl.isTuple: + for i in 1 ..< typeImpl.len: + result.add FieldDescription(typ: typeImpl[i], name: ident("Field" & $(i - 1))) + return + + let objectType = case typeImpl.kind + of nnkObjectTy: typeImpl + of nnkTypeDef: typeImpl[2] + else: + macros.error("object type expected", typeImpl) + return + + collectFieldsInHierarchy(result, objectType) + +macro field*(obj: typed, fieldName: static string): untyped = + newDotExpr(obj, ident fieldName) + +proc skipPragma*(n: NimNode): NimNode = + if n.kind == nnkPragmaExpr: n[0] + else: n + + +{.pop.} diff --git a/tests/overload/t19737.nim b/tests/overload/t19737.nim new file mode 100644 index 000000000..b33ba9d8b --- /dev/null +++ b/tests/overload/t19737.nim @@ -0,0 +1,15 @@ +# issue #19737 + +import ./m19737 + +var m: seq[uint64] + +proc foo(x: bool) = discard + +proc test[T: uint64|uint32](s: var seq[T]) = + var tmp = newSeq[T](1) + s = newSeq[T](1) + + foo s[0] > tmp[0] + +test(m) diff --git a/tests/overload/t23249.nim b/tests/overload/t23249.nim new file mode 100644 index 000000000..f4657833b --- /dev/null +++ b/tests/overload/t23249.nim @@ -0,0 +1,17 @@ +# issue #23249 + +type Control* = object +proc onAction*(c: Control, handler: proc(e: int) {.gcsafe.}) = discard +proc onAction*(c: Control, handler: proc() {.gcsafe.}) = discard + +template setControlHandlerBlock(c: Control, p: untyped, a: untyped) = + when compiles(c.p(nil)): + c.p() do() {.gcsafe.}: a + else: + c.p = proc() {.gcsafe.} = + a + +proc mkLayout() = + var b: Control + setControlHandlerBlock(b, onAction): + echo "hi" diff --git a/tests/overload/t23755.nim b/tests/overload/t23755.nim new file mode 100644 index 000000000..de338a2ce --- /dev/null +++ b/tests/overload/t23755.nim @@ -0,0 +1,62 @@ +type + BigInt[bits: static int] = object + limbs: array[8, uint64] + +block: + proc view[N](a: array[N, uint64]) = + discard + + proc view[N](a: var array[N, uint64]) = + discard + + var r: BigInt[64] + r.limbs.view() + + +type Limbs[N: static int] = array[N, uint64] + +block: + proc view(a: Limbs) = + discard + + proc view(a: var Limbs) = + discard + + var r: BigInt[64] + r.limbs.view() + + +block: + type IntArray[N: static[int]] = array[N, int] + + proc p[T](a: IntArray[T]): bool= true + proc p(a: IntArray[5]): bool= false + + var s: IntArray[5] + doAssert s.p == false + +block: + type IntArray[N: static[int]] = array[N, int] + + proc `$`(a: IntArray): string = + return "test" + + var s: IntArray[5] = [1,1,1,1,1] + doAssert `$`(s) == "test" + +block: + proc p[n:static[int]](a: array[n, char]):bool=true + proc p[T, IDX](a: array[IDX, T]):bool=false + + var g: array[32, char] + doAssert p(g) + +block: # issue #23823 + func p[N,T](a, b: array[N,T]) = + discard + + func p[N: static int; T](x, y: array[N, T]) = + discard + + var a: array[5, int] + p(a,a) diff --git a/tests/overload/t8829.nim b/tests/overload/t8829.nim index fe0dbf2bf..85d87f136 100644 --- a/tests/overload/t8829.nim +++ b/tests/overload/t8829.nim @@ -2,7 +2,7 @@ block: let txt = "Hello World" template `[]`[T](p: ptr T, span: Slice[int]): untyped = - toOpenArray(cast[ptr array[0, T]](p)[], span.a, span.b) + toOpenArray(cast[ptr UncheckedArray[T]](p), span.a, span.b) doAssert $cast[ptr uint8](txt[0].addr)[0 ..< txt.len] == "[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]" @@ -12,7 +12,7 @@ block: let txt = "Hello World" template `[]`[T](p: ptr T, span: Slice[int]): untyped = - toOpenArray(cast[ptr array[0, T]](p)[], span.a, span.b) + toOpenArray(cast[ptr UncheckedArray[T]](p), span.a, span.b) doAssert $cast[ptr uint8](txt[0].addr)[0 ..< txt.len] == "[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]" diff --git a/tests/overload/tgenericalias.nim b/tests/overload/tgenericalias.nim new file mode 100644 index 000000000..50a44bd32 --- /dev/null +++ b/tests/overload/tgenericalias.nim @@ -0,0 +1,13 @@ +block: # issue #13799 + type + X[A, B] = object + a: A + b: B + + Y[A] = X[A, int] + template s(T: type X): X = T() + template t[A, B](T: type X[A, B]): X[A, B] = T() + proc works1(): Y[int] = s(X[int, int]) + proc works2(): Y[int] = t(X[int, int]) + proc works3(): Y[int] = t(Y[int]) + proc broken(): Y[int] = s(Y[int]) diff --git a/tests/overload/tor_isnt_better.nim b/tests/overload/tor_isnt_better.nim index 5ef8bc7c4..bee125386 100644 --- a/tests/overload/tor_isnt_better.nim +++ b/tests/overload/tor_isnt_better.nim @@ -1,18 +1,41 @@ -discard """ - errormsg: "ambiguous call;" - line: 16 -""" - -# bug #8568 - type D[T] = object E[T] = object -proc g(a: D|E): string = "foo D|E" -proc g(a: D): string = "foo D" +block: # PR #22261 + proc d(x: D):bool= false + proc d(x: int | D[SomeInteger]):bool= true + doAssert d(D[5]()) == false -proc test() = - let x = g D[int]() +block: # bug #8568 +#[ + Since PR #22261 and amendment has been made. Since D is a subset of D | E but + not the other way around `checkGeneric` should favor proc g(a: D) instead + of asserting ambiguity +]# + proc g(a: D|E): string = "foo D|E" + proc g(a: D): string = "foo D" + doAssert g(D[int]()) == "foo D" -test() +type Obj1[T] = object + v: T +converter toObj1[T](t: T): Obj1[T] = return Obj1[T](v: t) +block: # issue #10019 + proc fun1[T](elements: seq[T]): string = "fun1 seq" + proc fun1(o: object|tuple): string = "fun1 object|tuple" + proc fun2[T](elements: openArray[T]): string = "fun2 openarray" + proc fun2(o: object): string = "fun2 object" + proc fun_bug[T](elements: openArray[T]): string = "fun_bug openarray" + proc fun_bug(o: object|tuple):string = "fun_bug object|tuple" + proc main() = + var x = @["hello", "world"] + block: + # no ambiguity error shown here even though this would compile if we remove either 1st or 2nd overload of fun1 + doAssert fun1(x) == "fun1 seq" + block: + # ditto + doAssert fun2(x) == "fun2 openarray" + block: + # Error: ambiguous call; both t0065.fun_bug(elements: openarray[T])[declared in t0065.nim(17, 5)] and t0065.fun_bug(o: object or tuple)[declared in t0065.nim(20, 5)] match for: (array[0..1, string]) + doAssert fun_bug(x) == "fun_bug openarray" + main() diff --git a/tests/overload/toverl4.nim b/tests/overload/toverl4.nim index 537925674..21cedaa96 100644 --- a/tests/overload/toverl4.nim +++ b/tests/overload/toverl4.nim @@ -1,5 +1,6 @@ discard """ - output: '''true''' + output: '''true +5.0''' """ #bug #592 @@ -75,3 +76,26 @@ proc add*[TKey, TData](root: var PElement[TKey, TData], key: TKey, data: TData) var tree = PElement[int, int](kind: ElementKind.inner, key: 0, left: nil, right: nil) let result = add(tree, 1, 1) echo(result) + +# bug #3748 +type + Foo = object + bar: int + +proc bar(cur: Foo, val: int, s:seq[string]) = + discard cur.bar + +proc does_fail(): Foo = + let a = @["a"] + result.bar(5, a) + +doAssert does_fail().bar == 0 + +# bug #20645 + +type Zzz[Gen] = object + +proc testZ(z: Zzz) = + echo z.Gen(5) + +testZ(Zzz[float]()) diff --git a/tests/overload/toverload_issues.nim b/tests/overload/toverload_issues.nim index 5db7b54fa..26bf89091 100644 --- a/tests/overload/toverload_issues.nim +++ b/tests/overload/toverload_issues.nim @@ -77,27 +77,30 @@ testPred(1) -# bug #6526 -type - BaseObj = ref object of RootObj - DerivedObj = ref object of BaseObj - OtherDerivate = ref object of BaseObj - -proc `==`*[T1, T2: BaseObj](a: T1, b: T2): bool = - echo "baseobj ==" - return true - -let a = DerivedObj() -let b = DerivedObj() -echo a == b - -proc `==`*[T1, T2: OtherDerivate](a: T1, b: T2): bool = - echo "even better! ==" - return true - -let a2 = OtherDerivate() -let b2 = OtherDerivate() -echo a2 == b2 +block: # bug #6526 + type + BaseObj = ref object of RootObj + DerivedObj = ref object of BaseObj + OtherDerivate = ref object of BaseObj + + proc p[T](a: T, b: T): bool = + assert false + + proc p[T1, T2: BaseObj](a: T1, b: T2): bool = + echo "baseobj ==" + return true + + let a = DerivedObj() + let b = DerivedObj() + echo p(a,b) + + proc p[T1, T2: OtherDerivate](a: T1, b: T2): bool = + echo "even better! ==" + return true + + let a2 = OtherDerivate() + let b2 = OtherDerivate() + echo p(a2, b2) diff --git a/tests/overload/toverload_various.nim b/tests/overload/toverload_various.nim index 0741fce60..d195a069d 100644 --- a/tests/overload/toverload_various.nim +++ b/tests/overload/toverload_various.nim @@ -506,3 +506,63 @@ block: doAssert(p2(F(float,1.0),F(float,2)) == 3.0) doAssert(p2(F(float,1.0),F(float,2.0)) == 3.0) #doAssert(p2(F(float,1),F(int,2.0)) == 3.0) + +block: # PR #23870 + type + A {.inheritable.} = object + B = object of A + C = object of B + + proc p[T: A](x: T): int = 0 + proc p[T: B](x: T): int = 1 + + proc d(x: A): int = 0 + proc d(x: B): int = 1 + + proc g[T:A](x: typedesc[T]): int = 0 + proc g[T: B](x: typedesc[T]): int = 1 + + proc f[T](x: typedesc[T]): int = 0 + proc f[T:B](x: typedesc[T]): int = 1 + + assert p(C()) == 1 + assert d(C()) == 1 + assert g(C) == 1 + assert f(C) == 1 + +block: # PR #23870 + type + A = object of RootObj + PT = proc(ev: A) {.closure.} + sdt = seq[(PT, PT)] + + proc encap() = + proc p(a: A) {.closure.} = + discard + + var s: sdt + s.add (p, nil) + + encap() + +block: # PR #23870 + type + A = object of RootObj + B = object of A + C = object of B + + proc p(a: B | RootObj): int = + 0 + + proc p(a: A | A): int = + 1 + + assert p(C()) == 0 + + proc d(a: RootObj | B): int = + 0 + + proc d(a: A | A): int = + 1 + + assert d(C()) == 0 diff --git a/tests/overload/tproc_types_dont_like_subtypes.nim b/tests/overload/tproc_types_dont_like_subtypes.nim index d322f41be..6774be156 100644 --- a/tests/overload/tproc_types_dont_like_subtypes.nim +++ b/tests/overload/tproc_types_dont_like_subtypes.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "got <B, proc (b: B){.closure, gcsafe, locks: 0.}>" + errormsg: "got <B, proc (b: B){.closure, gcsafe.}>" line: 20 """ diff --git a/tests/overload/tstatic_with_converter.nim b/tests/overload/tstatic_with_converter.nim index e830e8a22..2bc1dfaab 100644 --- a/tests/overload/tstatic_with_converter.nim +++ b/tests/overload/tstatic_with_converter.nim @@ -1,7 +1,6 @@ discard """ output: ''' 9.0 - ''' """ @@ -39,12 +38,11 @@ proc `^`(x: vfloat, exp: static[float]): vfloat = when exp == 0.5: sqrt(x) else: - pow(x, exp) + pow(x, exp) proc `$`(x: vfloat): string = let y = cast[ptr float](addr x) - # xxx not sure if intentional in this issue, but this returns "" - echo y[] + result = $y[] let x = set1(9.0) echo x^0.5 diff --git a/tests/overload/tuntypedarg.nim b/tests/overload/tuntypedarg.nim new file mode 100644 index 000000000..9aa4fad3b --- /dev/null +++ b/tests/overload/tuntypedarg.nim @@ -0,0 +1,19 @@ +import macros + +block: # issue #7385 + type CustomSeq[T] = object + data: seq[T] + macro `[]`[T](s: CustomSeq[T], args: varargs[untyped]): untyped = + ## The end goal is to replace the joker "_" by something else + result = newIntLitNode(10) + proc foo1(): CustomSeq[int] = + result.data.newSeq(10) + # works since no overload matches first argument with type `CustomSeq` + # except magic `[]`, which always matches without checking arguments + doAssert result[_] == 10 + doAssert foo1() == CustomSeq[int](data: newSeq[int](10)) + proc foo2[T](): CustomSeq[T] = + result.data.newSeq(10) + # works fine with generic return type + doAssert result[_] == 10 + doAssert foo2[int]() == CustomSeq[int](data: newSeq[int](10)) diff --git a/tests/overload/tvartypeclass.nim b/tests/overload/tvartypeclass.nim new file mode 100644 index 000000000..04f3f5a91 --- /dev/null +++ b/tests/overload/tvartypeclass.nim @@ -0,0 +1,11 @@ +# issue #13302 + +proc foo(x: object): int = x.i*2 +proc foo(x: var object) = x.i*=2 +type Foo = object + i: int +let x = Foo(i: 3) +var y = Foo(i: 4) +doAssert foo(x) == 6 +foo(y) +doAssert y.i == 8 diff --git a/tests/overload/tvaruintconv.nim b/tests/overload/tvaruintconv.nim new file mode 100644 index 000000000..87ebd285d --- /dev/null +++ b/tests/overload/tvaruintconv.nim @@ -0,0 +1,207 @@ +discard """ + action: compile +""" + +# https://github.com/status-im/nimbus-eth2/pull/6554#issuecomment-2354977102 +# failed with "for a 'var' type a variable needs to be passed; but 'uint64(result)' is immutable" + +import + std/[typetraits, macros] + +type + DefaultFlavor = object + +template serializationFormatImpl(Name: untyped) {.dirty.} = + type Name = object + +template serializationFormat(Name: untyped) = + serializationFormatImpl(Name) + +template setReader(Format, FormatReader: distinct type) = + when arity(FormatReader) > 1: + template Reader(T: type Format, F: distinct type = DefaultFlavor): type = FormatReader[F] + else: + template ReaderType(T: type Format): type = FormatReader + template Reader(T: type Format): type = FormatReader + +template useDefaultReaderIn(T: untyped, Flavor: type) = + mixin Reader + + template readValue(r: var Reader(Flavor), value: var T) = + mixin readRecordValue + readRecordValue(r, value) + +import mvaruintconv + +type + FieldTag[RecordType: object; fieldName: static string] = distinct void + +func declval*(T: type): T {.compileTime.} = + default(ptr T)[] + +macro enumAllSerializedFieldsImpl(T: type, body: untyped): untyped = + var typeAst = getType(T)[1] + var typeImpl: NimNode + let isSymbol = not typeAst.isTuple + + if not isSymbol: + typeImpl = typeAst + else: + typeImpl = getImpl(typeAst) + result = newStmtList() + + var i = 0 + for field in recordFields(typeImpl): + let + fieldIdent = field.name + realFieldName = newLit($fieldIdent.skipPragma) + fieldName = realFieldName + fieldIndex = newLit(i) + + let fieldNameDefs = + if isSymbol: + quote: + const fieldName {.inject, used.} = `fieldName` + const realFieldName {.inject, used.} = `realFieldName` + else: + quote: + const fieldName {.inject, used.} = $`fieldIndex` + const realFieldName {.inject, used.} = $`fieldIndex` + + let field = + if isSymbol: + quote do: declval(`T`).`fieldIdent` + else: + quote do: declval(`T`)[`fieldIndex`] + + result.add quote do: + block: + `fieldNameDefs` + + template FieldType: untyped {.inject, used.} = typeof(`field`) + + `body` + + # echo repr(result) + +template enumAllSerializedFields(T: type, body): untyped = + enumAllSerializedFieldsImpl(T, body) + +type + FieldReader[RecordType, Reader] = tuple[ + fieldName: string, + reader: proc (rec: var RecordType, reader: var Reader) + {.gcsafe, nimcall.} + ] + +proc totalSerializedFieldsImpl(T: type): int = + mixin enumAllSerializedFields + enumAllSerializedFields(T): inc result + +template totalSerializedFields(T: type): int = + (static(totalSerializedFieldsImpl(T))) + +template GetFieldType(FT: type FieldTag): type = + typeof field(declval(FT.RecordType), FT.fieldName) + +proc makeFieldReadersTable(RecordType, ReaderType: distinct type, + numFields: static[int]): + array[numFields, FieldReader[RecordType, ReaderType]] = + mixin enumAllSerializedFields, handleReadException + var idx = 0 + + enumAllSerializedFields(RecordType): + proc readField(obj: var RecordType, reader: var ReaderType) + {.gcsafe, nimcall.} = + + mixin readValue + + type F = FieldTag[RecordType, realFieldName] + field(obj, realFieldName) = reader.readValue(GetFieldType(F)) + + result[idx] = (fieldName, readField) + inc idx + +proc fieldReadersTable(RecordType, ReaderType: distinct type): auto = + mixin readValue + type T = RecordType + const numFields = totalSerializedFields(T) + var tbl {.threadvar.}: ref array[numFields, FieldReader[RecordType, ReaderType]] + if tbl == nil: + tbl = new typeof(tbl) + tbl[] = makeFieldReadersTable(RecordType, ReaderType, numFields) + return addr(tbl[]) + +proc readValue(reader: var auto, T: type): T = + mixin readValue + reader.readValue(result) + +template decode(Format: distinct type, + input: string, + RecordType: distinct type): auto = + mixin Reader + block: # https://github.com/nim-lang/Nim/issues/22874 + var reader: Reader(Format) + reader.readValue(RecordType) + +template readValue(Format: type, + ValueType: type): untyped = + mixin Reader, init, readValue + var reader: Reader(Format) + readValue reader, ValueType + +template parseArrayImpl(numElem: untyped, + actionValue: untyped) = + actionValue + +serializationFormat Json +template createJsonFlavor(FlavorName: untyped, + skipNullFields = false) {.dirty.} = + type FlavorName = object + + template Reader(T: type FlavorName): type = Reader(Json, FlavorName) +type + JsonReader[Flavor = DefaultFlavor] = object + +Json.setReader JsonReader + +template parseArray(r: var JsonReader; body: untyped) = + parseArrayImpl(idx): body + +template parseArray(r: var JsonReader; idx: untyped; body: untyped) = + parseArrayImpl(idx): body + +proc readRecordValue[T](r: var JsonReader, value: var T) = + type + ReaderType {.used.} = type r + T = type value + + discard T.fieldReadersTable(ReaderType) + +proc readValue[T](r: var JsonReader, value: var T) = + mixin readValue + + when value is seq: + r.parseArray: + readValue(r, value[0]) + + elif value is object: + readRecordValue(r, value) + +type + RemoteSignerInfo = object + id: uint32 + RemoteKeystore = object + +proc readValue(reader: var JsonReader, value: var RemoteKeystore) = + discard reader.readValue(seq[RemoteSignerInfo]) + +createJsonFlavor RestJson +useDefaultReaderIn(RemoteSignerInfo, RestJson) +proc readValue(reader: var JsonReader[RestJson], value: var uint64) = + discard reader.readValue(string) + +discard Json.decode("", RemoteKeystore) +block: # https://github.com/nim-lang/Nim/issues/22874 + var reader: Reader(RestJson) + discard reader.readValue(RemoteSignerInfo) diff --git a/tests/parallel/t10913.nim b/tests/parallel/t10913.nim index d8459ecd0..191939100 100644 --- a/tests/parallel/t10913.nim +++ b/tests/parallel/t10913.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" errormsg: "'spawn'ed function cannot have a 'typed' or 'untyped' parameter" """ diff --git a/tests/parallel/t7535.nim b/tests/parallel/t7535.nim index 052dcdc3a..7817a1c9e 100644 --- a/tests/parallel/t7535.nim +++ b/tests/parallel/t7535.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" errormsg: "'spawn' takes a call expression; got: proc (x: uint32) = echo [x]" """ diff --git a/tests/parallel/t9691.nim b/tests/parallel/t9691.nim index bbf2b1bc7..254f03416 100644 --- a/tests/parallel/t9691.nim +++ b/tests/parallel/t9691.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" errormsg: "'spawn'ed function cannot have a 'typed' or 'untyped' parameter" """ diff --git a/tests/parallel/tblocking_channel.nim b/tests/parallel/tblocking_channel.nim index eb5fcb715..f3ccd166a 100644 --- a/tests/parallel/tblocking_channel.nim +++ b/tests/parallel/tblocking_channel.nim @@ -1,8 +1,8 @@ discard """ output: "" -disabled: "freebsd" +disabled: "freebsd" # see #15725 """ -# disabled pending bug #15725 + import threadpool, os var chan: Channel[int] diff --git a/tests/parallel/tconvexhull.nim b/tests/parallel/tconvexhull.nim index 0a07e6b76..a89aa910b 100644 --- a/tests/parallel/tconvexhull.nim +++ b/tests/parallel/tconvexhull.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: ''' ''' """ diff --git a/tests/parallel/tdeepcopy.nim b/tests/parallel/tdeepcopy.nim index 499ea94d4..96ca15ca3 100644 --- a/tests/parallel/tdeepcopy.nim +++ b/tests/parallel/tdeepcopy.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: ''' 13 abc called deepCopy for int diff --git a/tests/parallel/tdeepcopy2.nim b/tests/parallel/tdeepcopy2.nim index a9caab604..e8305173d 100644 --- a/tests/parallel/tdeepcopy2.nim +++ b/tests/parallel/tdeepcopy2.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: ''' called deepCopy for int called deepCopy for int diff --git a/tests/parallel/tdisjoint_slice1.nim b/tests/parallel/tdisjoint_slice1.nim index edcc30ece..6892e7383 100644 --- a/tests/parallel/tdisjoint_slice1.nim +++ b/tests/parallel/tdisjoint_slice1.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" outputsub: "EVEN 28" """ diff --git a/tests/parallel/tflowvar.nim b/tests/parallel/tflowvar.nim index 9d93bc7c8..e44b29a87 100644 --- a/tests/parallel/tflowvar.nim +++ b/tests/parallel/tflowvar.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''foobarfoobar bazbearbazbear diff --git a/tests/parallel/tguard1.nim b/tests/parallel/tguard1.nim index b1eb7e7c5..f4c92319b 100644 --- a/tests/parallel/tguard1.nim +++ b/tests/parallel/tguard1.nim @@ -5,7 +5,7 @@ output: "90" when false: template lock(a, b: ptr Lock; body: stmt) = - if cast[ByteAddress](a) < cast[ByteAddress](b): + if cast[int](a) < cast[int](b): pthread_mutex_lock(a) pthread_mutex_lock(b) else: diff --git a/tests/parallel/tinvalid_array_bounds.nim b/tests/parallel/tinvalid_array_bounds.nim index 15bf526df..8dc93c33f 100644 --- a/tests/parallel/tinvalid_array_bounds.nim +++ b/tests/parallel/tinvalid_array_bounds.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:refc" errormsg: "cannot prove (i)..(i) disjoint from (i + 1)..(i + 1)" - line: 20 + line: 21 """ import threadpool diff --git a/tests/parallel/tlet_spawn.nim b/tests/parallel/tlet_spawn.nim index 62341d8f0..853ffc443 100644 --- a/tests/parallel/tlet_spawn.nim +++ b/tests/parallel/tlet_spawn.nim @@ -4,7 +4,7 @@ done999 999 ''' """ -import threadpool +import std/[threadpool, os] proc foo(): int = 999 @@ -17,3 +17,12 @@ proc main = echo "done", f, " ", b main() + +# bug #13781 +proc thread(): string = + os.sleep(1000) + return "ok" + +var fv = spawn thread() +sync() +doAssert ^fv == "ok" diff --git a/tests/parallel/tmissing_deepcopy.nim b/tests/parallel/tmissing_deepcopy.nim index 7803439fa..ea77936ad 100644 --- a/tests/parallel/tmissing_deepcopy.nim +++ b/tests/parallel/tmissing_deepcopy.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" ccodeCheck: "@'genericDeepCopy(' .*" action: compile """ diff --git a/tests/parallel/tnon_disjoint_slice1.nim b/tests/parallel/tnon_disjoint_slice1.nim index 72d008bbd..51762187d 100644 --- a/tests/parallel/tnon_disjoint_slice1.nim +++ b/tests/parallel/tnon_disjoint_slice1.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:refc" errormsg: "cannot prove (i)..(i) disjoint from (i + 1)..(i + 1)" - line: 20 + line: 21 """ import threadpool diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim index 4b3610c67..cf1bc9336 100644 --- a/tests/parallel/tparfind.nim +++ b/tests/parallel/tparfind.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: "500" """ diff --git a/tests/parallel/tpi.nim b/tests/parallel/tpi.nim index 1abed6f23..cd965d585 100644 --- a/tests/parallel/tpi.nim +++ b/tests/parallel/tpi.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''3.141792613595791 3.141792613595791''' """ diff --git a/tests/parallel/tsendtwice.nim b/tests/parallel/tsendtwice.nim index 03b7fda47..9f4a2e06e 100644 --- a/tests/parallel/tsendtwice.nim +++ b/tests/parallel/tsendtwice.nim @@ -1,18 +1,10 @@ discard """ - output: '''ob2 @[] -ob @[] -ob3 @[] -3 -ob2 @[] -ob @[] -ob3 @[] -''' - cmd: "nim c -r --threads:on $file" + matrix: "--mm:refc" """ # bug #4776 -import tables +import tables, algorithm type Base* = ref object of RootObj @@ -35,20 +27,21 @@ globalTable.add("ob", d) globalTable.add("ob2", d) globalTable.add("ob3", d) +proc `<`(x, y: seq[int]): bool = x.len < y.len +proc kvs(t: TableRef[string, Base]): seq[(string, seq[int])] = + for k, v in t.pairs: result.add (k, v.someSeq) + result.sort + proc testThread(channel: ptr TableChannel) {.thread.} = globalTable = channel[].recv() - for k, v in pairs globaltable: - echo k, " ", v.someSeq var myObj: Base deepCopy(myObj, globalTable["ob"]) myObj.someSeq = newSeq[int](100) let table = channel[].recv() # same table - echo table.len - for k, v in mpairs table: - echo k, " ", v.someSeq assert(table.contains("ob")) # fails! assert(table.contains("ob2")) # fails! assert(table.contains("ob3")) # fails! + assert table.kvs == globalTable.kvs # Last to see above spot checks first var channel: TableChannel diff --git a/tests/parallel/tsimple_array_checks.nim b/tests/parallel/tsimple_array_checks.nim index 650b809e0..ab292f935 100644 --- a/tests/parallel/tsimple_array_checks.nim +++ b/tests/parallel/tsimple_array_checks.nim @@ -61,3 +61,15 @@ maino() # Doesn't work outside a proc when true: main() + +block two: + proc f(a: openArray[int]) = + discard + + proc main() = + var a: array[0..9, int] = [0,1,2,3,4,5,6,7,8,9] + parallel: + spawn f(a[0..2]) + + + main() \ No newline at end of file diff --git a/tests/parallel/tsysspawn.nim b/tests/parallel/tsysspawn.nim index 09a77b358..b7ecd1264 100644 --- a/tests/parallel/tsysspawn.nim +++ b/tests/parallel/tsysspawn.nim @@ -5,7 +5,7 @@ discard """ 2 2 ''' - cmd: "nim $target --threads:on $options $file" + matrix: "--mm:refc" """ import threadpool diff --git a/tests/parallel/tuseafterdef.nim b/tests/parallel/tuseafterdef.nim index f1ae6e923..64f835a1b 100644 --- a/tests/parallel/tuseafterdef.nim +++ b/tests/parallel/tuseafterdef.nim @@ -1,6 +1,8 @@ discard """ + matrix: "--mm:refc" + disabled: true errormsg: "(k)..(k) not disjoint from (k)..(k)" - line: 23 + line: 24 action: compile """ diff --git a/tests/parallel/twaitany.nim b/tests/parallel/twaitany.nim index b58cadd86..d57c5f40f 100644 --- a/tests/parallel/twaitany.nim +++ b/tests/parallel/twaitany.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: '''true''' """ diff --git a/tests/parser/t12274.nim b/tests/parser/t12274.nim index 40c85f158..6b7c9f55a 100644 --- a/tests/parser/t12274.nim +++ b/tests/parser/t12274.nim @@ -1,3 +1,7 @@ +discard """ + joinable: false +""" + var s: seq[int] s.add block: let i = 1 diff --git a/tests/parser/t19430.nim b/tests/parser/t19430.nim new file mode 100644 index 000000000..c1aa6a92d --- /dev/null +++ b/tests/parser/t19430.nim @@ -0,0 +1,3 @@ +let x = proc() = ## abc +let y = 3 #[tt.Error +^ invalid indentation]# diff --git a/tests/parser/t20922.nim b/tests/parser/t20922.nim new file mode 100644 index 000000000..110610fb1 --- /dev/null +++ b/tests/parser/t20922.nim @@ -0,0 +1,35 @@ +discard """ + cmd: "nim check $options --verbosity:0 --hints:off $file" + action: "reject" + nimout: ''' +t20922.nim(26, 5) Error: expression expected, but found ':' +t20922.nim(34, 7) Error: expression expected, but found ':' +t20922.nim(35, 5) Error: ':' or '=' expected, but got 'keyword of' +Error: in expression ' '+'': identifier expected, but found '' +t20922.nim(26, 7) Error: attempting to call undeclared routine: '<Error>' +Error: in expression ' '+'': identifier expected, but found '' +t20922.nim(26, 7) Error: attempting to call undeclared routine: '<Error>' +t20922.nim(26, 7) Error: expression '' cannot be called +t20922.nim(26, 7) Error: expression '' has no type (or is ambiguous) +t20922.nim(26, 7) Error: VM problem: dest register is not set +''' +""" +# original test case issue #20922 +type Token = enum + incDataPtr, + incDataPtrByte + +proc mapInstrToToken(instr: char): Token = + case instr: + of '>': + incDataPtr + of: '+': + incDataPtrByte + +# same issue with `of` in object branches (different parser procs calling `exprList`) +type + Bar = enum A, B + Foo = object + case kind: Bar + of: x: int + of B: y: float diff --git a/tests/parser/tbinarynotindented.nim b/tests/parser/tbinarynotindented.nim new file mode 100644 index 000000000..8d124aade --- /dev/null +++ b/tests/parser/tbinarynotindented.nim @@ -0,0 +1,3 @@ +type Foo = ref int + not nil #[tt.Error + ^ invalid indentation]# diff --git a/tests/parser/tbinarynotsameline.nim b/tests/parser/tbinarynotsameline.nim new file mode 100644 index 000000000..ca417e023 --- /dev/null +++ b/tests/parser/tbinarynotsameline.nim @@ -0,0 +1,10 @@ +# issue #23565 + +func foo: bool = + true + +const bar = block: + type T = int + not foo() + +doAssert not bar diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim index b25ec4bd8..f37c34f63 100644 --- a/tests/parser/tcommand_as_expr.nim +++ b/tests/parser/tcommand_as_expr.nim @@ -36,3 +36,12 @@ echo f -4 echo int -1 # doesn't compile echo int `-` 1 # compiles + +var num = 1 +num += int 2 +doAssert num == 3 + +import options +var opt = some some none int +opt = some some none int +opt = some none Option[int] diff --git a/tests/parser/tcommandequals.nim b/tests/parser/tcommandequals.nim new file mode 100644 index 000000000..f41b318ac --- /dev/null +++ b/tests/parser/tcommandequals.nim @@ -0,0 +1,17 @@ +discard """ + output: ''' +5 +''' +""" + +proc foo(a, b: int) = + echo a + b + +foo a = 2, b = 3 + +import macros + +macro bar(args: varargs[untyped]): untyped = + doAssert args[0].kind == nnkExprEqExpr + +bar "a" = 1 diff --git a/tests/parser/tcommandindent.nim b/tests/parser/tcommandindent.nim new file mode 100644 index 000000000..449c218db --- /dev/null +++ b/tests/parser/tcommandindent.nim @@ -0,0 +1,16 @@ +when false: # parse the following + let foo = Obj( + field1: proc (src: pointer, srcLen: Natural) + {.nimcall, gcsafe, raises: [IOError, Defect].} = + var file = FileOutputStream(s).file + + implementWrites s.buffers, src, srcLen, "FILE", + writeStartAddr, writeLen, + file.writeBuffer(writeStartAddr, writeLen) + , + field2: proc {.nimcall, gcsafe, raises: [IOError, Defect].} = + flushFile FileOutputStream(s).file + , + field3: proc () {.nimcall, gcsafe, raises: [IOError, Defect].} = + close FileOutputStream(s).file + ) diff --git a/tests/misc/trfc_341.nim b/tests/parser/tdotlikeoperators.nim index 37cf675c6..c2d23bd15 100644 --- a/tests/misc/trfc_341.nim +++ b/tests/parser/tdotlikeoperators.nim @@ -1,3 +1,6 @@ +discard """ + matrix: "-d:nimPreviewDotLikeOps" +""" # test for https://github.com/nim-lang/RFCs/issues/341 import std/json import std/jsonutils diff --git a/tests/parser/tdoublenotnil.nim b/tests/parser/tdoublenotnil.nim new file mode 100644 index 000000000..c61008c54 --- /dev/null +++ b/tests/parser/tdoublenotnil.nim @@ -0,0 +1,3 @@ +when false: + type Foo = Bar not nil not nil #[tt.Error + ^ invalid indentation]# diff --git a/tests/parser/tifextracolon.nim b/tests/parser/tifextracolon.nim new file mode 100644 index 000000000..171569111 --- /dev/null +++ b/tests/parser/tifextracolon.nim @@ -0,0 +1,8 @@ +# issue #21982 + +if true: + if true: + discard default int: +else: #[tt.Error +^ invalid indentation]# + discard diff --git a/tests/parser/tpostexprblocks.nim b/tests/parser/tpostexprblocks.nim index d272c712f..6cd4a8350 100644 --- a/tests/parser/tpostexprblocks.nim +++ b/tests/parser/tpostexprblocks.nim @@ -498,6 +498,13 @@ StmtList StmtList DiscardStmt Empty + + Call + Ident "foo" + Finally + StmtList + DiscardStmt + Empty ''' """ @@ -655,3 +662,7 @@ dumpTree: discard finally: discard + + foo: + finally: + discard diff --git a/tests/parser/tprocexprasstmt.nim b/tests/parser/tprocexprasstmt.nim new file mode 100644 index 000000000..22fb4a7c8 --- /dev/null +++ b/tests/parser/tprocexprasstmt.nim @@ -0,0 +1,14 @@ +func r(): auto = + func(): int = 2 +doAssert r()() == 2 + +block: # issue #11726 + let foo = block: + var x: int + proc = inc x # "identifier expected, but got '='" + + template paint(): untyped = + proc (s: string): string = s + + let s = paint() + doAssert s("abc") == "abc" diff --git a/tests/parser/ttry.nim b/tests/parser/ttry.nim new file mode 100644 index 000000000..190b0b8dc --- /dev/null +++ b/tests/parser/ttry.nim @@ -0,0 +1,27 @@ +# bug #21144 +block: + try: + let c = try: + 10 + except ValueError as exc: + 10 + except ValueError as exc: + discard + +if true: + block: + let c = try: + 10 + except ValueError as exc: + 10 + except OSError: + 99 + + +try: + let c = try: + 10 + except ValueError as exc: + 10 +except ValueError as exc: + discard \ No newline at end of file diff --git a/tests/parser/ttupleunpack.nim b/tests/parser/ttupleunpack.nim index c7ab9ea15..993501fbb 100644 --- a/tests/parser/ttupleunpack.nim +++ b/tests/parser/ttupleunpack.nim @@ -27,3 +27,68 @@ proc main() = main() main2() + +block: # nested unpacking + block: # simple let + let (a, (b, c), d) = (1, (2, 3), 4) + doAssert (a, b, c, d) == (1, 2, 3, 4) + let foo = (a, (b, c), d) + let (a2, (b2, c2), d2) = foo + doAssert (a, b, c, d) == (a2, b2, c2, d2) + + block: # var and assignment + var (x, (y, z), t) = ('a', (true, @[123]), "abc") + doAssert (x, y, z, t) == ('a', true, @[123], "abc") + (x, (y, z), t) = ('b', (false, @[456]), "def") + doAssert (x, y, z, t) == ('b', false, @[456], "def") + + block: # very nested + let (_, (_, (_, (_, (_, a))))) = (1, (2, (3, (4, (5, 6))))) + doAssert a == 6 + + block: # const + const (a, (b, c), d) = (1, (2, 3), 4) + doAssert (a, b, c, d) == (1, 2, 3, 4) + const foo = (a, (b, c), d) + const (a2, (b2, c2), d2) = foo + doAssert (a, b, c, d) == (a2, b2, c2, d2) + + block: # evaluation semantics preserved between literal and not literal + var s: seq[string] + block: # literal + let (a, (b, c), d) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4)) + doAssert (a, b, c, d) == (1, 2, 3, 4) + doAssert s == @["a", "b", "c", "d"] + block: # underscore + s = @[] + let (a, (_, c), _) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4)) + doAssert (a, c) == (1, 3) + doAssert s == @["a", "b", "c", "d"] + block: # temp + s = @[] + let foo = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4)) + let (a, (b, c), d) = foo + doAssert (a, b, c, d) == (1, 2, 3, 4) + doAssert s == @["a", "b", "c", "d"] + +block: # unary assignment unpacking + var a: int + (a,) = (1,) + doAssert a == 1 + +block: # type annotations + block: # basic + let (a, b): (int, int) = (1, 2) + doAssert (a, b) == (1, 2) + block: # type inference + let (a, b): (byte, float) = (1, 2) + doAssert (a, b) == (1.byte, 2.0) + block: # type mismatch + doAssert not (compiles do: + let (a, b): (int, string) = (1, 2)) + block: # nested + let (a, (b, c)): (int, (int, int)) = (1, (2, 3)) + doAssert (a, b, c) == (1, 2, 3) + block: # nested type inference + let (a, (b, c)): (byte, (float, cstring)) = (1, (2, "abc")) + doAssert (a, b, c) == (1.byte, 2.0, cstring"abc") diff --git a/tests/parser/ttypeexprobject.nim b/tests/parser/ttypeexprobject.nim new file mode 100644 index 000000000..6895f1731 --- /dev/null +++ b/tests/parser/ttypeexprobject.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "invalid indentation" + line: 10 + column: 14 +""" + +type + A = (object | tuple | int) + B = int | object | tuple + C = object | tuple | int # issue #8846 diff --git a/tests/parser/ttypeexprs.nim b/tests/parser/ttypeexprs.nim new file mode 100644 index 000000000..e40efc7d9 --- /dev/null +++ b/tests/parser/ttypeexprs.nim @@ -0,0 +1,25 @@ +proc foo[T: ptr int | ptr string](x: T) = discard +var x = "abc" +foo(addr x) + +let n = 3'u32 +type Double = ( + when n.sizeof == 4: uint64 + elif n.sizeof == 2: uint32 + else: uint16 +) + +type + A = (ref | ptr | pointer) + B = pointer | ptr | ref + C = ref | ptr | pointer + +template `+`(a, b): untyped = (b, a) +template `*`(a, b): untyped = (a, b) + +doAssert (ref int + ref float * ref string + ref bool) is + (ref bool, ((ref float, ref string), ref int)) +type X = ref int + ref float * ref string + ref bool +doAssert X is (ref bool, ((ref float, ref string), ref int)) + +type SomePointer = proc | ref | ptr | pointer diff --git a/tests/pragmas/monoff1.nim b/tests/pragmas/monoff1.nim new file mode 100644 index 000000000..85d6c57b3 --- /dev/null +++ b/tests/pragmas/monoff1.nim @@ -0,0 +1 @@ +proc on*() = discard diff --git a/tests/pragmas/mqualifiedmacro.nim b/tests/pragmas/mqualifiedmacro.nim new file mode 100644 index 000000000..908973206 --- /dev/null +++ b/tests/pragmas/mqualifiedmacro.nim @@ -0,0 +1,10 @@ +template t*(x:untyped): untyped = + echo "template t" + +import macros +macro m*(name: static string, x: untyped): untyped = + let newName = ident(name) + result = quote do: + type `newName` = object + if result.kind == nnkStmtList: + result = result[^1] diff --git a/tests/pragmas/t12640.nim b/tests/pragmas/t12640.nim index 60177d034..c85185699 100644 --- a/tests/pragmas/t12640.nim +++ b/tests/pragmas/t12640.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" nimout: '''1 2 3 @@ -10,7 +11,7 @@ discard """ [1, 2, 3]''' """ - +# todo fixme it doesn't work with ORC proc doIt(a: openArray[int]) = echo a diff --git a/tests/pragmas/t22713.nim b/tests/pragmas/t22713.nim new file mode 100644 index 000000000..3d3384632 --- /dev/null +++ b/tests/pragmas/t22713.nim @@ -0,0 +1,12 @@ +import std/macros + + +template myPragma(x: int) {.pragma.} + +type + A = object + x: int64 + + B {.myPragma(sizeof(A)).} = object + +doAssert B.getCustomPragmaVal(myPragma) == 8 \ No newline at end of file diff --git a/tests/pragmas/t8741.nim b/tests/pragmas/t8741.nim index 221c732b0..bf97b0e29 100644 --- a/tests/pragmas/t8741.nim +++ b/tests/pragmas/t8741.nim @@ -1,7 +1,7 @@ discard """ cmd: "nim check --hint:processing:off $file" errormsg: "3 is not two" - nimout: '''t8741.nim(13, 9) Error: cannot attach a custom pragma to 'a' + nimout: '''t8741.nim(13, 9) Error: invalid pragma: foobar t8741.nim(29, 15) template/generic instantiation of `onlyTwo` from here t8741.nim(25, 12) Error: 3 is not two ''' diff --git a/tests/pragmas/tcompile_missing_file.nim b/tests/pragmas/tcompile_missing_file.nim new file mode 100644 index 000000000..fd90bd57d --- /dev/null +++ b/tests/pragmas/tcompile_missing_file.nim @@ -0,0 +1,5 @@ +discard """ + joinable: false + errormsg: "cannot find: noexist.c" +""" +{.compile: "noexist.c".} diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index db2536188..11a6df813 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -399,6 +399,40 @@ block: discard Hello(a: 1.0, b: 12) +# test routines +block: + template prag {.pragma.} + proc hello {.prag.} = discard + iterator hello2: int {.prag.} = discard + template hello3(x: int): int {.prag.} = x + macro hello4(x: int): int {.prag.} = x + func hello5(x: int): int {.prag.} = x + doAssert hello.hasCustomPragma(prag) + doAssert hello2.hasCustomPragma(prag) + doAssert hello3.hasCustomPragma(prag) + doAssert hello4.hasCustomPragma(prag) + doAssert hello5.hasCustomPragma(prag) + +# test push doesn't break +block: + template prag {.pragma.} + {.push prag.} + proc hello = discard + iterator hello2: int = discard + template hello3(x: int): int = x + macro hello4(x: int): int = x + func hello5(x: int): int = x + type + Foo = enum a + Bar[T] = ref object of RootObj + x: T + case y: bool + of false: discard + else: + when true: discard + for a in [1]: discard a + {.pop.} + # issue #11511 when false: template myAttr {.pragma.} @@ -416,6 +450,31 @@ when false: doAssert hasMyAttr(TObj) + +# bug #11415 +template noserialize() {.pragma.} + +type + Point[T] = object + x, y: T + + ReplayEventKind = enum + FoodAppeared, FoodEaten, DirectionChanged + + ReplayEvent = object + case kind: ReplayEventKind + of FoodEaten, FoodAppeared: # foodPos is in multiple branches + foodPos {.noserialize.}: Point[float] + of DirectionChanged: + playerPos: float +let ev = ReplayEvent( + kind: FoodEaten, + foodPos: Point[float](x: 5.0, y: 1.0) + ) + +doAssert ev.foodPos.hasCustomPragma(noserialize) + + when false: # misc {.pragma: haha.} @@ -432,3 +491,50 @@ when false: # left-to-right priority/override order for getCustomPragmaVal assert bb.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he") + +{.experimental: "dynamicBindSym".} + +# const +block: + template myAttr() {.pragma.} + template myAttr2(x: int) {.pragma.} + template myAttr3(x: string) {.pragma.} + + type + MyObj2 = ref object + + const a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0 + const b {.myAttr,myAttr2(2),myAttr3:"test".} = 0 + + macro forceHasCustomPragma(x: untyped, y: typed): untyped = + var x = bindSym(x.repr) + for c in x: + if c.symKind == nskConst: + x = c + break + result = getAst(hasCustomPragma(x, y)) + + macro forceGetCustomPragmaVal(x: untyped, y: typed): untyped = + var x = bindSym(x.repr) + for c in x: + if c.symKind == nskConst: + x = c + break + result = getAst(getCustomPragmaVal(x, y)) + + template check(s: untyped) = + doAssert forceHasCustomPragma(s, myAttr) + doAssert forceHasCustomPragma(s, myAttr2) + doAssert forceGetCustomPragmaVal(s, myAttr2) == 2 + doAssert forceHasCustomPragma(s, myAttr3) + doAssert forceGetCustomPragmaVal(s, myAttr3) == "test" + + check(a) + check(b) + +block: # https://forum.nim-lang.org/t/12522, backticks + template `mypragma`() {.pragma.} + # Error: invalid pragma: `mypragma` + type Test = object + field {.`mypragma`.}: int + doAssert Test().field.hasCustomPragma(mypragma) diff --git a/tests/pragmas/tinvalid_user_pragma.nim b/tests/pragmas/tinvalid_user_pragma.nim new file mode 100644 index 000000000..3081db842 --- /dev/null +++ b/tests/pragmas/tinvalid_user_pragma.nim @@ -0,0 +1,9 @@ +discard """ +cmd: "nim check $file" +""" + +{.pragma test: foo.} #[tt.Error +^ invalid pragma: {.pragma, test: foo.} ]# + +{.pragma: 1.} #[tt.Error +^ invalid pragma: {.pragma: 1.} ]# diff --git a/tests/pragmas/tinvalidcustompragma.nim b/tests/pragmas/tinvalidcustompragma.nim new file mode 100644 index 000000000..a31695809 --- /dev/null +++ b/tests/pragmas/tinvalidcustompragma.nim @@ -0,0 +1,23 @@ +discard """ + cmd: "nim check $file" +""" + +# issue #21652 +type Foo = object +template foo() {.tags:[Foo].} = #[tt.Error + ^ invalid pragma: tags: [Foo]]# + discard + +{.foobar.} #[tt.Error + ^ invalid pragma: foobar]# +type A = enum a {.foobar.} #[tt.Error + ^ invalid pragma: foobar]# +for b {.foobar.} in [1]: discard #[tt.Error + ^ invalid pragma: foobar]# +template foobar {.pragma.} +{.foobar.} #[tt.Error + ^ cannot attach a custom pragma to 'tinvalidcustompragma'; custom pragmas are not supported for modules]# +type A = enum a {.foobar.} #[tt.Error + ^ cannot attach a custom pragma to 'a'; custom pragmas are not supported for enum fields]# +for b {.foobar.} in [1]: discard #[tt.Error + ^ cannot attach a custom pragma to 'b'; custom pragmas are not supported for `for` loop variables]# diff --git a/tests/pragmas/tlocks.nim b/tests/pragmas/tlocks.nim index 6c2a9f9e9..5d6fcdd9c 100644 --- a/tests/pragmas/tlocks.nim +++ b/tests/pragmas/tlocks.nim @@ -1,7 +1,3 @@ -discard """ - matrix: "--mm:arc; --mm:refc" -""" - type SomeBase* = ref object of RootObj type SomeDerived* = ref object of SomeBase memberProc*: proc () diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim index 6d0466df3..6a58055fe 100644 --- a/tests/pragmas/tnoreturn.nim +++ b/tests/pragmas/tnoreturn.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" ccodeCheck: "\\i @'__attribute__((noreturn))' .*" action: compile """ diff --git a/tests/pragmas/tonoff1.nim b/tests/pragmas/tonoff1.nim new file mode 100644 index 000000000..20ba7def2 --- /dev/null +++ b/tests/pragmas/tonoff1.nim @@ -0,0 +1,8 @@ +# issue #23002 + +import monoff1 + +proc test() = + {.warning[ProveInit]: on.} + +test() diff --git a/tests/pragmas/tonoff2.nim b/tests/pragmas/tonoff2.nim new file mode 100644 index 000000000..9dff5ef11 --- /dev/null +++ b/tests/pragmas/tonoff2.nim @@ -0,0 +1,14 @@ +discard """ + action: compile +""" + +# issue #22841 + +import unittest + +proc on() = + discard + +suite "some suite": + test "some test": + discard diff --git a/tests/pragmas/tpragmas_misc.nim b/tests/pragmas/tpragmas_misc.nim index 6dc2e6b80..adb7e73c3 100644 --- a/tests/pragmas/tpragmas_misc.nim +++ b/tests/pragmas/tpragmas_misc.nim @@ -68,3 +68,8 @@ block: # issue #10994 proc a {.bar.} = discard # works proc b {.bar, foo.} = discard # doesn't + +block: # issue #22525 + macro catch(x: typed) = x + proc thing {.catch.} = discard + thing() diff --git a/tests/pragmas/tpragmas_reorder.nim b/tests/pragmas/tpragmas_reorder.nim new file mode 100644 index 000000000..c4b1a6b0a --- /dev/null +++ b/tests/pragmas/tpragmas_reorder.nim @@ -0,0 +1,19 @@ +discard """ + matrix: "--experimental:codeReordering" +""" + +runnableExamples: + import strtabs + var t = newStringTable() + t["name"] = "John" + t["city"] = "Monaco" + doAssert t.len == 2 + doAssert t.hasKey "name" + doAssert "name" in t + +include "system/inclrtl" + +{.pragma: rtlFunc, rtl.} + +proc hasKey*(): bool {.rtlFunc.} = + discard \ No newline at end of file diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim index 5ecfe9704..9c6b85c4e 100644 --- a/tests/pragmas/tpush.nim +++ b/tests/pragmas/tpush.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + # test the new pragmas {.push warnings: off, hints: off.} @@ -13,3 +17,128 @@ proc WarnMe() = x: int echo(x) +# bug #11852 +proc foo(x: string, y: int, res: int) = + {.push checks: off} + var a: ptr char = unsafeAddr(x[y]) + {.pop.} + if x.len > y: + doAssert ord(a[]) == 51 + else: + doAssert x.len + 48 == res + +foo("", 0, 48) +foo("abc", 40, 51) + +# bug #22362 +{.push staticBoundChecks: on.} +proc main(): void = + {.pop.} + discard + {.push staticBoundChecks: on.} + +main() + + +proc timnFoo[T](obj: T) {.noSideEffect.} = discard # BUG + +{.push exportc.} +proc foo1() = + var s1 = "bar" + timnFoo(s1) + var s2 = @[1] + timnFoo(s2) +{.pop.} + + +block: # bug #22913 + block: + type r = object + + template std[T](x: T) = + let ttt {.used.} = x + result = $ttt + + proc bar[T](x: T): string = + std(x) + + {.push exportc: "$1".} + proc foo(): r = + let s = bar(123) + {.pop.} + + discard foo() + + block: + type r = object + {.push exportc: "$1".} + proc foo2(): r = + let s = $result + {.pop.} + + discard foo2() + +block: # bug #23019 + proc f(x: bool) + + proc a(x: int) = + if false: f(true) + + proc f(x: bool) = + if false: a(0) + + proc k(r: int|int) {.inline.} = # seems to require being generic and inline + if false: a(0) + + + # {.push tags: [].} + {.push raises: [].} + + {.push warning[ObservableStores]:off.} # can be any warning, off or on + let w = 0 + k(w) + {.pop.} + {.pop.} + +{.push exportC.} + +block: + proc foo11() = + const factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + proc foo21() = + const factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + + foo11() + foo21() + +template foo31() = + let factor = [1, 2, 3, 4] + doAssert factor[0] == 1 +template foo41() = + let factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + +foo31() +foo41() + +{.pop.} + +import macros + +block: + {.push deprecated.} + template test() = discard + test() + {.pop.} + macro foo(): bool = + let ast = getImpl(bindSym"test") + var found = false + if ast[4].kind == nnkPragma: + for x in ast[4]: + if x.eqIdent"deprecated": + found = true + break + result = newLit(found) + doAssert foo() diff --git a/tests/pragmas/tpushnotes.nim b/tests/pragmas/tpushnotes.nim new file mode 100644 index 000000000..27ba0bec4 --- /dev/null +++ b/tests/pragmas/tpushnotes.nim @@ -0,0 +1,13 @@ +discard """ + matrix: "--warningAsError:HoleEnumConv" +""" + +type + e = enum + a = 0 + b = 2 + +var i: int +{.push warning[HoleEnumConv]:off.} +discard i.e +{.pop.} diff --git a/tests/pragmas/tqualifiedmacro.nim b/tests/pragmas/tqualifiedmacro.nim new file mode 100644 index 000000000..bc95ec1ea --- /dev/null +++ b/tests/pragmas/tqualifiedmacro.nim @@ -0,0 +1,14 @@ +discard """ + output: ''' +template t +''' +""" + +# issue #12696 + +import mqualifiedmacro +proc p() {. mqualifiedmacro.t .} = # errors with identifier expected but a.t found + echo "proc p" + +type Foo {. mqualifiedmacro.m("Bar") .} = object +doAssert Bar is object diff --git a/tests/pragmas/tuserpragmaargs.nim b/tests/pragmas/tuserpragmaargs.nim new file mode 100644 index 000000000..791d703ac --- /dev/null +++ b/tests/pragmas/tuserpragmaargs.nim @@ -0,0 +1,5 @@ +var foo {.exportc: "abc".} = 123 +{.pragma: importc2, importc.} +var bar {.importc2: "abc".}: int #[tt.Error + ^ user pragma cannot have arguments]# +echo bar diff --git a/tests/defaultprocparam/mdefaultprocparam.nim b/tests/proc/mdefaultprocparam.nim index 4a17277c0..4a17277c0 100644 --- a/tests/defaultprocparam/mdefaultprocparam.nim +++ b/tests/proc/mdefaultprocparam.nim diff --git a/tests/proc/t15949.nim b/tests/proc/t15949.nim index bc3fddc84..6467ed5d3 100644 --- a/tests/proc/t15949.nim +++ b/tests/proc/t15949.nim @@ -1,14 +1,9 @@ -# bug #15949 +# bug #15949 and RFC #480 -discard """ -errormsg: "parameter 'a' requires a type" -nimout: ''' -t15949.nim(20, 14) Error: parameter 'a' requires a type''' -""" +proc procWarn(a, b = 1): (int, int) = (a, b) #[tt.Warning + ^ a, b all have default value '1', this may be unintentional, either use ';' (semicolon) or explicitly write each default value [ImplicitDefaultValue]]# - -# line 10 -proc procGood(a, b = 1): (int, int) = (a, b) +proc procGood(a = 1, b = 1): (int, int) = (a, b) doAssert procGood() == (1, 1) doAssert procGood(b = 3) == (1, 3) @@ -17,4 +12,5 @@ doAssert procGood(a = 5, b = 6) == (5, 6) # The type (and default value propagation breaks in the below example # as semicolon is used instead of comma. -proc procBad(a; b = 1): (int, int) = (a, b) +proc procBad(a; b = 1): (int, int) = (a, b) #[tt.Error + ^ parameter 'a' requires a type]# diff --git a/tests/proc/t17157.nim b/tests/proc/t17157.nim index 2927eeee8..020e93fce 100644 --- a/tests/proc/t17157.nim +++ b/tests/proc/t17157.nim @@ -1,6 +1,5 @@ discard """ errormsg: "'untyped' is only allowed in templates and macros or magic procs" - disabled: true """ template something(op: proc (v: untyped): void): void = diff --git a/tests/proc/t19795.nim b/tests/proc/t19795.nim new file mode 100644 index 000000000..677ec0a63 --- /dev/null +++ b/tests/proc/t19795.nim @@ -0,0 +1,19 @@ +discard """ + matrix: "--mm:arc" +""" + +# bug #19795 +# bug #21085 + +type Vector = seq[int] + +var vect: Vector = newSeq[int](5) +doAssert vect == @[0, 0, 0, 0, 0] + +# Needed to get the problem. Could also use "var". +let vectCopy = vect + +# Then some procedure definition is needed to get the problem. +proc p(): int = 3 + +doAssert vect == @[0, 0, 0, 0, 0] \ No newline at end of file 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/misc/tcolonisproc.nim b/tests/proc/tcolonisproc.nim index c10dabcf1..c10dabcf1 100644 --- a/tests/misc/tcolonisproc.nim +++ b/tests/proc/tcolonisproc.nim diff --git a/tests/defaultprocparam/tdefaultprocparam.nim b/tests/proc/tdefaultprocparam.nim index 90edfa8c9..90edfa8c9 100644 --- a/tests/defaultprocparam/tdefaultprocparam.nim +++ b/tests/proc/tdefaultprocparam.nim 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/tillegalreturntype.nim b/tests/proc/tillegalreturntype.nim index 799cad53a..1076f7f75 100644 --- a/tests/proc/tillegalreturntype.nim +++ b/tests/proc/tillegalreturntype.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim check $file" + cmd: "nim check --hints:off $file" errormsg: "" nimout: ''' tillegalreturntype.nim(11, 11) Error: return type 'typed' is only valid for macros and templates 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/misc/tlambdadonotation.nim b/tests/proc/tlambdadonotation.nim index af51efdbf..3160c0972 100644 --- a/tests/misc/tlambdadonotation.nim +++ b/tests/proc/tlambdadonotation.nim @@ -67,7 +67,7 @@ proc main2() = proc foo() = subscriber.consume() - emitter.on_event() do: + emitter.on_event() do (): subscriber.consume() # this works diff --git a/tests/namedparams/tnamedparams.nim b/tests/proc/tnamedparams.nim index d0774f0d8..d0774f0d8 100644 --- a/tests/namedparams/tnamedparams.nim +++ b/tests/proc/tnamedparams.nim diff --git a/tests/namedparams/tnamedparams2.nim b/tests/proc/tnamedparams2.nim index 9acdeed87..9acdeed87 100644 --- a/tests/namedparams/tnamedparams2.nim +++ b/tests/proc/tnamedparams2.nim diff --git a/tests/namedparams/tnamedparams3.nim b/tests/proc/tnamedparams3.nim index e736c338c..e736c338c 100644 --- a/tests/namedparams/tnamedparams3.nim +++ b/tests/proc/tnamedparams3.nim diff --git a/tests/misc/tparamsindefault.nim b/tests/proc/tparamsindefault.nim index 3fe917f2b..3fe917f2b 100644 --- a/tests/misc/tparamsindefault.nim +++ b/tests/proc/tparamsindefault.nim diff --git a/tests/procvar/tprocvar.nim b/tests/proc/tprocvar.nim index 14f24efdc..14f24efdc 100644 --- a/tests/procvar/tprocvar.nim +++ b/tests/proc/tprocvar.nim diff --git a/tests/procvar/tprocvarmismatch.nim b/tests/proc/tprocvarmismatch.nim index 4d6be9be6..4d6be9be6 100644 --- a/tests/procvar/tprocvarmismatch.nim +++ b/tests/proc/tprocvarmismatch.nim 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/tunderscoreparam.nim b/tests/proc/tunderscoreparam.nim new file mode 100644 index 000000000..8d60603f1 --- /dev/null +++ b/tests/proc/tunderscoreparam.nim @@ -0,0 +1,122 @@ +discard """ + targets: "c cpp js" +""" + +import std/[assertions, sequtils] + +proc test() = + block: + proc ok(_, _, a: int): int = + doAssert not compiles(_) + a + doassert ok(4, 2, 5) == 5 + + block: + proc ok(_: int, _: int, a: int): int = a + doAssert ok(4, 2, 5) == 5 + + block: + proc ok(_: int, _: float, a: int): int = a + doAssert ok(1, 2.0, 5) == 5 + + block: + proc ok(_: int, _: float, _: string, a: int): int = a + doAssert ok(1, 2.6, "5", 5) == 5 + + block: + proc ok[T](_, _, a: T): T = + doAssert not compiles(_) + a + doAssert ok(4, 2, 5) == 5 + doAssert ok("a", "b", "c") == "c" + doAssert not compiles(ok(1, 2, "a")) + + block: + let ok = proc (_, _, a: int): int = + doAssert not compiles(_) + a + doAssert ok(4, 2, 5) == 5 + + block: + proc foo(lam: proc (_, _, a: int): int): int = + lam(4, 2, 5) + doAssert foo(proc (_, _, a: auto): auto = + doAssert not compiles(_) + a) == 5 + + block: + iterator fn(_, _: int, c: int): int = yield c + doAssert toSeq(fn(1,2,3)) == @[3] + + block: + template ok(_, _, a: int): int = a + doAssert ok(4, 2, 5) == 5 + + block: + doAssert not (compiles do: + template bad(_: int): int = _ + discard bad(3)) + + block: + template ok(_: int, _: int, a: int): int = a + doAssert ok(4, 2, 5) == 5 + + block: + template ok(_: int, _: float, a: int): int = a + doAssert ok(1, 2.0, 5) == 5 + + block: + template ok(_: int, _: float, _: string, a: int): int = a + doAssert ok(1, 2.6, "5", 5) == 5 + + block: + template main2() = + iterator fn(_, _: int, c: int): int = yield c + main2() + + block: + template main = + proc foo(_: int) = + let a = _ + doAssert not compiles(main()) + + block: # generic params + doAssert not (compiles do: + proc foo[_](t: typedesc[_]): seq[_] = @[default(_)] + doAssert foo[int]() == 0) + + block: + proc foo[_, _](): int = 123 + doAssert foo[int, bool]() == 123 + + block: + proc foo[T; U](_: typedesc[T]; _: typedesc[U]): (T, U) = (default(T), default(U)) + doAssert foo(int, bool) == (0, false) + +proc closureTest() = + var x = 0 + + block: + proc foo(_, _: int) = x += 5 + + foo(1, 2) + doAssert x == 5 + + block: + proc foo(_: int, _: float) = x += 5 + + foo(1, 2) + doAssert x == 10 + + block: + proc foo(_: int, _: float, _: string) = x += 5 + + foo(1, 2, "5") + doAssert x == 15 + +static: test() +test() + +when not defined(js): + static: closureTest() +closureTest() 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] diff --git a/tests/range/t19678.nim b/tests/range/t19678.nim new file mode 100644 index 000000000..88f7eff89 --- /dev/null +++ b/tests/range/t19678.nim @@ -0,0 +1,17 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +t19678.nim(13, 13) Error: range of string is invalid + + + +''' +""" + +case "5": + of "0" .. "9": + discard + else: + discard + diff --git a/tests/range/tcompiletime_range_checks.nim b/tests/range/tcompiletime_range_checks.nim index 29e2c48a8..2d3f292ec 100644 --- a/tests/range/tcompiletime_range_checks.nim +++ b/tests/range/tcompiletime_range_checks.nim @@ -1,8 +1,8 @@ discard """ cmd: "nim check --hint:Processing:off --hint:Conf:off $file" errormsg: "18446744073709551615 can't be converted to int8" - nimout: '''tcompiletime_range_checks.nim(36, 21) Error: 2147483648 can't be converted to int32 -tcompiletime_range_checks.nim(37, 23) Error: -1 can't be converted to uint64 + nimout: ''' +tcompiletime_range_checks.nim(36, 21) Error: 2147483648 can't be converted to int32 tcompiletime_range_checks.nim(38, 34) Error: 255 can't be converted to FullNegativeRange tcompiletime_range_checks.nim(39, 34) Error: 18446744073709551615 can't be converted to HalfNegativeRange tcompiletime_range_checks.nim(40, 34) Error: 300 can't be converted to FullPositiveRange diff --git a/tests/range/texplicitvarconv.nim b/tests/range/texplicitvarconv.nim new file mode 100644 index 000000000..8da8a8878 --- /dev/null +++ b/tests/range/texplicitvarconv.nim @@ -0,0 +1,13 @@ +# related to issue #24032 + +proc `++`(n: var int) = + n += 1 + +type + r = range[ 0..15 ] + +var a: r = 14 + +++int(a) # this should be mutable + +doAssert a == 15 diff --git a/tests/range/toutofrangevarconv.nim b/tests/range/toutofrangevarconv.nim new file mode 100644 index 000000000..1ee4d340e --- /dev/null +++ b/tests/range/toutofrangevarconv.nim @@ -0,0 +1,14 @@ +discard """ + outputsub: "value out of range: 5 notin 0 .. 3 [RangeDefect]" + exitcode: "1" +""" + +# make sure out of bounds range conversion is detected for `var` conversions + +type R = range[0..3] + +proc foo(x: var R) = + doAssert x in 0..3 + +var x = 5 +foo(R(x)) diff --git a/tests/range/trange.nim b/tests/range/trange.nim index 92ab5ea86..abfa7d474 100644 --- a/tests/range/trange.nim +++ b/tests/range/trange.nim @@ -74,37 +74,37 @@ block tn8vsint16: import strutils block tcolors: - type TColor = distinct int32 + type TColor = distinct uint32 proc rgb(r, g, b: range[0..255]): TColor = result = TColor(r or g shl 8 or b shl 16) proc `$`(c: TColor): string = - result = "#" & toHex(int32(c), 6) + result = "#" & toHex(uint32(c), 6) echo rgb(34, 55, 255) - when false: + block: type - TColor = distinct int32 - TColorComponent = distinct int8 + TColor = distinct uint32 + TColorComponent = distinct uint8 proc red(a: TColor): TColorComponent = - result = TColorComponent(int32(a) and 0xff'i32) + result = TColorComponent(uint32(a) and 0xff'u32) proc green(a: TColor): TColorComponent = - result = TColorComponent(int32(a) shr 8'i32 and 0xff'i32) + result = TColorComponent(uint32(a) shr 8'u32 and 0xff'u32) proc blue(a: TColor): TColorComponent = - result = TColorComponent(int32(a) shr 16'i32 and 0xff'i32) + result = TColorComponent(uint32(a) shr 16'u32 and 0xff'u32) proc rgb(r, g, b: range[0..255]): TColor = result = TColor(r or g shl 8 or b shl 8) proc `+!` (a, b: TColorComponent): TColorComponent = ## saturated arithmetic: - result = TColorComponent(min(ze(int8(a)) + ze(int8(b)), 255)) + result = TColorComponent(min(int(uint8(a)) + int(uint8(b)), 255)) proc `+` (a, b: TColor): TColor = ## saturated arithmetic for colors makes sense, I think: - return rgb(red(a) +! red(b), green(a) +! green(b), blue(a) +! blue(b)) + return rgb(int(red(a) +! red(b)), int(green(a) +! green(b)), int(blue(a) +! blue(b))) - rgb(34, 55, 255) + discard rgb(34, 55, 255) block: type diff --git a/tests/readme.md b/tests/readme.md index b67ec55db..f638ddc10 100644 --- a/tests/readme.md +++ b/tests/readme.md @@ -2,14 +2,14 @@ This directory contains the test cases. Each test must have a filename of the form: ``t*.nim`` -**Note:** Testament is only aware of tests under a directory (eg `tests/foo/`) and will ignore +**Note:** [Testament](https://nim-lang.github.io/Nim/testament.html) is only aware of tests under a directory (eg `tests/foo/`) and will ignore top-level tests like `tests/tbar.nim`. # Specs Each test can contain a spec in a ``discard """ ... """`` block. -**Check out the [``parseSpec`` procedure](https://github.com/nim-lang/Nim/blob/devel/testament/specs.nim#L158) in the ``specs`` module for a full and reliable reference** +**Check out the [``parseSpec`` procedure](https://github.com/nim-lang/Nim/blob/devel/testament/specs.nim#L315) in the ``specs`` module for a full and reliable reference** ## action diff --git a/tests/refc/tsinkbug.nim b/tests/refc/tsinkbug.nim new file mode 100644 index 000000000..de2ec98a5 --- /dev/null +++ b/tests/refc/tsinkbug.nim @@ -0,0 +1,26 @@ +discard """ + matrix: "--gc:refc; --gc:arc" + output: ''' +Value is: 42 +Value is: 42''' +""" + +type AnObject* = object of RootObj + value*: int + +proc mutate(a: sink AnObject) = + a.value = 1 + +var obj = AnObject(value: 42) +echo "Value is: ", obj.value +mutate(obj) +echo "Value is: ", obj.value + +proc p(x: sink string) = + var y = move(x) + doAssert x.len == 0 + doAssert y.len == 4 + +p("1234") +var s = "oooo" +p(s) diff --git a/tests/sets/t13764.nim b/tests/sets/t13764.nim new file mode 100644 index 000000000..1634f113d --- /dev/null +++ b/tests/sets/t13764.nim @@ -0,0 +1,6 @@ +discard """ +errormsg: "conversion from int literal(1000000) to range 0..255(int) is invalid" +line: 6 +""" + +let a = {1_000_000} # Compiles diff --git a/tests/sets/t20997.nim b/tests/sets/t20997.nim new file mode 100644 index 000000000..b320eee1a --- /dev/null +++ b/tests/sets/t20997.nim @@ -0,0 +1,18 @@ +discard """ + joinable: false +""" + +{.passC: "-flto".} +{.passL: "-flto".} + +template f(n: int) = discard card(default(set[range[0 .. (1 shl n) - 1]])) +f( 7) +f( 8) +f( 9) +f(10) +f(11) +f(12) +f(13) +f(14) +f(15) +f(16) diff --git a/tests/sets/thugeset.nim b/tests/sets/thugeset.nim new file mode 100644 index 000000000..1d82ebede --- /dev/null +++ b/tests/sets/thugeset.nim @@ -0,0 +1,10 @@ +let x = 20_000 +let s = {x, 123} #[tt.Warning + ^ type 'int' is too big to be a `set` element, assuming a range of 0..65535, explicitly write this range to get rid of warning [AboveMaxSizeSet]]# +doAssert x in s +doAssert 20_000 in s +{.push warningAsError[AboveMaxSizeSet]: on.} +let s2 = {range[0..65535](x), 123} +doAssert x in s +doAssert 20_000 in s +{.pop.} diff --git a/tests/misc/tnewsets.nim b/tests/sets/tnewsets.nim index f239d4aa2..f239d4aa2 100644 --- a/tests/misc/tnewsets.nim +++ b/tests/sets/tnewsets.nim diff --git a/tests/sets/trangeincompatible.nim b/tests/sets/trangeincompatible.nim new file mode 100644 index 000000000..554a50235 --- /dev/null +++ b/tests/sets/trangeincompatible.nim @@ -0,0 +1,32 @@ +block: # issue #20142 + let + s1: set['a' .. 'g'] = {'a', 'e'} + s2: set['a' .. 'g'] = {'b', 'c', 'd', 'f'} # this works fine + s3 = {'b', 'c', 'd', 'f'} + + doAssert s1 != s2 + doAssert s1 == {range['a'..'g'] 'a', 'e'} + doAssert s2 == {range['a'..'g'] 'b', 'c', 'd', 'f'} + # literal conversion: + doAssert s1 == {'a', 'e'} + doAssert s2 == {'b', 'c', 'd', 'f'} + doAssert s3 == {'b', 'c', 'd', 'f'} + doAssert not compiles(s1 == s3) + doAssert not compiles(s2 == s3) + # can't convert literal 'z', overload match fails + doAssert not compiles(s1 == {'a', 'z'}) + +block: # issue #18396 + var s1: set[char] = {'a', 'b'} + var s2: set['a'..'z'] = {'a', 'b'} + doAssert s1 == {'a', 'b'} + doAssert s2 == {range['a'..'z'] 'a', 'b'} + doAssert s2 == {'a', 'b'} + doAssert not compiles(s1 == s2) + +block: # issue #16270 + var s1: set[char] = {'a', 'b'} + var s2: set['a'..'z'] = {'a', 'c'} + doAssert not (compiles do: s2 = s2 + s1) + s2 = s2 + {'a', 'b'} + doAssert s2 == {'a', 'b', 'c'} diff --git a/tests/sets/tsets.nim b/tests/sets/tsets.nim index 517c0b89c..6125a3715 100644 --- a/tests/sets/tsets.nim +++ b/tests/sets/tsets.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c cpp" +""" + # Test builtin sets # xxx these tests are not very good, this should be revisited. @@ -21,6 +25,10 @@ block: k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k60, k61, k62, k63, k64, k65, k66, k67, k68, k69, k70, k71, k72, k73, k74, k75, k76, k77, k78, k79, k80, k81, k82, k83, k84, k85, k86, k87, k88, k89, k90, k91, k92, k93, k94, k95, k96, k97, k98, k99, k100, k101, k102, k103, k104, k105, k106, k107, k108, k109, k110, k111, k112, k113, k114, k115, k116, k117, k118, k119, k120, k121, k122, k123, k124, k125, k126, k127, k128, k129, k130, k131, k132, k133, k134, k135, k136, k137, k138, k139, k140, k141, k142, k143, k144, k145, k146, k147, k148, k149, k150, k151, k152, k153, k154, k155, k156, k157, k158, k159, k160, k161, k162, k163, k164, k165, k166, k167, k168, k169, k170, k171, k172, k173, k174, k175, k176, k177, k178, k179, k180, k181, k182, k183, k184, k185, k186, k187, k188, k189, k190, k191, k192, k193, k194, k195, k196, k197, k198, k199, k200, k201, k202, k203, k204, k205, k206, k207, k208, k209, k210, k211, k212, k213, k214, k215, k216, k217, k218, k219, k220, k221, k222, k223, k224, k225, k226, k227, k228, k229, k230, k231, k232, k233, k234, k235, k236, k237, k238, k239, k240, k241, k242, k243, k244, k245, k246, k247, k248, k249 FakeTokTypeRange = range[k2..k101] FakeTokTypes = set[FakeTokTypeRange] + Foo = object + field: set[Bar] #Bug: 6259 + Bar = enum + bar1, bar2, bar3 const toktypes: FakeTokTypes = {FakeTokTypeRange(k2)..pred(k64), k72..k74} @@ -89,3 +97,37 @@ block: doAssert k99 notin s1 doAssert k99 notin s2 + +block: # bug #23422 + block: + var a: set[uint8] = {1'u8} + + proc printLen(x: set[uint8]): int = + doAssert x.len == card(x) + result = card(x) + + proc printLenVar(x: var set[uint8]): int = + doAssert x.len == card(x) + result = card(x) + + doAssert a.len == 1 + doAssert printLen(a) == 1 + doAssert printLenVar(a) == card(a) + + block: + type Fruit = enum + Apple, Banana, Melon + + var a: set[Fruit] = {Apple} + + proc printLen(x: set[Fruit]): int = + doAssert x.len == card(x) + result = card(x) + + proc printLenVar(x: var set[Fruit]): int = + doAssert x.len == card(x) + result = card(x) + + doAssert a.len == 1 + doAssert printLen(a) == 1 + doAssert printLenVar(a) == card(a) diff --git a/tests/sets/twrongenumrange.nim b/tests/sets/twrongenumrange.nim new file mode 100644 index 000000000..a8d64ac44 --- /dev/null +++ b/tests/sets/twrongenumrange.nim @@ -0,0 +1,50 @@ +discard """ + cmd: "nim check --hints:off $file" +""" + +# issue #17848 + +block: + # generate with: + # var a = "" + # for i in 0..<80: a.add "k" & $i & ", " + # echo a + type + TMsgKind = enum + k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k60, k61, k62, k63, k64, k65, k66, k67, k68, k69, k70, k71, k72, k73, k74, k75, k76, k77, k78, k79 + type + TNoteKind = range[k10..k79] + Conf = ref object + notes: set[TNoteKind] + proc bad(conf: Conf, noteSet: set[TMsgKind]) = + conf.notes = noteSet #[tt.Error + ^ type mismatch: got <set[TMsgKind]> but expected 'set[TNoteKind]']# + var conf = Conf() + bad(conf, {k10..k60}) + +block: + type + TMsgKind = enum k0, k1, k2, k3 + TNoteKind = range[k1..k2] + TNoteKinds = set[TNoteKind] + type Conf = ref object + notes: TNoteKinds + proc fn(conf: Conf, b: set[TMsgKind]) = + conf.notes = b #[tt.Error + ^ type mismatch: got <set[TMsgKind]> but expected 'TNoteKinds = set[TNoteKind]']# + var conf = Conf() + conf.fn({k0..k3}) # BUG: this should give error + echo conf.notes # {k1, k2} + +block: + #[ + compiler/bitsets.nim(43, 9) `elem >= 0` [AssertionDefect] + ]# + type + TMsgKind = enum k0, k1, k2, k3 + TNoteKind = range[k1..k2] + var notes: set[TNoteKind] + notes = {k0} #[tt.Error + ^ type mismatch: got <set[TMsgKind]> but expected 'set[TNoteKind]']# + notes = {k0..k3} #[tt.Error + ^ type mismatch: got <set[TMsgKind]> but expected 'set[TNoteKind]']# diff --git a/tests/showoff/tgenericmacrotypes.nim b/tests/showoff/tgenericmacrotypes.nim new file mode 100644 index 000000000..cc07f4355 --- /dev/null +++ b/tests/showoff/tgenericmacrotypes.nim @@ -0,0 +1,55 @@ +# issue #7974 + +import macros + +macro genTypeA(arg: typed): untyped = + if arg.typeKind != ntyTypeDesc: + error("expected typedesc", arg) + + result = arg.getTypeInst[1] + +macro genTypeB(arg: typed): untyped = + if arg.typeKind != ntyTypeDesc: + error("expected typedesc", arg) + + + let typeSym = arg.getTypeInst[1] + result = + nnkTupleTy.newTree( + nnkIdentDefs.newTree( + ident"a", typeSym, newEmptyNode() + ) + ) + +type + # this is the trivial case, MyTypeA[T] is basically just T, nothing else. But it works. + MyTypeA[T] = genTypeA(T) + # in this case I generate `tuple[a: T]`. This this is something the compiler does not want + MyTypeB[T] = genTypeB(T) + +# these are just alias types for int32 and float32, nothing really happens, but it works +var a1: MyTypeA[int32] +doAssert a1 is MyTypeA[int32] +doAssert a1 is int32 +a1 = 0'i32 +var a2: MyTypeA[float32] +doAssert a2 is MyTypeA[float32] +doAssert a2 is float32 +a2 = 0'f32 +var a3: MyTypeA[float32] +doAssert a3 is MyTypeA[float32] +doAssert a3 is float32 +a3 = 0'f32 + +var b1: MyTypeB[int32] # cannot generate VM code fur tuple[a: int32] +doAssert b1 is MyTypeB[int32] +doAssert b1 is tuple[a: int32] +b1 = (a: 0'i32) +var b2: MyTypeB[float32] +doAssert b2 is MyTypeB[float32] +doAssert b2 is tuple[a: float32] +b2 = (a: 0'f32) +var b3: MyTypeB[float32] +doAssert b3 is MyTypeB[float32] +doAssert b3 is tuple[a: float32] +b3 = (a: 0'f32) diff --git a/tests/slice/tdistinct.nim b/tests/slice/tdistinct.nim deleted file mode 100644 index d99b529a7..000000000 --- a/tests/slice/tdistinct.nim +++ /dev/null @@ -1,2 +0,0 @@ -type Foo = distinct uint64 -const slice = 0 ..< 42.Foo diff --git a/tests/specialops/tcallops.nim b/tests/specialops/tcallops.nim index 0508a37a1..c541a0c1d 100644 --- a/tests/specialops/tcallops.nim +++ b/tests/specialops/tcallops.nim @@ -37,3 +37,13 @@ doAssert a(b) == "(12)" doAssert a.b(c) == `()`(b, a, c) doAssert (a.b)(c) == `()`(a.b, c) doAssert `()`(a.b, c) == `()`(`()`(b, a), c) + +block: # bug #1072 + var x: int + + proc foo(some:int):int = some + proc `()`(l,r:string): string = discard + + block: + var foo = 42 + doAssert x.foo == 0 diff --git a/tests/specialops/terrmsgs.nim b/tests/specialops/terrmsgs.nim new file mode 100644 index 000000000..081bca451 --- /dev/null +++ b/tests/specialops/terrmsgs.nim @@ -0,0 +1,76 @@ +discard """ +action: reject +cmd: '''nim check $options $file''' +matrix: "; -d:testWithout; --mm:refc" +""" + +when not defined(testWithout): # test for same errors before and after + {.experimental: "dotOperators".} + {.experimental: "callOperator".} + +# issue #13063 + +block: + type Foo = object + type Bar = object + x1: int + var b: Bar + block: + template `.`(a: Foo, b: untyped): untyped = 123 + echo b.x #[tt.Error + ^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + block: + template `.()`(a: Foo, b: untyped): untyped = 123 + echo b.x() #[tt.Error + ^ attempting to call undeclared routine: 'x']# + block: + template `.=`(a: Foo, b: untyped, c: untyped) = b = c + b.x = 123 #[tt.Error + ^ undeclared field: 'x=' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + # yeah it says x= but does it matter in practice + block: + template `()`(a: Foo, b: untyped, c: untyped) = echo "something" + + # completely undeclared:: + xyz(123) #[tt.Error + ^ undeclared identifier: 'xyz']# + + # already declared routine: + min(123) #[tt.Error + ^ type mismatch: got <int literal(123)>]# + + # non-routine type shows `()` overloads: + b(123) #[tt.Error + ^ attempting to call routine: 'b']# + + echo b.x #[tt.Error + ^ undeclared field: 'x' for type terrmsgs.Bar [type declared in terrmsgs.nim(15, 8)]]# + echo b.x() #[tt.Error + ^ attempting to call undeclared routine: 'x']# + +# issue #7777 + +import macros + +block: + type TestType = object + private_field: string + + when false: + template getField(obj, field: untyped): untyped = obj.field + + macro `.`(obj: TestType, field: untyped): untyped = + let private = newIdentNode("private_" & $field) + result = quote do: + `obj`.getField(`private`) #[tt.Error + ^ attempting to call undeclared routine: 'getField']# + + var tt: TestType + discard tt.field + +block: # related to issue #6981 + proc `()`(a:string, b:string):string = a & b + proc mewSeq[T](a,b:int)=discard + proc mewSeq[T](c:int)= discard + mewSeq[int]() #[tt.Error + ^ type mismatch: got <>]# diff --git a/tests/specialops/tnewseq.nim b/tests/specialops/tnewseq.nim new file mode 100644 index 000000000..970a5a8c2 --- /dev/null +++ b/tests/specialops/tnewseq.nim @@ -0,0 +1,22 @@ +# issue #6981 + +import std/assertions + +{.experimental: "callOperator".} + +block: # issue #6981 + proc `()`(a:string, b:string):string = a & b + + var s = newSeq[int](3) + + doAssert s == @[0, 0, 0] + +block: # generalized example from #6981 + proc mewSeq[T](a: int)=discard + proc mewSeq[T]()= discard + mewSeq[int]() + +block: # issue #9831 + type Foo = object + proc `()`(foo: Foo) = discard + let x = newSeq[int]() diff --git a/tests/specialops/tsetter.nim b/tests/specialops/tsetter.nim new file mode 100644 index 000000000..6175cbec4 --- /dev/null +++ b/tests/specialops/tsetter.nim @@ -0,0 +1,10 @@ +block: # ensure RHS of setter statement is treated as call operand + proc `b=`(a: var int, c: proc (x: int): int) = + a = c(a) + + proc foo(x: int): int = x + 1 + proc foo(x: float): float = x - 1 + + var a = 123 + a.b = foo + doAssert a == 124 diff --git a/tests/statictypes/t20148.nim b/tests/statictypes/t20148.nim new file mode 100644 index 000000000..d74a7755e --- /dev/null +++ b/tests/statictypes/t20148.nim @@ -0,0 +1,8 @@ +type Percent = range[0.0 .. 1.0] +# type Percent = float # using unlimited `float` works fine + +proc initColor*(alpha: Percent): bool = + echo alpha + +const moduleInstanceStyle = initColor(1) +# let moduleInstanceStyle = initColor(1) # using runtime conversion works fine diff --git a/tests/statictypes/t5780.nim b/tests/statictypes/t5780.nim new file mode 100644 index 000000000..85548aaad --- /dev/null +++ b/tests/statictypes/t5780.nim @@ -0,0 +1,3 @@ +type StringArray[N:int] = array[N, string] +let a = ["one", "two"] +doAssert a is StringArray diff --git a/tests/statictypes/t9255.nim b/tests/statictypes/t9255.nim index 99ca2a23c..aec2fbaf5 100644 --- a/tests/statictypes/t9255.nim +++ b/tests/statictypes/t9255.nim @@ -1,6 +1,6 @@ discard """ errormsg: ''' -type mismatch: got <proc (a0: int): string{.noSideEffect, gcsafe, locks: 0.}> +type mismatch: got <proc (a0: int): string{.noSideEffect, gcsafe.}> ''' line: 13 """ diff --git a/tests/statictypes/tgenericcomputedrange.nim b/tests/statictypes/tgenericcomputedrange.nim new file mode 100644 index 000000000..9e3a49ae0 --- /dev/null +++ b/tests/statictypes/tgenericcomputedrange.nim @@ -0,0 +1,125 @@ +import math + +block: # issue #19916 + type + Test[S: static[Natural]] = object + a: array[ceilDiv(S, 8), uint8] + + let a = Test[32]() + doAssert a.a.len == 4 + +block: # issue #20514 + type Foo[S:static[array[2, int]]] = object + values: array[prod(S), float] + + doAssert Foo[[4,5]]().values.len == 20 + +block: # issue #20937 + type + Vec3[T: SomeNumber] {.bycopy.} = tuple[x, y, z: T] + + func volume[T](v: Vec3[T]): T = + when T is SomeUnsignedInt: + v.x * v.y * v.z + else: + abs (v.x * v.y * v.z) + + type + Matrix3[C: static Vec3[uint], T] = object + cells: array[C.volume, T] + + let m = Matrix3[(1.uint, 1.uint, 1.uint), uint](cells: [0.uint]) + doAssert m.cells.len == 1 + let m2 = Matrix3[(4.uint, 3.uint, 5.uint), uint]() + doAssert m2.cells.len == 60 + +block: # issue #19284 + type Board[N, M: static Slice[int]] = array[len(N)*len(M), int8] + + var t: Board[0..4, 0..4] + doAssert t.len == 25 + +block: # minimal issue #19284 + proc foo[T](x: T): int = + result = 0 + type Foo[N: static int] = array[0..foo(N), int] + + var t: Foo[5] + doAssert t.len == 1 + +block: + type Foo[T; U: static T] = range[T(0) .. U] + + block: + var x: array[Foo[int, 1], int] + x[0] = 1 + x[1] = 2 + doAssert x == [0: 1, 1: 2] + doAssert x is array[0 .. 1, int] + + block: + type Bar = enum a, b, c + var x: array[Foo[Bar, c], int] + x[a] = 1 + x[b] = 2 + x[c] = 3 + doAssert x == [a: 1, b: 2, c: 3] + doAssert x is array[a .. c, int] + +block: + type Foo[T; U: static T] = array[T(0) .. U, int] + + block: + var x: Foo[int, 1] + x[0] = 1 + x[1] = 2 + doAssert x == [0: 1, 1: 2] + doAssert x is array[0 .. 1, int] + + block: + type Bar = enum a, b, c + var x: Foo[Bar, c] + x[a] = 1 + x[b] = 2 + x[c] = 3 + doAssert x == [a: 1, b: 2, c: 3] + doAssert x is array[a .. c, int] + +block: + type Foo[T; U: static T] = array[T(0) .. U + 1, int] + + block: + var x: Foo[int, 1] + x[0] = 1 + x[1] = 2 + x[2] = 3 + doAssert x == [0: 1, 1: 2, 2: 3] + doAssert x is array[0 .. 2, int] + +block: + type Foo[T; U: static T] = array[T(0) .. (U * 2) + 1, int] + + block: + var x: Foo[int, 1] + x[0] = 1 + x[1] = 2 + x[2] = 3 + x[3] = 4 + doAssert x == [0: 1, 1: 2, 2: 3, 3: 4] + doAssert x is array[0 .. 3, int] + +block: # issue #22187 + template m(T: type, s: int64): int64 = s + func p(n: int64): int = int(n) + type F[T; s: static int64] = object + k: array[p(m(T, s)), int64] + var x: F[int, 3] + doAssert x.k is array[3, int64] + +block: # issue #22490 + proc log2trunc(x: uint64): int = + if x == 0: int(0) else: int(0) + template maxChunkIdx(T: typedesc): int64 = 0'i64 + template layer(vIdx: int64): int = log2trunc(0'u64) + type HashList[T] = object + indices: array[int(layer(maxChunkIdx(T))), int] diff --git a/tests/statictypes/tstaticgenericparam.nim b/tests/statictypes/tstaticgenericparam.nim new file mode 100644 index 000000000..6acd05b70 --- /dev/null +++ b/tests/statictypes/tstaticgenericparam.nim @@ -0,0 +1,24 @@ +# static types that depend on a generic parameter + +block: # issue #19365 + var ss: seq[string] + proc f[T](x: static T) = + ss.add($x & ": " & $T) + + f(123) + doAssert ss == @["123: int"] + f("abc") + doAssert ss == @["123: int", "abc: string"] + +block: # issue #7209 + type Modulo[A; M: static[A]] = distinct A + + proc `$`[A; M: static[A]](x: Modulo[A, M]): string = + $(A(x)) & " mod " & $(M) + + proc modulo[A](a: A, M: static[A]): Modulo[A, M] = Modulo[A, M](a %% M) + + proc `+`[A; M: static[A]](x, y: Modulo[A, M]): Modulo[A, M] = + (A(x) + A(y)).modulo(M) + + doAssert $(3.modulo(7) + 5.modulo(7)) == "1 mod 7" diff --git a/tests/statictypes/tstaticprocparams.nim b/tests/statictypes/tstaticprocparams.nim new file mode 100644 index 000000000..75d8288ac --- /dev/null +++ b/tests/statictypes/tstaticprocparams.nim @@ -0,0 +1,16 @@ +proc consumer[T: static proc(i: int): int{.nimcall.}](i: int): int = T(i) +proc consumer(T: static proc(i: int): int{.nimcall.}, i: int): int = T(i) + +proc addIt(i: int): int = i + i +proc add(i: int): int = i + i # Checks if we can use overloads +proc squareIt(i: int): int = i * i + +assert consumer[addIt](10) == 20 +assert consumer[add](10) == 20 +assert consumer[squareIt](30) == 900 +assert consumer[proc(i: int): int{.nimcall.} = i * i + i](10) == 110 + +assert consumer(addIt, 10) == 20 +assert consumer(add, 10) == 20 +assert consumer(squareIt, 30) == 900 +assert consumer(proc(i: int): int{.nimcall.} = i * i + i, 10) == 110 diff --git a/tests/statictypes/tstatictypes.nim b/tests/statictypes/tstatictypes.nim index 5df3f35fd..572b8c4a5 100644 --- a/tests/statictypes/tstatictypes.nim +++ b/tests/statictypes/tstatictypes.nim @@ -22,7 +22,7 @@ heyho Val1 Val1 ''' -matrix: "--hints:off" +matrix: "--hints:off --mm:orc; --hints:off --mm:refc" """ import macros @@ -391,3 +391,69 @@ var sorted = newSeq[int](1000) for i in 0..<sorted.len: sorted[i] = i*2 doAssert isSorted2(sorted, compare) doAssert isSorted2(sorted, proc (a, b: int): bool {.inline.} = a < b) + + +block: # Ensure static descriminated objects compile + type + ObjKind = enum + KindA, KindB, KindC + + MyObject[kind: static[ObjKind]] = object of RootObj + myNumber: int + when kind != KindA: + driverType: int + otherField: int + elif kind == KindC: + driverType: uint + otherField: int + + var instance: MyObject[KindA] + discard instance + discard MyObject[KindC]() + +block: # more cases of above, issue #8446 + type + Color = enum + red, green, blue + Blah[color: static[Color]] = object + when color == red: + a: string + else: + b: int + + proc foo(blah: Blah) = discard + foo(Blah[red](a: "abc")) + + type + Mytype[K: static[int]] = object + when K < 16: + data: uint8 + else: + data: uint64 + proc usingMyt(k: Mytype) = discard # triggers Error: cannot generate code for: K + +block: # bug #22600 + proc f(n: static int): int = n * 2 # same for template + + type + a[N: static int] = object + field : array[N, uint8] + + b[N: static int] = object + field : a[N] + + c[N: static int] = object + f0 : a[N ] # works + f1 : a[N + 1 ] # asserts + f2 : a[f(N) ] # asserts + + f3 : b[N ] # works + f4 : b[N + 1 ] # asserts + f5 : b[f(N) ] # asserts + + proc init[N: static int](x : var a[N]) = discard + proc init[N: static int](x : var b[N]) = discard + proc init[N: static int](x : var c[N]) = x.f1.init() # this is needed + + var x: c[2] + x.init() diff --git a/tests/stdlib/concurrency/tatomics.nim b/tests/stdlib/concurrency/tatomics.nim index beae0ed6d..08f2e7d3e 100644 --- a/tests/stdlib/concurrency/tatomics.nim +++ b/tests/stdlib/concurrency/tatomics.nim @@ -1,6 +1,14 @@ +discard """ + # test C with -d:nimUseCppAtomics as well to check nothing breaks + matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics" + targets: "c cpp" +""" + # test atomic operations import std/[atomics, bitops] +import std/assertions + type Object = object diff --git a/tests/stdlib/concurrency/tatomics_size.nim b/tests/stdlib/concurrency/tatomics_size.nim index 49387c0c1..f64adb308 100644 --- a/tests/stdlib/concurrency/tatomics_size.nim +++ b/tests/stdlib/concurrency/tatomics_size.nim @@ -1,7 +1,10 @@ discard """ + # test C with -d:nimUseCppAtomics as well to check nothing breaks + matrix: "--mm:refc; --mm:orc; --mm:refc -d:nimUseCppAtomics; --mm:orc -d:nimUseCppAtomics" targets: "c cpp" """ import std/atomics +import std/assertions block testSize: # issue 12726 type @@ -15,4 +18,4 @@ block testSize: # issue 12726 f: AtomicFlag static: doAssert sizeof(Node) == sizeof(pointer) - doAssert sizeof(MyChannel) == sizeof(pointer) * 2 \ No newline at end of file + doAssert sizeof(MyChannel) == sizeof(pointer) * 2 diff --git a/tests/stdlib/config.nims b/tests/stdlib/config.nims index 0c0c5bd88..dffae2812 100644 --- a/tests/stdlib/config.nims +++ b/tests/stdlib/config.nims @@ -1,2 +1,5 @@ switch("styleCheck", "usages") -switch("styleCheck", "error") \ No newline at end of file +switch("styleCheck", "error") +switch("define", "nimPreviewSlimSystem") +switch("define", "nimPreviewCstringConversion") +switch("define", "nimPreviewProcConversion") diff --git a/tests/stdlib/mgenast.nim b/tests/stdlib/mgenast.nim index 2b5381891..b0904847e 100644 --- a/tests/stdlib/mgenast.nim +++ b/tests/stdlib/mgenast.nim @@ -31,6 +31,8 @@ macro bindme6UseExpose*(): untyped = genAst: var tst = "sometext" var ss = newStringStream("anothertext") + when defined(gcArc) or defined(gcOrc): + prepareMutation(tst) writeData(ss, tst[0].addr, 2) discard readData(ss, tst[0].addr, 2) @@ -40,6 +42,8 @@ macro bindme6UseExposeFalse*(): untyped = genAstOpt({kDirtyTemplate}, newStringStream, writeData, readData): var tst = "sometext" var ss = newStringStream("anothertext") + when defined(gcArc) or defined(gcOrc): + prepareMutation(tst) writeData(ss, tst[0].addr, 2) discard readData(ss, tst[0].addr, 2) diff --git a/tests/stdlib/mimportutils.nim b/tests/stdlib/mimportutils.nim index e89d58d27..678d9ec02 100644 --- a/tests/stdlib/mimportutils.nim +++ b/tests/stdlib/mimportutils.nim @@ -26,6 +26,12 @@ type H1*[T] = ref H2[T] H*[T] = H1[T] + Pity[T] = object + a: T + PityRef*[T] = ref Pity[T] + Hope*[T] = ref object + a: T + type BAalias* = typeof(B.default) # typeof is not a transparent abstraction, creates a `tyAlias` diff --git a/tests/stdlib/mintsets.nim b/tests/stdlib/mintsets.nim index b4d9ed516..98786e9ba 100644 --- a/tests/stdlib/mintsets.nim +++ b/tests/stdlib/mintsets.nim @@ -1,4 +1,5 @@ import std/intsets +import std/assertions proc test1*[]() = let a = initIntSet() diff --git a/tests/stdlib/t10231.nim b/tests/stdlib/t10231.nim index 3b2b684f3..3d09721aa 100644 --- a/tests/stdlib/t10231.nim +++ b/tests/stdlib/t10231.nim @@ -5,6 +5,7 @@ discard """ """ import os +import std/assertions # consider moving this inside tosproc (taking care that it's for cpp mode) diff --git a/tests/stdlib/t14139.nim b/tests/stdlib/t14139.nim index 07d2ff137..866bdb45f 100644 --- a/tests/stdlib/t14139.nim +++ b/tests/stdlib/t14139.nim @@ -1,4 +1,5 @@ -import heapqueue +import std/heapqueue +import std/assertions var test_queue : HeapQueue[int] diff --git a/tests/stdlib/t15663.nim b/tests/stdlib/t15663.nim index 1ad5677fd..8e8bfd9a8 100644 --- a/tests/stdlib/t15663.nim +++ b/tests/stdlib/t15663.nim @@ -3,5 +3,7 @@ discard """ output: "Test" """ +import std/widestrs + let ws = newWideCString("Test") -echo ws \ No newline at end of file +echo ws diff --git a/tests/stdlib/t19304.nim b/tests/stdlib/t19304.nim new file mode 100644 index 000000000..5e8795ac5 --- /dev/null +++ b/tests/stdlib/t19304.nim @@ -0,0 +1,7 @@ +import times + +type DjangoDateTime* = distinct DateTime + +# proc toTime*(x: DjangoDateTime): Time {.borrow.} # <-- works +proc format*(x: DjangoDateTime, f: TimeFormat, + loc: DateTimeLocale = DefaultLocale): string {.borrow.} diff --git a/tests/stdlib/t20023.nim b/tests/stdlib/t20023.nim new file mode 100644 index 000000000..8f12f8993 --- /dev/null +++ b/tests/stdlib/t20023.nim @@ -0,0 +1,10 @@ +import std/[tables, hashes, assertions] + + +let t = () +var a = toTable({t:t}) +del(a,t) +let b = default(typeof(a)) + +doAssert a==b , "tables are not equal" +doAssert hash(a) == hash(b), "table hashes are not equal" diff --git a/tests/stdlib/t21251.nim b/tests/stdlib/t21251.nim new file mode 100644 index 000000000..4402e9b7e --- /dev/null +++ b/tests/stdlib/t21251.nim @@ -0,0 +1,6 @@ +import std / [tables, sets, sharedtables] + +var shared: SharedTable[int, int] +shared.init + +shared[1] = 1 diff --git a/tests/stdlib/t21406.nim b/tests/stdlib/t21406.nim new file mode 100644 index 000000000..86bf7b0c7 --- /dev/null +++ b/tests/stdlib/t21406.nim @@ -0,0 +1,7 @@ +import std/[times, strformat] +import std/assertions + +let aTime = getTime() +doAssert fmt"{aTime}" == $aTime +let aNow = now() +doAssert fmt"{aNow}" == $aNow diff --git a/tests/stdlib/t21564.nim b/tests/stdlib/t21564.nim new file mode 100644 index 000000000..0a5777d12 --- /dev/null +++ b/tests/stdlib/t21564.nim @@ -0,0 +1,32 @@ +discard """ +targets: "c js" +""" + +import bitops +import std/assertions + +proc main() = + block: # bug #21564 + # tesk `bitops.bitsliced` patch + doAssert(0x17.bitsliced(4..7) == 0x01) + doAssert(0x17.bitsliced(0..3) == 0x07) + + block: + # test in-place `bitops.bitslice` + var t = 0x12F4 + t.bitslice(4..7) + + doAssert(t == 0xF) + + block: + # test `bitops.toMask` patch via bitops.masked + doAssert(0x12FFFF34.masked(8..23) == 0x00FFFF00) + + block: # bug #22687 + var a: uint8 = 0b1111_1111 + doAssert a.bitsliced(4..7).int == 15 + +main() + +static: + main() diff --git a/tests/stdlib/t7686.nim b/tests/stdlib/t7686.nim index c174dfb51..9902cfcb5 100644 --- a/tests/stdlib/t7686.nim +++ b/tests/stdlib/t7686.nim @@ -1,4 +1,5 @@ -import strutils +import std/strutils +import std/assertions type MyEnum = enum diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim index 61d2bc62f..e2024df0c 100644 --- a/tests/stdlib/talgorithm.nim +++ b/tests/stdlib/talgorithm.nim @@ -1,11 +1,13 @@ discard """ targets: "c js" + matrix: "--mm:refc; --mm:orc" output:'''@["3", "2", "1"] ''' """ #12928,10456 import std/[sequtils, algorithm, json, sugar] +import std/assertions proc test() = try: diff --git a/tests/stdlib/tarithmetics.nim b/tests/stdlib/tarithmetics.nim index 296ccd56e..0a6dd1fcf 100644 --- a/tests/stdlib/tarithmetics.nim +++ b/tests/stdlib/tarithmetics.nim @@ -1,7 +1,8 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ - +import std/assertions # TODO: in future work move existing arithmetic tests (tests/arithm/*) into this file # FYI https://github.com/nim-lang/Nim/pull/17767 diff --git a/tests/stdlib/tasynchttpserver.nim b/tests/stdlib/tasynchttpserver.nim index aed21099d..5a7e2da40 100644 --- a/tests/stdlib/tasynchttpserver.nim +++ b/tests/stdlib/tasynchttpserver.nim @@ -7,6 +7,7 @@ discard """ import strutils from net import TimeoutError +import std/assertions import httpclient, asynchttpserver, asyncdispatch, asyncfutures @@ -108,6 +109,7 @@ proc testCustomContentLength() {.async.} = doAssert(body == "") doAssert(response.headers.hasKey("Content-Length")) doAssert(response.headers["Content-Length"] == "0") + doAssert contentLength(response) == 0 # bug #22778 runTest(handler, request, test) diff --git a/tests/stdlib/tasynchttpserver_transferencoding.nim b/tests/stdlib/tasynchttpserver_transferencoding.nim index cdd30d04b..886ba0f33 100644 --- a/tests/stdlib/tasynchttpserver_transferencoding.nim +++ b/tests/stdlib/tasynchttpserver_transferencoding.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:arc --threads:on; --gc:arc --threads:on -d:danger; --threads:on" + matrix: "--mm:arc; --mm:arc -d:danger; --mm:refc" disabled: "freebsd" """ @@ -8,6 +8,7 @@ import net import std/asyncnet import std/nativesockets +import std/assertions const postBegin = """ POST / HTTP/1.1 diff --git a/tests/stdlib/tbase64.nim b/tests/stdlib/tbase64.nim index 8ef5adf57..c3bfb818e 100644 --- a/tests/stdlib/tbase64.nim +++ b/tests/stdlib/tbase64.nim @@ -1,7 +1,8 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ - +import std/assertions import std/base64 template main() = @@ -17,6 +18,8 @@ template main() = doAssert encode("") == "" doAssert decode("") == "" + doAssert decode(" ") == "" + const testInputExpandsTo76 = "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++" const testInputExpands = "++++++++++++++++++++++++++++++" const longText = """Man is distinguished, not only by his reason, but by this @@ -52,5 +55,9 @@ template main() = doAssert encode("", safe = true) == "" doAssert encode("the quick brown dog jumps over the lazy fox", safe = true) == "dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA==" +func mainNoSideEffects() = main() + static: main() main() +static: mainNoSideEffects() +mainNoSideEffects() diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim index f807993d6..3ecab2c64 100644 --- a/tests/stdlib/tbitops.nim +++ b/tests/stdlib/tbitops.nim @@ -1,10 +1,12 @@ discard """ nimout: "OK" + matrix: "--mm:refc; --mm:orc" output: ''' OK ''' """ import bitops +import std/assertions proc main() = const U8 = 0b0011_0010'u8 diff --git a/tests/stdlib/tbitops_utils.nim b/tests/stdlib/tbitops_utils.nim index b571baeae..e3f96fecc 100644 --- a/tests/stdlib/tbitops_utils.nim +++ b/tests/stdlib/tbitops_utils.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/private/bitops_utils +import std/assertions template chk(a, b) = let a2 = castToUnsigned(a) diff --git a/tests/stdlib/tcasts.nim b/tests/stdlib/tcasts.nim new file mode 100644 index 000000000..e01c7e940 --- /dev/null +++ b/tests/stdlib/tcasts.nim @@ -0,0 +1,26 @@ +import std/[strutils] +import std/[assertions, objectdollar] + +# bug #19101 +type + Small = object + a: int + + Big = object + a, b, c, d: int + +proc main = + var + n = 1'i8 + f = 2.0 + s = Small(a: 1) + b = Big(a: 12345, b: 23456, c: 34567, d: 45678) + + doAssert $cast[int](f).toBin(64) == "0100000000000000000000000000000000000000000000000000000000000000" + f = cast[float](n) + doAssert $cast[int](f).toBin(64) == "0000000000000000000000000000000000000000000000000000000000000001" + + doAssert $b == "(a: 12345, b: 23456, c: 34567, d: 45678)" + b = cast[Big](s) + doAssert $b == "(a: 1, b: 0, c: 0, d: 0)" +main() diff --git a/tests/stdlib/tcgi.nim b/tests/stdlib/tcgi.nim index 993728712..ef39450da 100644 --- a/tests/stdlib/tcgi.nim +++ b/tests/stdlib/tcgi.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/unittest import std/[cgi, strtabs, sugar] +import std/assertions block: # Test cgi module const queryString = "foo=bar&фу=бар&checked=✓&list=1,2,3&with_space=text%20with%20space" diff --git a/tests/stdlib/tclosures.nim b/tests/stdlib/tclosures.nim new file mode 100644 index 000000000..84b033fa8 --- /dev/null +++ b/tests/stdlib/tclosures.nim @@ -0,0 +1,47 @@ +discard """ + targets: "c js" +""" + +import std/assertions + +block: # bug #4299 + proc scopeProc() = + proc normalProc() = + discard + + proc genericProc[T]() = + normalProc() + + genericProc[string]() + + scopeProc() + +block: # bug #12492 + proc foo() = + var i = 0 + proc bar() = + inc i + + bar() + doAssert i == 1 + + foo() + static: + foo() + +block: # bug #10849 + type + Generic[T] = ref object + getState: proc(): T + + proc newGeneric[T](): Generic[T] = + var state: T + + proc getState[T](): T = + state + + Generic[T](getState: getState) + + let g = newGeneric[int]() + let state = g.getState() + doAssert state == 0 diff --git a/tests/stdlib/tcmdline.nim b/tests/stdlib/tcmdline.nim index bc78d6057..8b428900b 100644 --- a/tests/stdlib/tcmdline.nim +++ b/tests/stdlib/tcmdline.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" joinable: false """ import std/os +import std/assertions var params = paramCount() doAssert params == 0 diff --git a/tests/stdlib/tcomplex.nim b/tests/stdlib/tcomplex.nim index 15267b905..ca83314b9 100644 --- a/tests/stdlib/tcomplex.nim +++ b/tests/stdlib/tcomplex.nim @@ -1,5 +1,9 @@ -import std/[complex, math] +discard """ + matrix: "--mm:refc; --mm:orc" +""" +import std/[complex, math] +import std/assertions proc `=~`[T](x, y: Complex[T]): bool = result = abs(x.re-y.re) < 1e-6 and abs(x.im-y.im) < 1e-6 @@ -80,6 +84,9 @@ let t = polar(a) doAssert(rect(t.r, t.phi) =~ a) doAssert(rect(1.0, 2.0) =~ complex(-0.4161468365471424, 0.9092974268256817)) +doAssert(almostEqual(a, a + complex(1e-16, 1e-16))) +doAssert(almostEqual(a, a + complex(2e-15, 2e-15), unitsInLastPlace = 5)) + let i64: Complex32 = complex(0.0f, 1.0f) diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim index 0a36cbebc..3ff0f3bae 100644 --- a/tests/stdlib/tcookies.nim +++ b/tests/stdlib/tcookies.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[cookies, times, strtabs] +import std/assertions let expire = fromUnix(0) + 1.seconds diff --git a/tests/stdlib/tcritbits.nim b/tests/stdlib/tcritbits.nim index b350cb280..e6282f045 100644 --- a/tests/stdlib/tcritbits.nim +++ b/tests/stdlib/tcritbits.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[sequtils,critbits] +import std/assertions template main = var r: CritBitTree[void] diff --git a/tests/stdlib/tcstring.nim b/tests/stdlib/tcstring.nim index 04a26b53c..d7fdd7738 100644 --- a/tests/stdlib/tcstring.nim +++ b/tests/stdlib/tcstring.nim @@ -5,6 +5,7 @@ discard """ from std/sugar import collect from stdtest/testutils import whenRuntimeJs, whenVMorJs +import std/assertions template testMitems() = block: diff --git a/tests/stdlib/tcstrutils.nim b/tests/stdlib/tcstrutils.nim index ba3b1de68..e73b2b681 100644 --- a/tests/stdlib/tcstrutils.nim +++ b/tests/stdlib/tcstrutils.nim @@ -1,9 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/cstrutils - +import std/assertions proc main() = let s = cstring "abcdef" diff --git a/tests/stdlib/tdb.nim b/tests/stdlib/tdb.nim new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/stdlib/tdb.nim diff --git a/tests/stdlib/tdb.nims b/tests/stdlib/tdb.nims new file mode 100644 index 000000000..d31d0b26f --- /dev/null +++ b/tests/stdlib/tdb.nims @@ -0,0 +1 @@ +--styleCheck:off \ No newline at end of file diff --git a/tests/stdlib/tdb_mysql.nim b/tests/stdlib/tdb_mysql.nim index 21a7afd4f..e69de29bb 100644 --- a/tests/stdlib/tdb_mysql.nim +++ b/tests/stdlib/tdb_mysql.nim @@ -1,4 +0,0 @@ -import std/db_mysql - -doAssert dbQuote("SELECT * FROM foo WHERE col1 = 'bar_baz'") == "'SELECT * FROM foo WHERE col1 = \\'bar_baz\\''" -doAssert dbQuote("SELECT * FROM foo WHERE col1 LIKE '%bar_baz%'") == "'SELECT * FROM foo WHERE col1 LIKE \\'%bar_baz%\\''" diff --git a/tests/stdlib/tdecls.nim b/tests/stdlib/tdecls.nim index 4e7407045..42dc646f2 100644 --- a/tests/stdlib/tdecls.nim +++ b/tests/stdlib/tdecls.nim @@ -1,7 +1,8 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ - +import std/assertions import std/decls template fun() = @@ -13,18 +14,18 @@ template fun() = var b {.byaddr.}: int = s[0] doAssert a.addr == b.addr - when false: - # template specific redeclaration issue - # see https://github.com/nim-lang/Nim/issues/8275 - doAssert not compiles(block: - # redeclaration not allowed - var foo = 0 - var foo {.byaddr.} = s[0]) - - doAssert not compiles(block: - # ditto - var foo {.byaddr.} = s[0] - var foo {.byaddr.} = s[0]) + {.push warningAsError[ImplicitTemplateRedefinition]: on.} + # in the future ImplicitTemplateRedefinition will be an error anyway + doAssert not compiles(block: + # redeclaration not allowed + var foo = 0 + var foo {.byaddr.} = s[0]) + + doAssert not compiles(block: + # ditto + var foo {.byaddr.} = s[0] + var foo {.byaddr.} = s[0]) + {.pop.} block: var b {.byaddr.} = s[1] # redeclaration ok in sub scope diff --git a/tests/stdlib/tdecode_helpers.nim b/tests/stdlib/tdecode_helpers.nim index 626a014fc..1c0735e05 100644 --- a/tests/stdlib/tdecode_helpers.nim +++ b/tests/stdlib/tdecode_helpers.nim @@ -1,5 +1,5 @@ import std/private/decode_helpers - +import std/assertions block: var i = 0 diff --git a/tests/stdlib/tdeques.nim b/tests/stdlib/tdeques.nim index 03e951fce..39ff996d1 100644 --- a/tests/stdlib/tdeques.nim +++ b/tests/stdlib/tdeques.nim @@ -1,11 +1,11 @@ discard """ - matrix: "--gc:refc; --gc:orc" + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/deques from std/sequtils import toSeq - +import std/assertions block: proc index(self: Deque[int], idx: Natural): int = @@ -183,6 +183,61 @@ proc main() = clear(a) doAssert len(a) == 0 + block: # bug #21278 + var a = [10, 20, 30, 40].toDeque + + a.shrink(fromFirst = 0, fromLast = 1) + doAssert $a == "[10, 20, 30]" + + block: + var a, b: Deque[int] + for i in 1 .. 256: + a.addLast(i) + for i in 1 .. 255: + a.popLast + b.addLast(1) + doAssert a == b + + block: + # Issue 23275 + # Test `==`. + block: + var a, b = initDeque[int]() + doAssert a == b + doAssert a.hash == b.hash + a.addFirst(1) + doAssert a != b + doAssert a.hash != b.hash + b.addLast(1) + doAssert a == b + doAssert a.hash == b.hash + a.popFirst + b.popLast + doAssert a == b + doAssert a.hash == b.hash + a.addLast 2 + doAssert a != b + doAssert a.hash != b.hash + b.addFirst 2 + doAssert a == b + doAssert a.hash == b.hash + + block: + var a, b = initDeque[int]() + for i in countDown(100, 1): + a.addFirst(i) + for i in 1..100: + b.addLast(i) + doAssert a == b + for i in 1..99: + a.popLast + let a1 = [1].toDeque + doAssert a == a1 + doAssert a.hash == a1.hash + var c = initDeque[int]() + c.addLast(1) + doAssert a == c + doAssert a.hash == c.hash static: main() main() diff --git a/tests/stdlib/tdiff.nim b/tests/stdlib/tdiff.nim index 694ac6198..132f7120b 100644 --- a/tests/stdlib/tdiff.nim +++ b/tests/stdlib/tdiff.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import experimental/diff import std/strutils +import std/assertions proc testHelper(f: seq[Item]): string = for it in f: diff --git a/tests/distros/tdistros_detect.nim b/tests/stdlib/tdistros_detect.nim index 9639cfeb9..1176c8993 100644 --- a/tests/distros/tdistros_detect.nim +++ b/tests/stdlib/tdistros_detect.nim @@ -1,9 +1,4 @@ -import distros - -discard """ - exitcode: 0 - output: "" -""" +import std/[assertions, distros] when defined(windows): doAssert detectOs(Windows) == true diff --git a/tests/stdlib/tdochelpers.nim b/tests/stdlib/tdochelpers.nim index 0ad49427c..4d532b5d0 100644 --- a/tests/stdlib/tdochelpers.nim +++ b/tests/stdlib/tdochelpers.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: ''' [Suite] Integration with Nim @@ -9,6 +10,7 @@ discard """ import ../../lib/packages/docutils/[rstast, rst, dochelpers] import unittest +import std/assertions proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind, arg: string) = @@ -201,3 +203,19 @@ suite "Integration with Nim": name: "Copyflag") check inputRst.fromRst == expected check inputMd.fromMd == expected + + test "prefixed module": + let inputRst = "`module std / paths`_" + let inputMd = "[module std / paths]" + let expected = LangSymbol(symKind: "module", + name: "std/paths") + check inputRst.fromRst == expected + check inputMd.fromMd == expected + + test "postfixed module": + let inputRst = "`std / paths module`_" + let inputMd = "[std / paths module]" + let expected = LangSymbol(symKind: "module", + name: "std/paths") + check inputRst.fromRst == expected + check inputMd.fromMd == expected diff --git a/tests/stdlib/teditdistance.nim b/tests/stdlib/teditdistance.nim index 433535635..14ba6df97 100644 --- a/tests/stdlib/teditdistance.nim +++ b/tests/stdlib/teditdistance.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/editdistance +import std/assertions doAssert editDistance("", "") == 0 doAssert editDistance("kitten", "sitting") == 3 # from Wikipedia diff --git a/tests/stdlib/tencodings.nim b/tests/stdlib/tencodings.nim index 8ca55dbd9..2f4daaba3 100644 --- a/tests/stdlib/tencodings.nim +++ b/tests/stdlib/tencodings.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/encodings +import std/assertions var fromGBK = open("utf-8", "gbk") var toGBK = open("gbk", "utf-8") @@ -96,3 +101,7 @@ block: doAssert orig == "\195\182\195\164\195\188\195\159" doAssert ibm850 == "\148\132\129\225" doAssert convert(ibm850, current, "ibm850") == orig + +block: # fixes about #23481 + doAssertRaises EncodingError: + discard open(destEncoding="this is a invalid enc") diff --git a/tests/stdlib/tenumerate.nim b/tests/stdlib/tenumerate.nim index 7a1c2d10a..2789ebe3a 100644 --- a/tests/stdlib/tenumerate.nim +++ b/tests/stdlib/tenumerate.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/enumerate +import std/assertions let a = @[1, 3, 5, 7] diff --git a/tests/stdlib/tenumutils.nim b/tests/stdlib/tenumutils.nim index 11142216c..2662a660d 100644 --- a/tests/stdlib/tenumutils.nim +++ b/tests/stdlib/tenumutils.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/enumutils from std/sequtils import toSeq +import std/assertions template main = block: # items @@ -33,5 +35,15 @@ template main = doAssert $b == "kb0" static: doAssert B.high.symbolName == "b2" + block: + type + Color = enum + Red = "red", Yellow = "yellow", Blue = "blue" + + var s = Red + doAssert symbolName(s) == "Red" + var x: range[Red..Blue] = Yellow + doAssert symbolName(x) == "Yellow" + static: main() main() diff --git a/tests/stdlib/tenvvars.nim b/tests/stdlib/tenvvars.nim index b39ce5f72..1a07f02b8 100644 --- a/tests/stdlib/tenvvars.nim +++ b/tests/stdlib/tenvvars.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" joinable: false targets: "c js cpp" """ @@ -7,6 +7,10 @@ discard """ import std/envvars from std/sequtils import toSeq import stdtest/testutils +import std/[assertions] + +when not defined(js): + import std/typedthreads # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386) const unicodeUtf8 = "\xc3\x86" @@ -45,9 +49,11 @@ template main = doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE") doAssert not existsEnv("NIM_TESTS_TOSENV_PUT") +static: main() main() when defined(windows): + import std/widestrs proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".} proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".} @@ -67,7 +73,7 @@ when not defined(js) and not defined(nimscript): doAssertRaises(OSError): delEnv("foo=bar") -when defined(windows): +when defined(windows) and not defined(nimscript): import std/encodings proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".} diff --git a/tests/stdlib/texitprocs.nim b/tests/stdlib/texitprocs.nim index 9d5378fe8..ea29d8f58 100644 --- a/tests/stdlib/texitprocs.nim +++ b/tests/stdlib/texitprocs.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" targets: "c cpp js" output: ''' ok4 diff --git a/tests/stdlib/tfdleak.nim b/tests/stdlib/tfdleak.nim index 79d7ee0d0..272a7507c 100644 --- a/tests/stdlib/tfdleak.nim +++ b/tests/stdlib/tfdleak.nim @@ -1,12 +1,15 @@ discard """ exitcode: 0 output: "" - matrix: "; -d:nimInheritHandles" + matrix: "; -d:nimInheritHandles; --mm:refc" joinable: false """ import os, osproc, strutils, nativesockets, net, selectors, memfiles, asyncdispatch, asyncnet + +import std/[assertions, syncio] + when defined(windows): import winlean @@ -56,7 +59,7 @@ proc isValidHandle(f: int): bool = proc main() = if paramCount() == 0: # Parent process - let f = system.open("__test_fdleak", fmReadWrite) + let f = syncio.open("__test_fdleak", fmReadWrite) defer: close f leakCheck(f.getOsFileHandle, "system.open()") diff --git a/tests/stdlib/tfdleak_multiple.nim b/tests/stdlib/tfdleak_multiple.nim index 22387607f..c26681217 100644 --- a/tests/stdlib/tfdleak_multiple.nim +++ b/tests/stdlib/tfdleak_multiple.nim @@ -3,6 +3,7 @@ joinable: false """ import os, osproc, strutils +import std/assertions const Iterations = 200 diff --git a/tests/stdlib/tfenv.nim b/tests/stdlib/tfenv.nim index 5bcd1ea7c..a486b8a9d 100644 --- a/tests/stdlib/tfenv.nim +++ b/tests/stdlib/tfenv.nim @@ -1,4 +1,5 @@ import std/fenv +import std/assertions func is_significant(x: float): bool = diff --git a/tests/stdlib/tfilesanddirs.nim b/tests/stdlib/tfilesanddirs.nim new file mode 100644 index 000000000..a1920d4f2 --- /dev/null +++ b/tests/stdlib/tfilesanddirs.nim @@ -0,0 +1,36 @@ +import std/[paths, files, dirs, appdirs] + +from stdtest/specialpaths import buildDir +import std/[syncio, assertions] + +block fileOperations: + let files = @[Path"these.txt", Path"are.x", Path"testing.r", Path"files.q"] + let dirs = @[Path"some", Path"created", Path"test", Path"dirs"] + + let dname = Path"__really_obscure_dir_name" + + createDir(dname.Path) + doAssert dirExists(Path(dname)) + + # Test creating files and dirs + for dir in dirs: + createDir(Path(dname/dir)) + doAssert dirExists(Path(dname/dir)) + + for file in files: + let fh = open(string(dname/file), fmReadWrite) # createFile + fh.close() + doAssert fileExists(Path(dname/file)) + +block: # getCacheDir + doAssert getCacheDir().dirExists + +block: # moveFile + let tempDir = getTempDir() / Path("D20221022T151608") + createDir(tempDir) + defer: removeDir(tempDir) + +block: # moveDir + let tempDir = getTempDir() / Path("D20220609T161443") + createDir(tempDir) + defer: removeDir(tempDir) diff --git a/tests/stdlib/tfrexp1.nim b/tests/stdlib/tfrexp1.nim index 85110231d..aa734ddac 100644 --- a/tests/stdlib/tfrexp1.nim +++ b/tests/stdlib/tfrexp1.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "js c cpp" """ import std/math +import std/assertions const manualTest = false diff --git a/tests/stdlib/tgenast.nim b/tests/stdlib/tgenast.nim index 0904b83dd..d99c9312e 100644 --- a/tests/stdlib/tgenast.nim +++ b/tests/stdlib/tgenast.nim @@ -1,8 +1,13 @@ +discard """ + matrix: "--mm:orc; --mm:refc" +""" + # xxx also test on js import std/genasts import std/macros from std/strformat import `&` +import std/assertions import ./mgenast proc main = diff --git a/tests/stdlib/tgetaddrinfo.nim b/tests/stdlib/tgetaddrinfo.nim index ed8ec8b68..3a90034c8 100644 --- a/tests/stdlib/tgetaddrinfo.nim +++ b/tests/stdlib/tgetaddrinfo.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" exitcode: 0 output: "" """ @@ -6,6 +7,7 @@ discard """ # bug: https://github.com/nim-lang/Nim/issues/10198 import nativesockets +import std/assertions block DGRAM_UDP: let aiList = getAddrInfo("127.0.0.1", 999.Port, AF_INET, SOCK_DGRAM, IPPROTO_UDP) diff --git a/tests/stdlib/tgetfileinfo.nim b/tests/stdlib/tgetfileinfo.nim index 099ce1c22..ae1480a4c 100644 --- a/tests/stdlib/tgetfileinfo.nim +++ b/tests/stdlib/tgetfileinfo.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: "pcDir\npcFile\npcLinkToDir\npcLinkToFile\n" joinable: false """ import os, strutils +import std/[syncio, assertions] # Cases # 1 - String : Existing File : Symlink true # 2 - String : Existing File : Symlink false @@ -126,10 +128,37 @@ proc testGetFileInfo = echo pcLinkToDir echo pcLinkToFile + doAssert dirInfo.isSpecial == false + doAssert fileInfo.isSpecial == false + when defined(posix): + doAssert linkDirInfo.isSpecial == false + doAssert linkFileInfo.isSpecial == false + removeDir(dirPath) removeFile(filePath) when defined(posix): removeFile(linkDirPath) removeFile(linkFilePath) + # Test that `isSpecial` is set correctly + block: + when defined(posix): + let + tmp = getTempDir() + fifoPath = tmp / "test-fifo" + linkFifoPath = tmp / "test-link-fifo" + + doAssert execShellCmd("mkfifo " & fifoPath) == 0 + createSymlink(fifoPath, linkFifoPath) + + let + fifoInfo = getFileInfo(fifoPath) + linkFifoInfo = getFileInfo(linkFifoPath) + + doAssert fifoInfo.isSpecial == true + doAssert linkFifoInfo.isSpecial == true + + removeFile(fifoPath) + removeFile(linkFifoPath) + testGetFileInfo() diff --git a/tests/stdlib/tgetprotobyname.nim b/tests/stdlib/tgetprotobyname.nim index 014c18845..1fc060ffe 100644 --- a/tests/stdlib/tgetprotobyname.nim +++ b/tests/stdlib/tgetprotobyname.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import nativesockets +import std/assertions doAssert getProtoByName("ipv6") == 41 doAssert getProtoByName("tcp") == 6 diff --git a/tests/stdlib/tglobs.nim b/tests/stdlib/tglobs.nim index 739a127f8..4aa21992c 100644 --- a/tests/stdlib/tglobs.nim +++ b/tests/stdlib/tglobs.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/private/globs +import std/assertions template main = when defined(windows): diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim index 46576ef12..4555fbcb3 100644 --- a/tests/stdlib/thashes.nim +++ b/tests/stdlib/thashes.nim @@ -1,9 +1,10 @@ discard """ - targets: "c cpp js" + matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:on; --backend:c -d:nimStringHash2; --backend:cpp -d:nimStringHash2; --backend:js -d:nimStringHash2" """ import std/hashes from stdtest/testutils import disableVm, whenVMorJs +import std/assertions when not defined(js) and not defined(cpp): block: @@ -28,6 +29,10 @@ block hashes: const wy123 = hashWangYi1(123) doAssert wy123 != 0 doAssert hashWangYi1(123) == wy123 + const wyNeg123 = hashWangYi1(-123) + doAssert wyNeg123 != 0 + when not defined(js): # TODO: fixme it doesn't work for JS + doAssert hashWangYi1(-123) == wyNeg123 # "hashIdentity value incorrect at 456" @@ -41,20 +46,31 @@ block hashes: else: doAssert hashWangYi1(456) == -6421749900419628582 +template jsNoInt64: untyped = + when defined js: + when compiles(compileOption("jsbigint64")): + when not compileOption("jsbigint64"): true + else: false + else: false + else: false +const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false) + block empty: + const emptyStrHash = # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash] + when sHash2: 0 else: cast[Hash](-7286425919675154353i64) var a = "" b = newSeq[char]() c = newSeq[int]() d = cstring"" e = "abcd" - doAssert hash(a) == 0 - doAssert hash(b) == 0 + doAssert hash(a) == emptyStrHash + doAssert hash(b) == emptyStrHash doAssert hash(c) == 0 - doAssert hash(d) == 0 + doAssert hash(d) == emptyStrHash doAssert hashIgnoreCase(a) == 0 doAssert hashIgnoreStyle(a) == 0 - doAssert hash(e, 3, 2) == 0 + doAssert hash(e, 3, 2) == emptyStrHash block sameButDifferent: doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) @@ -88,7 +104,10 @@ block largeSize: # longer than 4 characters proc main() = doAssert hash(0.0) == hash(0) # bug #16061 - doAssert hash(cstring"abracadabra") == 97309975 + when not sHash2: # Hash=int=4B on js even w/--jsbigint64:on => cast[Hash] + doAssert hash(cstring"abracadabra") == cast[Hash](-1119910118870047694i64) + else: + doAssert hash(cstring"abracadabra") == 97309975 doAssert hash(cstring"abracadabra") == hash("abracadabra") when sizeof(int) == 8 or defined(js): diff --git a/tests/stdlib/theapqueue.nim b/tests/stdlib/theapqueue.nim index 3b68166af..afb09c7e3 100644 --- a/tests/stdlib/theapqueue.nim +++ b/tests/stdlib/theapqueue.nim @@ -1,5 +1,9 @@ -import std/heapqueue +discard """ + matrix: "--mm:refc; --mm:orc" +""" +import std/heapqueue +import std/assertions proc toSortedSeq[T](h: HeapQueue[T]): seq[T] = var tmp = h diff --git a/tests/stdlib/thighlite.nim b/tests/stdlib/thighlite.nim index 5134215c1..0cd334254 100644 --- a/tests/stdlib/thighlite.nim +++ b/tests/stdlib/thighlite.nim @@ -1,6 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" import unittest, strutils import ../../lib/packages/docutils/highlite +import std/objectdollar block: # Nim tokenizing test "string literals and escape seq": @@ -30,3 +34,12 @@ block: # Cmd (shell) tokenizing ("file.nim", gtIdentifier), ("\n", gtWhitespace), ("out: file [SuccessX]", gtProgramOutput) ]) + +block: # bug #21232 + let code = "/" + var toknizr: GeneralTokenizer + + initGeneralTokenizer(toknizr, code) + + getNextToken(toknizr, langC) + check $toknizr == """(kind: gtOperator, start: 0, length: 1, buf: "/", pos: 1, state: gtEof, lang: langC)""" diff --git a/tests/stdlib/thtmlparser.nim b/tests/stdlib/thtmlparser.nim index f35785b25..853a1c0cc 100644 --- a/tests/stdlib/thtmlparser.nim +++ b/tests/stdlib/thtmlparser.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" output: ''' true @@ -11,7 +12,7 @@ import htmlparser import xmltree import strutils from streams import newStringStream - +import std/assertions block t2813: const diff --git a/tests/stdlib/thttpclient.nim b/tests/stdlib/thttpclient.nim index 8563a0c26..0bd479670 100644 --- a/tests/stdlib/thttpclient.nim +++ b/tests/stdlib/thttpclient.nim @@ -14,6 +14,9 @@ from net import TimeoutError import nativesockets, os, httpclient, asyncdispatch +import std/[assertions, syncio] +from stdtest/testutils import enableRemoteNetworking + const manualTests = false proc makeIPv6HttpServer(hostname: string, port: Port, @@ -50,12 +53,13 @@ proc asyncTest() {.async.} = doAssert("<title>Example Domain</title>" in body) resp = await client.request("http://example.com/404") - doAssert(resp.code.is4xx) - doAssert(resp.code == Http404) - doAssert(resp.status == $Http404) + doAssert(resp.code.is4xx or resp.code.is5xx) + doAssert(resp.code == Http404 or resp.code == Http500) + doAssert(resp.status == $Http404 or resp.status == $Http500) - resp = await client.request("https://google.com/") - doAssert(resp.code.is2xx or resp.code.is3xx) + when false: # occasionally does not give success code + resp = await client.request("https://google.com/") + doAssert(resp.code.is2xx or resp.code.is3xx) # getContent try: @@ -111,12 +115,13 @@ proc syncTest() = doAssert("<title>Example Domain</title>" in resp.body) resp = client.request("http://example.com/404") - doAssert(resp.code.is4xx) - doAssert(resp.code == Http404) - doAssert(resp.status == $Http404) + doAssert(resp.code.is4xx or resp.code.is5xx) + doAssert(resp.code == Http404 or resp.code == Http500) + doAssert(resp.status == $Http404 or resp.status == $Http500) - resp = client.request("https://google.com/") - doAssert(resp.code.is2xx or resp.code.is3xx) + when false: # occasionally does not give success code + resp = client.request("https://google.com/") + doAssert(resp.code.is2xx or resp.code.is3xx) # getContent try: @@ -176,5 +181,7 @@ proc ipv6Test() = client.close() ipv6Test() -syncTest() -waitFor(asyncTest()) + +when enableRemoteNetworking: + syncTest() + waitFor(asyncTest()) diff --git a/tests/stdlib/thttpclient_ssl.nim b/tests/stdlib/thttpclient_ssl.nim index 3acdacfe3..6b963f029 100644 --- a/tests/stdlib/thttpclient_ssl.nim +++ b/tests/stdlib/thttpclient_ssl.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim $target --threads:on -d:ssl $options $file" + cmd: "nim $target --mm:refc -d:ssl $options $file" disabled: "openbsd" """ @@ -13,9 +13,12 @@ discard """ ## Test with: ## ./bin/nim c -d:ssl -p:. --threads:on -r tests/stdlib/thttpclient_ssl.nim -when not defined(windows): - # Disabled on Windows due to old OpenSSL version +from stdtest/testutils import disableSSLTesting + +when not defined(windows) and not disableSSLTesting(): + # Disabled on Windows due to old OpenSSL version + import std/[formatfloat, syncio] import httpclient, net, diff --git a/tests/stdlib/thttpclient_standalone.nim b/tests/stdlib/thttpclient_standalone.nim index 362b1cb86..2f432eede 100644 --- a/tests/stdlib/thttpclient_standalone.nim +++ b/tests/stdlib/thttpclient_standalone.nim @@ -4,6 +4,8 @@ discard """ import asynchttpserver, httpclient, asyncdispatch, strutils, net +import std/assertions + block: # bug #16436 proc startServer(): AsyncHttpServer = result = newAsyncHttpServer() diff --git a/tests/stdlib/thttpcore.nim b/tests/stdlib/thttpcore.nim index 6f88e9536..93e7d85c6 100644 --- a/tests/stdlib/thttpcore.nim +++ b/tests/stdlib/thttpcore.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import httpcore, strutils +import std/assertions block: block HttpCode: diff --git a/tests/stdlib/timportutils.nim b/tests/stdlib/timportutils.nim index be912e702..672092282 100644 --- a/tests/stdlib/timportutils.nim +++ b/tests/stdlib/timportutils.nim @@ -1,4 +1,8 @@ -import std/importutils +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/[importutils, assertions] import stdtest/testutils import mimportutils @@ -134,5 +138,14 @@ template main = privateAccess PtA a.ha1 == 0 + block: + privateAccess PityRef + let x = PityRef[int](a: 1) # works + doAssert x.a == 1 + + privateAccess Hope + let y = Hope[int](a: 1) + doAssert y.a == 1 + static: main() main() diff --git a/tests/stdlib/tio.nim b/tests/stdlib/tio.nim index 0da64f9c2..80a119763 100644 --- a/tests/stdlib/tio.nim +++ b/tests/stdlib/tio.nim @@ -1,7 +1,12 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + # xxx move to here other tests that belong here; io is a proper module import std/os from stdtest/specialpaths import buildDir +import std/[assertions, syncio] block: # readChars let file = buildDir / "D20201118T205105.txt" @@ -35,3 +40,21 @@ block: # readChars break doAssert n2s == @[2,2,2,1,0] doAssert s2 == s + + +import std/strutils + +block: # bug #21273 + let FILE = buildDir / "D20220119T134305.txt" + + let hex = "313632313920313632343720313632353920313632363020313632393020323035363520323037323120323131353020323239393820323331303520323332313020323332343820323332363820" + + + writeFile FILE, parseHexStr(hex) + + doAssert readFile(FILE).toHex == hex + + let f = open(FILE) + var s = newString(80) + while f.readLine(s): + doAssert s.toHex == hex diff --git a/tests/stdlib/tisolation.nim b/tests/stdlib/tisolation.nim index c3857f483..18b83ea2e 100644 --- a/tests/stdlib/tisolation.nim +++ b/tests/stdlib/tisolation.nim @@ -4,7 +4,7 @@ discard """ """ import std/[isolation, json] - +import std/[assertions, objectdollar] proc main(moveZeroesOut: static bool) = diff --git a/tests/stdlib/tjsbigints.nim b/tests/stdlib/tjsbigints.nim index fcf699c67..29b0ac3e7 100644 --- a/tests/stdlib/tjsbigints.nim +++ b/tests/stdlib/tjsbigints.nim @@ -2,7 +2,7 @@ discard """ targets: "js" """ -import std/jsbigints +import std/[jsbigints, assertions] let big1: JsBigInt = big"2147483647" diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index 336558ff3..e425501f6 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -1,5 +1,5 @@ discard """ - targets: "c cpp js" + matrix: "; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ @@ -8,11 +8,13 @@ Note: Macro tests are in tests/stdlib/tjsonmacro.nim ]# import std/[json,parsejson,strutils] +import std/private/jsutils from std/math import isNaN when not defined(js): import std/streams import stdtest/testutils from std/fenv import epsilon +import std/[assertions, objectdollar] proc testRoundtrip[T](t: T, expected: string) = # checks that `T => json => T2 => json2` is such that json2 = json @@ -312,7 +314,8 @@ block: # bug #17383 else: testRoundtrip(int.high): "9223372036854775807" testRoundtrip(uint.high): "18446744073709551615" - when not defined(js): + whenJsNoBigInt64: discard + do: testRoundtrip(int64.high): "9223372036854775807" testRoundtrip(uint64.high): "18446744073709551615" diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 9b59c7dc3..5a1b4b294 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -1,9 +1,11 @@ discard """ output: "" + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import json, strutils, options, tables +import std/assertions # The definition of the `%` proc needs to be here, since the `% c` calls below # can only find our custom `%` proc for `Pix` if defined in global scope. @@ -435,11 +437,7 @@ proc testJson() = block: let s = """{"a": 1, "b": 2}""" let t = parseJson(s).to(Table[string, int]) - when not defined(js): - # For some reason on the JS backend `{"b": 2, "a": 0}` is - # sometimes the value of `t`. This needs investigation. I can't - # reproduce it right now in an isolated test. - doAssert t["a"] == 1 + doAssert t["a"] == 1 doAssert t["b"] == 2 block: diff --git a/tests/stdlib/tjsonutils.nim b/tests/stdlib/tjsonutils.nim index d5809ee73..9acf4c9e5 100644 --- a/tests/stdlib/tjsonutils.nim +++ b/tests/stdlib/tjsonutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ @@ -7,6 +8,7 @@ import std/json from std/math import isNaN, signbit from std/fenv import epsilon from stdtest/testutils import whenRuntimeJs +import std/[assertions, objectdollar] proc testRoundtrip[T](t: T, expected: string) = # checks that `T => json => T2 => json2` is such that json2 = json @@ -59,8 +61,7 @@ template fn() = testRoundtrip(pointer(nil)): """0""" testRoundtrip(cast[pointer](nil)): """0""" - # causes workaround in `fromJson` potentially related to - # https://github.com/nim-lang/Nim/issues/12282 + # refs bug #9423 testRoundtrip(Foo(1.5)): """1.5""" block: # OrderedTable @@ -409,6 +410,39 @@ template fn() = doAssert foo.c == 0 doAssert foo.c0 == 42 + + block testInvalidTupleLength: + let json = parseJson("[0]") + # Should raise ValueError instead of index error + doAssertRaises(ValueError): + discard json.jsonTo((int, int)) + + type + InnerEnum = enum + A + B + C + InnerObject = object + x: string + y: InnerEnum + + block testOptionsArePassedWhenDeserialising: + let json = parseJson("""{"x": "hello"}""") + let inner = json.jsonTo(Option[InnerObject], Joptions(allowMissingKeys: true)) + doAssert inner.isSome() + doAssert inner.get().x == "hello" + doAssert inner.get().y == A + + block testOptionsArePassedWhenSerialising: + let inner = some InnerObject(x: "hello", y: A) + let json = inner.toJson(ToJsonOptions(enumMode: joptEnumSymbol)) + doAssert $json == """{"x":"hello","y":"A"}""" + + block: # bug #21638 + type Something = object + + doAssert "{}".parseJson.jsonTo(Something) == Something() + when false: ## TODO: Implement support for nested variant objects allowing the tests ## bellow to pass. diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim index 00c5b1a27..5993278c7 100644 --- a/tests/stdlib/tlists.nim +++ b/tests/stdlib/tlists.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[lists, sequtils] +import std/assertions const data = [1, 2, 3, 4, 5, 6] diff --git a/tests/stdlib/tlocks.nim b/tests/stdlib/tlocks.nim index 0815c5d01..1c5f67119 100644 --- a/tests/stdlib/tlocks.nim +++ b/tests/stdlib/tlocks.nim @@ -1,10 +1,11 @@ discard """ targets: "c cpp js" - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" """ #bug #6049 import uselocks +import std/assertions var m = createMyType[int]() doAssert m.use() == 3 diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim index 299eac49b..06a9a9c27 100644 --- a/tests/stdlib/tmacros.nim +++ b/tests/stdlib/tmacros.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + #[ xxx macros tests need to be reorganized to makes sure each API is tested once See also: @@ -5,6 +9,7 @@ See also: ]# import std/macros +import std/assertions block: # hasArgOfName macro m(u: untyped): untyped = @@ -144,3 +149,201 @@ block: # extractDocCommentsAndRunnables proc c() {.checkComments("Hello world").} = ## Hello world + +block: # bug #19020 + type + foo = object + + template typ(T:typedesc) {.pragma.} + + proc bar() {.typ: foo.} = discard + + static: + doAssert $bar.getCustomPragmaVal(typ) == "foo" + doAssert $bar.getCustomPragmaVal(typ) == "foo" + +block hasCustomPragmaGeneric: + template examplePragma() {.pragma.} + type + Foo[T] {.examplePragma.} = object + x {.examplePragma.}: T + var f: Foo[string] + doAssert f.hasCustomPragma(examplePragma) + doAssert f.x.hasCustomPragma(examplePragma) + +block getCustomPragmaValGeneric: + template examplePragma(x: int) {.pragma.} + type + Foo[T] {.examplePragma(42).} = object + x {.examplePragma(25).}: T + var f: Foo[string] + doAssert f.getCustomPragmaVal(examplePragma) == 42 + doAssert f.x.getCustomPragmaVal(examplePragma) == 25 + +block: # bug #21326 + macro foo(body: untyped): untyped = + let a = body.lineInfoObj() + let aLit = a.newLit + result = quote do: + doAssert $`a` == $`aLit` + + foo: + let c = 1 + + template name(a: LineInfo): untyped = + discard a # `aLit` works though + + macro foo3(body: untyped): untyped = + let a = body.lineInfoObj() + # let ax = newLit(a) + result = getAst(name(a)) + + foo3: + let c = 1 + +block: # bug #7375 + macro fails(b: static[bool]): untyped = + doAssert b == false + result = newStmtList() + + macro foo(): untyped = + + var b = false + + ## Fails + result = quote do: + fails(`b`) + + foo() + + macro someMacro(): untyped = + template tmpl(boolean: bool) = + when boolean: + discard "it's true!" + else: + doAssert false + result = getAst(tmpl(true)) + + someMacro() + +block: + macro foo(): untyped = + result = quote do: `littleEndian` + + doAssert littleEndian == foo() + +block: + macro eqSym(x, y: untyped): untyped = + let eq = $x == $y # Unfortunately eqIdent compares to string. + result = quote do: `eq` + + var r, a, b: int + + template fma(result: var int, a, b: int, op: untyped) = + # fused multiple-add + when eqSym(op, `+=`): + discard "+=" + else: + discard "+" + + fma(r, a, b, `+=`) + +block: + template test(boolArg: bool) = + static: + doAssert typeof(boolArg) is bool + let x: bool = boolArg # compile error here, because boolArg became an int + + macro testWrapped1(boolArg: bool): untyped = + # forwarding boolArg directly works + result = getAst(test(boolArg)) + + macro testWrapped2(boolArg: bool): untyped = + # forwarding boolArg via a local variable also works + let b = boolArg + result = getAst(test(b)) + + macro testWrapped3(boolArg: bool): untyped = + # but using a literal `true` as a local variable will be converted to int + let b = true + result = getAst(test(b)) + + test(true) # ok + testWrapped1(true) # ok + testWrapped2(true) # ok + testWrapped3(true) + +block: + macro foo(): untyped = + var s = { 'a', 'b' } + quote do: + let t = `s` + doAssert $typeof(t) == "set[char]" + + foo() + +block: # bug #9607 + proc fun1(info:LineInfo): string = "bar" + proc fun2(info:int): string = "bar" + + macro echoL(args: varargs[untyped]): untyped = + let info = args.lineInfoObj + let fun1 = bindSym"fun1" + let fun2 = bindSym"fun2" + + # this would work instead + # result = newCall(bindSym"fun2", info.line.newLit) + + result = quote do: + + # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil + `fun1`(`info`) + + macro echoM(args: varargs[untyped]): untyped = + let info = args.lineInfoObj + let fun1 = bindSym"fun1" + let fun2 = bindSym"fun2" + + # this would work instead + # result = newCall(bindSym"fun2", info.line.newLit) + + result = quote do: + + # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil + `fun2`(`info`.line) + + + doAssert echoL() == "bar" + doAssert echoM() == "bar" + +block: + macro hello[T](x: T): untyped = + result = quote do: + let m: `T` = `x` + discard m + + hello(12) + +block: + proc hello(x: int, y: typedesc) = + discard + + macro main = + let x = 12 + result = quote do: + `hello`(12, type(x)) + + main() + +block: # bug #22947 + macro bar[N: static int](a: var array[N, int]) = + result = quote do: + for i in 0 ..< `N`: + `a`[i] = i + + func foo[N: static int](a: var array[N, int]) = + bar(a) + + + var a: array[4, int] + foo(a) diff --git a/tests/stdlib/tmarshal.nim b/tests/stdlib/tmarshal.nim index 6b71e3beb..32991ccc9 100644 --- a/tests/stdlib/tmarshal.nim +++ b/tests/stdlib/tmarshal.nim @@ -3,6 +3,7 @@ discard """ """ import std/marshal +import std/[assertions, objectdollar, streams] # TODO: add static tests @@ -165,6 +166,46 @@ block: let a: ref A = new(B) doAssert $$a[] == "{}" # not "{f: 0}" +# bug #16496 +block: + type + A = ref object + data: seq[int] + + B = ref object + x: A + let o = A(data: @[1, 2, 3, 4]) + let s1 = @[B(x: o), B(x: o)] + let m = $$ s1 + let s2 = to[seq[B]](m) + doAssert s2[0].x.data == s2[1].x.data + doAssert s1[0].x.data == s2[1].x.data + + +block: + type + Obj = ref object + i: int + b: bool + + let + strm = newStringStream() + + var + o = Obj(i: 1, b: false) + t1 = @[o, o] + t2: seq[Obj] + + doAssert t1[0] == t1[1] + + strm.store(t1) + strm.setPosition(0) + strm.load(t2) + strm.close() + + doAssert t2[0] == t2[1] + + template checkMarshal(data: typed) = let orig = data let m = $$orig diff --git a/tests/stdlib/tmarshalsegfault.nim b/tests/stdlib/tmarshalsegfault.nim new file mode 100644 index 000000000..71f2766c8 --- /dev/null +++ b/tests/stdlib/tmarshalsegfault.nim @@ -0,0 +1,54 @@ +# issue #12405 + +import std/[marshal, streams, times, tables, os, assertions] + +type AiredEpisodeState * = ref object + airedAt * : DateTime + tvShowId * : string + seasonNumber * : int + number * : int + title * : string + +type ShowsWatchlistState * = ref object + aired * : seq[AiredEpisodeState] + +type UiState * = ref object + shows: ShowsWatchlistState + +# Helpers to marshal and unmarshal +proc load * ( state : var UiState, file : string ) = + var strm = newFileStream( file, fmRead ) + + strm.load( state ) + + strm.close() + +proc store * ( state : UiState, file : string ) = + var strm = newFileStream( file, fmWrite ) + + strm.store( state ) + + strm.close() + +# 1. We fill the state initially +var state : UiState = UiState( shows: ShowsWatchlistState( aired: @[] ) ) + +# VERY IMPORTANT: For some reason, small numbers (like 2 or 3) don't trigger the bug. Anything above 7 or 8 on my machine triggers though +for i in 0..30: + var episode = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" ) + + state.shows.aired.add( episode ) + +# 2. Store it in a file with the marshal module, and then load it back up +store( state, "tmarshalsegfault_data" ) +load( state, "tmarshalsegfault_data" ) +removeFile("tmarshalsegfault_data") + +# 3. VERY IMPORTANT: Without this line, for some reason, everything works fine +state.shows.aired[ 0 ] = AiredEpisodeState( airedAt: now(), tvShowId: "1", seasonNumber: 1, number: 1, title: "string" ) + +# 4. And formatting the airedAt date will now trigger the exception +for ep in state.shows.aired: + let x = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")" + let y = $ep.seasonNumber & "x" & $ep.number & " (" & $ep.airedAt & ")" + doAssert x == y diff --git a/tests/stdlib/tmath.nim b/tests/stdlib/tmath.nim index 5e501c09b..22e5f7d88 100644 --- a/tests/stdlib/tmath.nim +++ b/tests/stdlib/tmath.nim @@ -1,12 +1,14 @@ discard """ targets: "c cpp js" - matrix:"; -d:danger" + matrix:"; -d:danger; --mm:refc" """ # xxx: there should be a test with `-d:nimTmathCase2 -d:danger --passc:-ffast-math`, # but it requires disabling certain lines with `when not defined(nimTmathCase2)` import std/math +import std/assertions + # Function for approximate comparison of floats proc `==~`(x, y: float): bool = abs(x - y) < 1e-9 @@ -184,7 +186,22 @@ template main() = when not defined(nimTmathCase2): doAssert classify(trunc(f_nan.float32)) == fcNan doAssert classify(trunc(0.0'f32)) == fcZero - + + block: # divmod + doAssert divmod(int.high, 1) == (int.high, 0) + doAssert divmod(-1073741823, 17) == (-63161283, -12) + doAssert divmod(int32.high, 1.int32) == (int32.high, 0.int32) + doAssert divmod(1073741823.int32, 5.int32) == (214748364.int32, 3.int32) + doAssert divmod(4611686018427387903.int64, 5.int64) == (922337203685477580.int64, 3.int64) + when not defined(js) and (not compileOption("panics")) and compileOption("overflowChecks"): + when nimvm: + discard # cannot catch OverflowDefect here + else: + doAssertRaises(OverflowDefect, (discard divmod(cint.low, -1.cint))) + doAssertRaises(OverflowDefect, (discard divmod(clong.low, -1.clong))) + doAssertRaises(OverflowDefect, (discard divmod(clonglong.low, -1.clonglong))) + doAssertRaises(DivByZeroDefect, (discard divmod(1, 0))) + block: # log doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0) doAssert log2(8.0'f64) == 3.0'f64 @@ -437,6 +454,20 @@ template main() = doAssert lgamma(-0.0) == Inf doAssert lgamma(-1.0) == Inf - static: main() main() + +when not defined(js) and not defined(danger): + block: # bug #21792 + block: + type Digit = 0..9 + var x = [Digit 4, 7] + + doAssertRaises(RangeDefect): + discard sum(x) + + block: + var x = [int8 124, 127] + + doAssertRaises(OverflowDefect): + discard sum(x) diff --git a/tests/stdlib/tmd5.nim b/tests/stdlib/tmd5.nim deleted file mode 100644 index 4017ac677..000000000 --- a/tests/stdlib/tmd5.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - targets: "c cpp js" -""" - -import md5 - -proc main() {.raises: [].} = - doAssert(getMD5("Franz jagt im komplett verwahrlosten Taxi quer durch Bayern") == - "a3cca2b2aa1e3b5b3b5aad99a8529074") - doAssert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") == - "7e716d0e702df0505fc72e2b89467910") - doAssert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e") - -main() - -static: main() diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim index 21a65369f..33657256c 100644 --- a/tests/stdlib/tmemfiles1.nim +++ b/tests/stdlib/tmemfiles1.nim @@ -1,4 +1,6 @@ import memfiles, os +import std/syncio + var mm: MemFile fn = "test.mmap" diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim index 1b249898e..c79f85ebf 100644 --- a/tests/stdlib/tmemfiles2.nim +++ b/tests/stdlib/tmemfiles2.nim @@ -4,6 +4,9 @@ discard """ Half read size: 10 Data: Hello''' """ import memfiles, os +import std/syncio + + const fn = "test.mmap" var @@ -12,8 +15,9 @@ var if fileExists(fn): removeFile(fn) -# Create a new file, data all zeros -mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20) +# Create a new file, data all zeros, starting at size 10 +mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 10, allowRemap=true) +mm.resize 20 # resize up to 20 mm.close() # read, change diff --git a/tests/stdlib/tmemlinesBuf.nim b/tests/stdlib/tmemlinesBuf.nim index 3f0bd5182..7bd89d4f2 100644 --- a/tests/stdlib/tmemlinesBuf.nim +++ b/tests/stdlib/tmemlinesBuf.nim @@ -1,4 +1,4 @@ -import memfiles +import std/[memfiles, assertions] var inp = memfiles.open("tests/stdlib/tmemlinesBuf.nim") var buffer: string = "" var lineCount = 0 diff --git a/tests/stdlib/tmemmapstreams.nim b/tests/stdlib/tmemmapstreams.nim index dd011d777..9cfae62c7 100644 --- a/tests/stdlib/tmemmapstreams.nim +++ b/tests/stdlib/tmemmapstreams.nim @@ -12,6 +12,8 @@ Readed line: Hello! Position after reading line: 7''' """ import os, streams, memfiles +import std/syncio + const fn = "test.mmapstream" var diff --git a/tests/stdlib/tmersenne.nim b/tests/stdlib/tmersenne.nim index 54eb7b216..64450a045 100644 --- a/tests/stdlib/tmersenne.nim +++ b/tests/stdlib/tmersenne.nim @@ -1,4 +1,5 @@ import std/mersenne +import std/assertions template main() = var mt = newMersenneTwister(2525) diff --git a/tests/stdlib/tmget.nim b/tests/stdlib/tmget.nim index 52e61fd24..f41963f02 100644 --- a/tests/stdlib/tmget.nim +++ b/tests/stdlib/tmget.nim @@ -1,16 +1,21 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''Can't access 6 10 11 +2 Can't access 6 10 11 +2 Can't access 6 10 11 +2 Can't access 6 10 11 +2 0 10 11 @@ -40,6 +45,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = newTable[int, int]() @@ -52,6 +60,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = initOrderedTable[int, int]() @@ -64,6 +75,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = newOrderedTable[int, int]() @@ -76,6 +90,9 @@ block: x[5] += 1 var c = x[5] echo c + x.mgetOrPut(7).inc + x.mgetOrPut(7).inc + echo x[7] block: var x = initCountTable[int]() diff --git a/tests/stdlib/tmimetypes.nim b/tests/stdlib/tmimetypes.nim index 6435309e1..fd66ebd97 100644 --- a/tests/stdlib/tmimetypes.nim +++ b/tests/stdlib/tmimetypes.nim @@ -1,16 +1,28 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/mimetypes +import std/assertions + + template main() = var m = newMimetypes() doAssert m.getMimetype("mp4") == "video/mp4" doAssert m.getExt("application/json") == "json" + doAssert m.getMimetype("json") == "application/json" m.register("foo", "baa") doAssert m.getMimetype("foo") == "baa" + doAssert m.getMimetype("txt") == "text/plain" + doAssert m.getExt("text/plain") == "txt" # see also `runnableExamples`. # xxx we should have a way to avoid duplicating code between runnableExamples and tests + doAssert m.getMimetype("nim") == "text/nim" + doAssert m.getMimetype("nimble") == "text/nimble" + doAssert m.getMimetype("nimf") == "text/nim" + doAssert m.getMimetype("nims") == "text/nim" + static: main() main() diff --git a/tests/stdlib/tmisc_issues.nim b/tests/stdlib/tmisc_issues.nim index ed57818b1..86dcf4162 100644 --- a/tests/stdlib/tmisc_issues.nim +++ b/tests/stdlib/tmisc_issues.nim @@ -1,7 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ +import std/assertions + # bug #20227 type Data = object @@ -15,3 +18,22 @@ type var x: Object = Object(data: Test(Data(id: 12))) doAssert Data(x.data).id == 12 + +block: # bug #16771 + type A = object + n: int + + proc foo(a, b: var A) = + swap a, b + + var a, b: A + a.n = 42 + b.n = 1 + doAssert a.n == 42 + doAssert b.n == 1 + a.swap b + doAssert a.n == 1 + doAssert b.n == 42 + a.foo b + doAssert a.n == 42 + doAssert b.n == 1 diff --git a/tests/stdlib/tmitems.nim b/tests/stdlib/tmitems.nim index c0ced7cab..cc515a175 100644 --- a/tests/stdlib/tmitems.nim +++ b/tests/stdlib/tmitems.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''@[11, 12, 13] @[11, 12, 13] @[1, 3, 5] @@ -62,6 +63,7 @@ block: block: var x = "foobar" + prepareMutation(x) var y = cast[cstring](addr x[0]) for c in y.mitems: inc c @@ -75,6 +77,7 @@ block: block: var x = "foobar" + prepareMutation(x) var y = cast[cstring](addr x[0]) for i, c in y.mpairs: inc c, i diff --git a/tests/stdlib/tmonotimes.nim b/tests/stdlib/tmonotimes.nim index 2933bb686..1366dbfe9 100644 --- a/tests/stdlib/tmonotimes.nim +++ b/tests/stdlib/tmonotimes.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[monotimes, times] +import std/assertions let d = initDuration(nanoseconds = 10) let t1 = getMonoTime() diff --git a/tests/stdlib/tnativesockets.nim b/tests/stdlib/tnativesockets.nim index 6a1a00881..8242beb83 100644 --- a/tests/stdlib/tnativesockets.nim +++ b/tests/stdlib/tnativesockets.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/nativesockets import stdtest/testutils +import std/assertions block: let hostname = getHostname() diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim index 4ec62d88f..27a6ac49c 100644 --- a/tests/stdlib/tnet.nim +++ b/tests/stdlib/tnet.nim @@ -1,9 +1,11 @@ discard """ +matrix: "--mm:refc; --mm:orc" outputsub: "" """ import net, nativesockets import unittest +import std/assertions block: # isIpAddress tests block: # 127.0.0.1 is valid diff --git a/tests/stdlib/tnet_ll.nim b/tests/stdlib/tnet_ll.nim index 2d340cea8..199946482 100644 --- a/tests/stdlib/tnet_ll.nim +++ b/tests/stdlib/tnet_ll.nim @@ -1,5 +1,6 @@ discard """ action: run + matrix: "--mm:refc; --mm:orc" output: ''' [Suite] inet_ntop tests @@ -29,7 +30,7 @@ suite "inet_ntop tests": check: ip4.s_addr == 0x10111213'u32 var buff: array[0..255, char] - let r = inet_ntop(AF_INET, cast[pointer](ip4.s_addr.addr), buff[0].addr, buff.len.int32) + let r = inet_ntop(AF_INET, cast[pointer](ip4.s_addr.addr), cast[cstring](buff[0].addr), buff.len.int32) let res = if r == nil: "" else: $r check: res == "19.18.17.16" @@ -41,7 +42,7 @@ suite "inet_ntop tests": var ip6 = [0x1000'u16, 0x1001, 0x2000, 0x2001, 0x3000, 0x3001, 0x4000, 0x4001] var buff: array[0..255, char] - let r = inet_ntop(AF_INET6, cast[pointer](ip6[0].addr), buff[0].addr, buff.len.int32) + let r = inet_ntop(AF_INET6, cast[pointer](ip6[0].addr), cast[cstring](buff[0].addr), buff.len.int32) let res = if r == nil: "" else: $r check: not ipv6Support or res == "10:110:20:120:30:130:40:140" diff --git a/tests/stdlib/tnetbind.nim b/tests/stdlib/tnetbind.nim index 734b6c5e7..84f9ac464 100644 --- a/tests/stdlib/tnetbind.nim +++ b/tests/stdlib/tnetbind.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" joinable: false """ diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim index 3a80df19f..ae654aed9 100644 --- a/tests/stdlib/tnetconnect.nim +++ b/tests/stdlib/tnetconnect.nim @@ -1,9 +1,11 @@ discard """ + disabled: "i386" matrix: "-d:ssl" """ import std/net from std/strutils import `%` +from stdtest/testutils import enableRemoteNetworking # bug #15215 proc test() = @@ -24,4 +26,5 @@ proc test() = except TimeoutError, OSError: fn("www.google.com") -test() +when enableRemoteNetworking: + test() diff --git a/tests/stdlib/tnetdial.nim b/tests/stdlib/tnetdial.nim index b836fb78d..a1e147ad5 100644 --- a/tests/stdlib/tnetdial.nim +++ b/tests/stdlib/tnetdial.nim @@ -5,6 +5,7 @@ discard """ """ import os, net, nativesockets, asyncdispatch +import std/[assertions, typedthreads] ## Test for net.dial diff --git a/tests/stdlib/tnre.nim b/tests/stdlib/tnre.nim index f13c16052..3b40e9e83 100644 --- a/tests/stdlib/tnre.nim +++ b/tests/stdlib/tnre.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" # Since the tests for nre are all bundled together we treat failure in one test as an nre failure # When running 'testament/tester' a failed check() in the test suite will cause the exit # codes to differ and be reported as a failure diff --git a/tests/stdlib/tntpath.nim b/tests/stdlib/tntpath.nim index 39798d816..8efdd6bd0 100644 --- a/tests/stdlib/tntpath.nim +++ b/tests/stdlib/tntpath.nim @@ -1,7 +1,9 @@ discard """ + matrix: "--mm:refc; --mm:orc" """ import std/private/ntpath +import std/assertions block: # From Python's `Lib/test/test_ntpath.py` doAssert splitDrive(r"c:\foo\bar") == (r"c:", r"\foo\bar") diff --git a/tests/stdlib/toids.nim b/tests/stdlib/toids.nim index f162dbe57..dd5b84c51 100644 --- a/tests/stdlib/toids.nim +++ b/tests/stdlib/toids.nim @@ -1,6 +1,15 @@ -import std/oids +discard """ + matrix: "--mm:refc; --mm:orc" +""" +import std/oids +import std/assertions block: # genOid let x = genOid() doAssert ($x).len == 24 + +block: + let x = genOid() + let y = parseOid(cstring($x)) + doAssert x == y diff --git a/tests/stdlib/topenssl.nim b/tests/stdlib/topenssl.nim index 4c38b4216..af259627f 100644 --- a/tests/stdlib/topenssl.nim +++ b/tests/stdlib/topenssl.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wordwrap import openssl +import std/assertions const PubKey = r"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAknKWvrdnncCIzBnIGrZ5qtZrPH+Yo3t7ag9WZIu6Gmc/JgIDDaZhJeyGW0YSnifeAEhooWvM4jDWhTEARzktalSHqYtmwI/1Oxwp6NTYH8akMe2LCpZ5pX9FVA6m9o2tkbdXatbDKRqeD4UA8Ow7Iyrdo6eb1SU8vk+26i+uXHTtsb25p8uf2ppOJrJCy+1vr8Gsnuwny1UdoYZTxMsxRFPf+UX/LrSXMHVq/oPVa3SJ4VHMpYrG/httAugVP6K58xiZ93jst63/dd0JL85mWJu1uS3uz92aL5O97xzth3wR4BbdmDUlN4LuTIwi6DtEcC7gUOTnOzH4zgp2b5RyHwIDAQAB" const PrivateKey = r"MIIEpAIBAAKCAQEAknKWvrdnncCIzBnIGrZ5qtZrPH+Yo3t7ag9WZIu6Gmc/JgIDDaZhJeyGW0YSnifeAEhooWvM4jDWhTEARzktalSHqYtmwI/1Oxwp6NTYH8akMe2LCpZ5pX9FVA6m9o2tkbdXatbDKRqeD4UA8Ow7Iyrdo6eb1SU8vk+26i+uXHTtsb25p8uf2ppOJrJCy+1vr8Gsnuwny1UdoYZTxMsxRFPf+UX/LrSXMHVq/oPVa3SJ4VHMpYrG/httAugVP6K58xiZ93jst63/dd0JL85mWJu1uS3uz92aL5O97xzth3wR4BbdmDUlN4LuTIwi6DtEcC7gUOTnOzH4zgp2b5RyHwIDAQABAoIBACSOxmLFlfAjaALLTNCeTLEA5bQshgYJhT1sprxixQpiS7lJN0npBsdYzBFs5KjmetzHNpdVOcgdOO/204L0Gwo4H8WLLxNS3HztAulEeM813zc3fUYfWi6eHshk//j8VR/TDNd21TElm99z7FA4KGsXAE0iQhxrN0aqz5aWYIhjprtHA5KxXIiESnTkof5Cud8oXEnPiwPGNhq93QeQzh7xQIKSaDKBcdAa6edTFhzc4RLUQRfrik/GqJzouEDQ9v6H/uiOLTB3FxxwErQIf6dvSVhD9gs1nSLQfyj3S2Hxe9S2zglTl07EsawTQUxtVQkdZUOok67c7CPBxecZ2wECgYEA2c31gr/UJwczT+P/AE52GkHHETXMxqE3Hnh9n4CitfAFSD5X0VwZvGjZIlln2WjisTd92Ymf65eDylX2kCm93nzZ2GfXgS4zl4oY1N87+VeNQlx9f2+6GU7Hs0HFdfu8bGd+0sOuWA1PFqQCobxCACMPTkuzsG9M7knUTN59HS8CgYEArCEoP4ReYoOFveXUE0AteTPb4hryvR9VDEolP+LMoiPe8AzBMeB5fP493TPdjtnWmrPCXNLc7UAFSj2CZsRhau4PuiqnNrsb5iz/7iXVl3E8wZvS4w7WYpO4m33L0cijA6MdcdqilQu4Z5tw4nG45lAW9UYyOc9D4hJTzgtGHhECgYA6QyDoj931brSoK0ocT+DB11Sj4utbOuberMaV8zgTSRhwodSl+WgdAUMMMDRacPcrBrgQiAMSZ15msqYZHEFhEa7Id8arFKvSXquTzf9iDKyJ0unzO/ThLjS3W+GxVNyrdufzA0tQ3IaKfOcDUrOpC7fdbtyrVqqSl4dF5MI9GwKBgQCl3OF6qyOEDDZgsUk1L59h7k3QR6VmBf4e9IeGUxZamvQlHjU/yY1nm1mjgGnbUB/SPKtqZKoMV6eBTVoNiuhQcItpGda9D3mnx+7p3T0/TBd+fJeuwcplfPDjrEktogcq5w/leQc3Ve7gr1EMcwb3r28f8/9L42QHQR/OKODs8QKBgQCFAvxDRPyYg7V/AgD9rt1KzXi4+b3Pls5NXZa2g/w+hmdhHUNxV5IGmHlqFnptGyshgYgQGxMMkW0iJ1j8nLamFnkbFQOp5/UKbdPLRKiB86oPpxsqYtPXucDUqEfcMsp57mD1CpGVODbspogFpSUvQpMECkhvI0XLMbolMdo53g==" diff --git a/tests/stdlib/toptions.nim b/tests/stdlib/toptions.nim index 633be6c04..63a10e746 100644 --- a/tests/stdlib/toptions.nim +++ b/tests/stdlib/toptions.nim @@ -1,11 +1,12 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/[json, options] -when defined(nimPreviewSlimSystem): - import std/objectdollar +import std/assertions +import std/objectdollar # RefPerson is used to test that overloaded `==` operator is not called by @@ -195,6 +196,12 @@ proc main() = doAssert x.isNone doAssert $x == "none(cstring)" - static: main() main() + +when not defined(js): + block: # bug #22932 + var it = iterator: int {.closure.} = discard + doAssert it.option.isSome # Passes. + it = nil + doAssert it.option.isNone # Passes. diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index d02fed714..611659fdb 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -22,12 +22,13 @@ __really_obscure_dir_name/test Raises Raises ''' + matrix: "--mm:refc; --mm:orc" joinable: false """ # test os path creation, iteration, and deletion -import os, strutils, pathnorm from stdtest/specialpaths import buildDir +import std/[syncio, assertions, osproc, os, strutils, pathnorm] block fileOperations: let files = @["these.txt", "are.x", "testing.r", "files.q"] @@ -159,6 +160,18 @@ block fileOperations: # createDir should not fail if `dir` is empty createDir("") + + when defined(linux): # bug #24174 + createDir("a/b") + open("a/file.txt", fmWrite).close + + if not fileExists("a/fifoFile"): + doAssert execCmd("mkfifo -m 600 a/fifoFile") == 0 + + copyDir("a/", "../dest/a/", skipSpecial = true) + copyDirWithPermissions("a/", "../dest2/a/", skipSpecial = true) + removeDir("a") + # Symlink handling in `copyFile`, `copyFileWithPermissions`, `copyFileToDir`, # `copyDir`, `copyDirWithPermissions`, `moveFile`, and `moveDir`. block: @@ -343,6 +356,8 @@ block walkDirRec: removeDir("walkdir_test") +import std/sequtils + block: # walkDir doAssertRaises(OSError): for a in walkDir("nonexistent", checkDir = true): discard @@ -357,6 +372,21 @@ block: # walkDir doAssert k == pcLinkToDir removeDir("walkdir_test") + when defined(posix): + block walkDirSpecial: + createDir("walkdir_test") + doAssert execShellCmd("mkfifo walkdir_test/fifo") == 0 + createSymlink("fifo", "walkdir_test/fifo_link") + let withSpecialFiles = toSeq(walkDir("walkdir_test", relative = true)) + doAssert (withSpecialFiles.len == 2 and + (pcFile, "fifo") in withSpecialFiles and + (pcLinkToFile, "fifo_link") in withSpecialFiles) + # now Unix special files are excluded from walkdir output: + let skipSpecialFiles = toSeq(walkDir("walkdir_test", relative = true, + skipSpecial = true)) + doAssert skipSpecialFiles.len == 0 + removeDir("walkdir_test") + block normalizedPath: doAssert normalizedPath("") == "" block relative: @@ -671,32 +701,6 @@ block: # normalizePathEnd doAssert r"E:/".normalizePathEnd(trailingSep = true) == r"E:\" doAssert "/".normalizePathEnd == r"\" -block: # isValidFilename - # Negative Tests. - doAssert not isValidFilename("abcd", maxLen = 2) - doAssert not isValidFilename("0123456789", maxLen = 8) - doAssert not isValidFilename("con") - doAssert not isValidFilename("aux") - doAssert not isValidFilename("prn") - doAssert not isValidFilename("OwO|UwU") - doAssert not isValidFilename(" foo") - doAssert not isValidFilename("foo ") - doAssert not isValidFilename("foo.") - doAssert not isValidFilename("con.txt") - doAssert not isValidFilename("aux.bat") - doAssert not isValidFilename("prn.exe") - doAssert not isValidFilename("nim>.nim") - doAssert not isValidFilename(" foo.log") - # Positive Tests. - doAssert isValidFilename("abcd", maxLen = 42.Positive) - doAssert isValidFilename("c0n") - doAssert isValidFilename("foo.aux") - doAssert isValidFilename("bar.prn") - doAssert isValidFilename("OwO_UwU") - doAssert isValidFilename("cron") - doAssert isValidFilename("ux.bat") - doAssert isValidFilename("nim.nim") - doAssert isValidFilename("foo.log") import sugar @@ -715,7 +719,23 @@ block: # isAdmin # In Azure on POSIX tests run as a normal user if isAzure and defined(posix): doAssert not isAdmin() -import std/sequtils + +import sugar + +block: # normalizeExe + doAssert "".dup(normalizeExe) == "" + when defined(posix): + doAssert "foo".dup(normalizeExe) == "./foo" + doAssert "foo/../bar".dup(normalizeExe) == "foo/../bar" + when defined(windows): + doAssert "foo".dup(normalizeExe) == "foo" + +block: # isAdmin + let isAzure = existsEnv("TF_BUILD") # xxx factor with testament.specs.isAzure + # In Azure on Windows tests run as an admin user + if isAzure and defined(windows): doAssert isAdmin() + # In Azure on POSIX tests run as a normal user + if isAzure and defined(posix): doAssert not isAdmin() when doslikeFileSystem: import std/private/ntpath @@ -792,3 +812,64 @@ else: doAssert parentDirs("/home/user", fromRoot=false).toSeq == @["/home/user", "/home", "/"] doAssert parentDirs("home/user", fromRoot=true).toSeq == @["home/", "home/user"] doAssert parentDirs("home/user", fromRoot=false).toSeq == @["home/user", "home"] + + +# https://github.com/nim-lang/Nim/pull/19643#issuecomment-1235102314 +block: # isValidFilename + # Negative Tests. + doAssert not isValidFilename("abcd", maxLen = 2) + doAssert not isValidFilename("0123456789", maxLen = 8) + doAssert not isValidFilename("con") + doAssert not isValidFilename("aux") + doAssert not isValidFilename("prn") + doAssert not isValidFilename("OwO|UwU") + doAssert not isValidFilename(" foo") + doAssert not isValidFilename("foo ") + doAssert not isValidFilename("foo.") + doAssert not isValidFilename("con.txt") + doAssert not isValidFilename("aux.bat") + doAssert not isValidFilename("prn.exe") + doAssert not isValidFilename("nim>.nim") + doAssert not isValidFilename(" foo.log") + # Positive Tests. + doAssert isValidFilename("abcd", maxLen = 42.Positive) + doAssert isValidFilename("c0n") + doAssert isValidFilename("foo.aux") + doAssert isValidFilename("bar.prn") + doAssert isValidFilename("OwO_UwU") + doAssert isValidFilename("cron") + doAssert isValidFilename("ux.bat") + doAssert isValidFilename("nim.nim") + doAssert isValidFilename("foo.log") + +block: # searchExtPos + doAssert "foo.nim".searchExtPos == 3 + doAssert "/foo.nim".searchExtPos == 4 + doAssert "".searchExtPos == -1 + doAssert "/".searchExtPos == -1 + doAssert "a.b/foo".searchExtPos == -1 + doAssert ".".searchExtPos == -1 + doAssert "foo.".searchExtPos == 3 + doAssert "foo..".searchExtPos == 4 + doAssert "..".searchExtPos == -1 + doAssert "...".searchExtPos == -1 + doAssert "./".searchExtPos == -1 + doAssert "../".searchExtPos == -1 + doAssert "/.".searchExtPos == -1 + doAssert "/..".searchExtPos == -1 + doAssert ".b".searchExtPos == -1 + doAssert "..b".searchExtPos == -1 + doAssert "/.b".searchExtPos == -1 + doAssert "a/.b".searchExtPos == -1 + doAssert ".a.b".searchExtPos == 2 + doAssert "a/.b.c".searchExtPos == 4 + doAssert "a/..b".searchExtPos == -1 + doAssert "a/b..c".searchExtPos == 4 + + when doslikeFileSystem: + doAssert "c:a.b".searchExtPos == 3 + doAssert "c:.a".searchExtPos == -1 + doAssert r"c:\.a".searchExtPos == -1 + doAssert "c:..a".searchExtPos == -1 + doAssert r"c:\..a".searchExtPos == -1 + doAssert "c:.a.b".searchExtPos == 4 diff --git a/tests/stdlib/tos_unc.nim b/tests/stdlib/tos_unc.nim index e55de11ce..194deeb42 100644 --- a/tests/stdlib/tos_unc.nim +++ b/tests/stdlib/tos_unc.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" disabled: "posix" """ # bug 10952, UNC paths import os +import std/assertions doAssert r"\\hostname\foo\bar" / "baz" == r"\\hostname\foo\bar\baz" doAssert r"\\?\C:\foo" / "bar" == r"\\?\C:\foo\bar" diff --git a/tests/stdlib/tosenv.nim b/tests/stdlib/tosenv.nim index 310bfe202..17e397987 100644 --- a/tests/stdlib/tosenv.nim +++ b/tests/stdlib/tosenv.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--threads" + matrix: "--mm:refc; --mm:arc" joinable: false targets: "c js cpp" """ @@ -8,6 +8,9 @@ import std/os from std/sequtils import toSeq import stdtest/testutils +when defined(nimPreviewSlimSystem): + import std/[assertions] + # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386) const unicodeUtf8 = "\xc3\x86" @@ -49,10 +52,13 @@ static: main() main() when defined(windows): + import std/widestrs proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".} proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".} when not defined(js) and not defined(nimscript): + when defined(nimPreviewSlimSystem): + import std/typedthreads block: # bug #18533 var thr: Thread[void] proc threadFunc {.thread.} = putEnv("foo", "fooVal2") diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim index f55dd3e21..da4f6252d 100644 --- a/tests/stdlib/tosproc.nim +++ b/tests/stdlib/tosproc.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" joinable: false """ @@ -9,6 +10,7 @@ because it'd need cleanup up stdout see also: tests/osproc/*.nim; consider merging those into a single test here (easier to factor and test more things as a single self contained test) ]# +import std/[assertions, syncio] when defined(case_testfile): # compiled test file for child process from posix import exitnow @@ -92,9 +94,7 @@ else: # main driver const sourcePath = currentSourcePath() let dir = getCurrentDir() / "tests" / "osproc" - template deferScoped(cleanup, body) = - # pending https://github.com/nim-lang/RFCs/issues/236#issuecomment-646855314 - # xxx move to std/sugar or (preferably) some low level module + template deferring(cleanup, body) = try: body finally: cleanup @@ -119,7 +119,10 @@ else: # main driver runTest("exit_0", 0) runTest("exitnow_139", 139) runTest("c_exit2_139", 139) - runTest("quit_139", 139) + when defined(posix): + runTest("quit_139", 127) # The quit value gets saturated to 127 + else: + runTest("quit_139", 139) block execCmdTest: let output = compileNimProg("-d:release -d:case_testfile", "D20220705T221100") @@ -245,14 +248,14 @@ else: # main driver var x = newStringOfCap(120) block: # startProcess stdout poStdErrToStdOut (replaces old test `tstdout` + `ta_out`) var p = startProcess(output, dir, options={poStdErrToStdOut}) - deferScoped: p.close() + deferring: p.close() do: var sout: seq[string] while p.outputStream.readLine(x): sout.add x doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stderr", "to stderr", "to stdout", "to stdout", "end ta_out"] block: # startProcess stderr (replaces old test `tstderr` + `ta_out`) var p = startProcess(output, dir, options={}) - deferScoped: p.close() + deferring: p.close() do: var serr, sout: seq[string] while p.errorStream.readLine(x): serr.add x diff --git a/tests/stdlib/tosprocterminate.nim b/tests/stdlib/tosprocterminate.nim index 8e9041b81..93b0317f7 100644 --- a/tests/stdlib/tosprocterminate.nim +++ b/tests/stdlib/tosprocterminate.nim @@ -1,10 +1,11 @@ discard """ cmd: "nim $target $options -r $file" targets: "c cpp" - matrix: "--threads:on; " + matrix: "--mm:refc; --mm:orc" """ import os, osproc, times, std / monotimes +import std/assertions when defined(windows): const ProgramWhichDoesNotEnd = "notepad" diff --git a/tests/stdlib/tpackedsets.nim b/tests/stdlib/tpackedsets.nim index d0149adc5..f519c08a7 100644 --- a/tests/stdlib/tpackedsets.nim +++ b/tests/stdlib/tpackedsets.nim @@ -1,9 +1,15 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/packedsets import std/sets import sequtils import algorithm +import std/assertions + block basicIntSetTests: var y = initPackedSet[int]() y.incl(1) diff --git a/tests/stdlib/tparsecfg.nim b/tests/stdlib/tparsecfg.nim index b2e57ac3d..2600d6f66 100644 --- a/tests/stdlib/tparsecfg.nim +++ b/tests/stdlib/tparsecfg.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import parsecfg, streams, sequtils +import std/assertions when not defined(js): from stdtest/specialpaths import buildDir diff --git a/tests/stdlib/tparsecsv.nim b/tests/stdlib/tparsecsv.nim index 0d004d45d..5a1e41bce 100644 --- a/tests/stdlib/tparsecsv.nim +++ b/tests/stdlib/tparsecsv.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + include parsecsv import strutils, os +import std/assertions block: # Tests for reading the header row let content = "\nOne,Two,Three,Four\n1,2,3,4\n10,20,30,40,\n100,200,300,400\n" diff --git a/tests/stdlib/tparseipv6.nim b/tests/stdlib/tparseipv6.nim index 9b9c464c7..31ec4ecfb 100644 --- a/tests/stdlib/tparseipv6.nim +++ b/tests/stdlib/tparseipv6.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: "all ok" """ diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim index 8ef67f5dc..cd582551d 100644 --- a/tests/stdlib/tparsesql.nim +++ b/tests/stdlib/tparsesql.nim @@ -1,7 +1,9 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import parsesql +import std/assertions doAssert treeRepr(parseSql("INSERT INTO STATS VALUES (10, 5.5); ") ) == """ diff --git a/tests/stdlib/tparseuints.nim b/tests/stdlib/tparseuints.nim index ef8c782b3..9c71a27d6 100644 --- a/tests/stdlib/tparseuints.nim +++ b/tests/stdlib/tparseuints.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import unittest, strutils block: # parseutils diff --git a/tests/stdlib/tparseutils.nim b/tests/stdlib/tparseutils.nim index db7a0ac8d..b69900864 100644 --- a/tests/stdlib/tparseutils.nim +++ b/tests/stdlib/tparseutils.nim @@ -1,52 +1,112 @@ -import std/[parseutils, sequtils, sugar] - - -let input = "$test{} $this is ${an{ example}} " -let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"), - (ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")] -doAssert toSeq(interpolatedFragments(input)) == expected - -var value = 0 -discard parseHex("0x38", value) -doAssert value == 56 - -value = -1 -doAssert(parseSaturatedNatural("848", value) == 3) -doAssert value == 848 - -value = -1 -discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value) -doAssert value == high(int) - -value = -1 -discard parseSaturatedNatural("9223372036854775808", value) -doAssert value == high(int) - -value = -1 -discard parseSaturatedNatural("9223372036854775807", value) -doAssert value == high(int) - -value = -1 -discard parseSaturatedNatural("18446744073709551616", value) -doAssert value == high(int) - -value = -1 -discard parseSaturatedNatural("18446744073709551615", value) -doAssert value == high(int) - -value = -1 -doAssert(parseSaturatedNatural("1_000_000", value) == 9) -doAssert value == 1_000_000 - -var i64Value: int64 -discard parseBiggestInt("9223372036854775807", i64Value) -doAssert i64Value == 9223372036854775807 - -block: - var f: float - let res = collect: - for x in ["9.123456789012345+","11.123456789012345+","9.123456789012345-","8.123456789012345+","9.12345678901234-","9.123456789012345"]: - (parseFloat(x, f, 0), $f) - doAssert res == @[(17, "9.123456789012344"), (18, "11.123456789012344"), - (17, "9.123456789012344"), (17, "8.123456789012344"), - (16, "9.12345678901234"), (17, "9.123456789012344")] +discard """ + matrix: "--mm:refc; --mm:orc" + targets: "c cpp" +""" + +import std/[parseutils, sequtils, sugar, formatfloat] +import std/assertions + +proc test() = + let input = "$test{} $this is ${an{ example}} " + let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"), + (ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")] + doAssert toSeq(interpolatedFragments(input)) == expected + + var value = 0 + discard parseHex("0x38", value) + doAssert value == 56 + + value = -1 + doAssert(parseSaturatedNatural("848", value) == 3) + doAssert value == 848 + + value = -1 + discard parseSaturatedNatural("84899999999999999999324234243143142342135435342532453", value) + doAssert value == high(int) + + value = -1 + discard parseSaturatedNatural("9223372036854775808", value) + doAssert value == high(int) + + value = -1 + discard parseSaturatedNatural("9223372036854775807", value) + doAssert value == high(int) + + value = -1 + discard parseSaturatedNatural("18446744073709551616", value) + doAssert value == high(int) + + value = -1 + discard parseSaturatedNatural("18446744073709551615", value) + doAssert value == high(int) + + value = -1 + doAssert(parseSaturatedNatural("1_000_000", value) == 9) + doAssert value == 1_000_000 + + var i64Value: int64 + discard parseBiggestInt("9223372036854775807", i64Value) + doAssert i64Value == 9223372036854775807 + + block: + var f: float + let res = collect: + for x in ["9.123456789012345+","11.123456789012345+","9.123456789012345-","8.123456789012345+","9.12345678901234-","9.123456789012345"]: + (parseFloat(x, f, 0), $f) + doAssert res == @[(17, "9.123456789012344"), (18, "11.123456789012344"), + (17, "9.123456789012344"), (17, "8.123456789012344"), + (16, "9.12345678901234"), (17, "9.123456789012344")] + +test() +static: test() + +block: # With this included, static: test() crashes the compiler (from a + # VM problem with parseSize calling parseFloat). + var sz: int64 + template checkParseSize(s, expectLen, expectVal) = + if (let got = parseSize(s, sz); got != expectLen): + raise newException(IOError, "got len " & $got & " != " & $expectLen) + if sz != expectVal: + raise newException(IOError, "got sz " & $sz & " != " & $expectVal) + # STRING LEN SZ + # Good, complete parses + checkParseSize "1 b" , 4, 1 + checkParseSize "1 B" , 4, 1 + checkParseSize "1k" , 2, 1000 + checkParseSize "1 kib" , 5, 1024 + checkParseSize "1 ki" , 4, 1024 + checkParseSize "1mi" , 3, 1048576 + checkParseSize "1 mi" , 4, 1048576 + checkParseSize "1 mib" , 5, 1048576 + checkParseSize "1 Mib" , 5, 1048576 + checkParseSize "1 MiB" , 5, 1048576 + checkParseSize "1.23GiB", 7, 1320702444 # 1320702443.52 rounded + checkParseSize "0.001k" , 6, 1 + checkParseSize "0.0004k", 7, 0 + checkParseSize "0.0006k", 7, 1 + # Incomplete parses + checkParseSize "1 " , 1, 1 # Trailing white IGNORED + checkParseSize "1 B " , 4, 1 # Trailing white IGNORED + checkParseSize "1 B/s" , 4, 1 # Trailing junk IGNORED + checkParseSize "1 kX" , 3, 1000 + checkParseSize "1 kiX" , 4, 1024 + checkParseSize "1j" , 1, 1 # Unknown prefix IGNORED + checkParseSize "1 jib" , 2, 1 # Unknown prefix post space + checkParseSize "1 ji" , 3, 1 + # Bad parses; `sz` should stay last good|incomplete value + checkParseSize "-1b" , 0, 1 # Negative numbers + checkParseSize "abc" , 0, 1 # Non-numeric + checkParseSize " 12" , 0, 1 # Leading white + # Value Edge cases + checkParseSize "9223372036854775807", 19, int64.high + +block: # bug #23936 + func parsePyFloat( + a: openArray[char], # here must be openArray instead of string to reproduce this bug + res: var BiggestFloat): int = + result = parseFloat(a, res) + + static: + var f = 0.0 + doAssert "1.0".parsePyFloat(f) == 3 + doAssert f == 1.0 diff --git a/tests/stdlib/tparsopt.nim b/tests/stdlib/tparsopt.nim index 54a470cb3..f3a9a9798 100644 --- a/tests/stdlib/tparsopt.nim +++ b/tests/stdlib/tparsopt.nim @@ -9,6 +9,8 @@ disabled: true import parseopt +import std/[assertions, syncio] + proc writeHelp() = writeLine(stdout, "Usage: tparsopt [options] filename [options]") diff --git a/tests/stdlib/tpathnorm.nim b/tests/stdlib/tpathnorm.nim index 2cb644e3c..3dd287a77 100644 --- a/tests/stdlib/tpathnorm.nim +++ b/tests/stdlib/tpathnorm.nim @@ -1,7 +1,9 @@ discard """ + matrix: "--mm:refc; --mm:orc" """ import std/os +import std/assertions when doslikeFileSystem: import std/pathnorm diff --git a/tests/stdlib/tpaths.nim b/tests/stdlib/tpaths.nim new file mode 100644 index 000000000..edb56209a --- /dev/null +++ b/tests/stdlib/tpaths.nim @@ -0,0 +1,238 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/paths +import std/assertions +import pathnorm +from std/private/ospaths2 {.all.} import joinPathImpl +import std/[sugar, sets] + + +proc normalizePath*(path: Path; dirSep = DirSep): Path = + result = Path(pathnorm.normalizePath(path.string, dirSep)) + +func joinPath*(parts: varargs[Path]): Path = + var estimatedLen = 0 + var state = 0 + for p in parts: estimatedLen += p.string.len + var res = newStringOfCap(estimatedLen) + for i in 0..high(parts): + joinPathImpl(res, state, parts[i].string) + result = Path(res) + + +func joinPath(head, tail: Path): Path {.inline.} = + head / tail + +block absolutePath: + doAssertRaises(ValueError): discard absolutePath(Path"a", Path"b") + doAssert absolutePath(Path"a") == getCurrentDir() / Path"a" + doAssert absolutePath(Path"a", Path"/b") == Path"/b" / Path"a" + when defined(posix): + doAssert absolutePath(Path"a", Path"/b/") == Path"/b" / Path"a" + doAssert absolutePath(Path"a", Path"/b/c") == Path"/b/c" / Path"a" + doAssert absolutePath(Path"/a", Path"b/") == Path"/a" + +block splitFile: + doAssert splitFile(Path"") == (Path"", Path"", "") + doAssert splitFile(Path"abc/") == (Path"abc", Path"", "") + doAssert splitFile(Path"/") == (Path"/", Path"", "") + doAssert splitFile(Path"./abc") == (Path".", Path"abc", "") + doAssert splitFile(Path".txt") == (Path"", Path".txt", "") + doAssert splitFile(Path"abc/.txt") == (Path"abc", Path".txt", "") + doAssert splitFile(Path"abc") == (Path"", Path"abc", "") + doAssert splitFile(Path"abc.txt") == (Path"", Path"abc", ".txt") + doAssert splitFile(Path"/abc.txt") == (Path"/", Path"abc", ".txt") + doAssert splitFile(Path"/foo/abc.txt") == (Path"/foo", Path"abc", ".txt") + doAssert splitFile(Path"/foo/abc.txt.gz") == (Path"/foo", Path"abc.txt", ".gz") + doAssert splitFile(Path".") == (Path"", Path".", "") + doAssert splitFile(Path"abc/.") == (Path"abc", Path".", "") + doAssert splitFile(Path"..") == (Path"", Path"..", "") + doAssert splitFile(Path"a/..") == (Path"a", Path"..", "") + doAssert splitFile(Path"/foo/abc....txt") == (Path"/foo", Path"abc...", ".txt") + +# execShellCmd is tested in tosproc + +block ospaths: + doAssert unixToNativePath(Path"") == Path"" + doAssert unixToNativePath(Path".") == Path($CurDir) + doAssert unixToNativePath(Path"..") == Path($ParDir) + doAssert isAbsolute(unixToNativePath(Path"/")) + doAssert isAbsolute(unixToNativePath(Path"/", Path"a")) + doAssert isAbsolute(unixToNativePath(Path"/a")) + doAssert isAbsolute(unixToNativePath(Path"/a", Path"a")) + doAssert isAbsolute(unixToNativePath(Path"/a/b")) + doAssert isAbsolute(unixToNativePath(Path"/a/b", Path"a")) + doAssert unixToNativePath(Path"a/b") == joinPath(Path"a", Path"b") + + when defined(macos): + doAssert unixToNativePath(Path"./") == Path":" + doAssert unixToNativePath(Path"./abc") == Path":abc" + doAssert unixToNativePath(Path"../abc") == Path"::abc" + doAssert unixToNativePath(Path"../../abc") == Path":::abc" + doAssert unixToNativePath(Path"/abc", Path"a") == Path"abc" + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"abc:def" + elif doslikeFileSystem: + doAssert unixToNativePath(Path"./") == Path(".\\") + doAssert unixToNativePath(Path"./abc") == Path(".\\abc") + doAssert unixToNativePath(Path"../abc") == Path("..\\abc") + doAssert unixToNativePath(Path"../../abc") == Path("..\\..\\abc") + doAssert unixToNativePath(Path"/abc", Path"a") == Path("a:\\abc") + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path("a:\\abc\\def") + else: + #Tests for unix + doAssert unixToNativePath(Path"./") == Path"./" + doAssert unixToNativePath(Path"./abc") == Path"./abc" + doAssert unixToNativePath(Path"../abc") == Path"../abc" + doAssert unixToNativePath(Path"../../abc") == Path"../../abc" + doAssert unixToNativePath(Path"/abc", Path"a") == Path"/abc" + doAssert unixToNativePath(Path"/abc/def", Path"a") == Path"/abc/def" + + block extractFilenameTest: + doAssert extractFilename(Path"") == Path"" + when defined(posix): + doAssert extractFilename(Path"foo/bar") == Path"bar" + doAssert extractFilename(Path"foo/bar.txt") == Path"bar.txt" + doAssert extractFilename(Path"foo/") == Path"" + doAssert extractFilename(Path"/") == Path"" + when doslikeFileSystem: + doAssert extractFilename(Path(r"foo\bar")) == Path"bar" + doAssert extractFilename(Path(r"foo\bar.txt")) == Path"bar.txt" + doAssert extractFilename(Path(r"foo\")) == Path"" + doAssert extractFilename(Path(r"C:\")) == Path"" + + block lastPathPartTest: + doAssert lastPathPart(Path"") == Path"" + when defined(posix): + doAssert lastPathPart(Path"foo/bar.txt") == Path"bar.txt" + doAssert lastPathPart(Path"foo/") == Path"foo" + doAssert lastPathPart(Path"/") == Path"" + when doslikeFileSystem: + doAssert lastPathPart(Path(r"foo\bar.txt")) == Path"bar.txt" + doAssert lastPathPart(Path(r"foo\")) == Path"foo" + + template canon(x): Path = normalizePath(Path(x), '/') + doAssert canon"/foo/../bar" == Path"/bar" + doAssert canon"foo/../bar" == Path"bar" + + doAssert canon"/f/../bar///" == Path"/bar" + doAssert canon"f/..////bar" == Path"bar" + + doAssert canon"../bar" == Path"../bar" + doAssert canon"/../bar" == Path"/../bar" + + doAssert canon("foo/../../bar/") == Path"../bar" + doAssert canon("./bla/blob/") == Path"bla/blob" + doAssert canon(".hiddenFile") == Path".hiddenFile" + doAssert canon("./bla/../../blob/./zoo.nim") == Path"../blob/zoo.nim" + + doAssert canon("C:/file/to/this/long") == Path"C:/file/to/this/long" + doAssert canon("") == Path"" + doAssert canon("foobar") == Path"foobar" + doAssert canon("f/////////") == Path"f" + + doAssert relativePath(Path"/foo/bar//baz.nim", Path"/foo", '/') == Path"bar/baz.nim" + doAssert normalizePath(Path"./foo//bar/../baz", '/') == Path"foo/baz" + + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other/bad", '/') == Path"../../me/bar/z.nim" + + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/other", '/') == Path"../me/bar/z.nim" + + # `//` is a UNC path, `/` is the current working directory's drive, so can't + # run this test on Windows. + when not doslikeFileSystem: + doAssert relativePath(Path"/Users///me/bar//z.nim", Path"//Users/", '/') == Path"me/bar/z.nim" + doAssert relativePath(Path"/Users/me/bar/z.nim", Path"/Users/me", '/') == Path"bar/z.nim" + doAssert relativePath(Path"", Path"/users/moo", '/') == Path"" + doAssert relativePath(Path"foo", Path"", '/') == Path"foo" + doAssert relativePath(Path"/foo", Path"/Foo", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".") + doAssert relativePath(Path"/Foo", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../Foo" else: Path".") + doAssert relativePath(Path"/foo", Path"/fOO", '/') == (when FileSystemCaseSensitive: Path"../foo" else: Path".") + doAssert relativePath(Path"/foO", Path"/foo", '/') == (when FileSystemCaseSensitive: Path"../foO" else: Path".") + + doAssert relativePath(Path"foo", Path".", '/') == Path"foo" + doAssert relativePath(Path".", Path".", '/') == Path"." + doAssert relativePath(Path"..", Path".", '/') == Path".." + + doAssert relativePath(Path"foo", Path"foo") == Path"." + doAssert relativePath(Path"", Path"foo") == Path"" + doAssert relativePath(Path"././/foo", Path"foo//./") == Path"." + + doAssert relativePath(getCurrentDir() / Path"bar", Path"foo") == Path"../bar".unixToNativePath + doAssert relativePath(Path"bar", getCurrentDir() / Path"foo") == Path"../bar".unixToNativePath + + when doslikeFileSystem: + doAssert relativePath(r"c:\foo.nim".Path, r"C:\".Path) == r"foo.nim".Path + doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"c:\foo".Path) == r"bar\baz.nim".Path + doAssert relativePath(r"c:\foo\bar\baz.nim".Path, r"d:\foo".Path) == r"c:\foo\bar\baz.nim".Path + doAssert relativePath(r"\foo\baz.nim".Path, r"\foo".Path) == r"baz.nim".Path + doAssert relativePath(r"\foo\bar\baz.nim".Path, r"\bar".Path) == r"..\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\bar".Path) == r"baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foO\bar".Path) == r"baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\bar\bar".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\foo\car".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\\goo\bar".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"c:\".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"\\foo\bar\baz.nim".Path, r"\foo".Path) == r"\\foo\bar\baz.nim".Path + doAssert relativePath(r"c:\foo.nim".Path, r"\foo".Path) == r"c:\foo.nim".Path + + doAssert joinPath(Path"usr", Path"") == unixToNativePath(Path"usr") + doAssert joinPath(Path"usr", Path"") == (Path"usr").dup(add Path"") + doAssert joinPath(Path"", Path"lib") == Path"lib" + doAssert joinPath(Path"", Path"lib") == Path"".dup(add Path"lib") + doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib") + doAssert joinPath(Path"", Path"/lib") == unixToNativePath(Path"/lib") + doAssert joinPath(Path"usr/", Path"/lib") == Path"usr/".dup(add Path"/lib") + doAssert joinPath(Path"", Path"") == unixToNativePath(Path"") # issue #13455 + doAssert joinPath(Path"", Path"") == Path"".dup(add Path"") + doAssert joinPath(Path"", Path"/") == unixToNativePath(Path"/") + doAssert joinPath(Path"", Path"/") == Path"".dup(add Path"/") + doAssert joinPath(Path"/", Path"/") == unixToNativePath(Path"/") + doAssert joinPath(Path"/", Path"/") == Path"/".dup(add Path"/") + doAssert joinPath(Path"/", Path"") == unixToNativePath(Path"/") + doAssert joinPath(Path"/" / Path"") == unixToNativePath(Path"/") # weird test case... + doAssert joinPath(Path"/", Path"/a/b/c") == unixToNativePath(Path"/a/b/c") + doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo/", Path"abc") == unixToNativePath(Path"foo/abc") + doAssert joinPath(Path"foo//./", Path"abc/.//") == unixToNativePath(Path"foo/abc/") + doAssert Path"foo//./".dup(add Path"abc/.//") == unixToNativePath(Path"foo/abc/") + doAssert joinPath(Path"foo", Path"abc") == unixToNativePath(Path"foo/abc") + doAssert Path"foo".dup(add Path"abc") == unixToNativePath(Path"foo/abc") + doAssert joinPath(Path"", Path"abc") == unixToNativePath(Path"abc") + + doAssert joinPath(Path"zook/.", Path"abc") == unixToNativePath(Path"zook/abc") + + # controversial: inconsistent with `joinPath("zook/.","abc")` + # on linux, `./foo` and `foo` are treated a bit differently for executables + # but not `./foo/bar` and `foo/bar` + doAssert joinPath(Path".", Path"/lib") == unixToNativePath(Path"./lib") + doAssert joinPath(Path".", Path"abc") == unixToNativePath(Path"./abc") + + # cases related to issue #13455 + doAssert joinPath(Path"foo", Path"", Path"") == Path"foo" + doAssert joinPath(Path"foo", Path"") == Path"foo" + doAssert joinPath(Path"foo/", Path"") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo/", Path".") == Path"foo" + doAssert joinPath(Path"foo", Path"./") == unixToNativePath(Path"foo/") + doAssert joinPath(Path"foo", Path"", Path"bar/") == unixToNativePath(Path"foo/bar/") + + # issue #13579 + doAssert joinPath(Path"/foo", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/.", Path"../a") == unixToNativePath(Path"/a") + doAssert joinPath(Path"/foo/.b", Path"../a") == unixToNativePath(Path"/foo/a") + doAssert joinPath(Path"/foo///", Path"..//a/") == unixToNativePath(Path"/a/") + doAssert joinPath(Path"foo/", Path"../a") == unixToNativePath(Path"a") + + when doslikeFileSystem: + doAssert joinPath(Path"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\", Path"..\\..\\VC\\vcvarsall.bat") == r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat".Path + doAssert joinPath(Path"C:\\foo", Path"..\\a") == r"C:\a".Path + doAssert joinPath(Path"C:\\foo\\", Path"..\\a") == r"C:\a".Path + + +block: # bug #23663 + var s: HashSet[Path] + s.incl("/a/b/c/..".Path) + doAssert "/a/b/".Path in s + doAssert "/a/b/c".Path notin s diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim index c3d8942cf..da3fc14b7 100644 --- a/tests/stdlib/tpegs.nim +++ b/tests/stdlib/tpegs.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" output: ''' PEG AST traversal output @@ -54,7 +55,7 @@ Event parser output when defined(nimHasEffectsOf): {.experimental: "strictEffects".} -import std/[strutils, streams, pegs] +import std/[strutils, streams, pegs, assertions] const indent = " " @@ -106,9 +107,9 @@ block: block: var - pStack: seq[string] = @[] - valStack: seq[float] = @[] - opStack = "" + pStack {.threadvar.}: seq[string] + valStack {.threadvar.}: seq[float] + opStack {.threadvar.}: string let parseArithExpr = pegAst.eventParser: pkNonTerminal: @@ -158,6 +159,10 @@ block: privateAccess(NonTerminal) privateAccess(Captures) + if "test" =~ peg"s <- {{\ident}}": # bug #19104 + doAssert matches[0] == "test" + doAssert matches[1] == "test", $matches[1] + doAssert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27" doAssert match("(a b c)", peg"'(' @ ')'") doAssert match("W_HI_Le", peg"\y 'while'") @@ -324,7 +329,16 @@ call() doAssert program.len == program.rawMatch(grammar, 0, c) doAssert c.ml == 1 + block: + # bug #21632 + + let p = peg""" + atext <- \w / \d + """ + + doAssert "a".match(p) + doAssert "1".match(p) + pegsTest() static: pegsTest() - diff --git a/tests/stdlib/tposix.nim b/tests/stdlib/tposix.nim index 14f1fd6e2..060482229 100644 --- a/tests/stdlib/tposix.nim +++ b/tests/stdlib/tposix.nim @@ -1,5 +1,6 @@ discard """ -outputsub: "" + matrix: "--mm:refc; --mm:orc" + disabled: windows """ # Test Posix interface @@ -7,6 +8,7 @@ outputsub: "" when not defined(windows): import posix + import std/[assertions, syncio] var u: Utsname @@ -17,3 +19,70 @@ when not defined(windows): writeLine(stdout, u.nodename) writeLine(stdout, u.release) writeLine(stdout, u.machine) + + when not (defined(nintendoswitch) or defined(macos) or defined(macosx)): + block: + type Message = object + value: int + + const MQ_PATH: cstring = "/top_level_file" + const MQ_PRIORITY: cuint = 170 + const MQ_MESSAGE_SIZE: csize_t = csize_t(sizeof(Message)) + + let mqd_a: posix.MqAttr = MqAttr(mq_maxmsg: 10, mq_msgsize: clong(MQ_MESSAGE_SIZE)) + let writable: posix.Mqd = posix.mq_open( + MQ_PATH, + posix.O_CREAT or posix.O_WRONLY or posix.O_NONBLOCK, + posix.S_IRWXU, + addr(mqd_a) + ) + let readable: posix.Mqd = posix.mq_open( + MQ_PATH, + posix.O_RDONLY or posix.O_NONBLOCK, + posix.S_IRWXU, + addr(mqd_a) + ) + + let sent: Message = Message(value: 88) + block: + let success: int = writable.mq_send( + cast[cstring](sent.addr), + MQ_MESSAGE_SIZE, + MQ_PRIORITY + ) + doAssert success == 0, $success + + block: + var buffer: Message + var priority: cuint + let bytesRead: int = readable.mq_receive( + cast[cstring](buffer.addr), + MQ_MESSAGE_SIZE, + priority + ) + doAssert buffer == sent + doAssert bytesRead == int(MQ_MESSAGE_SIZE) + + block: + var rl: RLimit + var res = getrlimit(RLIMIT_STACK, rl) + doAssert res == 0 + + # save old value + let oldrlim = rl.rlim_cur + + # set new value + rl.rlim_cur = rl.rlim_max - 1 + res = setrlimit(RLIMIT_STACK, rl) + doAssert res == 0 + + # get new value + var rl1: RLimit + res = getrlimit(RLIMIT_STACK, rl1) + doAssert res == 0 + doAssert rl1.rlim_cur == rl.rlim_max - 1 + + # restore old value + rl.rlim_cur = oldrlim + res = setrlimit(RLIMIT_STACK, rl) + doAssert res == 0 diff --git a/tests/stdlib/tprelude.nim b/tests/stdlib/tprelude.nim index a60bcf70a..47f46b511 100644 --- a/tests/stdlib/tprelude.nim +++ b/tests/stdlib/tprelude.nim @@ -8,6 +8,8 @@ when defined nimTestTpreludeCase1: else: include prelude +import std/assertions + template main() = doAssert toSeq(1..3) == @[1,2,3] static: main() diff --git a/tests/stdlib/tpunycode.nim b/tests/stdlib/tpunycode.nim deleted file mode 100644 index bb2b4beb4..000000000 --- a/tests/stdlib/tpunycode.nim +++ /dev/null @@ -1,205 +0,0 @@ -import punycode, std/unicode - -doAssert(decode(encode("", "bücher")) == "bücher") -doAssert(decode(encode("münchen")) == "münchen") -doAssert encode("xn--", "münchen") == "xn--mnchen-3ya" - -# source: https://datatracker.ietf.org/doc/html/rfc3492.html#section-7 -let punycode_testcases = [ - # (A) Arabic (Egyptian): - ( - input: - "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" & - "\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F", - output: - "egbpdaj6bu4bxfgehfvwxn" - ), - - # (B) Chinese (simplified): - ( - input: - "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587", - output: - "ihqwcrb4cv8a8dqg056pqjye" - ), - - # (C) Chinese (traditional): - ( - input: - "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587", - output: - "ihqwctvzc91f659drss3x8bo0yb" - ), - - # (D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky - ( - input: - "\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" & - "\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" & - "\u0065\u0073\u006B\u0079", - output: - "Proprostnemluvesky-uyb24dma41a" - ), - - # (E) Hebrew: - ( - input: - "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" & - "\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" & - "\u05D1\u05E8\u05D9\u05EA", - output: - "4dbcagdahymbxekheh6e0a7fei0b" - ), - - # (F) Hindi (Devanagari): - ( - input: - "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" & - "\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" & - "\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" & - "\u0939\u0948\u0902", - output: - "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd" - ), - - # (G) Japanese (kanji and hiragana): - ( - input: - "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" & - "\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B", - output: - "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa" - ), - - # (H) Korean (Hangul syllables): - ( - input: - "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" & - "\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" & - "\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C", - output: - "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c" - ), - - # (I) Russian (Cyrillic): - ( - input: - "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" & - "\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" & - "\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" & - "\u0438", - output: - "b1abfaaepdrnnbgefbaDotcwatmq2g4l" - ), - - # (J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol - ( - input: - "\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" & - "\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" & - "\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" & - "\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" & - "\u0061\u00F1\u006F\u006C", - output: - "PorqunopuedensimplementehablarenEspaol-fmd56a" - ), - - # (K) Vietnamese: - # T<adotbelow>isaoh<odotbelow>kh<ocirc>ngth<ecirchookabove>ch\ - # <ihookabove>n<oacute>iti<ecircacute>ngVi<ecircdotbelow>t - ( - input: - "\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" & - "\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" & - "\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" & - "\u0056\u0069\u1EC7\u0074", - output: - "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g" - ), - - # (L) 3<nen>B<gumi><kinpachi><sensei> - ( - input: - "\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F", - output: - "3B-ww4c5e180e575a65lsy2b" - ), - - # (M) <amuro><namie>-with-SUPER-MONKEYS - ( - input: - "\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" & - "\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" & - "\u004F\u004E\u004B\u0045\u0059\u0053", - output: - "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n" - ), - - # (N) Hello-Another-Way-<sorezore><no><basho> - ( - input: - "\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" & - "\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" & - "\u305D\u308C\u305E\u308C\u306E\u5834\u6240", - output: - "Hello-Another-Way--fc4qua05auwb3674vfr0b" - ), - - # (O) <hitotsu><yane><no><shita>2 - ( - input: - "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032", - output: - "2-u9tlzr9756bt3uc0v" - ), - - # (P) Maji<de>Koi<suru>5<byou><mae> - ( - input: - "\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" & - "\u308B\u0035\u79D2\u524D", - output: - "MajiKoi5-783gue6qz075azm5e" - ), - - # (Q) <pafii>de<runba> - ( - input: - "\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0", - output: - "de-jg4avhby1noc0d" - ), - - # (R) <sono><supiido><de> - ( - input: - "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067", - output: - "d9juau41awczczp" - ), - - # (S) -> $1.00 <- - ( - input: - "\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" & - "\u003C\u002D", - output: - "-> $1.00 <--" - ) -] - -block encodeTests: - for (uni, puny) in punycode_testcases: - # Need to convert both strings to lower case, since - # some of the extended encodings use upper case, but our - # code produces only lower case. Converting just puny to - # lower is also insufficient, since some of the input characters - # are upper case. - doAssert encode(uni).toLower() == puny.toLower() - -block decodeTests: - for (uni, puny) in punycode_testcases: - doAssert decode(puny) == uni - -block decodeInvalidTest: - doAssertRaises(PunyError): discard decode("xn--w&") diff --git a/tests/stdlib/tquit.nim b/tests/stdlib/tquit.nim deleted file mode 100644 index 81726fd7f..000000000 --- a/tests/stdlib/tquit.nim +++ /dev/null @@ -1,15 +0,0 @@ -discard """ -output: ''' -just exiting... -''' -joinable: false -""" - -# Test `addQuitProc` (now deprecated by `addExitProc`) - -proc myExit() {.noconv.} = - write(stdout, "just exiting...\n") - -{.push warning[deprecated]: off.} -addQuitProc(myExit) -{.pop.} diff --git a/tests/stdlib/trandom.nim b/tests/stdlib/trandom.nim index 61e858f86..eb32f7757 100644 --- a/tests/stdlib/trandom.nim +++ b/tests/stdlib/trandom.nim @@ -1,9 +1,10 @@ discard """ joinable: false # to avoid messing with global rand state - targets: "c js" + matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ - +import std/[assertions, formatfloat] import std/[random, math, stats, sets, tables] +import std/private/jsutils when not defined(js): import std/os @@ -46,6 +47,8 @@ block: type DiceRoll = range[0..6] when not defined(js): doAssert rand(DiceRoll).int == 3 + elif compileOption("jsbigint64"): + doAssert rand(DiceRoll).int == 1 else: doAssert rand(DiceRoll).int == 6 @@ -191,9 +194,7 @@ block: # bug #17467 # This used to fail for each i in 0..<26844, i.e. the 1st produced value # was predictable and < 1e-4, skewing distributions. -const withUint = false # pending exporting `proc rand[T: uint | uint64](r: var Rand; max: T): T =` - -block: # bug #16360 +block: # bug #16360, Natural overload var r = initRand() template test(a) = let a2 = a @@ -205,23 +206,38 @@ block: # bug #16360 let a3 = rand(a2) doAssert a3 <= a2 doAssert a3.type is a2.type - when withUint: - test cast[uint](int.high) - test cast[uint](int.high) + 1 - when not defined(js): - # pending bug #16411 - test uint64.high - test uint64.high - 1 - test uint.high - 2 - test uint.high - 1 - test uint.high test int.high test int.high - 1 test int.high - 2 test 0 - when withUint: - test 0'u - test 0'u64 + +block: # same as above but use slice overload + var r = initRand() + template test[T](a: T) = + let a2: T = a + block: + let a3 = r.rand(T(0) .. a2) + doAssert a3 <= a2 + doAssert a3.type is a2.type + block: + let a3 = rand(T(0) .. a2) + doAssert a3 <= a2 + doAssert a3.type is a2.type + test cast[uint](int.high) + test cast[uint](int.high) + 1 + whenJsNoBigInt64: discard + do: + test uint64.high + test uint64.high - 1 + test uint.high - 2 + test uint.high - 1 + test uint.high + test int.high + test int.high - 1 + test int.high - 2 + test 0 + test 0'u + test 0'u64 block: # bug #16296 var r = initRand() @@ -239,16 +255,12 @@ block: # bug #16296 test(int.low .. -1) test(int.low .. 1) test(int64.low .. 1'i64) - when not defined(js): - # pending bug #16411 - test(10'u64 .. uint64.high) + test(10'u64 .. uint64.high) block: # bug #17670 - when not defined(js): - # pending bug #16411 - type UInt48 = range[0'u64..2'u64^48-1] - let x = rand(UInt48) - doAssert x is UInt48 + type UInt48 = range[0'u64..2'u64^48-1] + let x = rand(UInt48) + doAssert x is UInt48 block: # bug #17898 # Checks whether `initRand()` generates unique states. @@ -272,3 +284,27 @@ block: # bug #17898 for j in 0..<numRepeat: discard rands[i].next doAssert rands[i] notin randSet + +block: # bug #22360 + const size = 1000 + var fc = 0 + var tc = 0 + + for _ in 1..size: + let s = rand(bool) + + if s: + inc tc + else: + inc fc + + when defined(js) and not compileOption("jsbigint64"): + doAssert (tc, fc) == (515, 485), $(tc, fc) + else: + doAssert (tc, fc) == (510, 490), $(tc, fc) + +block: + when defined(js) and not compileOption("jsbigint64"): + doAssert rand(int32.high) == 335507522 + else: + doAssert rand(int32.high) == 607539621 diff --git a/tests/rational/trat_float.nim b/tests/stdlib/trat_float.nim index 663973bf9..663973bf9 100644 --- a/tests/rational/trat_float.nim +++ b/tests/stdlib/trat_float.nim diff --git a/tests/rational/trat_init.nim b/tests/stdlib/trat_init.nim index 2be0c0099..2be0c0099 100644 --- a/tests/rational/trat_init.nim +++ b/tests/stdlib/trat_init.nim diff --git a/tests/stdlib/trationals.nim b/tests/stdlib/trationals.nim index 0a3a95a9a..22d7f5c2d 100644 --- a/tests/stdlib/trationals.nim +++ b/tests/stdlib/trationals.nim @@ -1,10 +1,16 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/[rationals, math] +import std/assertions template main() = var z = Rational[int](num: 0, den: 1) o = initRational(num = 1, den = 1) a = initRational(1, 2) + u = 3u // 2 b = -1 // -2 m1 = -1 // 1 tt = 10 // 2 @@ -99,5 +105,13 @@ template main() = when sizeof(int) == 8: doAssert almostEqual(PI.toRational.toFloat, PI) + # unsigned + doAssert u == u + doAssert u + u == 3u // 1 + doAssert 3u.toRational - u == u + doAssert u * 2 == 3u // 1 + + + static: main() main() diff --git a/tests/stdlib/tre.nim b/tests/stdlib/tre.nim index 9f27f7db2..39637434d 100644 --- a/tests/stdlib/tre.nim +++ b/tests/stdlib/tre.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/re +import std/assertions proc testAll() = doAssert match("(a b c)", rex"\( .* \)") diff --git a/tests/misc/treadln.nim b/tests/stdlib/treadln.nim index b716c4711..4a070e848 100644 --- a/tests/misc/treadln.nim +++ b/tests/stdlib/treadln.nim @@ -6,6 +6,8 @@ Macintosh, Unix or Windows text format. ''' """ +import std/syncio + # test the improved readline handling that does not care whether its # Macintosh, Unix or Windows text format. @@ -13,7 +15,7 @@ var inp: File line: string -if open(inp, "tests/misc/treadln.nim"): +if open(inp, "tests/stdlib/treadln.nim"): while not endOfFile(inp): line = readLine(inp) if line.len >= 2 and line[0] == '#' and line[1] == ' ': diff --git a/tests/stdlib/tregex.nim b/tests/stdlib/tregex.nim index 21f4e6743..9dd66cd60 100644 --- a/tests/stdlib/tregex.nim +++ b/tests/stdlib/tregex.nim @@ -1,5 +1,6 @@ discard """ output: "key: keyAYes!" + matrix: "--mm:refc; --mm:orc" """ # Test the new regular expression module # which is based on the PCRE library @@ -11,7 +12,7 @@ when defined(powerpc64): else: import re - + import std/syncio if "keyA = valueA" =~ re"\s*(\w+)\s*\=\s*(\w+)": write(stdout, "key: ", matches[0]) elif "# comment!" =~ re.re"\s*(\#.*)": diff --git a/tests/stdlib/tregistry.nim b/tests/stdlib/tregistry.nim index 8bf084f6d..25aed8df8 100644 --- a/tests/stdlib/tregistry.nim +++ b/tests/stdlib/tregistry.nim @@ -1,10 +1,11 @@ discard """ disabled: "unix" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ when defined(windows): import std/registry + import std/assertions block: # bug #14010 let path = "Environment" diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim index 82c991805..3956b98f9 100644 --- a/tests/stdlib/trepr.nim +++ b/tests/stdlib/trepr.nim @@ -1,12 +1,13 @@ discard """ targets: "c cpp js" - matrix: ";--gc:arc" + matrix: "--mm:refc;--mm:arc" """ # if excessive, could remove 'cpp' from targets from strutils import endsWith, contains, strip from std/macros import newLit +import std/assertions macro deb(a): string = newLit a.repr.strip macro debTyped(a: typed): string = newLit a.repr.strip @@ -39,7 +40,7 @@ template main() = #[ BUG: --gc:arc returns `"abc"` - regular gc returns with address, e.g. 0x1068aae60"abc", but only + regular gc returns with address, e.g. 0x1068aae60"abc", but only for c,cpp backends (not js, vm) ]# block: @@ -270,5 +271,58 @@ func fn2(): int = ## comment result = 1""" + block: # block calls + let a = deb: + foo(a, b, (c, d)): + e + f + do: g + of h: i + elif j: k + except m: n + do () -> u: v + finally: o + + a + b: + c + d + do: + e + f + else: g + + *a: b + do: c + + doAssert a == """foo(a, b, (c, d)): + e + f +do: + g +of h: + i +elif j: + k +except m: + n +do -> u: + v +finally: + o +a + b: + c + d +do: + e + f +else: + g +*a: + b +do: + c""" + + doAssert repr(1..2) == "1 .. 2" + static: main() main() diff --git a/tests/stdlib/tropes.nim b/tests/stdlib/tropes.nim index 5a9150a33..eb0edc364 100644 --- a/tests/stdlib/tropes.nim +++ b/tests/stdlib/tropes.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/ropes +import std/assertions template main() = block: diff --git a/tests/stdlib/trst.nim b/tests/stdlib/trst.nim index a92ab2daa..ceab34bc9 100644 --- a/tests/stdlib/trst.nim +++ b/tests/stdlib/trst.nim @@ -7,6 +7,8 @@ discard """ [Suite] RST indentation +[Suite] Markdown indentation + [Suite] Warnings [Suite] RST include directive @@ -14,7 +16,10 @@ discard """ [Suite] RST escaping [Suite] RST inline markup + +[Suite] Misc isssues ''' +matrix: "--mm:refc; --mm:orc" """ # tests for rst module @@ -23,9 +28,12 @@ import ../../lib/packages/docutils/[rstgen, rst, rstast] import unittest, strutils import std/private/miscdollars import os +import std/[assertions, syncio] const preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled} +# legacy nimforum / old default mode: const preferRst = {roSupportMarkdown, roNimFile, roSandboxDisabled} +const pureRst = {roNimFile, roSandboxDisabled} proc toAst(input: string, rstOptions: RstParseOptions = preferMarkdown, @@ -57,13 +65,52 @@ proc toAst(input: string, result = "" var (rst, _, _) = rstParse(input, filen, line=LineRstInit, column=ColRstInit, - rstOptions, myFindFile, testMsgHandler) + rstOptions, myFindFile, nil, testMsgHandler) result = treeRepr(rst) except EParseError as e: if e.msg != "": result = e.msg suite "RST parsing": + test "Standalone punctuation is not parsed as heading overlines": + check(dedent""" + Paragraph + + !""".toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Paragraph' + rnParagraph + rnLeaf '!' + """) + + check(dedent""" + Paragraph1 + + ... + + Paragraph2""".toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Paragraph1' + rnParagraph + rnLeaf '...' + rnParagraph + rnLeaf 'Paragraph2' + """) + + check(dedent""" + --- + Paragraph""".toAst == + dedent""" + rnInner + rnLeaf '---' + rnLeaf ' ' + rnLeaf 'Paragraph' + """) + test "References are whitespace-neutral and case-insensitive": # refname is 'lexical-analysis', the same for all the 3 variants: check(dedent""" @@ -123,12 +170,12 @@ suite "RST parsing": check(dedent""" Paragraph:: - >x""".toAst == expected) + >x""".toAst(rstOptions = preferRst) == expected) check(dedent""" Paragraph:: - >x""".toAst == expected) + >x""".toAst(rstOptions = preferRst) == expected) test "RST quoted literal blocks, :: at a separate line": let expected = @@ -147,7 +194,7 @@ suite "RST parsing": :: >x - >>y""".toAst == expected) + >>y""".toAst(rstOptions = preferRst) == expected) check(dedent""" Paragraph @@ -155,7 +202,7 @@ suite "RST parsing": :: >x - >>y""".toAst == expected) + >>y""".toAst(rstOptions = preferRst) == expected) test "Markdown quoted blocks": check(dedent""" @@ -481,11 +528,77 @@ suite "RST parsing": rnFieldBody rnLeaf 'Nim' rnLiteralBlock - rnLeaf ' - let a = 1 + rnLeaf 'let a = 1 ```' """ + test "Markdown footnotes": + # Testing also 1) correct order of manually-numbered and automatically- + # numbered footnotes; 2) no spaces between references (html & 3 below): + + check(dedent""" + Paragraph [^1] [^html-hyphen][^3] and [^latex] + + [^1]: footnote1 + + [^html-hyphen]: footnote2 + continuation2 + + [^latex]: footnote4 + + [^3]: footnote3 + continuation3 + """.toAst == + dedent""" + rnInner + rnInner + rnLeaf 'Paragraph' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '1' + rnLeaf 'footnote-1' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '2' + rnLeaf 'footnote-htmlminushyphen' + rnFootnoteRef + rnInner + rnLeaf '3' + rnLeaf 'footnote-3' + rnLeaf ' ' + rnLeaf 'and' + rnLeaf ' ' + rnFootnoteRef + rnInner + rnLeaf '4' + rnLeaf 'footnote-latex' + rnFootnoteGroup + rnFootnote anchor='footnote-1' + rnInner + rnLeaf '1' + rnLeaf 'footnote1' + rnFootnote anchor='footnote-htmlminushyphen' + rnInner + rnLeaf '2' + rnInner + rnLeaf 'footnote2' + rnLeaf ' ' + rnLeaf 'continuation2' + rnFootnote anchor='footnote-latex' + rnInner + rnLeaf '4' + rnLeaf 'footnote4' + rnFootnote anchor='footnote-3' + rnInner + rnLeaf '3' + rnInner + rnLeaf 'footnote3' + rnLeaf ' ' + rnLeaf 'continuation3' + """) + test "Markdown code blocks with more > 3 backticks": check(dedent""" ```` @@ -525,8 +638,7 @@ suite "RST parsing": rnLeaf 'test' rnFieldBody rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf 'let a = 1' """) check(dedent""" @@ -549,8 +661,7 @@ suite "RST parsing": rnFieldBody rnLeaf '1' rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf 'let a = 1' """) test "additional indentation < 4 spaces is handled fine": @@ -570,8 +681,7 @@ suite "RST parsing": rnLeaf 'nim' [nil] rnLiteralBlock - rnLeaf ' - let a = 1' + rnLeaf ' let a = 1' """) # | | # | \ indentation of exactly two spaces before 'let a = 1' @@ -605,8 +715,7 @@ suite "RST parsing": rnFieldBody rnLeaf 'Nim' rnLiteralBlock - rnLeaf ' - CodeBlock()' + rnLeaf 'CodeBlock()' rnLeaf ' ' rnLeaf 'Other' rnLeaf ' ' @@ -686,6 +795,32 @@ suite "RST parsing": rnLeaf 'desc2' """) + test "definition lists work correctly with additional indentation in Markdown": + check(dedent""" + Paragraph: + -c desc1 + -b desc2 + """.toAst() == + dedent""" + rnInner + rnInner + rnLeaf 'Paragraph' + rnLeaf ':' + rnOptionList + rnOptionListItem order=1 + rnOptionGroup + rnLeaf '-' + rnLeaf 'c' + rnDescription + rnLeaf 'desc1' + rnOptionListItem order=2 + rnOptionGroup + rnLeaf '-' + rnLeaf 'b' + rnDescription + rnLeaf 'desc2' + """) + test "RST comment": check(dedent""" .. comment1 @@ -778,7 +913,7 @@ suite "RST parsing": code - """.toAst == + """.toAst(rstOptions = preferRst) == dedent""" rnInner rnLeaf 'Check' @@ -787,6 +922,32 @@ suite "RST parsing": rnLeaf 'code' """) + test "Markdown indented code blocks": + check(dedent""" + See + + some code""".toAst == + dedent""" + rnInner + rnInner + rnLeaf 'See' + rnLiteralBlock + rnLeaf 'some code' + """) + + # not a code block -- no blank line before: + check(dedent""" + See + some code""".toAst == + dedent""" + rnInner + rnLeaf 'See' + rnLeaf ' ' + rnLeaf 'some' + rnLeaf ' ' + rnLeaf 'code' + """) + suite "RST tables": test "formatting in tables works": @@ -822,10 +983,31 @@ suite "RST tables": ====== ====== Inputs Output ====== ====== - """.toAst(error=error) == "") + """.toAst(rstOptions = pureRst, error = error) == "") check(error[] == "input(2, 2) Error: Illformed table: " & "this word crosses table column from the right") + # In nimforum compatibility mode & Markdown we raise a warning instead: + let expected = dedent""" + rnTable colCount=2 + rnTableRow + rnTableDataCell + rnLeaf 'Inputs' + rnTableDataCell + rnLeaf 'Output' + """ + for opt in [preferRst, preferMarkdown]: + var warnings = new seq[string] + + check( + dedent""" + ====== ====== + Inputs Output + ====== ====== + """.toAst(rstOptions = opt, warnings = warnings) == expected) + check(warnings[] == @[ + "input(2, 2) Warning: RST style: this word crosses table column from the right"]) + test "tables with slightly overflowed cells cause an error (2)": var error = new string check("" == dedent""" @@ -834,7 +1016,7 @@ suite "RST tables": ===== ===== ====== False False False ===== ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(2, 8) Error: Illformed table: " & "this word crosses table column from the right") @@ -846,7 +1028,7 @@ suite "RST tables": ===== ===== ====== False False False ===== ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(2, 7) Error: Illformed table: " & "this word crosses table column from the left") @@ -859,7 +1041,7 @@ suite "RST tables": ===== ====== False False ===== ======= - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(5, 14) Error: Illformed table: " & "end of table column #2 should end at position 13") @@ -871,7 +1053,7 @@ suite "RST tables": ===== ======= False False ===== ====== - """.toAst(error=error)) + """.toAst(rstOptions = pureRst, error = error)) check(error[] == "input(3, 14) Error: Illformed table: " & "end of table column #2 should end at position 13") @@ -1237,6 +1419,31 @@ suite "RST indentation": rnLeaf 'term3definition2' """) +suite "Markdown indentation": + test "Markdown paragraph indentation": + # Additional spaces (<=3) of indentation does not break the paragraph. + # TODO: in 2nd case de-indentation causes paragraph to break, this is + # reasonable but does not seem to conform the Markdown spec. + check(dedent""" + Start1 + stop1 + + Start2 + stop2 + """.toAst == + dedent""" + rnInner + rnParagraph + rnLeaf 'Start1' + rnLeaf ' ' + rnLeaf 'stop1' + rnParagraph + rnLeaf 'Start2' + rnParagraph + rnLeaf 'stop2' + rnLeaf ' ' + """) + suite "Warnings": test "warnings for broken footnotes/links/substitutions": let input = dedent""" @@ -1775,3 +1982,13 @@ suite "RST inline markup": rnLeaf ')' """) check(warnings[] == @["input(1, 5) Warning: broken link 'f'"]) + +suite "Misc isssues": + test "Markdown CodeblockFields in one line (lacking enclosing ```)": + let message = """ + ```llvm-profdata merge first.profraw second.profraw third.profraw <more stuff maybe> -output data.profdata```""" + + try: + echo rstgen.rstToHtml(message, {roSupportMarkdown}, nil) + except EParseError: + discard diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 6edacfc24..6253e7146 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" outputsub: "" """ @@ -8,6 +9,7 @@ import ../../lib/packages/docutils/rstgen import ../../lib/packages/docutils/rst import unittest, strutils, strtabs import std/private/miscdollars +import std/assertions const NoSandboxOpts = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled} @@ -616,8 +618,8 @@ context2 This is too short to be a transition: --- - context2 +--- """ var error2 = new string let output2 = input2.toHtml(error=error2) @@ -631,7 +633,7 @@ Test literal block :: check """ - let output1 = input1.toHtml + let output1 = input1.toHtml(preferRst) doAssert "<pre>" in output1 test "Markdown code block": @@ -1126,7 +1128,7 @@ Test1 Paragraph2 ref `internal anchor`_. """ - let output9 = input9.toHtml + let output9 = input9.toHtml(preferRst) # _`internal anchor` got erased: check "href=\"#internal-anchor\"" notin output9 check "href=\"#citation-another\"" in output9 @@ -1154,7 +1156,7 @@ Test1 doAssert "<a href=\"#citation-third\">[Third]</a>" in output10 let input11 = ".. [note]\n" # should not crash - let output11 = input11.toHtml + let output11 = input11.toHtml(preferRst) doAssert "<a href=\"#citation-note\">[note]</a>" in output11 # check that references to auto-numbered footnotes work @@ -1244,7 +1246,7 @@ Test1 "input(8, 4) Warning: language 'anotherLang' not supported" ]) check(output == "<pre class = \"listing\">anything</pre>" & - "<p><pre class = \"listing\">\nsomeCode</pre> </p>") + "<p><pre class = \"listing\">someCode</pre> </p>") test "RST admonitions": # check that all admonitions are implemented @@ -1441,7 +1443,7 @@ Test1 Ref. target103_. """ - let output2 = input2.toHtml + let output2 = input2.toHtml(preferRst) # "target101" should be erased and changed to "section-xyz": doAssert "href=\"#target300\"" notin output2 doAssert "id=\"target300\"" notin output2 @@ -1683,3 +1685,8 @@ suite "local file inclusion": discard "```nim file = ./readme.md\n```".toHtml(error=error) check(error[] == "input(1, 23) Error: disabled directive: 'file'") +proc documentToHtml*(doc: string, isMarkdown: bool = false): string {.gcsafe.} = + var options = {roSupportMarkdown} + if isMarkdown: + options.incl roPreferMarkdown + result = rstToHtml(doc, options, defaultConfig()) diff --git a/tests/stdlib/tsequtils.nim b/tests/stdlib/tsequtils.nim index ddc023434..1094ae233 100644 --- a/tests/stdlib/tsequtils.nim +++ b/tests/stdlib/tsequtils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ @@ -7,6 +8,7 @@ discard """ import std/sequtils import strutils from algorithm import sorted +import std/assertions {.experimental: "strictEffects".} {.push warningAsError[Effect]: on.} @@ -387,6 +389,11 @@ block: # newSeqWith tests seq2D[0][1] = true doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]] +block: # bug #21538 + var x: seq[int] = @[2, 4] + var y = newSeqWith(x.pop(), true) + doAssert y == @[true, true, true, true] + block: # mapLiterals tests let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int) doAssert x is array[4, int] diff --git a/tests/stdlib/tsetutils.nim b/tests/stdlib/tsetutils.nim index f2fb81e6a..c8498f23e 100644 --- a/tests/stdlib/tsetutils.nim +++ b/tests/stdlib/tsetutils.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/setutils +import std/assertions type Colors = enum diff --git a/tests/stdlib/tsha1.nim b/tests/stdlib/tsha1.nim deleted file mode 100644 index 6dca1f197..000000000 --- a/tests/stdlib/tsha1.nim +++ /dev/null @@ -1,23 +0,0 @@ -import std/sha1 - -let hash1 = secureHash("a93tgj0p34jagp9[agjp98ajrhp9aej]") -doAssert hash1 == hash1 -doAssert parseSecureHash($hash1) == hash1 - -template checkVector(s, exp: string) = - doAssert secureHash(s) == parseSecureHash(exp) - -checkVector("", "da39a3ee5e6b4b0d3255bfef95601890afd80709") -checkVector("abc", "a9993e364706816aba3e25717850c26c9cd0d89d") -checkVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "84983e441c3bd26ebaae4aa1f95129e5e54670f1") - -proc testIsValidSha1Hash = - doAssert not isValidSha1Hash("") - doAssert not isValidSha1Hash("042D4BE2B90ED0672E717D71850ABDB0A2D19CD11") - doAssert not isValidSha1Hash("042G4BE2B90ED0672E717D71850ABDB0A2D19CD1") - doAssert isValidSha1Hash("042D4BE2B90ED0672E717D71850ABDB0A2D19CD1") - doAssert isValidSha1Hash("042d4be2b90ed0672e717d71850abdb0a2d19cd1") - doAssert isValidSha1Hash("042d4be2b90ed0672e717D71850ABDB0A2D19CD1") - -testIsValidSha1Hash() diff --git a/tests/stdlib/tsharedlist.nim b/tests/stdlib/tsharedlist.nim index 693f1018e..b91302d19 100644 --- a/tests/stdlib/tsharedlist.nim +++ b/tests/stdlib/tsharedlist.nim @@ -1,8 +1,9 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:orc; --mm:refc" """ import std/sharedlist +import std/assertions block: var diff --git a/tests/stdlib/tsharedtable.nim b/tests/stdlib/tsharedtable.nim index 0a8f7bcc0..10ad5f658 100644 --- a/tests/stdlib/tsharedtable.nim +++ b/tests/stdlib/tsharedtable.nim @@ -1,10 +1,11 @@ discard """ -cmd: "nim $target --threads:on $options $file" +matrix: "--mm:refc; --mm:orc" output: ''' ''' """ import sharedtables +import std/assertions block: var table: SharedTable[int, int] diff --git a/tests/stdlib/tsince.nim b/tests/stdlib/tsince.nim index d0320ff12..a0a4229cb 100644 --- a/tests/stdlib/tsince.nim +++ b/tests/stdlib/tsince.nim @@ -1,4 +1,5 @@ import std/private/since +import std/assertions proc fun1(): int {.since: (1, 3).} = 12 proc fun1Bad(): int {.since: (99, 3).} = 12 @@ -26,7 +27,6 @@ doAssert ok since (99, 3): doAssert false -when false: - # pending bug #15920 - # Error: cannot attach a custom pragma to 'fun3' - template fun3(): int {.since: (1, 3).} = 12 +template fun3(): int {.since: (1, 3).} = 12 + +doAssert declared(fun3) diff --git a/tests/stdlib/tsocketstreams.nim b/tests/stdlib/tsocketstreams.nim index 0cf952810..a37e7c34c 100644 --- a/tests/stdlib/tsocketstreams.nim +++ b/tests/stdlib/tsocketstreams.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: ''' OM NIM diff --git a/tests/stdlib/tsortcall.nim b/tests/stdlib/tsortcall.nim index 242e3fe4c..32e004921 100644 --- a/tests/stdlib/tsortcall.nim +++ b/tests/stdlib/tsortcall.nim @@ -1,5 +1,5 @@ discard """ -outputsub: "" + matrix: "--mm:refc; --mm:orc" """ import algorithm diff --git a/tests/stdlib/tsqlitebindatas.nim b/tests/stdlib/tsqlitebindatas.nim index b2c3247fa..e69de29bb 100644 --- a/tests/stdlib/tsqlitebindatas.nim +++ b/tests/stdlib/tsqlitebindatas.nim @@ -1,78 +0,0 @@ -discard """ - action: "run" - exitcode: 0 -""" -import db_sqlite -import random -import os -from stdtest/specialpaths import buildDir - -block tsqlitebindatas: ## db_sqlite binary data - const dbName = buildDir / "tsqlitebindatas.db" - - let origName = "Bobby" - var orig = newSeq[float64](150) - randomize() - for x in orig.mitems: - x = rand(1.0)/10.0 - - discard tryRemoveFile(dbName) - let db = open(dbName, "", "", "") - let createTableStr = sql"""CREATE TABLE test( - id INTEGER NOT NULL PRIMARY KEY, - name TEXT, - data BLOB - ) - """ - db.exec(createTableStr) - - var dbuf = newSeq[byte](orig.len*sizeof(float64)) - copyMem(addr(dbuf[0]), addr(orig[0]), dbuf.len) - - var insertStmt = db.prepare("INSERT INTO test (id, name, data) VALUES (?, ?, ?)") - insertStmt.bindParams(1, origName, dbuf) - let bres = db.tryExec(insertStmt) - doAssert(bres) - - finalize(insertStmt) - - var nameTest = db.getValue(sql"SELECT name FROM test WHERE id = ?", 1) - doAssert nameTest == origName - - var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1) - let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64)) - var res: seq[float64] = newSeq[float64](seqSize) - copyMem(addr(res[0]), addr(dataTest[0]), dataTest.len) - doAssert res.len == orig.len - doAssert res == orig - - db.close() - doAssert tryRemoveFile(dbName) - - -block: - block: - const dbName = buildDir / "db.sqlite3" - var db = db_sqlite.open(dbName, "", "", "") - var witness = false - try: - db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) - db.exec(sql("REPLACE INTO table (url, another_field) VALUES (?, '123');")) - except DbError as e: - witness = true - doAssert e.msg == "The number of \"?\" given exceeds the number of parameters present in the query." - finally: - db.close() - removeFile(dbName) - - doAssert witness - - block: - const dbName = buildDir / "db.sqlite3" - var db = db_sqlite.open(dbName, "", "", "") - try: - db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) - db.exec(sql("INSERT INTO table1 (url, other_field) VALUES (?, ?);"), "http://domain.com/test?param=1", 123) - finally: - db.close() - removeFile(dbName) diff --git a/tests/stdlib/tsqlparser.nim b/tests/stdlib/tsqlparser.nim index 11ee22e2b..6f123f21d 100644 --- a/tests/stdlib/tsqlparser.nim +++ b/tests/stdlib/tsqlparser.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''true''' """ diff --git a/tests/stdlib/tssl.nim b/tests/stdlib/tssl.nim index fd85cb55b..1628b9326 100644 --- a/tests/stdlib/tssl.nim +++ b/tests/stdlib/tssl.nim @@ -1,10 +1,12 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false - disabled: "freebsd" - disabled: "openbsd" + disabled: "freebsd" # see #15713 + disabled: "openbsd" # see #15713 + disabled: "netbsd" # see #15713 """ -# disabled: pending bug #15713 -import net, nativesockets + +import std/[net, nativesockets, assertions, typedthreads] when defined(posix): import os, posix else: @@ -16,22 +18,9 @@ when not defined(ssl): const DummyData = "dummy data\n" -proc createSocket(): Socket = - result = newSocket(buffered = false) - result.setSockOpt(OptReuseAddr, true) - result.setSockOpt(OptReusePort, true) - -proc createServer(serverContext: SslContext): (Socket, Port) = - var server = createSocket() - serverContext.wrapSocket(server) - server.bindAddr(address = "localhost") - let (_, port) = server.getLocalAddr() - server.listen() - return (server, port) - proc abruptShutdown(port: Port) {.thread.} = let clientContext = newContext(verifyMode = CVerifyNone) - var client = createSocket() + var client = newSocket(buffered = false) clientContext.wrapSocket(client) client.connect("localhost", port) @@ -40,7 +29,7 @@ proc abruptShutdown(port: Port) {.thread.} = proc notifiedShutdown(port: Port) {.thread.} = let clientContext = newContext(verifyMode = CVerifyNone) - var client = createSocket() + var client = newSocket(buffered = false) clientContext.wrapSocket(client) client.connect("localhost", port) @@ -62,7 +51,13 @@ proc main() = keyFile = "tests/testdata/mycert.pem") block peer_close_during_write_without_shutdown: - var (server, port) = createServer(serverContext) + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + var clientThread: Thread[Port] createThread(clientThread, abruptShutdown, port) @@ -80,14 +75,19 @@ proc main() = discard finally: peer.close() - server.close() when defined(posix): if sigaction(SIGPIPE, oldSigPipeHandler, nil) == -1: raiseOSError(osLastError(), "Couldn't restore SIGPIPE handler") block peer_close_before_received_shutdown: - var (server, port) = createServer(serverContext) + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + var clientThread: Thread[Port] createThread(clientThread, abruptShutdown, port) @@ -106,10 +106,15 @@ proc main() = discard peer.getFd.shutdown(SD_SEND) finally: peer.close() - server.close() block peer_close_after_received_shutdown: - var (server, port) = createServer(serverContext) + var server = newSocket(buffered = false) + defer: server.close() + serverContext.wrapSocket(server) + server.bindAddr(address = "localhost") + let (_, port) = server.getLocalAddr() + server.listen() + var clientThread: Thread[Port] createThread(clientThread, notifiedShutdown, port) @@ -129,6 +134,5 @@ proc main() = discard peer.getFd.shutdown(SD_SEND) finally: peer.close() - server.close() when isMainModule: main() diff --git a/tests/stdlib/tstackframes.nim b/tests/stdlib/tstackframes.nim index 618ff7b92..b0f05d51d 100644 --- a/tests/stdlib/tstackframes.nim +++ b/tests/stdlib/tstackframes.nim @@ -1,4 +1,4 @@ -import std/[strformat,os,osproc] +import std/[strformat,os,osproc,assertions] import stdtest/unittest_light proc main(opt: string, expected: string) = diff --git a/tests/stdlib/tstaticos.nim b/tests/stdlib/tstaticos.nim new file mode 100644 index 000000000..41ab995dd --- /dev/null +++ b/tests/stdlib/tstaticos.nim @@ -0,0 +1,8 @@ +import std/[assertions, staticos, os] + +block: + static: + doAssert staticDirExists("MISSINGFILE") == false + doAssert staticFileExists("MISSINGDIR") == false + doAssert staticDirExists(currentSourcePath().parentDir) + doAssert staticFileExists(currentSourcePath()) diff --git a/tests/stdlib/tstats.nim b/tests/stdlib/tstats.nim index 92a2ed8b8..728d93d09 100644 --- a/tests/stdlib/tstats.nim +++ b/tests/stdlib/tstats.nim @@ -1,7 +1,13 @@ -import std/stats +discard """ + matrix: "--mm:refc; --mm:orc" +""" -proc `~=`(x, y: float): bool = - abs(x - y) < 10e-8 +import std/[stats, assertions] +import std/math + + +func `~=`(x, y: float32): bool = + math.almostEqual(x, y) template main() = var rs: RunningStat @@ -28,21 +34,21 @@ template main() = doAssert rs1.kurtosis ~= rs.kurtosis rs1.clear() rs1.push(@[1.0, 2.2, 1.4, 4.9]) - doAssert(rs1.sum == 9.5) - doAssert(rs1.mean() == 2.375) + doAssert rs1.sum ~= 9.5 + doAssert rs1.mean() ~= 2.375 when not defined(cpu32): # XXX For some reason on 32bit CPUs these results differ var rr: RunningRegress rr.push(@[0.0, 1.0, 2.8, 3.0, 4.0], @[0.0, 1.0, 2.3, 3.0, 4.0]) - doAssert(rr.slope() == 0.9695585996955861) - doAssert(rr.intercept() == -0.03424657534246611) - doAssert(rr.correlation() == 0.9905100362239381) + doAssert rr.slope() ~= 0.9695585996955861 + doAssert rr.intercept() ~= -0.03424657534246611 + doAssert rr.correlation() ~= 0.9905100362239381 var rr1, rr2: RunningRegress rr1.push(@[0.0, 1.0], @[0.0, 1.0]) rr2.push(@[2.8, 3.0, 4.0], @[2.3, 3.0, 4.0]) let rr3 = rr1 + rr2 - doAssert(rr3.correlation() == rr.correlation()) + doAssert rr3.correlation() ~= rr.correlation() doAssert rr3.slope() ~= rr.slope() doAssert rr3.intercept() ~= rr.intercept() diff --git a/tests/stdlib/tstdlib_issues.nim b/tests/stdlib/tstdlib_issues.nim index 323bf09c6..b7b806db8 100644 --- a/tests/stdlib/tstdlib_issues.nim +++ b/tests/stdlib/tstdlib_issues.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" output: ''' 02 1 @@ -17,7 +18,7 @@ Second readLine raised an exception ''' """ -import terminal, colors, re, encodings, strutils, os +import std/[terminal, colors, re, encodings, strutils, os, assertions, syncio] block t9394: @@ -77,7 +78,7 @@ block t5349: const fn = "file9char.txt" writeFile(fn, "123456789") - var f = system.open(fn) + var f = syncio.open(fn) echo getFileSize(f) var line = newString(10) diff --git a/tests/stdlib/tstdlib_various.nim b/tests/stdlib/tstdlib_various.nim index bc90d6ef4..bac5018fa 100644 --- a/tests/stdlib/tstdlib_various.nim +++ b/tests/stdlib/tstdlib_various.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" output: ''' abc def @@ -26,15 +27,14 @@ Hi Andreas! How do you feel, Rumpf? [2, 3, 4, 5] [2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6] -true <h1><a href="http://force7.de/nim">Nim</a></h1> ''' """ import - critbits, sets, strutils, tables, random, algorithm, re, ropes, - segfaults, lists, parsesql, streams, os, htmlgen, xmltree, strtabs - + std/[critbits, sets, strutils, tables, random, algorithm, re, ropes, + segfaults, lists, parsesql, streams, os, htmlgen, xmltree, strtabs] +import std/[syncio, assertions] block tcritbits: var r: CritBitTree[void] @@ -206,11 +206,7 @@ block tsplit2: s.add("#") s.add(w) - try: - discard "hello".split("") - echo "false" - except AssertionDefect: - echo "true" + doAssert "true".split("") == @["true"] diff --git a/tests/stdlib/tstrbasics.nim b/tests/stdlib/tstrbasics.nim index bf562d9ec..a965ff15f 100644 --- a/tests/stdlib/tstrbasics.nim +++ b/tests/stdlib/tstrbasics.nim @@ -1,9 +1,9 @@ discard """ targets: "c cpp js" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ -import std/[strbasics, sugar] +import std/[strbasics, sugar, assertions] template strip2(input: string, args: varargs[untyped]): untyped = var a = input diff --git a/tests/stdlib/tstreams.nim b/tests/stdlib/tstreams.nim index cc1343651..60c63b450 100644 --- a/tests/stdlib/tstreams.nim +++ b/tests/stdlib/tstreams.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" input: "Arne" output: ''' Hello! What is your name? @@ -16,7 +16,7 @@ GROOT """ -import streams +import std/[syncio, streams, assertions] block tstreams: @@ -50,6 +50,12 @@ block tstreams3: echo line s.close + +block: + let fs = newFileStream("amissingfile.txt") + defer: fs.close() + doAssert isNil(fs) + # bug #12410 var a = newStringStream "hehohihahuhyh" @@ -86,6 +92,10 @@ static: # Ensure streams it doesnt break with nimscript on arc/orc #19716 let s = newStringStream("a") doAssert s.data == "a" +static: # issue #24054, readStr + var s = newStringStream("foo bar baz") + doAssert s.readStr(3) == "foo" + template main = var strm = newStringStream("abcde") var buffer = "12345" diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim index ea7be8297..ff406f898 100644 --- a/tests/stdlib/tstrformat.nim +++ b/tests/stdlib/tstrformat.nim @@ -1,10 +1,12 @@ -# xxx: test js target +discard """ + matrix: "--mm:refc; --mm:orc" +""" import genericstrformat import std/[strformat, strutils, times, tables, json] -when defined(nimPreviewSlimSystem): - import std/objectdollar +import std/[assertions, formatfloat] +import std/objectdollar proc main() = block: # issue #7632 @@ -475,15 +477,17 @@ proc main() = # Note: times.format adheres to the format protocol. Test that this # works: + when nimvm: + discard + else: + var dt = dateTime(2000, mJan, 01, 00, 00, 00) + check &"{dt:yyyy-MM-dd}", "2000-01-01" - var dt = initDateTime(01, mJan, 2000, 00, 00, 00) - check &"{dt:yyyy-MM-dd}", "2000-01-01" + var tm = fromUnix(0) + discard &"{tm}" - var tm = fromUnix(0) - discard &"{tm}" - - var noww = now() - check &"{noww}", $noww + var noww = now() + check &"{noww}", $noww # Unicode string tests check &"""{"αβγ"}""", "αβγ" @@ -558,5 +562,29 @@ proc main() = doAssert &"""{(if true: "'" & "'" & ')' else: "")}""" == "'')" doAssert &"{(if true: \"\'\" & \"'\" & ')' else: \"\")}" == "'')" doAssert fmt"""{(if true: "'" & ')' else: "")}""" == "')" -# xxx static: main() + + block: # issue #20381 + var ss: seq[string] + template myTemplate(s: string) = + ss.add s + ss.add s + proc foo() = + myTemplate fmt"hello" + foo() + doAssert ss == @["hello", "hello"] + + block: + proc noraises() {.raises: [].} = + const + flt = 0.0 + str = "str" + + doAssert fmt"{flt} {str}" == "0.0 str" + + noraises() + + block: + doAssert not compiles(fmt"{formatting errors detected at compile time") + +static: main() main() diff --git a/tests/stdlib/tstrformatlineinfo.nim b/tests/stdlib/tstrformatlineinfo.nim new file mode 100644 index 000000000..3a7bf0d33 --- /dev/null +++ b/tests/stdlib/tstrformatlineinfo.nim @@ -0,0 +1,8 @@ +# issue #21759 + +{.hint[ConvFromXToItselfNotNeeded]: on.} + +import std/strformat + +echo fmt"{string ""abc""}" #[tt.Hint + ^ conversion from string to itself is pointless]# diff --git a/tests/stdlib/tstrimpl.nim b/tests/stdlib/tstrimpl.nim new file mode 100644 index 000000000..a8933e53f --- /dev/null +++ b/tests/stdlib/tstrimpl.nim @@ -0,0 +1,12 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/private/strimpl + +import std/assertions + +doAssert find(cstring"Hello Nim", cstring"Nim") == 6 +doAssert find(cstring"Hello Nim", cstring"N") == 6 +doAssert find(cstring"Hello Nim", cstring"I") == -1 +doAssert find(cstring"Hello Nim", cstring"O") == -1 diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim index 3e2ccb251..b9b3c78a3 100644 --- a/tests/stdlib/tstring.nim +++ b/tests/stdlib/tstring.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ from std/sequtils import toSeq, map from std/sugar import `=>` +import std/assertions proc tester[T](x: T) = let test = toSeq(0..4).map(i => newSeq[int]()) diff --git a/tests/stdlib/tstrmiscs.nim b/tests/stdlib/tstrmiscs.nim index 2e9131ff8..b42f2e1fe 100644 --- a/tests/stdlib/tstrmiscs.nim +++ b/tests/stdlib/tstrmiscs.nim @@ -1,4 +1,9 @@ -import strmisc +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/strmisc +import std/assertions doAssert expandTabs("\t", 4) == " " diff --git a/tests/stdlib/tstrscans.nim b/tests/stdlib/tstrscans.nim index 24a3c02f7..ae7fd98ca 100644 --- a/tests/stdlib/tstrscans.nim +++ b/tests/stdlib/tstrscans.nim @@ -1,8 +1,8 @@ discard """ - output: "" + matrix: "--mm:refc; --mm:orc" """ -import strscans, strutils +import std/[strscans, strutils, assertions] block ParsePasswd: proc parsePasswd(content: string): seq[string] = diff --git a/tests/stdlib/tstrset.nim b/tests/stdlib/tstrset.nim index feae66ff7..bbb6c2677 100644 --- a/tests/stdlib/tstrset.nim +++ b/tests/stdlib/tstrset.nim @@ -1,3 +1,7 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + # test a simple yet highly efficient set of strings type @@ -6,7 +10,7 @@ type TRadixNode {.inheritable.} = object kind: TRadixNodeKind TRadixNodeLinear = object of TRadixNode - len: int8 + len: uint8 keys: array[0..31, char] vals: array[0..31, PRadixNode] TRadixNodeFull = object of TRadixNode @@ -24,7 +28,7 @@ proc search(r: PRadixNode, s: string): PRadixNode = case r.kind of rnLinear: var x = PRadixNodeLinear(r) - for j in 0..ze(x.len)-1: + for j in 0..int(x.len)-1: if x.keys[j] == s[i]: if s[i] == '\0': return r r = x.vals[j] @@ -63,9 +67,9 @@ proc excl*(r: var PRadixNode, s: string) = of rnFull: PRadixNodeFull(x).b['\0'] = nil of rnLinear: var x = PRadixNodeLinear(x) - for i in 0..ze(x.len)-1: + for i in 0..int(x.len)-1: if x.keys[i] == '\0': - swap(x.keys[i], x.keys[ze(x.len)-1]) + swap(x.keys[i], x.keys[int(x.len)-1]) dec(x.len) break diff --git a/tests/stdlib/tstrtabs.nim b/tests/stdlib/tstrtabs.nim index f629c183c..d261abe76 100644 --- a/tests/stdlib/tstrtabs.nim +++ b/tests/stdlib/tstrtabs.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" sortoutput: true output: ''' key1: value1 @@ -88,7 +89,7 @@ value1 = value2 ''' """ -import strtabs +import std/[strtabs, assertions, syncio] var tab = newStringTable({"key1": "val1", "key2": "val2"}, modeStyleInsensitive) diff --git a/tests/stdlib/tstrtabs.nims b/tests/stdlib/tstrtabs.nims index c8ed4ac40..3563ad0ad 100644 --- a/tests/stdlib/tstrtabs.nims +++ b/tests/stdlib/tstrtabs.nims @@ -1,4 +1,4 @@ -import strtabs +import std/[strtabs, assertions] static: let t = {"name": "John", "city": "Monaco"}.newStringTable diff --git a/tests/stdlib/tstrtabs2.nim b/tests/stdlib/tstrtabs2.nim index cb534f198..a4030ec77 100644 --- a/tests/stdlib/tstrtabs2.nim +++ b/tests/stdlib/tstrtabs2.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/strtabs +import std/assertions macro m = var t = {"name": "John"}.newStringTable @@ -13,3 +15,18 @@ block: doAssert t["name"] == "John" m() + +proc fun()= + let ret = newStringTable(modeCaseSensitive) + ret["foo"] = "bar" + + doAssert $ret == "{foo: bar}" + + let b = ret["foo"] + doAssert b == "bar" + +proc main()= + static: fun() + fun() + +main() diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim index e17277ef2..35f6bc669 100644 --- a/tests/stdlib/tstrutils.nim +++ b/tests/stdlib/tstrutils.nim @@ -1,9 +1,11 @@ discard """ - targets: "c cpp js" + matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ import std/strutils from stdtest/testutils import disableVm +import std/assertions +import std/private/jsutils # xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed template rejectParse(e) = @@ -51,6 +53,15 @@ template main() = doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "] doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "] doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "] + # Empty string: + doAssert "".split() == @[""] + doAssert "".split(" ") == @[""] + doAssert "".split({' '}) == @[""] + # Empty separators: + doAssert "".split({}) == @[""] + doAssert "".split("") == @[""] + doAssert s.split({}) == @[s] + doAssert s.split("") == @[s] block: # splitLines let fixture = "a\nb\rc\r\nd" @@ -61,12 +72,21 @@ template main() = block: # rsplit doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"] doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"] - doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[ - " foo bar", ""] + doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[" foo bar", ""] doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"] doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"] doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"] doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"] + # Empty string: + doAssert "".rsplit() == @[""] + doAssert "".rsplit(" ") == @[""] + doAssert "".rsplit({' '}) == @[""] + # Empty separators: + let s = " this is an example " + doAssert "".rsplit({}) == @[""] + doAssert "".rsplit("") == @[""] + doAssert s.rsplit({}) == @[s] + doAssert s.rsplit("") == @[s] block: # splitWhitespace let s = " this is an example " @@ -360,19 +380,23 @@ template main() = doAssert "///".rfind("//", start=3) == -1 # searching for empty string - doAssert "".rfind("") == -1 - doAssert "abc".rfind("") == -1 - doAssert "abc".rfind("", start=1) == -1 - doAssert "abc".rfind("", start=2) == -1 - doAssert "abc".rfind("", start=3) == -1 - doAssert "abc".rfind("", start=4) == -1 - doAssert "abc".rfind("", start=400) == -1 - - doAssert "abc".rfind("", start=1, last=3) == -1 - doAssert "abc".rfind("", start=1, last=2) == -1 - doAssert "abc".rfind("", start=1, last=1) == -1 - doAssert "abc".rfind("", start=1, last=0) == -1 - doAssert "abc".rfind("", start=1, last = -1) == -1 + doAssert "".rfind("") == 0 + doAssert "abc".rfind("") == 3 + doAssert "abc".rfind("", start=1) == 3 + doAssert "abc".rfind("", start=2) == 3 + doAssert "abc".rfind("", start=3) == 3 + doAssert "abc".rfind("", start=4) == 4 + doAssert "abc".rfind("", start=400) == 400 + + doAssert "abc".rfind("", start=1, last=3) == 3 + doAssert "abc".rfind("", start=1, last=2) == 2 + doAssert "abc".rfind("", start=1, last=1) == 1 + # This returns the start index instead of the last index + # because start > last + doAssert "abc".rfind("", start=1, last=0) == 1 + doAssert "abc".rfind("", start=1, last = -1) == 3 + + doAssert "abc".rfind("", start=0, last=0) == 0 # when last <= start, searching for non-empty string block: @@ -428,6 +452,9 @@ template main() = x = "1e0" x.trimZeros() doAssert x == "1e0" + x = "1.23" + x.trimZeros() + doAssert x == "1.23" block: # countLines proc assertCountLines(s: string) = doAssert s.countLines == s.splitLines.len @@ -500,8 +527,9 @@ template main() = block: # toHex doAssert(toHex(100i16, 32) == "00000000000000000000000000000064") - doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C") - when not defined js: + whenJsNoBigInt64: discard + do: + doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C") doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF") doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF") doAssert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF") @@ -522,11 +550,12 @@ template main() = doAssert(spaces(0) == "") block: # toBin, toOct - block:# bug #11369 + whenJsNoBigInt64: # bug #11369 + discard + do: var num: int64 = -1 - when not defined js: - doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111" - doAssert num.toOct(24) == "001777777777777777777777" + doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111" + doAssert num.toOct(24) == "001777777777777777777777" block: # replace doAssert "oo".replace("", "abc") == "oo" @@ -650,11 +679,22 @@ template main() = doAssert b == f2 doAssert c == f3 - block: # parseEnum TODO: merge above - type MyEnum = enum enA, enB, enC, enuD, enE - doAssert parseEnum[MyEnum]("enu_D") == enuD - - doAssert parseEnum("invalid enum value", enC) == enC + block: + type MyEnum = enum enA, enB, enC, enuD, enE + doAssert parseEnum[MyEnum]("enu_D") == enuD + + doAssert parseEnum("invalid enum value", enC) == enC + + block: # issue #22726 + type SomeEnum = enum A, B, C + + proc assignEnum(dest: var enum, s: string) = + type ty = typeof(dest) + dest = parseEnum[ty](s) + + var v: SomeEnum + v.assignEnum("A") + doAssert v == A block: # indentation doAssert 0 == indentation """ @@ -733,7 +773,8 @@ bar block: # formatSize disableVm: - when not defined(js): + whenJsNoBigInt64: discard + do: doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231 doAssert formatSize((2.234*1024*1024).int) == "2.234MiB" doAssert formatSize(4096) == "4KiB" @@ -863,5 +904,10 @@ bar doAssert nimIdentNormalize("Foo_bar") == "Foobar" doAssert nimIdentNormalize("_Foo_bar") == "_foobar" + block: # bug #19500 + doAssert "abc \0 def".find("def") == 6 + doAssert "abc \0 def".find('d') == 6 + + static: main() main() diff --git a/tests/stdlib/tstrutils2.nim b/tests/stdlib/tstrutils2.nim deleted file mode 100644 index a8bf08eed..000000000 --- a/tests/stdlib/tstrutils2.nim +++ /dev/null @@ -1,37 +0,0 @@ -discard """ - matrix: "--gc:refc; --gc:orc" -""" - -import "$lib/.." / compiler/strutils2 - -block: # setLen - var a = "abc" - a.setLen 0 - a.setLen 3, isInit = false - when defined(gcRefc): # bug #19763 - doAssert a[1] == 'b' - a.setLen 0 - a.setLen 3, isInit = true - doAssert a[1] == '\0' - -block: # forceCopy - var a: string - a = "foo" - shallow(a) - var b: string - b = a - doAssert b[0].addr == a[0].addr - var c: string - c.forceCopy a - doAssert c == a - doAssert c[0].addr != a[0].addr - -block: # toLowerAscii - var a = "fooBAr" - a.toLowerAscii - doAssert a == "foobar" - -block: # dataPointer - var a: string - discard a.dataPointer - # doAssert a.dataPointer == nil # not guaranteed diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim index 72abadae7..2ea96cfbb 100644 --- a/tests/stdlib/tsugar.nim +++ b/tests/stdlib/tsugar.nim @@ -1,9 +1,33 @@ discard """ + targets: "c js" + matrix: "--mm:refc; --mm:orc" output: ''' x + y = 30 ''' """ -import std/[sugar, algorithm, random, sets, tables, strutils] +import std/[sugar, algorithm, random, sets, tables, strutils, sequtils] +import std/[syncio, assertions] + +type # for capture test, ref #20679 + FooCapture = ref object + x: int + +proc mainProc() = + block: # bug #16967 + var s = newSeq[proc (): int](5) + {.push exportc.} + proc bar() = + for i in 0 ..< s.len: + let foo = i + 1 + capture foo: + s[i] = proc(): int = foo + {.pop.} + + bar() + + for i, p in s.pairs: + let foo = i + 1 + doAssert p() == foo template main() = block: # `=>` @@ -79,21 +103,61 @@ template main() = closure2 = () => (i, j) doAssert closure2() == (5, 3) - block: # bug #16967 - var s = newSeq[proc (): int](5) - {.push exportc.} - proc bar() = - for i in 0 ..< s.len: - let foo = i + 1 - capture foo: - s[i] = proc(): int = foo - {.pop.} + block: # issue #20679 + # this should compile. Previously was broken as `var int` is an `nnkHiddenDeref` + # which was not handled correctly - bar() + block: + var x = 5 + var s1 = newSeq[proc (): int](2) + proc function(data: var int) = + for i in 0 ..< 2: + data = (i+1) * data + capture data: + s1[i] = proc(): int = data + function(x) + doAssert s1[0]() == 5 + doAssert s1[1]() == 10 - for i, p in s.pairs: - let foo = i + 1 - doAssert p() == foo + + block: + var y = @[5, 10] + var s2 = newSeq[proc (): seq[int]](2) + proc functionS(data: var seq[int]) = + for i in 0 ..< 2: + data.add (i+1) * 5 + capture data: + s2[i] = proc(): seq[int] = data + functionS(y) + doAssert s2[0]() == @[5, 10, 5] + doAssert s2[1]() == @[5, 10, 5, 10] + + + template typeT(typ, val: untyped): untyped = + var x = val + var s = newSeq[proc (): typ](2) + + proc functionT[T](data: var T) = + for i in 0 ..< 2: + if i == 1: + data = default(T) + capture data: + s[i] = proc (): T = data + + functionT(x) + doAssert s[0]() == val + doAssert s[1]() == x # == default + doAssert s[1]() == default(typ) + + block: + var x = 1.1 + typeT(float, x) + block: + var x = "hello" + typeT(string, x) + block: + var f = FooCapture(x: 5) + typeT(FooCapture, f) block: # dup block dup_with_field: @@ -208,17 +272,16 @@ template main() = discard collect(newSeq, for i in 1..3: i) foo() -proc mainProc() = block: # dump # symbols in templates are gensym'd let - x = 10 - y = 20 + x {.inject.} = 10 + y {.inject.} = 20 dump(x + y) # x + y = 30 block: # dumpToString template square(x): untyped = x * x - let x = 10 + let x {.inject.} = 10 doAssert dumpToString(square(x)) == "square(x): x * x = 100" let s = dumpToString(doAssert 1+1 == 2) doAssert "failedAssertImpl" in s @@ -226,8 +289,22 @@ proc mainProc() = doAssertRaises(AssertionDefect): doAssert false doAssert "except AssertionDefect" in s2 -static: - main() + block: # bug #20704 + proc test() = + var xs, ys: seq[int] + for i in 0..5: + xs.add(i) + + xs.apply(proc (d: auto) = ys.add(d)) + # ^ can be turned into d => ys.add(d) when we can infer void return type, #16906 + doAssert ys == @[0, 1, 2, 3, 4, 5] + + test() + mainProc() + +when not defined(js): # TODO fixme JS VM + static: + main() + main() -mainProc() diff --git a/tests/stdlib/tsums.nim b/tests/stdlib/tsums.nim index 4c29d3e10..cf410cddf 100644 --- a/tests/stdlib/tsums.nim +++ b/tests/stdlib/tsums.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/sums from math import pow +import std/assertions var epsilon = 1.0 while 1.0 + epsilon != 1.0: diff --git a/tests/stdlib/tsysrand.nim b/tests/stdlib/tsysrand.nim index c6d43a8fb..7b7a0fc34 100644 --- a/tests/stdlib/tsysrand.nim +++ b/tests/stdlib/tsysrand.nim @@ -1,10 +1,10 @@ discard """ targets: "c cpp js" - matrix: "--experimental:vmopsDanger" + matrix: "--experimental:vmopsDanger; --experimental:vmopsDanger --mm:refc" """ import std/sysrand - +import std/assertions template main() = block: diff --git a/tests/stdlib/tsystem.nim b/tests/stdlib/tsystem.nim index a90a1d1d9..f634ce0c2 100644 --- a/tests/stdlib/tsystem.nim +++ b/tests/stdlib/tsystem.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import stdtest/testutils +import std/[assertions, formatfloat] # TODO: in future work move existing `system` tests here, where they belong @@ -81,12 +83,84 @@ block: X = object a: string b: set[char] + c: int + d: float + e: int64 - var y = X(b: {'a'}) + + var x = X(b: {'a'}, e: 10) + + var y = move x + + doAssert x.a == "" + doAssert x.b == {} + doAssert x.c == 0 + doAssert x.d == 0.0 + doAssert x.e == 0 reset(y) + doAssert y.a == "" doAssert y.b == {} + doAssert y.c == 0 + doAssert y.d == 0.0 + doAssert y.e == 0 + +block: + var x = 2 + var y = move x + doAssert y == 2 + doAssert x == 0 + reset y + doAssert y == 0 + +block: + type + X = object + a: string + b: float + + var y = X(b: 1314.521) + + reset(y) + + doAssert y.b == 0.0 + +block: + type + X = object + a: string + b: string + + var y = X(b: "1314") + + reset(y) + + doAssert y.b == "" + +block: + type + X = object + a: string + b: seq[int] + + var y = X(b: @[1, 3]) + + reset(y) + + doAssert y.b == @[] + +block: + type + X = object + a: string + b: tuple[a: int, b: string] + + var y = X(b: (1, "cc")) + + reset(y) + + doAssert y.b == (0, "") block: type @@ -101,3 +175,26 @@ block: reset(y) doAssert y.b == {} +block: # bug #20516 + type Foo = object + x {.bitsize:4.}: uint + y {.bitsize:4.}: uint + + when not defined(js): + let a = create(Foo) + +block: # bug #6549 + when not defined(js): + block: + const v = 18446744073709551615'u64 + + doAssert $v == "18446744073709551615" + doAssert $float32(v) == "1.8446744e+19", $float32(v) + doAssert $float64(v) == "1.8446744073709552e+19", $float64(v) + + block: + let v = 18446744073709551615'u64 + + doAssert $v == "18446744073709551615" + doAssert $float32(v) == "1.8446744e+19" + doAssert $float64(v) == "1.8446744073709552e+19" diff --git a/tests/stdlib/ttables.nim b/tests/stdlib/ttables.nim index c1ae89b32..c529aff9f 100644 --- a/tests/stdlib/ttables.nim +++ b/tests/stdlib/ttables.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import tables, hashes +import std/assertions type Person = object diff --git a/tests/stdlib/ttasks.nim b/tests/stdlib/ttasks.nim index e90823aba..ba65590d9 100644 --- a/tests/stdlib/ttasks.nim +++ b/tests/stdlib/ttasks.nim @@ -4,6 +4,7 @@ discard """ """ import std/[tasks, strformat] +import std/assertions block: var s = "" @@ -504,3 +505,57 @@ block: b.invoke() doAssert called == 36 + + block: + proc returnsSomething(a, b: int): int = a + b + + proc noArgsButReturnsSomething(): string = "abcdef" + + proc testReturnValues() = + let t = toTask returnsSomething(2233, 11) + var res: int + t.invoke(addr res) + doAssert res == 2233+11 + + let tb = toTask noArgsButReturnsSomething() + var resB: string + tb.invoke(addr resB) + doAssert resB == "abcdef" + + testReturnValues() + + +block: # bug #23635 + block: + type + Store = object + run: proc (a: int) {.nimcall, gcsafe.} + + block: + var count = 0 + proc hello(a: int) = + inc count, a + + var store = Store() + store.run = hello + + let b = toTask store.run(13) + b.invoke() + doAssert count == 13 + + block: + type + Store = object + run: proc () {.nimcall, gcsafe.} + + block: + var count = 0 + proc hello() = + inc count, 1 + + var store = Store() + store.run = hello + + let b = toTask store.run() + b.invoke() + doAssert count == 1 diff --git a/tests/stdlib/ttempfiles.nim b/tests/stdlib/ttempfiles.nim index 297410686..352788c42 100644 --- a/tests/stdlib/ttempfiles.nim +++ b/tests/stdlib/ttempfiles.nim @@ -1,9 +1,11 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false # not strictly necessary """ import std/tempfiles import std/[os, nre] +import std/[assertions, syncio] const prefix = "D20210502T100442" # safety precaution to only affect files/dirs with this prefix diff --git a/tests/stdlib/tterminal.nim b/tests/stdlib/tterminal.nim index 364c8d82e..16365e71c 100644 --- a/tests/stdlib/tterminal.nim +++ b/tests/stdlib/tterminal.nim @@ -1,7 +1,6 @@ discard """ action: compile """ - import terminal, colors styledEcho fgColor, colRed, "Test" diff --git a/tests/stdlib/tterminal_12759.nim b/tests/stdlib/tterminal_12759.nim index d6034ab57..e9ea3127c 100644 --- a/tests/stdlib/tterminal_12759.nim +++ b/tests/stdlib/tterminal_12759.nim @@ -3,6 +3,7 @@ discard """ """ import terminal +import std/syncio proc test() {.raises:[IOError, ValueError].} = setBackgroundColor(stdout, bgRed) diff --git a/tests/stdlib/ttestutils.nim b/tests/stdlib/ttestutils.nim index d24c5b39a..0f8bf16cf 100644 --- a/tests/stdlib/ttestutils.nim +++ b/tests/stdlib/ttestutils.nim @@ -1,4 +1,5 @@ import stdtest/testutils +import std/assertions block: # assertAll assertAll: diff --git a/tests/stdlib/tthreadpool.nim b/tests/stdlib/tthreadpool.nim index 897c7d173..1947074be 100644 --- a/tests/stdlib/tthreadpool.nim +++ b/tests/stdlib/tthreadpool.nim @@ -1,9 +1,9 @@ discard """ - matrix: "--threads:on --gc:arc" + matrix: "--mm:arc; --mm:refc" disabled: "freebsd" output: "42" """ - +import std/assertions from std/threadpool import spawn, `^`, sync block: # bug #12005 proc doworkok(i: int) {.thread.} = echo i diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index fd440eb20..0f04168dc 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -1,8 +1,9 @@ discard """ - targets: "c js" + matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off -d:nimStringHash2" """ import times, strutils, unittest +import std/assertions when not defined(js): import os @@ -10,12 +11,12 @@ when not defined(js): proc staticTz(hours, minutes, seconds: int = 0): Timezone {.noSideEffect.} = let offset = hours * 3600 + minutes * 60 + seconds - proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime {.locks: 0.} = + proc zonedTimeFromAdjTime(adjTime: Time): ZonedTime = result.isDst = false result.utcOffset = offset result.time = adjTime + initDuration(seconds = offset) - proc zonedTimeFromTime(time: Time): ZonedTime {.locks: 0.}= + proc zonedTimeFromTime(time: Time): ZonedTime = result.isDst = false result.utcOffset = offset result.time = time @@ -70,7 +71,7 @@ template runTimezoneTests() = "2006-01-12T22:04:05Z", 11) # RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" parseTest("2006-01-12T15:04:05.999999999Z-07:00", - "yyyy-MM-dd'T'HH:mm:ss'.999999999Z'zzz", "2006-01-12T22:04:05Z", 11) + "yyyy-MM-dd'T'HH:mm:ss.'999999999Z'zzz", "2006-01-12T22:04:05Z", 11) for tzFormat in ["z", "zz", "zzz"]: # formatting timezone as 'Z' for UTC parseTest("2001-01-12T22:04:05Z", "yyyy-MM-dd'T'HH:mm:ss" & tzFormat, @@ -741,3 +742,43 @@ block: # ttimes doAssert getWeeksInIsoYear(2014.IsoYear) == 52 doAssert getWeeksInIsoYear(2015.IsoYear) == 53 doAssert getWeeksInIsoYear(2016.IsoYear) == 52 + + block: # parse and generate iso years + # short calendar week with text + parseTest("KW 23 2023", "'KW' VV GGGG", + "2023-06-05T00:00:00Z", 155) + parseTest("KW 5 2023", "'KW' V GGGG", + "2023-01-30T00:00:00Z", 29) + parseTest("KW 05 23 Saturday", "'KW' V GG dddd", + "2023-02-04T00:00:00Z", 34) + parseTest("KW 53 20 Fri", "'KW' VV GG ddd", + "2021-01-01T00:00:00Z", 0) + + parseTestExcp("KW 23", "'KW' VV") # no year + parseTestExcp("KW 23", "'KW' V") # no year + parseTestExcp("KW 23", "'KW' GG") # no week + parseTestExcp("KW 2023", "'KW' GGGG") # no week + + var dt = initDateTime(5, mJan, 2023, 0, 0, 0, utc()) + check dt.format("V") == "1" + check dt.format("VV") == "01" + check dt.format("GG") == "23" + check dt.format("GGGG") == "2023" + check dt.format("dddd 'KW'V GGGG") == "Thursday KW1 2023" + + block: # Can be used inside gcsafe proc + proc test(): DateTime {.gcsafe.} = + result = "1970".parse("yyyy") + doAssert test().year == 1970 + + block: # test FormatLiterals + # since #23861 + block: + let dt = dateTime(2024, mJul, 21, 17, 01, 02, 123_321_123, utc()) + check dt.format("ss.fff") == "02.123" + check dt.format("fff.ffffff") == "123.123321" + block: + let dt = parse("2024.07.21", "yyyy.MM.dd") + check dt.year == 2024 + check dt.month == mJul + check dt.monthday == 21 diff --git a/tests/stdlib/ttypeinfo.nim b/tests/stdlib/ttypeinfo.nim index 1cddea781..9bbc2e92c 100644 --- a/tests/stdlib/ttypeinfo.nim +++ b/tests/stdlib/ttypeinfo.nim @@ -1,4 +1,9 @@ -import typeinfo +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/typeinfo +import std/assertions type TE = enum @@ -69,3 +74,20 @@ block: doAssert getEnumOrdinal(y, "Hello") == 0 doAssert getEnumOrdinal(y, "hello") == 1 + +block: # bug #23556 + proc test = + var + t: seq[int] + aseq = toAny(t) + + invokeNewSeq(aseq, 0) + + # Got random value only when loop 8 times. + for i in 1 .. 8: + extendSeq(aseq) + + doAssert t == @[0, 0, 0, 0, 0, 0, 0, 0] + + for i in 1 .. 7: + test() diff --git a/tests/stdlib/ttypetraits.nim b/tests/stdlib/ttypetraits.nim index 799bcf6e2..6851b9220 100644 --- a/tests/stdlib/ttypetraits.nim +++ b/tests/stdlib/ttypetraits.nim @@ -1,10 +1,12 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ # xxx merge with tests/metatype/ttypetraits.nim import std/typetraits +import std/assertions macro testClosure(fn: typed, flag: static bool) = if flag: diff --git a/tests/stdlib/tunicode.nim b/tests/stdlib/tunicode.nim index 3a8206c8f..b9e68b15b 100644 --- a/tests/stdlib/tunicode.nim +++ b/tests/stdlib/tunicode.nim @@ -1,5 +1,9 @@ -import std/unicode +discard """ + matrix: "--mm:refc; --mm:orc" +""" +import std/unicode +import std/assertions proc asRune(s: static[string]): Rune = ## Compile-time conversion proc for converting string literals to a Rune @@ -53,6 +57,7 @@ doAssert isAlpha("r") doAssert isAlpha("α") doAssert isAlpha("ϙ") doAssert isAlpha("ஶ") +doAssert isAlpha("网") doAssert(not isAlpha("$")) doAssert(not isAlpha("")) @@ -62,6 +67,7 @@ doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽") doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει") doAssert isAlpha("Јамогујестистаклоитоминештети") doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ") +doAssert isAlpha("编程语言") doAssert(not isAlpha("$Foo✓")) doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞")) diff --git a/tests/stdlib/tunidecode.nim b/tests/stdlib/tunidecode.nim index be8e0523c..653016ea9 100644 --- a/tests/stdlib/tunidecode.nim +++ b/tests/stdlib/tunidecode.nim @@ -5,6 +5,7 @@ discard """ import unidecode import std/unidecode # #14112 +import std/assertions loadUnidecodeTable("lib/pure/unidecode/unidecode.dat") diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim index 97a45e199..0442c7863 100644 --- a/tests/stdlib/tunittest.nim +++ b/tests/stdlib/tunittest.nim @@ -19,10 +19,12 @@ discard """ [Suite] test name filtering ''' +matrix: "--mm:refc; --mm:orc" targets: "c js" """ -import std/[unittest, sequtils] +import std/[unittest, sequtils, assertions] +from std/unittest {.all.} import matchFilter proc doThings(spuds: var int): int = spuds = 24 diff --git a/tests/stdlib/tunittestpass.nim b/tests/stdlib/tunittestpass.nim index cff37a3b7..d8de277b7 100644 --- a/tests/stdlib/tunittestpass.nim +++ b/tests/stdlib/tunittestpass.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ diff --git a/tests/stdlib/tunittesttemplate.nim b/tests/stdlib/tunittesttemplate.nim index 2ca50a18b..c29e0de01 100644 --- a/tests/stdlib/tunittesttemplate.nim +++ b/tests/stdlib/tunittesttemplate.nim @@ -8,9 +8,9 @@ discard """ """ -# bug #6736 -import unittest +# bug #6736 +import std/unittest type A = object diff --git a/tests/stdlib/tunixsocket.nim b/tests/stdlib/tunixsocket.nim new file mode 100644 index 000000000..636fd08c6 --- /dev/null +++ b/tests/stdlib/tunixsocket.nim @@ -0,0 +1,35 @@ +import std/[assertions, net, os, osproc] + +# XXX: Make this test run on Windows too when we add support for Unix sockets on Windows +when defined(posix) and not defined(nimNetLite): + const nim = getCurrentCompilerExe() + let + dir = currentSourcePath().parentDir() + serverPath = dir / "unixsockettest" + + let (_, err) = execCmdEx(nim & " c " & quoteShell(dir / "unixsockettest.nim")) + doAssert err == 0 + + let svproc = startProcess(serverPath, workingDir = dir) + doAssert svproc.running() + # Wait for the server to open the socket and listen from it + sleep(400) + + block unixSocketSendRecv: + let + unixSocketPath = dir / "usox" + socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE) + + socket.connectUnix(unixSocketPath) + # for a blocking Unix socket this should never fail + socket.send("data sent through the socket\c\l", maxRetries = 0) + var resp: string + socket.readLine(resp) + doAssert resp == "Hello from server" + + socket.send("bye\c\l") + socket.readLine(resp) + doAssert resp == "bye" + socket.close() + + svproc.close() diff --git a/tests/stdlib/turi.nim b/tests/stdlib/turi.nim index 79ddd773b..9c717c5b1 100644 --- a/tests/stdlib/turi.nim +++ b/tests/stdlib/turi.nim @@ -1,10 +1,12 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c js" """ import std/uri from std/uri {.all.} as uri2 import removeDotSegments from std/sequtils import toSeq +import std/assertions template main() = block: # encodeUrl, decodeUrl diff --git a/tests/stdlib/tuserlocks.nim b/tests/stdlib/tuserlocks.nim index 9251fa9e2..927077120 100644 --- a/tests/stdlib/tuserlocks.nim +++ b/tests/stdlib/tuserlocks.nim @@ -1,8 +1,9 @@ discard """ - matrix: "--threads:on" + matrix: "--mm:refc; --mm:orc" """ import std/rlocks +import std/assertions var r: RLock r.initRLock() diff --git a/tests/stdlib/tvarargs.nim b/tests/stdlib/tvarargs.nim index d56be154b..2edc26264 100644 --- a/tests/stdlib/tvarargs.nim +++ b/tests/stdlib/tvarargs.nim @@ -1,8 +1,8 @@ discard """ targets: "c js" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:orc" """ - +import std/assertions template main = proc hello(x: varargs[string]): seq[string] = diff --git a/tests/stdlib/tvarints.nim b/tests/stdlib/tvarints.nim index 3bba4f457..f9624ee5b 100644 --- a/tests/stdlib/tvarints.nim +++ b/tests/stdlib/tvarints.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/varints +import std/assertions # xxx doesn't work with js: tvarints.nim(18, 14) `wrLen == rdLen` [AssertionDefect] @@ -28,7 +33,7 @@ block: doAssert cast[float64](got) == test block: - var hugeIntArray: array[50, byte] + var hugeIntArray: array[9, byte] var readedInt: uint64 template chk(a) = diff --git a/tests/stdlib/tvmutils.nim b/tests/stdlib/tvmutils.nim index f43557ad8..63804c136 100644 --- a/tests/stdlib/tvmutils.nim +++ b/tests/stdlib/tvmutils.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc" joinable: false nimout: ''' 0 @@ -19,7 +20,6 @@ tvmutils.nim(29, 14) [opcIndCall] vmTrace(false) """ # line 20 (only showing a subset of nimout to avoid making the test rigid) import std/vmutils - proc main() = for i in 0..<7: echo i diff --git a/tests/stdlib/tvolatile.nim b/tests/stdlib/tvolatile.nim new file mode 100644 index 000000000..c097f9723 --- /dev/null +++ b/tests/stdlib/tvolatile.nim @@ -0,0 +1,15 @@ +import std/[volatile, assertions] + +var st: int +var foo: ptr int = addr st +volatileStore(foo, 12) +doAssert volatileLoad(foo) == 12 + +# bug #14623 +proc bar = + var st: int + var foo: ptr int = addr st + volatileStore(foo, 12) + doAssert volatileLoad(foo) == 12 + +bar() diff --git a/tests/stdlib/twchartoutf8.nim b/tests/stdlib/twchartoutf8.nim index a6602e3e3..e437177ac 100644 --- a/tests/stdlib/twchartoutf8.nim +++ b/tests/stdlib/twchartoutf8.nim @@ -1,13 +1,17 @@ discard """ + matrix: "--mm:refc; --mm:orc" output: '''OK''' """ +import std/[syncio, assertions] + #assume WideCharToMultiByte always produce correct result #windows only when not defined(windows): echo "OK" else: + import std/widestrs {.push gcsafe.} const CP_UTF8 = 65001'i32 @@ -66,8 +70,7 @@ else: #RFC-2781 "UTF-16, an encoding of ISO 10646" - var wc: WideCString - unsafeNew(wc, 1024 * 4 + 2) + var wc: WideCString = newWideCString(1024 * 2) #U+0000 to U+D7FF #skip the U+0000 diff --git a/tests/stdlib/twith.nim b/tests/stdlib/twith.nim index 80382f7c4..ceadbe7bf 100644 --- a/tests/stdlib/twith.nim +++ b/tests/stdlib/twith.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/with +import std/[assertions, formatfloat] type Foo = object @@ -21,3 +26,19 @@ with f: doAssert f.col == "(2, 3, 4)" doAssert f.pos == "(0.0, 1.0)" doAssert f.name == "bar" + +type + Baz* = object + a*, b*: int + Bar* = object + x*: int + baz*: Baz + +var bar: Bar +with bar: + x = 1 + with baz: + a = 2 + +doAssert bar.x == 1 +doAssert bar.baz.a == 2 diff --git a/tests/stdlib/twordwrap.nim b/tests/stdlib/twordwrap.nim index c90dd9581..5d49477d3 100644 --- a/tests/stdlib/twordwrap.nim +++ b/tests/stdlib/twordwrap.nim @@ -1,4 +1,9 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wordwrap +import std/assertions when true: let diff --git a/tests/stdlib/twrapnils.nim b/tests/stdlib/twrapnils.nim index a0549c1bc..3da230b5e 100644 --- a/tests/stdlib/twrapnils.nim +++ b/tests/stdlib/twrapnils.nim @@ -1,5 +1,10 @@ +discard """ + matrix: "--mm:refc; --mm:orc" +""" + import std/wrapnils from std/options import get, isSome +import std/assertions proc checkNotZero(x: float): float = doAssert x != 0 diff --git a/tests/stdlib/twrongstattype.nim b/tests/stdlib/twrongstattype.nim new file mode 100644 index 000000000..4a1fc30c6 --- /dev/null +++ b/tests/stdlib/twrongstattype.nim @@ -0,0 +1,14 @@ +# issue #24076 + +when defined(macosx) or defined(freebsd) or defined(openbsd) or defined(netbsd): + import std/posix + proc uid(x: uint32): Uid = Uid(x) + var y: uint32 + let myUid = geteuid() + discard myUid == uid(y) + proc dev(x: uint32): Dev = Dev(x) + let myDev = 1.Dev + discard myDev == dev(y) + proc nlink(x: uint32): Nlink = Nlink(x) + let myNlink = 1.Nlink + discard myNlink == nlink(y) diff --git a/tests/stdlib/txmltree.nim b/tests/stdlib/txmltree.nim index d2f713269..add12a3fc 100644 --- a/tests/stdlib/txmltree.nim +++ b/tests/stdlib/txmltree.nim @@ -1,4 +1,8 @@ -import xmltree +discard """ + matrix: "--mm:refc; --mm:orc" +""" + +import std/[xmltree, assertions, xmlparser] block: @@ -83,3 +87,34 @@ block: x.add newElement("sonTag") x.add newEntity("my entity") doAssert $x == "<myTag>my text<sonTag />&my entity;</myTag>" + +block: # bug #21290 + let x = newXmlTree("foo",[ + newXmlTree("bar",[ + newText("Hola"), + newXmlTree("qux",[ + newXmlTree("plugh",[]) + ]) + ]) + ]) + + let s = $x + doAssert $parseXml(s) == s + doAssert s == """<foo> + <bar>Hola<qux> <plugh /> </qux></bar> +</foo>""" + +block: #21541 + let root = <>root() + root.add <>child(newText("hello")) + root.add <>more(newVerbatimText("hola")) + let s = $root + doAssert s == """<root> + <child>hello</child> + <more>hola</more> +</root>""" + + let temp = newVerbatimText("Hello!") + doAssert temp.text == "Hello!" + temp.text = "Hola!" + doAssert temp.text == "Hola!" diff --git a/tests/stdlib/tyield.nim b/tests/stdlib/tyield.nim index 85be97365..f385ddd05 100644 --- a/tests/stdlib/tyield.nim +++ b/tests/stdlib/tyield.nim @@ -1,8 +1,10 @@ discard """ + matrix: "--mm:refc; --mm:orc" targets: "c cpp js" """ import std/[sugar, algorithm] +import std/assertions block: var x = @[(6.0, 6, '6'), diff --git a/tests/stdlib/unixsockettest.nim b/tests/stdlib/unixsockettest.nim new file mode 100644 index 000000000..8f95d0808 --- /dev/null +++ b/tests/stdlib/unixsockettest.nim @@ -0,0 +1,26 @@ +import std/[assertions, net, os] + +let unixSocketPath = getCurrentDir() / "usox" + +removeFile(unixSocketPath) + +let socket = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_NONE) +socket.bindUnix(unixSocketPath) +socket.listen() + +var + clientSocket: Socket + data: string + +socket.accept(clientSocket) +clientSocket.readLine(data) +doAssert data == "data sent through the socket" +clientSocket.send("Hello from server\c\l") + +clientSocket.readLine(data) +doAssert data == "bye" +clientSocket.send("bye\c\l") + +clientSocket.close() +socket.close() +removeFile(unixSocketPath) diff --git a/tests/stdlib/uselocks.nim b/tests/stdlib/uselocks.nim index e9d23f9d9..f87623b5e 100644 --- a/tests/stdlib/uselocks.nim +++ b/tests/stdlib/uselocks.nim @@ -1,4 +1,5 @@ import locks +import std/assertions type MyType* [T] = object lock: Lock diff --git a/tests/stmt/tforloop_tuple_multiple_underscore.nim b/tests/stmt/tforloop_tuple_multiple_underscore.nim index 2afdb0b77..96804df18 100644 --- a/tests/stmt/tforloop_tuple_multiple_underscore.nim +++ b/tests/stmt/tforloop_tuple_multiple_underscore.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "undeclared identifier: '_'" + errormsg: "the special identifier '_' is ignored in declarations and cannot be used" """ iterator iter(): (int, int, int) = @@ -7,4 +7,4 @@ iterator iter(): (int, int, int) = for (_, i, _) in iter(): - echo _ \ No newline at end of file + echo _ diff --git a/tests/stmt/tforloop_tuple_underscore.nim b/tests/stmt/tforloop_tuple_underscore.nim index 8cbb0fc10..eda42d527 100644 --- a/tests/stmt/tforloop_tuple_underscore.nim +++ b/tests/stmt/tforloop_tuple_underscore.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "undeclared identifier: '_'" + errormsg: "the special identifier '_' is ignored in declarations and cannot be used" """ iterator iter(): (int, int) = diff --git a/tests/stmt/tforloop_underscore.nim b/tests/stmt/tforloop_underscore.nim index c5b49da77..ce1c86386 100644 --- a/tests/stmt/tforloop_underscore.nim +++ b/tests/stmt/tforloop_underscore.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "undeclared identifier: '_'" + errormsg: "the special identifier '_' is ignored in declarations and cannot be used" """ for _ in ["a"]: diff --git a/tests/stmt/tgenericsunderscore.nim b/tests/stmt/tgenericsunderscore.nim new file mode 100644 index 000000000..be2b8ec78 --- /dev/null +++ b/tests/stmt/tgenericsunderscore.nim @@ -0,0 +1,4 @@ +# issue #21435 + +proc foo[_](x: typedesc[_]): string = "BAR" #[tt.Error + ^ the special identifier '_' is ignored in declarations and cannot be used]# diff --git a/tests/stmt/tmiscunderscore.nim b/tests/stmt/tmiscunderscore.nim new file mode 100644 index 000000000..c4bae1c3d --- /dev/null +++ b/tests/stmt/tmiscunderscore.nim @@ -0,0 +1,15 @@ +import std/assertions + +block: + proc _() = echo "one" + doAssert not compiles(_()) + proc _() = echo "two" + doAssert not compiles(_()) + +block: + type _ = int + doAssert not (compiles do: + let x: _ = 3) + type _ = float + doAssert not (compiles do: + let x: _ = 3) diff --git a/tests/stylecheck/foreign_package/foreign_package.nim b/tests/stylecheck/foreign_package/foreign_package.nim new file mode 100644 index 000000000..f95be006c --- /dev/null +++ b/tests/stylecheck/foreign_package/foreign_package.nim @@ -0,0 +1 @@ +include ../thint \ No newline at end of file diff --git a/tests/stylecheck/foreign_package/foreign_package.nimble b/tests/stylecheck/foreign_package/foreign_package.nimble new file mode 100644 index 000000000..a2c49e389 --- /dev/null +++ b/tests/stylecheck/foreign_package/foreign_package.nimble @@ -0,0 +1,2 @@ +# See `tstyleCheck` +# Needed to mark `mstyleCheck` as a foreign package. diff --git a/tests/stylecheck/t20397.nim b/tests/stylecheck/t20397.nim new file mode 100644 index 000000000..486a97d73 --- /dev/null +++ b/tests/stylecheck/t20397.nim @@ -0,0 +1,4 @@ +{.hintAsError[Name]:on.} +var a_b = 1 +discard a_b +{.hintAsError[Name]:off.} \ No newline at end of file diff --git a/tests/stylecheck/t20397_1.nim b/tests/stylecheck/t20397_1.nim new file mode 100644 index 000000000..76c03dca1 --- /dev/null +++ b/tests/stylecheck/t20397_1.nim @@ -0,0 +1,8 @@ +discard """ + matrix: "--styleCheck:off --hint:Name:on" +""" + +{.hintAsError[Name]:on.} +var a_b = 1 +discard a_b +{.hintAsError[Name]:off.} diff --git a/tests/stylecheck/t20397_2.nim b/tests/stylecheck/t20397_2.nim new file mode 100644 index 000000000..3b8e1c4d6 --- /dev/null +++ b/tests/stylecheck/t20397_2.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "'a_b' should be: 'aB'" + matrix: "--styleCheck:error" +""" + +var a_b = 1 +discard a_b \ No newline at end of file diff --git a/tests/stylecheck/tforeign_package.nim b/tests/stylecheck/tforeign_package.nim new file mode 100644 index 000000000..8594ad802 --- /dev/null +++ b/tests/stylecheck/tforeign_package.nim @@ -0,0 +1,16 @@ +discard """ + matrix: "--errorMax:0 --styleCheck:error" + action: compile +""" + +import foreign_package/foreign_package + +# This call tests that: +# - an instantiation of a generic in a foreign package doesn't raise errors +# when the generic body contains: +# - definition and usage violations +# - builtin pragma usage violations +# - user pragma usage violations +# - definition violations in foreign packages are ignored +# - usage violations in foreign packages are ignored +genericProc[int]() diff --git a/tests/stylecheck/thint.nim b/tests/stylecheck/thint.nim new file mode 100644 index 000000000..c19aac1b8 --- /dev/null +++ b/tests/stylecheck/thint.nim @@ -0,0 +1,43 @@ +discard """ + matrix: "--styleCheck:hint" + action: compile +""" + +# Test violating ident definition: +{.pragma: user_pragma.} #[tt.Hint + ^ 'user_pragma' should be: 'userPragma' [Name] ]# + +# Test violating ident usage style matches definition style: +{.userPragma.} #[tt.Hint + ^ 'userPragma' should be: 'user_pragma' [template declared in thint.nim(7, 9)] [Name] ]# + +# Test violating builtin pragma usage style: +{.no_side_effect.}: #[tt.Hint + ^ 'no_side_effect' should be: 'noSideEffect' [Name] ]# + discard 0 + +# Test: +# - definition style violation +# - user pragma usage style violation +# - builtin pragma usage style violation +proc generic_proc*[T] {.no_destroy, userPragma.} = #[tt.Hint + ^ 'generic_proc' should be: 'genericProc' [Name]; tt.Hint + ^ 'no_destroy' should be: 'nodestroy' [Name]; tt.Hint + ^ 'userPragma' should be: 'user_pragma' [template declared in thint.nim(7, 9)] [Name] ]# + # Test definition style violation: + let snake_case = 0 #[tt.Hint + ^ 'snake_case' should be: 'snakeCase' [Name] ]# + # Test user pragma definition style violation: + {.pragma: another_user_pragma.} #[tt.Hint + ^ 'another_user_pragma' should be: 'anotherUserPragma' [Name] ]# + # Test user pragma usage style violation: + {.anotherUserPragma.} #[tt.Hint + ^ 'anotherUserPragma' should be: 'another_user_pragma' [template declared in thint.nim(31, 11)] [Name] ]# + # Test violating builtin pragma usage style: + {.no_side_effect.}: #[tt.Hint + ^ 'no_side_effect' should be: 'noSideEffect' [Name] ]# + # Test usage style violation: + discard snakeCase #[tt.Hint + ^ 'snakeCase' should be: 'snake_case' [let declared in thint.nim(28, 7)] [Name] ]# + +generic_proc[int]() diff --git a/tests/stylecheck/treject.nim b/tests/stylecheck/treject.nim index b9d97a58d..458a2d039 100644 --- a/tests/stylecheck/treject.nim +++ b/tests/stylecheck/treject.nim @@ -1,7 +1,7 @@ discard """ action: reject nimout: '''treject.nim(14, 13) Error: 'iD' should be: 'id' [field declared in treject.nim(9, 5)]''' - matrix: "--styleCheck:error --styleCheck:usages" + matrix: "--styleCheck:error --styleCheck:usages --hint:Name:on" """ type @@ -14,4 +14,4 @@ template hello = echo name.iD echo iD -hello() \ No newline at end of file +hello() diff --git a/tests/stylecheck/tusages.nim b/tests/stylecheck/tusages.nim index 2f99c70c5..b689dabb3 100644 --- a/tests/stylecheck/tusages.nim +++ b/tests/stylecheck/tusages.nim @@ -1,11 +1,9 @@ discard """ action: reject - nimout: '''tusages.nim(22, 5) Error: 'BAD_STYLE' should be: 'BADSTYLE' [proc declared in tusages.nim(11, 6)]''' - matrix: "--styleCheck:error --styleCheck:usages" + nimout: '''tusages.nim(20, 5) Error: 'BAD_STYLE' should be: 'BADSTYLE' [proc declared in tusages.nim(9, 6)]''' + matrix: "--styleCheck:error --styleCheck:usages --hint:all:off --hint:Name:on" """ - - import strutils proc BADSTYLE(c: char) = discard diff --git a/tests/magics/t10307.nim b/tests/system/t10307.nim index b5bbfdfa8..b5a93c5c6 100644 --- a/tests/magics/t10307.nim +++ b/tests/system/t10307.nim @@ -1,5 +1,5 @@ discard """ - cmd: "nim c -d:useGcAssert $file" + cmd: "nim c --mm:refc -d:useGcAssert $file" output: '''running someProc(true) res: yes yes diff --git a/tests/system/t20938.nim b/tests/system/t20938.nim new file mode 100644 index 000000000..7341cbb91 --- /dev/null +++ b/tests/system/t20938.nim @@ -0,0 +1,12 @@ +discard """ + cmd: "nim c --mm:refc $file" + action: "compile" +""" + +template foo(x: typed) = + discard x + +foo: + var x = "hello" + x.shallowCopy("test") + true diff --git a/tests/system/tcomparisons.nim b/tests/system/tcomparisons.nim new file mode 100644 index 000000000..a661b14a1 --- /dev/null +++ b/tests/system/tcomparisons.nim @@ -0,0 +1,51 @@ +discard """ + targets: "c cpp js" +""" + +template main = + block: # proc equality + var prc: proc(): int {.closure.} + prc = nil + doAssert prc == nil + doAssert prc.isNil + prc = proc(): int = + result = 123 + doAssert prc != nil + doAssert not prc.isNil + doAssert prc == prc + let prc2 = prc + doAssert prc == prc2 + doAssert prc2 != nil + doAssert not prc2.isNil + doAssert not prc.isNil + prc = proc(): int = + result = 456 + doAssert prc != nil + doAssert not prc.isNil + doAssert prc != prc2 + block: # iterator equality + when nimvm: discard # vm does not support closure iterators + else: + when not defined(js): # js also does not support closure iterators + var iter: iterator(): int {.closure.} + iter = nil + doAssert iter == nil + doAssert iter.isNil + iter = iterator(): int = + yield 123 + doAssert iter != nil + doAssert not iter.isNil + doAssert iter == iter + let iter2 = iter + doAssert iter == iter2 + doAssert iter2 != nil + doAssert not iter2.isNil + doAssert not iter.isNil + iter = iterator(): int = + yield 456 + doAssert iter != nil + doAssert not iter.isNil + doAssert iter != iter2 + +static: main() +main() diff --git a/tests/concat/tconcat.nim b/tests/system/tconcat.nim index fdce3ea00..fdce3ea00 100644 --- a/tests/concat/tconcat.nim +++ b/tests/system/tconcat.nim diff --git a/tests/system/tdeepcopy.nim b/tests/system/tdeepcopy.nim index 383d2e8d1..92ba48115 100644 --- a/tests/system/tdeepcopy.nim +++ b/tests/system/tdeepcopy.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc; --mm:orc --deepcopy:on" output: "ok" """ diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim index 93fa5cb9e..eabee81b3 100644 --- a/tests/system/tdollars.nim +++ b/tests/system/tdollars.nim @@ -1,5 +1,5 @@ discard """ - targets: "c cpp js" + matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on" """ #[ @@ -12,6 +12,7 @@ duplication (which always results in weaker test coverage in practice). ]# import std/unittest +import std/private/jsutils template test[T](a: T, expected: string) = check $a == expected var b = a @@ -44,8 +45,7 @@ block: # `$`(SomeInteger) check $int8.low == "-128" check $int8(-128) == "-128" - when not defined js: # pending https://github.com/nim-lang/Nim/issues/14127 - check $cast[int8](-128) == "-128" + check $cast[int8](-128) == "-128" var a = 12345'u16 check $a == "12345" @@ -66,7 +66,8 @@ block: # `$`(SomeInteger) testType int testType bool - when not defined(js): # requires BigInt support + whenJsNoBigInt64: discard + do: testType uint64 testType int64 testType BiggestInt @@ -108,10 +109,10 @@ block: # if `uint8(a1)` changes meaning to `cast[uint8](a1)` in future, update this test; # until then, this is the correct semantics. let a3 = $a2 - doAssert a2 < 3 - doAssert a3 == "-1" + doAssert a2 == 255'u8 + doAssert a3 == "255" proc intToStr(a: uint8): cstring {.importjs: "(# + \"\")".} - doAssert $intToStr(a2) == "-1" + doAssert $intToStr(a2) == "255" else: block: let x = -1'i8 @@ -176,10 +177,10 @@ proc main()= res.addInt int64(i) doAssert res == "-9-8-7-6-5-4-3-2-10" - when not defined(js): + whenJsNoBigInt64: discard + do: test2 high(int64), "9223372036854775807" test2 low(int64), "-9223372036854775808" - test2 high(int32), "2147483647" test2 low(int32), "-2147483648" test2 high(int16), "32767" diff --git a/tests/misc/temptyecho.nim b/tests/system/temptyecho.nim index a3c407897..a3c407897 100644 --- a/tests/misc/temptyecho.nim +++ b/tests/system/temptyecho.nim diff --git a/tests/system/tensuremove.nim b/tests/system/tensuremove.nim new file mode 100644 index 000000000..668d5aed1 --- /dev/null +++ b/tests/system/tensuremove.nim @@ -0,0 +1,131 @@ +discard """ + targets: "c js" + matrix: "--cursorinference:on; --cursorinference:off" +""" + +block: + type + X = object + s: string + + proc `=copy`(x: var X, y: X) = + x.s = "copied " & y.s + + proc `=sink`(x: var X, y: X) = + `=destroy`(x) + wasMoved(x) + x.s = "moved " & y.s + + proc consume(x: sink X) = + discard x.s + + proc main = + let m = "abcdefg" + var x = X(s: ensureMove m) + consume(ensureMove x) + + static: main() + main() + +block: + type + String = object + id: string + + proc hello = + var s = String(id: "1") + var m = ensureMove s + doAssert m.id == "1" + + hello() + +block: + type + String = object + id: string + + proc hello = + var n = "1" + var s = String(id: ensureMove n) + var m = ensureMove s + doAssert m.id == "1" + + hello() + +block: + type + String = object + id: string + + proc hello = + var n = "1" + var s = [ensureMove n] + var m = ensureMove s + doAssert m[0] == "1" + + hello() + +block: + type + String = object + id: string + + proc hello = + var n = "1" + var s = @[ensureMove n] + var m = ensureMove s + doAssert m[0] == "1" + + hello() + +block: + type + String = object + id: string + + proc hello = + var s = String(id: "1") + var m = ensureMove s.id + doAssert m == "1" + + hello() + +block: + proc foo = + var x = 1 + let y = ensureMove x # move + when not defined(js): + doAssert (y, x) == (1, 0) # (1, 0) + foo() + +block: + proc foo = + var x = 1 + let y = ensureMove x # move + doAssert y == 1 + foo() + +block: + proc foo = + var x = @[1, 2, 3] + let y = ensureMove x[0] # move + doAssert y == 1 + when not defined(js): + doAssert x == @[0, 2, 3] + foo() + +block: + proc foo = + var x = [1, 2, 3] + let y = ensureMove x[0] # move + doAssert y == 1 + when not defined(js): + doAssert x == @[0, 2, 3] + foo() + +block: + proc foo = + var x = @["1", "2", "3"] + let y = ensureMove x[0] # move + doAssert y == "1" + foo() diff --git a/tests/system/tensuremove1.nim b/tests/system/tensuremove1.nim new file mode 100644 index 000000000..b7e19c4fb --- /dev/null +++ b/tests/system/tensuremove1.nim @@ -0,0 +1,16 @@ +discard """ + errormsg: "cannot move 's', which introduces an implicit copy" + matrix: "--cursorinference:on; --cursorinference:off" +""" + +type + String = object + id: string + +proc hello = + var s = String(id: "1") + var m = ensureMove s + discard m + discard s + +hello() \ No newline at end of file diff --git a/tests/system/tensuremove2.nim b/tests/system/tensuremove2.nim new file mode 100644 index 000000000..39bbeb22e --- /dev/null +++ b/tests/system/tensuremove2.nim @@ -0,0 +1,15 @@ +discard """ + errormsg: "Nested expressions cannot be moved: 'if true: s else: String()'" +""" + +type + String = object + id: string + +proc hello = + var s = String(id: "1") + var m = ensureMove(if true: s else: String()) + discard m + discard s + +hello() \ No newline at end of file diff --git a/tests/system/tensuremove3.nim b/tests/system/tensuremove3.nim new file mode 100644 index 000000000..eca032673 --- /dev/null +++ b/tests/system/tensuremove3.nim @@ -0,0 +1,28 @@ +discard """ + errormsg: "cannot move 'x', passing 'x' to a sink parameter introduces an implicit copy" + matrix: "--cursorinference:on; --cursorinference:off" +""" + +block: + type + X = object + s: string + + proc `=copy`(x: var X, y: X) = + x.s = "copied " & y.s + + proc `=sink`(x: var X, y: X) = + `=destroy`(x) + wasMoved(x) + x.s = "moved " & y.s + + proc consume(x: sink X) = + discard x.s + + proc main = + var s = "abcdefg" + var x = X(s: ensureMove s) + consume(ensureMove x) + discard x + + main() \ No newline at end of file diff --git a/tests/fields/tfielditerator.nim b/tests/system/tfielditerator.nim index d1fbf02f9..7e063c6cf 100644 --- a/tests/fields/tfielditerator.nim +++ b/tests/system/tfielditerator.nim @@ -109,4 +109,18 @@ block titerator2: echo key, ": ", val for val in fields(co): - echo val \ No newline at end of file + echo val + +block: + type + Enum = enum A, B + Object = object + case a: Enum + of A: + integer: int + of B: + time: string + + let x = A + let s = Object(a: x) + doAssert s.integer == 0 diff --git a/tests/fields/tfields.nim b/tests/system/tfields.nim index 0bf3a4e1a..0bf3a4e1a 100644 --- a/tests/fields/tfields.nim +++ b/tests/system/tfields.nim diff --git a/tests/system/tgcnone.nim b/tests/system/tgcnone.nim index 47c6c6014..1ccb9e29c 100644 --- a/tests/system/tgcnone.nim +++ b/tests/system/tgcnone.nim @@ -1,6 +1,7 @@ discard """ - matrix: "--gc:none -d:useMalloc --threads:off" + matrix: "--mm:none -d:useMalloc" """ # bug #15617 +# bug #22262 let x = 4 doAssert x == 4 diff --git a/tests/misc/tgcregions.nim b/tests/system/tgcregions.nim index e14865be3..e14865be3 100644 --- a/tests/misc/tgcregions.nim +++ b/tests/system/tgcregions.nim diff --git a/tests/misc/tinc.nim b/tests/system/timmutableinc.nim index 91f6223e2..e857800b3 100644 --- a/tests/misc/tinc.nim +++ b/tests/system/timmutableinc.nim @@ -1,6 +1,6 @@ discard """ errormsg: "type mismatch: got <int>" - file: "tinc.nim" + file: "timmutableinc.nim" line: 8 """ var x = 0 diff --git a/tests/misc/tnot.nim b/tests/system/tinvalidnot.nim index a3669705b..df0291a8a 100644 --- a/tests/misc/tnot.nim +++ b/tests/system/tinvalidnot.nim @@ -1,6 +1,6 @@ discard """ errormsg: "type mismatch" - file: "tnot.nim" + file: "tinvalidnot.nim" line: 14 """ # BUG: following compiles, but should not: diff --git a/tests/misc/tlocals.nim b/tests/system/tlocals.nim index e59976102..e59976102 100644 --- a/tests/misc/tlocals.nim +++ b/tests/system/tlocals.nim diff --git a/tests/misc/tlowhigh.nim b/tests/system/tlowhigh.nim index 6ae871255..6ae871255 100644 --- a/tests/misc/tlowhigh.nim +++ b/tests/system/tlowhigh.nim diff --git a/tests/magics/tmagics.nim b/tests/system/tmagics.nim index 0e412940c..6088c9600 100644 --- a/tests/magics/tmagics.nim +++ b/tests/system/tmagics.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" output: ''' true true @@ -56,10 +57,6 @@ block t9442: GC_ref(v3) GC_unref(v3) -block: # bug #6499 - let x = (chr, 0) - doAssert x[1] == 0 - block: # bug #12229 proc foo(T: typedesc) = discard foo(ref) diff --git a/tests/stdlib/tmemory.nim b/tests/system/tmemory.nim index 0349ba035..553037011 100644 --- a/tests/stdlib/tmemory.nim +++ b/tests/system/tmemory.nim @@ -1,3 +1,4 @@ +import std/assertions block: # cmpMem type diff --git a/tests/misc/tnew.nim b/tests/system/tnew.nim index 2d9a64461..c28c1187f 100644 --- a/tests/misc/tnew.nim +++ b/tests/system/tnew.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc; --mm:orc" outputsub: ''' Simple tree node allocation worked! Simple cycle allocation worked! @@ -24,7 +25,10 @@ proc finalizer(n: PNode) = write(stdout, " is now freed\n") proc newNode(data: int, le, ri: PNode): PNode = - new(result, finalizer) + when defined(gcDestructors): # using finalizer breaks the test for orc + new(result) + else: + new(result, finalizer) result.le = le result.ri = ri result.data = data diff --git a/tests/misc/tnewderef.nim b/tests/system/tnewderef.nim index 3394dbddf..3394dbddf 100644 --- a/tests/misc/tnewderef.nim +++ b/tests/system/tnewderef.nim diff --git a/tests/system/tnewstring_uninitialized.nim b/tests/system/tnewstring_uninitialized.nim new file mode 100644 index 000000000..9bc0e1622 --- /dev/null +++ b/tests/system/tnewstring_uninitialized.nim @@ -0,0 +1,11 @@ +discard """ + matrix: "--mm:refc;" +""" + +# bug #22555 +var x = newStringUninit(10) +doAssert x.len == 10 +for i in 0..<x.len: + x[i] = chr(ord('a') + i) + +doAssert x == "abcdefghij" diff --git a/tests/system/tnilconcats.nim b/tests/system/tnilconcats.nim index c1126405c..69fc3913c 100644 --- a/tests/system/tnilconcats.nim +++ b/tests/system/tnilconcats.nim @@ -26,7 +26,8 @@ when true: # casting an empty string as sequence with shallow() should not segfault var s2: string - shallow(s2) + when defined(gcRefc): + shallow(s2) s2 &= "foo" doAssert s2 == "foo" diff --git a/tests/system/tostring.nim b/tests/system/tostring.nim index cae20865e..bb6e453fb 100644 --- a/tests/system/tostring.nim +++ b/tests/system/tostring.nim @@ -47,7 +47,7 @@ import strutils let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0'] doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']" -doAssert $cstring(addr arr) == "Hello World!" +doAssert $cast[cstring](addr arr) == "Hello World!" proc takes(c: cstring) = doAssert c == cstring"" diff --git a/tests/system/trefs.nim b/tests/system/trefs.nim new file mode 100644 index 000000000..8c36aec52 --- /dev/null +++ b/tests/system/trefs.nim @@ -0,0 +1,15 @@ +discard """ + targets: "c js" +""" + +# bug #21317 +proc parseHook*(v: var ref int) = + var a: ref int + new(a) + a[] = 123 + v = a + +proc fromJson2*(): ref int = + parseHook(result) + +doAssert fromJson2()[] == 123 diff --git a/tests/misc/tslices.nim b/tests/system/tslices.nim index 987b50de1..d0c68f8cb 100644 --- a/tests/misc/tslices.nim +++ b/tests/system/tslices.nim @@ -57,3 +57,9 @@ echo mystr var s = "abcdef" s[1 .. ^2] = "xyz" assert s == "axyzf" + +# issue mentioned in PR #19219 +type Foo = distinct uint64 +# < here calls `pred` which used to cause a codegen error +# `pred` compiles because distinct ordinals are considered ordinal +const slice = 0 ..< 42.Foo diff --git a/tests/system/tslimsystem.nim b/tests/system/tslimsystem.nim index 690f4ee9b..4815306b5 100644 --- a/tests/system/tslimsystem.nim +++ b/tests/system/tslimsystem.nim @@ -1,6 +1,6 @@ discard """ output: "123" - matrix: "-d:nimPreviewSlimSystem" + matrix: "-d:nimPreviewSlimSystem --mm:refc; -d:nimPreviewSlimSystem --mm:arc" """ echo 123 \ No newline at end of file diff --git a/tests/system/tsystem_misc.nim b/tests/system/tsystem_misc.nim index 7f5914725..1debb7c48 100644 --- a/tests/system/tsystem_misc.nim +++ b/tests/system/tsystem_misc.nim @@ -212,3 +212,16 @@ block: doAssert not compiles(echo p.rawProc.repr) doAssert not compiles(echo p.rawEnv.repr) doAssert not compiles(echo p.finished) + +proc bug23223 = # bug #23223 + var stuff = "hello" + stuff.insert "" + doAssert stuff == "hello" + +bug23223() + +block: # bug #23894 + let v = high(uint) div 2 + let s = v + 1 # 9223372036854775808 + let m = succ v + doAssert s == m diff --git a/tests/system/tuse_version.nim b/tests/system/tuse_version.nim deleted file mode 100644 index 116ef3596..000000000 --- a/tests/system/tuse_version.nim +++ /dev/null @@ -1,49 +0,0 @@ -discard """ - matrix: "--useVersion:1.0" -""" - -{.warning[UnusedImport]: off.} - -import std/[ - # Core: - bitops, typetraits, lenientops, macros, volatile, - - # Algorithms: - algorithm, sequtils, - - # Collections: - critbits, deques, heapqueue, intsets, lists, options, sets, - sharedlist, tables, - - # Strings: - editdistance, wordwrap, parseutils, ropes, - pegs, punycode, strformat, strmisc, strscans, strtabs, - strutils, unicode, unidecode, - - # Generic operator system services: - os, streams, - - # Math libraries: - complex, math, mersenne, random, rationals, stats, sums, - - # Internet protocols: - httpcore, mimetypes, uri, - - # Parsers: - htmlparser, json, lexbase, parsecfg, parsecsv, parsesql, parsexml, - - # XML processing: - xmltree, xmlparser, - - # Generators: - htmlgen, - - # Hashing: - base64, hashes, - - # Miscellaneous: - colors, sugar, varints, -] - - -doAssert NimVersion == "1.0.100" diff --git a/tests/system/tuse_version16.nim b/tests/system/tuse_version16.nim index d5430db32..802b617ad 100644 --- a/tests/system/tuse_version16.nim +++ b/tests/system/tuse_version16.nim @@ -1,5 +1,5 @@ discard """ - matrix: "--useVersion:1.6" + matrix: "-d:NimMajor=1 -d:NimMinor=6 -d:NimPatch=100" """ {.warning[UnusedImport]: off.} @@ -17,7 +17,7 @@ import std/[ # Strings: editdistance, wordwrap, parseutils, ropes, - pegs, punycode, strformat, strmisc, strscans, strtabs, + pegs, strformat, strmisc, strscans, strtabs, strutils, unicode, unidecode, # Generic operator system services: diff --git a/tests/system/tvarargslen.nim b/tests/system/tvarargslen.nim index a129aa5c2..24b54a1e0 100644 --- a/tests/system/tvarargslen.nim +++ b/tests/system/tvarargslen.nim @@ -1,8 +1,8 @@ discard """ output: ''' -tvarargslen.nim:35:9 (1, 2) -tvarargslen.nim:36:9 12 -tvarargslen.nim:37:9 1 +tvarargslen.nim:35:2 (1, 2) +tvarargslen.nim:36:2 12 +tvarargslen.nim:37:2 1 tvarargslen.nim:38:8 done ''' diff --git a/tests/template/m1027a.nim b/tests/template/m1027a.nim new file mode 100644 index 000000000..fad915a2f --- /dev/null +++ b/tests/template/m1027a.nim @@ -0,0 +1 @@ +const version_str* = "mod a" diff --git a/tests/template/m1027b.nim b/tests/template/m1027b.nim new file mode 100644 index 000000000..5ff0b9714 --- /dev/null +++ b/tests/template/m1027b.nim @@ -0,0 +1 @@ +const version_str* = "mod b" diff --git a/tests/template/m19277_1.nim b/tests/template/m19277_1.nim new file mode 100644 index 000000000..840bd4767 --- /dev/null +++ b/tests/template/m19277_1.nim @@ -0,0 +1,2 @@ +template foo*(x: untyped) = + echo "got: ", x diff --git a/tests/template/m19277_2.nim b/tests/template/m19277_2.nim new file mode 100644 index 000000000..de72dad45 --- /dev/null +++ b/tests/template/m19277_2.nim @@ -0,0 +1,2 @@ +proc foo*(a: string) = + echo "got string: ", a diff --git a/tests/template/mdotcall.nim b/tests/template/mdotcall.nim new file mode 100644 index 000000000..fecd8ee26 --- /dev/null +++ b/tests/template/mdotcall.nim @@ -0,0 +1,82 @@ +# issue #20073 + +type Foo = object +proc foo(f: Foo) = discard + +template works*() = + var f: Foo + foo(f) + +template boom*() = + var f: Foo + f.foo() # Error: attempting to call undeclared routine: 'foo' + f.foo # Error: undeclared field: 'foo' for type a.Foo + +# issue #7085 + +proc bar(a: string): string = + return a & "bar" + +template baz*(a: string): string = + var b = a.bar() + b + +# issue #7223 + +import mdotcall2 + +type + Bytes* = seq[byte] + + BytesRange* = object + bytes*: Bytes + ibegin*, iend*: int + +proc privateProc(r: BytesRange): int = r.ibegin + +template rangeBeginAddr*(r: BytesRange): pointer = + r.bytes.baseAddr.shift(r.privateProc) + +# issue #11733 + +type ObjA* = object + +proc foo2(o: var ObjA) = discard +proc bar2(o: var ObjA, arg: Natural) = discard + +template publicTemplateObjSyntax*(o: var ObjA, arg: Natural, doStuff: untyped) = + o.foo2() + doStuff + o.bar2(arg) + +# issue #15246 +import os + +template sourceBaseName*(): string = + bind splitFile + instantiationInfo().filename.splitFile().name + +# issue #12683 + +import unicode +template toRune(s: string): Rune = s.runeAt(0) +proc heh*[T](x: Slice[T], chars: string) = discard chars.toRune + +# issue #7889 + +from streams import newStringStream, readData, writeData + +template bindmeTemplate*(): untyped = + var tst = "sometext" + var ss = newStringStream("anothertext") + ss.writeData(tst[0].addr, 2) + discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful + +from macros import quote, newIdentNode + +macro bindmeQuote*(): untyped = + quote do: + var tst = "sometext" + var ss = newStringStream("anothertext") + ss.writeData(tst[0].addr, 2) + discard ss.readData(tst[0].addr, 2) # <= comment this out to make compilation successful diff --git a/tests/template/mdotcall2.nim b/tests/template/mdotcall2.nim new file mode 100644 index 000000000..e906ac9d6 --- /dev/null +++ b/tests/template/mdotcall2.nim @@ -0,0 +1,7 @@ +# imported by mdotcall + +proc baseAddr*[T](x: openarray[T]): pointer = + cast[pointer](x) + +proc shift*(p: pointer, delta: int): pointer = + cast[pointer](cast[int](p) + delta) diff --git a/tests/template/mqualifiedtype1.nim b/tests/template/mqualifiedtype1.nim new file mode 100644 index 000000000..46569107f --- /dev/null +++ b/tests/template/mqualifiedtype1.nim @@ -0,0 +1,2 @@ +type A* = object + x*: int diff --git a/tests/template/mqualifiedtype2.nim b/tests/template/mqualifiedtype2.nim new file mode 100644 index 000000000..6a61c14bd --- /dev/null +++ b/tests/template/mqualifiedtype2.nim @@ -0,0 +1,2 @@ +type A* = object + x*: array[1000, byte] diff --git a/tests/template/t1027.nim b/tests/template/t1027.nim new file mode 100644 index 000000000..fe03c4ea9 --- /dev/null +++ b/tests/template/t1027.nim @@ -0,0 +1,22 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +t1027.nim(20, 19) Error: ambiguous identifier: 'version_str' -- use one of the following: + m1027a.version_str: string + m1027b.version_str: string +''' +""" + + + + + + +import m1027a, m1027b + +# bug #1027 +template wrap_me(stuff): untyped = + echo "Using " & version_str + +wrap_me("hey") diff --git a/tests/template/t11705.nim b/tests/template/t11705.nim new file mode 100644 index 000000000..65ddc7e6c --- /dev/null +++ b/tests/template/t11705.nim @@ -0,0 +1,17 @@ +type RefObj = ref object + +proc `[]`(val: static[int]) = # works with different name/overload or without static arg + discard + +template noRef*(T: typedesc): typedesc = # works without template indirection + typeof(default(T)[]) + +proc `=destroy`(x: var noRef(RefObj)) = + discard + +proc foo = + var x = new RefObj + doAssert $(x[]) == "()" + +# bug #11705 +foo() diff --git a/tests/template/t13426.nim b/tests/template/t13426.nim new file mode 100644 index 000000000..f7f44749c --- /dev/null +++ b/tests/template/t13426.nim @@ -0,0 +1,87 @@ +discard """ + cmd: "nim check --hints:off $file" + errormsg: "" + nimout: ''' +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 24) Error: type mismatch: got <int> but expected 'string' +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 17) Error: type mismatch: got <uint, string> +but expected one of: +proc `and`(x, y: uint): uint + first type mismatch at position: 2 + required type for y: uint + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint64): uint64 + first type mismatch at position: 2 + required type for y: uint64 + but expression 'high(@[1])' is of type: string +10 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them + +expression: 1'u and high(@[1]) +t13426.nim(81, 6) template/generic instantiation of `fun` from here +t13426.nim(80, 17) Error: expression '' has no type (or is ambiguous) +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 22) Error: type mismatch: got <int> but expected 'string' +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 15) Error: type mismatch: got <int literal(1), string> +but expected one of: +proc `and`(x, y: int): int + first type mismatch at position: 2 + required type for y: int + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int16): int16 + first type mismatch at position: 2 + required type for y: int16 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int32): int32 + first type mismatch at position: 2 + required type for y: int32 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int64): int64 + first type mismatch at position: 2 + required type for y: int64 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: int8): int8 + first type mismatch at position: 2 + required type for y: int8 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint): uint + first type mismatch at position: 2 + required type for y: uint + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint16): uint16 + first type mismatch at position: 2 + required type for y: uint16 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint32): uint32 + first type mismatch at position: 2 + required type for y: uint32 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint64): uint64 + first type mismatch at position: 2 + required type for y: uint64 + but expression 'high(@[1])' is of type: string +proc `and`(x, y: uint8): uint8 + first type mismatch at position: 2 + required type for y: uint8 + but expression 'high(@[1])' is of type: string +2 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them + +expression: 1 and high(@[1]) +t13426.nim(87, 6) template/generic instantiation of `fun` from here +t13426.nim(86, 15) Error: expression '' has no type (or is ambiguous) +''' +""" + +# bug # #13426 +block: + template bar(t): string = high(t) + proc fun[A](key: A) = + var h = 1'u and bar(@[1]) + fun(0) + +block: + template bar(t): string = high(t) + proc fun[A](key: A) = + var h = 1 and bar(@[1]) + fun(0) diff --git a/tests/template/t13515.nim b/tests/template/t13515.nim deleted file mode 100644 index ffebedcbe..000000000 --- a/tests/template/t13515.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - action: compile -""" - -template test: bool = true - -# compiles: -if not test: - echo "wtf" - -# does not compile: -template x = - if not test: - echo "wtf" - -x diff --git a/tests/template/t19149.nim b/tests/template/t19149.nim new file mode 100644 index 000000000..631e8fc30 --- /dev/null +++ b/tests/template/t19149.nim @@ -0,0 +1,19 @@ +type Foo = tuple[active: bool, index: int] + + +var f: Foo + +# template result type during match stage +# f:var Foo +# a:Foo +# tyVar +# tyTuple +# after change to proc +# f:Foo +# a:Foo +# tyTuple +# tyTuple + +template cursor(): var Foo = f +discard cursor() + diff --git a/tests/template/t19277.nim b/tests/template/t19277.nim new file mode 100644 index 000000000..16435a09c --- /dev/null +++ b/tests/template/t19277.nim @@ -0,0 +1,19 @@ +discard """ + output: ''' +got: 0 +''' +""" + +# issue #19277 + +import m19277_1, m19277_2 + +template injector(val: untyped): untyped = + template subtemplate: untyped = val + subtemplate() + +template methodCall(val: untyped): untyped = val + +{.push raises: [Defect].} + +foo(injector(0).methodCall()) diff --git a/tests/template/t19700.nim b/tests/template/t19700.nim new file mode 100644 index 000000000..cc2944944 --- /dev/null +++ b/tests/template/t19700.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "type mismatch: got <Obj, Obj, template (x: untyped, y: untyped): untyped>" +""" + +type Obj = object + +proc apply[T, R](a, b: T; f: proc(x, y: T): R): R = f(a, b) + +let a, b = Obj() +discard apply(a, b, `!=`) diff --git a/tests/template/t21231.nim b/tests/template/t21231.nim new file mode 100644 index 000000000..51e96cdd6 --- /dev/null +++ b/tests/template/t21231.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "undeclared identifier: 'x'" +""" + +var x: int +# bug #21231 +template f(y: untyped) = echo y.x +for i in 1 .. 10: + x = i + f(system) diff --git a/tests/template/t21532.nim b/tests/template/t21532.nim new file mode 100644 index 000000000..3193b0dc3 --- /dev/null +++ b/tests/template/t21532.nim @@ -0,0 +1,8 @@ + +template elementType(a: untyped): typedesc = + typeof(block: (for ai in a: ai)) + +func fn[T](a: T) = + doAssert elementType(a) is int + +@[1,2,3].fn \ No newline at end of file diff --git a/tests/template/t24112.nim b/tests/template/t24112.nim new file mode 100644 index 000000000..175fc7d5e --- /dev/null +++ b/tests/template/t24112.nim @@ -0,0 +1,19 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj --hints:off" + action: reject +""" + +# issue #24112, needs --experimental:openSym disabled + +block: # simplified + type + SomeObj = ref object # Doesn't error if you make SomeObj be non-ref + template foo = yield SomeObj() + when compiles(foo): discard + +import std/asyncdispatch +block: + proc someProc(): Future[void] {.async.} = discard + proc foo() = + await someProc() #[tt.Error + ^ Can only 'await' inside a proc marked as 'async'. Use 'waitFor' when calling an 'async' proc in a non-async scope instead]# diff --git a/tests/template/taliassyntax.nim b/tests/template/taliassyntax.nim new file mode 100644 index 000000000..2d8237d93 --- /dev/null +++ b/tests/template/taliassyntax.nim @@ -0,0 +1,74 @@ +type Foo = object + bar: int + +var foo = Foo(bar: 10) +template bar: int = foo.bar +doAssert bar == 10 +bar = 15 +doAssert bar == 15 +var foo2 = Foo(bar: -10) +doAssert bar == 15 +# works in generics +proc genericProc[T](x: T): string = + $(x, bar) +doAssert genericProc(true) == "(true, 15)" +# redefine +template bar: int {.redefine.} = foo2.bar +doAssert bar == -10 + +block: # subscript + var bazVal = @[1, 2, 3] + template baz: seq[int] = bazVal + doAssert baz[1] == 2 + proc genericProc2[T](x: T): string = + result = $(x, baz[1]) + baz[1] = 7 + doAssert genericProc2(true) == "(true, 2)" + doAssert baz[1] == 7 + baz[1] = 14 + doAssert baz[1] == 14 + +block: # type alias + template Int2: untyped = int + let x: Int2 = 123 + proc generic[T](): string = + template U: untyped = T + var x: U + result = $typeof(x) + doAssert result == $U + doAssert result == $T + doAssert generic[int]() == "int" + doAssert generic[Int2]() == "int" + doAssert generic[string]() == "string" + doAssert generic[seq[int]]() == "seq[int]" + doAssert generic[seq[Int2]]() == "seq[int]" + discard generic[123]() + proc genericStatic[X; T: static[X]](): string = + template U: untyped = T + result = $U + doAssert result == $T + doAssert genericStatic[int, 123]() == "123" + doAssert genericStatic[Int2, 123]() == "123" + doAssert genericStatic[(string, bool), ("a", true)]() == "(\"a\", true)" + +block: # issue #13515 + template test: bool = true + # compiles: + if not test: + doAssert false + # does not compile: + template x = + if not test: + doAssert false + x + +import macros + +block: # issue #21727 + template debugAnnotation(s: typed): string = + astToStr s + + macro cpsJump(x: int): untyped = + result = newLit(debugAnnotation(cpsJump)) + + doAssert cpsJump(13) == "cpsJump" diff --git a/tests/template/taliassyntaxerrors.nim b/tests/template/taliassyntaxerrors.nim new file mode 100644 index 000000000..f16acaf91 --- /dev/null +++ b/tests/template/taliassyntaxerrors.nim @@ -0,0 +1,28 @@ +discard """ + cmd: "nim check --hints:off $file" +""" + +block: # with params + type Foo = object + bar: int + + var foo = Foo(bar: 10) + template bar(x: int): int = x + foo.bar + let a = bar #[tt.Error + ^ invalid type: 'template (x: int): int' for let. Did you mean to call the template with '()'?]# + bar = 15 #[tt.Error + ^ 'bar' cannot be assigned to]# + +block: # generic template + type Foo = object + bar: int + + var foo = Foo(bar: 10) + template bar[T]: T = T(foo.bar) + let a = bar #[tt.Error + ^ invalid type: 'template (): T' for let. Did you mean to call the template with '()'?; tt.Error + ^ 'bar' has unspecified generic parameters]# + let b = bar[float]() + doAssert b == 10.0 + bar = 15 #[tt.Error + ^ 'bar' cannot be assigned to]# diff --git a/tests/template/tcallsitelineinfo.nim b/tests/template/tcallsitelineinfo.nim new file mode 100644 index 000000000..5fed93363 --- /dev/null +++ b/tests/template/tcallsitelineinfo.nim @@ -0,0 +1,17 @@ +discard """ + nimout: ''' +tcallsitelineinfo.nim(17, 4) Warning: abc [User] +''' + exitcode: 1 + outputsub: ''' +tcallsitelineinfo.nim(17) tcallsitelineinfo +Error: unhandled exception: def [ValueError] +''' +""" + +template foo(): untyped {.callsite.} = + {.warning: "abc".} + raise newException(ValueError, "def") + echo "hello" + +foo() diff --git a/tests/template/tcallsitelineinfo2.nim b/tests/template/tcallsitelineinfo2.nim new file mode 100644 index 000000000..d5f257474 --- /dev/null +++ b/tests/template/tcallsitelineinfo2.nim @@ -0,0 +1,20 @@ +discard """ + nimout: ''' +tcallsitelineinfo2.nim(18, 1) Warning: abc [User] +tcallsitelineinfo2.nim(19, 12) Warning: def [User] +''' + exitcode: 1 + outputsub: ''' +tcallsitelineinfo2.nim(20) tcallsitelineinfo2 +Error: unhandled exception: ghi [ValueError] +''' +""" + +template foo(a: untyped): untyped {.callsite.} = + {.warning: "abc".} + a + echo "hello" + +foo: # with `{.line.}:`, the following do not keep their line information: + {.warning: "def".} + raise newException(ValueError, "ghi") diff --git a/tests/template/tdefaultparam.nim b/tests/template/tdefaultparam.nim new file mode 100644 index 000000000..7ea0b2b25 --- /dev/null +++ b/tests/template/tdefaultparam.nim @@ -0,0 +1,56 @@ +block: + template foo(a: untyped, b: untyped = a(0)): untyped = + let x = a(0) + let y = b + (x, y) + proc bar(x: int): int = x + 1 + doAssert foo(bar, b = bar(0)) == (1, 1) + doAssert foo(bar) == (1, 1) + +block: # issue #23506 + var a: string + template foo(x: int; y = x) = + a = $($x, $y) + foo(1) + doAssert a == "(\"1\", \"1\")" + +block: # untyped params with default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: untyped = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: untyped = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" + template test3(body: untyped = willNotCompile) = + discard + test3() + +block: # typed params with `void` default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: typed = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: typed = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" diff --git a/tests/template/tdotcall.nim b/tests/template/tdotcall.nim new file mode 100644 index 000000000..dc97fd52e --- /dev/null +++ b/tests/template/tdotcall.nim @@ -0,0 +1,32 @@ +import mdotcall + +block: # issue #20073 + works() + boom() + +block: # issue #7085 + doAssert baz("hello") == "hellobar" + doAssert baz"hello" == "hellobar" + doAssert "hello".baz == "hellobar" + +block: # issue #7223 + var r = BytesRange(bytes: @[1.byte, 2, 3], ibegin: 0, iend: 2) + var a = r.rangeBeginAddr + +block: # issue #11733 + var a: ObjA + var evaluated = false + a.publicTemplateObjSyntax(42): evaluated = true + doAssert evaluated + +block: # issue #15246 + doAssert sourceBaseName() == "tdotcall" + +block: # issue #12683 + heh(0..40, "|") + +block: # issue #7889 + if false: + bindmeQuote() + if false: + bindmeTemplate() diff --git a/tests/template/template_issues.nim b/tests/template/template_issues.nim index 1fed694ef..58c40941d 100644 --- a/tests/template/template_issues.nim +++ b/tests/template/template_issues.nim @@ -296,3 +296,9 @@ block: # bug #12595 discard {i: ""} test() + +block: # bug #21920 + template t[T](): T = + discard + + t[void]() # Error: expression has no type: discard diff --git a/tests/template/template_various.nim b/tests/template/template_various.nim index 6b1290fb9..2088b1739 100644 --- a/tests/template/template_various.nim +++ b/tests/template/template_various.nim @@ -353,3 +353,54 @@ block gensym3: echo a ! b ! c ! d echo a ! b ! c ! d ! e echo x,y,z + +block: # issue #2465 + template t() = + template declX(str: string) {.gensym.} = + var x {.inject.} : string = str + + t() + doAssert not declared(declX) + doAssert not compiles(declX("a string")) + + template t2() = + template fooGensym() {.gensym.} = + echo 42 + + t2() + doAssert not declared(fooGensym) + doAssert not compiles(fooGensym()) + + +block identifier_construction_with_overridden_symbol: + # could use add, but wanna make sure it's an override no matter what + func examplefn = discard + func examplefn(x: int) = discard + + # the function our template wants to use + func examplefn1 = discard + + template exampletempl(n) = + # attempt to build a name using the overridden symbol "examplefn" + `examplefn n`() + + exampletempl(1) + +import typetraits + +block: # issue #4596 + type + T0 = object + T1 = object + + template printFuncsT() = + proc getV[A](a: typedesc[A]): string = + var s {. global .} = name(A) + return s + + printFuncsT() + + doAssert getV(T1) == "T1" + doAssert getV(T0) == "T0" + doAssert getV(T0) == "T0" + doAssert getV(T1) == "T1" diff --git a/tests/template/tgenericparam.nim b/tests/template/tgenericparam.nim new file mode 100644 index 000000000..becf75d36 --- /dev/null +++ b/tests/template/tgenericparam.nim @@ -0,0 +1,93 @@ +block: # basic template generic parameter substitution + block: # issue #13527 + template typeNameTempl[T](a: T): string = $T + proc typeNameProc[T](a: T): string = $T + doAssert typeNameTempl(1) == typeNameProc(1) + doAssert typeNameTempl(true) == typeNameProc(true) + doAssert typeNameTempl(1.0) == typeNameProc(1.0) + doAssert typeNameTempl(1u8) == typeNameProc(1u8) + + template isDefault[T](a: T): bool = a == default(T) + doAssert isDefault(0.0) + + block: # issue #17240 + func to(c: int, t: typedesc[float]): t = discard + template converted[I, T](i: seq[I], t: typedesc[T]): seq[T] = + var result = newSeq[T](2) + result[0] = i[0].to(T) + result + doAssert newSeq[int](3).converted(float) == @[0.0, 0.0] + + block: # issue #6340 + type A[T] = object + v: T + proc foo(x: int): string = "int" + proc foo(x: typedesc[int]): string = "typedesc[int]" + template fooT(x: int): string = "int" + template fooT(x: typedesc[int]): string = "typedesc[int]" + proc foo[T](x: A[T]): (string, string) = + (foo(T), fooT(T)) + template fooT[T](x: A[T]): (string, string) = + (foo(T), fooT(T)) + var x: A[int] + doAssert foo(x) == fooT(x) + + block: # issue #20033 + template run[T](): T = default(T) + doAssert run[int]() == 0 + +import options, tables, typetraits + +block: # complex cases of above with imports + block: # issue #19576, complex case + type RegistryKey = object + key, val: string + var regKey = @[RegistryKey(key: "abc", val: "def")] + template findFirst[T](s: seq[T], pred: proc(x: T): bool): Option[T] = + var res = none(T) # important line + for x in s: + if pred(x): + res = some(x) + break + res + proc getval(searchKey: string): Option[string] = + let found = regKey.findFirst(proc (rk: RegistryKey): bool = rk.key == searchKey) + if found.isNone: none(string) + else: some(found.get().val) + doAssert getval("strange") == none(string) + doAssert getval("abc") == some("def") + block: # issue #19076 + block: # case 1 + var tested: Table[string,int] + template `[]`[V](t:Table[string,V],key:string):untyped = + $V + doAssert tested["abc"] == "int" + template `{}`[V](t:Table[string,V],key:string):untyped = + ($V, tables.`[]`(t, key)) + doAssert (try: tested{"abc"} except KeyError: ("not there", 123)) == ("not there", 123) + tables.`[]=`(tested, "abc", 456) + doAssert tested["abc"] == "int" + doAssert tested{"abc"} == ("int", 456) + block: # case 2 + type Foo[A,T] = object + t:T + proc init[A,T](f:type Foo,a:typedesc[A],t:T):Foo[A,T] = Foo[A,T](t:t) + template fromOption[A](o:Option[A]):auto = + when o.isSome: + Foo.init(A,35) + else: + Foo.init(A,"hi") + let op = fromOption(some(5)) + block: # issue #7461 + template p[T](): untyped = none(T) + doAssert p[int]() == none(int) + block: # issue #7995 + var res: string + template copyRange[T](dest: seq[T], destOffset: int) = + when supportsCopyMem(T): + res = "A" + else: + res = "B" + var a = @[1, 2, 3] + copyRange(a, 0) + doAssert res == "A" diff --git a/tests/template/tgensymhijack.nim b/tests/template/tgensymhijack.nim new file mode 100644 index 000000000..72ff3d495 --- /dev/null +++ b/tests/template/tgensymhijack.nim @@ -0,0 +1,37 @@ +# issue #23326 + +type Result*[E] = object + e*: E + +proc error*[E](v: Result[E]): E = discard + +template valueOr*[E](self: Result[E], def: untyped): int = + when E isnot void: + when false: + # Comment line below to make it work + template error(): E {.used, gensym.} = s.e + discard + else: + template error(): E {.used, inject.} = + self.e + + def + else: + def + + +block: + let rErr = Result[string](e: "a") + let rErrV = rErr.valueOr: + ord(error[0]) + +block: + template foo(x: static bool): untyped = + when x: + let a = 123 + else: + template a: untyped {.gensym.} = 456 + a + + doAssert foo(false) == 456 + doAssert foo(true) == 123 diff --git a/tests/misc/tidentconcatenations.nim b/tests/template/tidentconcatenations.nim index ddd2e49cc..ddd2e49cc 100644 --- a/tests/misc/tidentconcatenations.nim +++ b/tests/template/tidentconcatenations.nim diff --git a/tests/template/tinnerouterproc.nim b/tests/template/tinnerouterproc.nim index 1f15fb13e..56e0d02df 100644 --- a/tests/template/tinnerouterproc.nim +++ b/tests/template/tinnerouterproc.nim @@ -6,3 +6,15 @@ block: # #20002 discard 3.bar # evaluates to 10 but only check if it compiles for now block: foo() + +block: # issue #23813 + template r(body: untyped) = + proc x() {.gensym.} = + body + template g() = + r: + let y = 0 + r: + proc y() = discard + y() + g() diff --git a/tests/template/tnested.nim b/tests/template/tnested.nim new file mode 100644 index 000000000..81e416a76 --- /dev/null +++ b/tests/template/tnested.nim @@ -0,0 +1,38 @@ +block: # issue #22775 + proc h(c: int) = discard + template k(v: int) = + template p() = v.h() + p() + let a = @[0] + k(0 and not a[0]) + +block: # issue #22775 case 2 + proc h(c: int, q: int) = discard + template k(v: int) = + template p() = h(v, v) + p() + let a = [0] + k(0 and not a[0]) + +block: # issue #22775 minimal cases + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + let a = [0] + k(not a[0]) + block: + k(-a[0]) + block: + proc f(x: int): int = x + k(f a[0]) + +block: # bracket assignment case of above tests + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + var a = [0] + k(not (block: + a[0] = 1 + 1)) diff --git a/tests/template/tobjectdeclfield.nim b/tests/template/tobjectdeclfield.nim new file mode 100644 index 000000000..afce2cae8 --- /dev/null +++ b/tests/template/tobjectdeclfield.nim @@ -0,0 +1,21 @@ +block: # issue #16005 + var x = 0 + + block: + type Foo = object + x: float # ok + + template main() = + block: + type Foo = object + x: float # Error: cannot use symbol of kind 'var' as a 'field' + + main() + +block: # issue #19552 + template test = + type + test2 = ref object + reset: int + + test() diff --git a/tests/template/topensym.nim b/tests/template/topensym.nim new file mode 100644 index 000000000..2f930407b --- /dev/null +++ b/tests/template/topensym.nim @@ -0,0 +1,209 @@ +{.experimental: "openSym".} + +block: # issue #24002 + type Result[T, E] = object + func value[T, E](self: Result[T, E]): T {.inline.} = + discard + func value[T: not void, E](self: var Result[T, E]): var T {.inline.} = + discard + template unrecognizedFieldWarning = + doAssert value == 123 + let x = value + doAssert value == x + proc readValue(value: var int) = + unrecognizedFieldWarning() + var foo: int = 123 + readValue(foo) + +block: # issue #22605 for templates, normal call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + template g(T: type): string = + var res = "ok" + let x = valueOr 123: + res = $error + "dummy" + res + + doAssert g(int) == "good" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = valueOr 123: + res = $error + "dummy" + res + + doAssert g2(int) == "bad" + +block: # issue #22605 for templates, method call syntax + const error = "bad" + + template valueOr(self: int, def: untyped): untyped = + case false + of true: "" + of false: + template error: untyped {.used, inject.} = "good" + def + + template g(T: type): string = + var res = "ok" + let x = 123.valueOr: + res = $error + "dummy" + res + + doAssert g(int) == "good" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = 123.valueOr: + res = $error + "dummy" + res + + doAssert g2(int) == "bad" + +block: # issue #22605 for templates, original complex example + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + + template g(T: type): string = + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + + doAssert g(int) == "f" + + template g2(T: type): string = + bind error # use the bad version on purpose + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + + doAssert g2(int) == "error" + +block: # issue #23865 for templates + type Xxx = enum + error + value + + type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate: bool + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + discard + else: + when E is void: + case oResultPrivate: bool + of false: + discard + of true: + vResultPrivate: T + else: + case oResultPrivate: bool + of false: + eResultPrivate: E + of true: + vResultPrivate: T + + func error[T, E](self: Result[T, E]): E = + ## Fetch error of result if set, or raise Defect + case self.oResultPrivate + of true: + when T isnot void: + raiseResultDefect("Trying to access error when value is set", self.vResultPrivate) + else: + raiseResultDefect("Trying to access error when value is set") + of false: + when E isnot void: + self.eResultPrivate + + template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + template g(T: type): string = + var res = "ok" + let x = f().valueOr: + res = $error + 123 + res + doAssert g(int) == "f" + +import std/sequtils + +block: # issue #15314 + var it: string + var nums = @[1,2,3] + + template doubleNums() = + nums.applyIt(it * 2) + + doubleNums() + doAssert nums == @[2, 4, 6] diff --git a/tests/template/topensymoverride.nim b/tests/template/topensymoverride.nim new file mode 100644 index 000000000..3d4bb59f1 --- /dev/null +++ b/tests/template/topensymoverride.nim @@ -0,0 +1,39 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj" +""" + +const value = "captured" +template fooOld(x: int, body: untyped): untyped = + let value {.inject.} = "injected" + body +template foo(x: int, body: untyped): untyped = + let value {.inject.} = "injected" + {.push experimental: "genericsOpenSym".} + body + {.pop.} + +proc old[T](): string = + fooOld(123): + return value +doAssert old[int]() == "captured" + +template oldTempl(): string = + block: + var res: string + fooOld(123): + res = value + res +doAssert oldTempl() == "captured" + +proc bar[T](): string = + foo(123): + return value +doAssert bar[int]() == "injected" + +template barTempl(): string = + block: + var res: string + foo(123): + res = value + res +doAssert barTempl() == "injected" diff --git a/tests/template/topensymwarning.nim b/tests/template/topensymwarning.nim new file mode 100644 index 000000000..0bbe0a9fb --- /dev/null +++ b/tests/template/topensymwarning.nim @@ -0,0 +1,60 @@ +discard """ + matrix: "--skipParentCfg --filenames:legacyRelProj" +""" + +type Xxx = enum + error + value + +type + Result[T, E] = object + when T is void: + when E is void: + oResultPrivate*: bool + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + discard + else: + when E is void: + case oResultPrivate*: bool + of false: + discard + of true: + vResultPrivate*: T + else: + case oResultPrivate*: bool + of false: + eResultPrivate*: E + of true: + vResultPrivate*: T + +template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped = + let s = (self) # TODO avoid copy + case s.oResultPrivate + of true: + s.vResultPrivate + of false: + when E isnot void: + template error: untyped {.used, inject.} = s.eResultPrivate + def + +proc f(): Result[int, cstring] = + Result[int, cstring](oResultPrivate: false, eResultPrivate: "f") + +template g(T: type): string = + var res = "ok" + let x = f().valueOr: + {.push warningAsError[IgnoredSymbolInjection]: on.} + # test spurious error + discard true + let _ = f + {.pop.} + res = $error #[tt.Warning + ^ a new symbol 'error' has been injected during template or generic instantiation, however 'error' [enumField declared in topensymwarning.nim(6, 3)] captured at the proc declaration will be used instead; either enable --experimental:openSym to use the injected symbol, or `bind` this captured symbol explicitly [IgnoredSymbolInjection]]# + 123 + res + +discard g(int) diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index b68d7e253..b559c2d9e 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -16,6 +16,7 @@ wth (total: 6) S1 5 +abc ''' """ # bug #1915 @@ -394,3 +395,11 @@ proc chunkedReadLoop2 = test2 test1(); test2() + +block: # bug #22846 + template foo2(x: proc (y: string)) = + let f = x + f("abc") + + foo2(proc (y: string) = echo y) + diff --git a/tests/template/tqualifiedident.nim b/tests/template/tqualifiedident.nim new file mode 100644 index 000000000..463b14ee7 --- /dev/null +++ b/tests/template/tqualifiedident.nim @@ -0,0 +1,8 @@ +block: # issue #19865 + template f() = discard default(system.int) + f() + +# issue #21221, same as above +type M = object +template r() = discard default(tqualifiedident.M) +r() diff --git a/tests/template/tqualifiedtype.nim b/tests/template/tqualifiedtype.nim new file mode 100644 index 000000000..6497af6ee --- /dev/null +++ b/tests/template/tqualifiedtype.nim @@ -0,0 +1,25 @@ +# issue #19866 + +# Switch module import order to switch which of last two +# doAsserts fails +import mqualifiedtype1 +import mqualifiedtype2 + +# this isn't officially supported but needed to point out the issue: +template f(moduleName: untyped): int = sizeof(`moduleName`.A) +template g(someType: untyped): int = sizeof(someType) + +# These are legitimately true. +doAssert sizeof(mqualifiedtype1.A) != sizeof(mqualifiedtype2.A) +doAssert g(mqualifiedtype1.A) != g(mqualifiedtype2.A) + +# Which means that this should not be true, but is in Nim 1.6 +doAssert f(`mqualifiedtype1`) != f(`mqualifiedtype2`) +doAssert f(mqualifiedtype1) != f(mqualifiedtype2) + +# These should be true, but depending on import order, exactly one +# fails in Nim 1.2, 1.6 and devel. +doAssert f(`mqualifiedtype1`) == g(mqualifiedtype1.A) +doAssert f(`mqualifiedtype2`) == g(mqualifiedtype2.A) +doAssert f(mqualifiedtype1) == g(mqualifiedtype1.A) +doAssert f(mqualifiedtype2) == g(mqualifiedtype2.A) diff --git a/tests/template/tredefinition_override.nim b/tests/template/tredefinition_override.nim index 0bda4025b..7ae232bba 100644 --- a/tests/template/tredefinition_override.nim +++ b/tests/template/tredefinition_override.nim @@ -1,4 +1,4 @@ -{.push warningAsError[TemplateRedefinition]: on.} +{.push warningAsError[ImplicitTemplateRedefinition]: on.} doAssert not (compiles do: template foo(): int = 1 diff --git a/tests/template/tunderscore1.nim b/tests/template/tunderscore1.nim new file mode 100644 index 000000000..d74e5ba63 --- /dev/null +++ b/tests/template/tunderscore1.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "the special identifier '_' is ignored in declarations and cannot be used" +""" + +# issue #12094, #13804 + +template foo = + let _ = 1 + echo _ + +foo() diff --git a/tests/template/twrongmapit.nim b/tests/template/twrongmapit.nim index 5b8663cf9..2d53d03f5 100644 --- a/tests/template/twrongmapit.nim +++ b/tests/template/twrongmapit.nim @@ -1,8 +1,6 @@ discard """ - output: "####" + joinable: false """ -# unfortunately our tester doesn't support multiple lines of compiler -# error messages yet... # bug #1562 type Foo* {.pure, final.} = object @@ -29,4 +27,4 @@ import sequtils (var i = @[""];i).applyIt(it) # now works: -echo "##", i[0], "##" +doAssert i[0] == "" diff --git a/tests/test_nimscript.nims b/tests/test_nimscript.nims index 5fc77f6e4..32b7d1416 100644 --- a/tests/test_nimscript.nims +++ b/tests/test_nimscript.nims @@ -6,7 +6,9 @@ from stdtest/specialpaths import buildDir when defined(nimPreviewSlimSystem): - import std/syncio + import std/[ + syncio, assertions, formatfloat, objectdollar, widestrs + ] import std/[ # Core: @@ -24,7 +26,7 @@ import std/[ # Strings: editdistance, wordwrap, parseutils, ropes, - pegs, punycode, strformat, strmisc, strscans, strtabs, + pegs, strformat, strmisc, strscans, strtabs, strutils, unicode, unidecode, cstrutils, # works but uses FFI: encodings @@ -62,7 +64,7 @@ import std/[ htmlgen, # Hashing: - base64, hashes, md5, + base64, hashes, # fails due to cstring cast/times import/endians import: oids # fails due to copyMem/endians import: sha1 diff --git a/tests/threads/t7172.nim b/tests/threads/t7172.nim index 983765dba..87e89417b 100644 --- a/tests/threads/t7172.nim +++ b/tests/threads/t7172.nim @@ -1,15 +1,17 @@ discard """ + disabled: i386 output: ''' In doStuff() In initProcess() -initProcess() done TEST +initProcess() done Crashes before getting here! ''' joinable: false """ import std/os +import std/typedthreads proc whatever() {.thread, nimcall.} = echo("TEST") @@ -18,8 +20,8 @@ proc initProcess(): void = echo("In initProcess()") var thread: Thread[void] createThread(thread, whatever) - echo("initProcess() done") joinThread(thread) + echo("initProcess() done") proc doStuff(): void = echo("In doStuff()") diff --git a/tests/threads/t8535.nim b/tests/threads/t8535.nim index 1af11f9ad..a4296df11 100644 --- a/tests/threads/t8535.nim +++ b/tests/threads/t8535.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 output: '''0 hello''' """ diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim index 50a1a4d34..90119aee7 100644 --- a/tests/threads/threadex.nim +++ b/tests/threads/threadex.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 outputsub: "Just a simple text for test" """ diff --git a/tests/threads/tjsthreads.nim b/tests/threads/tjsthreads.nim index 1085d9157..5122c9cd6 100644 --- a/tests/threads/tjsthreads.nim +++ b/tests/threads/tjsthreads.nim @@ -1,6 +1,6 @@ discard """ - targets: "c cpp js" - matrix: "--threads" + targets: "js" + matrix: "--threads:on" """ echo 123 diff --git a/tests/threads/tmanyjoin.nim b/tests/threads/tmanyjoin.nim index aca284965..af5bc460e 100644 --- a/tests/threads/tmanyjoin.nim +++ b/tests/threads/tmanyjoin.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 outputsub: "129" """ diff --git a/tests/threads/tmembug.nim b/tests/threads/tmembug.nim new file mode 100644 index 000000000..3618f0ecc --- /dev/null +++ b/tests/threads/tmembug.nim @@ -0,0 +1,51 @@ + +import std / [atomics, strutils, sequtils] + +type + BackendMessage* = object + field*: seq[int] + +var + chan1: Channel[BackendMessage] + chan2: Channel[BackendMessage] + +chan1.open() +chan2.open() + +proc routeMessage*(msg: BackendMessage) = + discard chan2.trySend(msg) + +var + recv: Thread[void] + stopToken: Atomic[bool] + +proc recvMsg() = + while not stopToken.load(moRelaxed): + let resp = chan1.tryRecv() + if resp.dataAvailable: + routeMessage(resp.msg) + echo "child consumes ", formatSize getOccupiedMem() + +createThread[void](recv, recvMsg) + +const MESSAGE_COUNT = 100 + +proc main() = + let msg: BackendMessage = BackendMessage(field: (0..500).toSeq()) + for j in 0..0: #100: + echo "New iteration" + + for _ in 1..MESSAGE_COUNT: + chan1.send(msg) + echo "After sending" + + var counter = 0 + while counter < MESSAGE_COUNT: + let resp = recv(chan2) + counter.inc + echo "After receiving ", formatSize getOccupiedMem() + + stopToken.store true, moRelaxed + joinThreads(recv) + +main() diff --git a/tests/threads/tonthreadcreation.nim b/tests/threads/tonthreadcreation.nim index f588a21c9..61529477d 100644 --- a/tests/threads/tonthreadcreation.nim +++ b/tests/threads/tonthreadcreation.nim @@ -1,4 +1,6 @@ discard """ + disabled: i386 + matrix: "--mm:refc; --mm:orc --deepcopy:on" output: '''some string here dying some string here''' """ diff --git a/tests/threads/tracy_allocator.nim b/tests/threads/tracy_allocator.nim index e8f0ec927..f3b39f4dc 100644 --- a/tests/threads/tracy_allocator.nim +++ b/tests/threads/tracy_allocator.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 output: '''true''' """ diff --git a/tests/threads/treusetvar.nim b/tests/threads/treusetvar.nim index 2b0017595..f0337801a 100644 --- a/tests/threads/treusetvar.nim +++ b/tests/threads/treusetvar.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 outputsub: "65" """ diff --git a/tests/threads/tthreadvars.nim b/tests/threads/tthreadvars.nim index 81aa2e5ec..745e3562c 100644 --- a/tests/threads/tthreadvars.nim +++ b/tests/threads/tthreadvars.nim @@ -1,4 +1,5 @@ discard """ +disabled: i386 output: ''' 10 1111 diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim index cadf6c550..fcff94e78 100644 --- a/tests/threads/ttryrecv.nim +++ b/tests/threads/ttryrecv.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" outputsub: "channel is empty" """ diff --git a/tests/tools/compile/tkoch.nim b/tests/tools/compile/tkoch.nim new file mode 100644 index 000000000..008721dc0 --- /dev/null +++ b/tests/tools/compile/tkoch.nim @@ -0,0 +1,5 @@ +discard """ + action: compile +""" + +include koch \ No newline at end of file diff --git a/tests/tools/compile/tniminst.nim b/tests/tools/compile/tniminst.nim new file mode 100644 index 000000000..78c736af0 --- /dev/null +++ b/tests/tools/compile/tniminst.nim @@ -0,0 +1,5 @@ +discard """ + action: compile +""" + +include tools/niminst/niminst \ No newline at end of file diff --git a/tests/tools/config.nims b/tests/tools/config.nims new file mode 100644 index 000000000..0f0cba8b4 --- /dev/null +++ b/tests/tools/config.nims @@ -0,0 +1,3 @@ +--d:nimPreviewSlimSystem +--d:nimPreviewCstringConversion +--d:nimPreviewProcConversion diff --git a/tests/tools/tlinter.nim b/tests/tools/tlinter.nim index a6d45ab3b..16f67905e 100644 --- a/tests/tools/tlinter.nim +++ b/tests/tools/tlinter.nim @@ -1,10 +1,10 @@ discard """ cmd: '''nim c --styleCheck:hint $file''' nimout: ''' +tlinter.nim(25, 1) Hint: 'tyPE' should be: 'type' [Name] tlinter.nim(21, 14) Hint: 'nosideeffect' should be: 'noSideEffect' [Name] tlinter.nim(21, 28) Hint: 'myown' should be: 'myOwn' [template declared in tlinter.nim(19, 9)] [Name] tlinter.nim(21, 35) Hint: 'inLine' should be: 'inline' [Name] -tlinter.nim(25, 1) Hint: 'tyPE' should be: 'type' [Name] tlinter.nim(23, 1) Hint: 'foO' should be: 'foo' [proc declared in tlinter.nim(21, 6)] [Name] tlinter.nim(27, 14) Hint: 'Foo_bar' should be: 'FooBar' [type declared in tlinter.nim(25, 6)] [Name] tlinter.nim(29, 6) Hint: 'someVAR' should be: 'someVar' [var declared in tlinter.nim(27, 5)] [Name] diff --git a/tests/tools/tnimgrep.nim b/tests/tools/tnimgrep.nim new file mode 100644 index 000000000..890a36e79 --- /dev/null +++ b/tests/tools/tnimgrep.nim @@ -0,0 +1,404 @@ +discard """ + output: ''' + +[Suite] nimgrep filesystem + +[Suite] nimgrep contents filtering +''' +""" +## Authors: quantimnot, a-mr + +import std/[osproc, os, streams, unittest, strutils] + +import std/syncio + +#======= +# setup +#======= + +var process: Process +var ngStdOut, ngStdErr: string +var ngExitCode: int +let previousDir = getCurrentDir() +let tempDir = getTempDir() +let testFilesRoot = tempDir / "nimgrep_test_files" + +template nimgrep(optsAndArgs): untyped = + process = startProcess(previousDir / "bin/nimgrep " & optsAndArgs, + options = {poEvalCommand}) + ngExitCode = process.waitForExit + ngStdOut = process.outputStream.readAll + ngStdErr = process.errorStream.readAll + +func fixSlash(s: string): string = + if DirSep == '/': + result = s + else: # on Windows + result = s.replace('/', DirSep) + +func initString(len = 1000, val = ' '): string = + result = newString(len) + for i in 0..<len: + result[i] = val + +# Create test file hierarchy. +createDir testFilesRoot +setCurrentDir testFilesRoot +createDir "a" / "b" +createDir "c" / "b" +createDir ".hidden" +writeFile("do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF", "PATTERN") +writeFile("a" / "b" / "only_the_pattern", "PATTERN") +writeFile("c" / "b" / "only_the_pattern", "PATTERN") +writeFile(".hidden" / "only_the_pattern", "PATTERN") +writeFile("null_in_first_1k", "\0PATTERN") +writeFile("null_after_first_1k", initString(1000) & "\0") +writeFile("empty", "") +writeFile("context_match_filtering", """ +- +CONTEXTPAT +- +PATTERN +- +- +- + +- +- +- +PATTERN +- +- +- +""") +writeFile("only_the_pattern.txt", "PATTERN") +writeFile("only_the_pattern.ascii", "PATTERN") + + +#======= +# tests +#======= + +suite "nimgrep filesystem": + + test "`--filename` with matching file": + nimgrep "-r --filename:KJKJHSFSFKASHFBKAF PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == fixSlash dedent""" + ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN + 1 matches + """ + + + test "`--dirname` with matching dir": + nimgrep "-r --dirname:.hid PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == fixSlash dedent""" + .hidden/only_the_pattern:1: PATTERN + 1 matches + """ + + let only_the_pattern = fixSlash dedent""" + a/b/only_the_pattern:1: PATTERN + c/b/only_the_pattern:1: PATTERN + 2 matches + """ + + let only_a = fixSlash dedent""" + a/b/only_the_pattern:1: PATTERN + 1 matches + """ + + test "`--dirname` with matching grandparent path segment": + nimgrep "-r --dirname:a PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == only_a + + test "`--dirpath` with matching grandparent path segment": + nimgrep "-r --dirp:a PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == only_a + + test "`--dirpath` with matching grandparent path segment": + nimgrep "-r --dirpath:a/b PATTERN".fixSlash + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == only_a + + + test "`--dirname` with matching parent path segment": + nimgrep "-r --dirname:b PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == only_the_pattern + + test "`--dirpath` with matching parent path segment": + nimgrep "-r --dirpath:b PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == only_the_pattern + + + let patterns_without_directory_a_b = fixSlash dedent""" + ./context_match_filtering:4: PATTERN + ./context_match_filtering:12: PATTERN + ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN + ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent""" + ./only_the_pattern.ascii:1: PATTERN + ./only_the_pattern.txt:1: PATTERN + .hidden/only_the_pattern:1: PATTERN + c/b/only_the_pattern:1: PATTERN + 8 matches + """ + + let patterns_without_directory_b = fixSlash dedent""" + ./context_match_filtering:4: PATTERN + ./context_match_filtering:12: PATTERN + ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN + ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent""" + ./only_the_pattern.ascii:1: PATTERN + ./only_the_pattern.txt:1: PATTERN + .hidden/only_the_pattern:1: PATTERN + 7 matches + """ + + test "`--ndirname` not matching grandparent path segment": + nimgrep "-r --ndirname:a PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == patterns_without_directory_a_b + + test "`--ndirname` not matching parent path segment": + nimgrep "-r --ndirname:b PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == patterns_without_directory_b + + test "`--notdirpath` not matching grandparent path segment": + nimgrep "-r --notdirpath:a PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == patterns_without_directory_a_b + + test "`--notdirpath` not matching parent path segment": + nimgrep "-r --ndirp:b PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == patterns_without_directory_b + + test "`--notdirpath` with matching grandparent/parent path segment": + nimgrep "-r --ndirp:a/b PATTERN".fixSlash + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == patterns_without_directory_a_b + + + test "`--text`, `-t`, `--bin:off` with file containing a null in first 1k chars": + nimgrep "-r --text PATTERN null_in_first_1k" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == "0 matches\n" + checkpoint "`--text`" + nimgrep "-r -t PATTERN null_in_first_1k" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == "0 matches\n" + checkpoint "`-t`" + nimgrep "-r --bin:off PATTERN null_in_first_1k" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == "0 matches\n" + checkpoint "`--binary:off`" + + + test "`--bin:only` with file containing a null in first 1k chars": + nimgrep "--bin:only -@ PATTERN null_in_first_1k null_after_first_1k only_the_pattern.txt" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == dedent""" + null_in_first_1k:1: ^@PATTERN + 1 matches + """ + + + test "`--bin:only` with file containing a null after first 1k chars": + nimgrep "--bin:only PATTERN null_after_first_1k only_the_pattern.txt" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == "0 matches\n" + + + # TODO: we need to throw a warning if e.g. both extension was provided and + # inappropriate filename was directly provided via command line + # + # test "`--ext:doesnotexist` without a matching file": + # # skip() # FIXME: this test fails + # nimgrep "--ext:doesnotexist PATTERN context_match_filtering only_the_pattern.txt" + # check ngExitCode == 0 + # check ngStdErr.len == 0 + # check ngStdOut == """ + #0 matches + #""" + # + # + # test "`--ext:txt` with a matching file": + # nimgrep "--ext:txt PATTERN context_match_filtering only_the_pattern.txt" + # check ngExitCode == 0 + # check ngStdErr.len == 0 + # check ngStdOut == """ + #only_the_pattern.txt:1: PATTERN + #1 matches + #""" + # + # + # test "`--ext:txt|doesnotexist` with some matching files": + # nimgrep "--ext:txt|doesnotexist PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii" + # check ngExitCode == 0 + # check ngStdErr.len == 0 + # check ngStdOut == """ + #only_the_pattern.txt:1: PATTERN + #1 matches + #""" + # + # + # test "`--ext` with some matching files": + # nimgrep "--ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii" + # check ngExitCode == 0 + # check ngStdErr.len == 0 + # check ngStdOut == """ + #context_match_filtering:4: PATTERN + #context_match_filtering:12: PATTERN + #2 matches + #""" + # + # + # test "`--ext:txt --ext` with some matching files": + # nimgrep "--ext:txt --ext PATTERN context_match_filtering only_the_pattern.txt only_the_pattern.ascii" + # check ngExitCode == 0 + # check ngStdErr.len == 0 + # check ngStdOut == """ + #context_match_filtering:4: PATTERN + #context_match_filtering:12: PATTERN + #only_the_pattern.txt:1: PATTERN + #3 matches + #""" + + +suite "nimgrep contents filtering": + + test "`--inFile` with matching file": + nimgrep "-r --inf:CONTEXTPAT PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == fixSlash dedent""" + ./context_match_filtering:4: PATTERN + ./context_match_filtering:12: PATTERN + 2 matches + """ + + + test "`--notinFile` with matching files": + nimgrep "-r --ninf:CONTEXTPAT PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == fixSlash dedent""" + ./do_not_create_another_file_with_this_pattern_KJKJHSFSFKASHFBKAF:1: PATTERN + ./null_in_first_1k:1: """ & "\0PATTERN\n" & dedent""" + ./only_the_pattern.ascii:1: PATTERN + ./only_the_pattern.txt:1: PATTERN + .hidden/only_the_pattern:1: PATTERN + a/b/only_the_pattern:1: PATTERN + c/b/only_the_pattern:1: PATTERN + 7 matches + """ + + + test "`--inContext` with missing context option": + # Using `--inContext` implies default -c:1 is used + nimgrep "-r --inContext:CONTEXTPAT PATTERN" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == "0 matches\n" + + + test "`--inContext` with PAT matching PATTERN": + # This tests the scenario where PAT always matches PATTERN and thus + # has the same effect as excluding the `inContext` option. + # I'm not sure of the desired behaviour here. + nimgrep "--context:2 --inc:PAT PATTERN context_match_filtering" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == dedent""" + context_match_filtering:2 CONTEXTPAT + context_match_filtering:3 - + context_match_filtering:4: PATTERN + context_match_filtering:5 - + context_match_filtering:6 - + + context_match_filtering:10 - + context_match_filtering:11 - + context_match_filtering:12: PATTERN + context_match_filtering:13 - + context_match_filtering:14 - + + 2 matches + """ + + + test "`--inContext` with PAT in context": + nimgrep "--context:2 --inContext:CONTEXTPAT PATTERN context_match_filtering" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == dedent""" + context_match_filtering:2 CONTEXTPAT + context_match_filtering:3 - + context_match_filtering:4: PATTERN + context_match_filtering:5 - + context_match_filtering:6 - + + 1 matches + """ + + + test "`--notinContext` with PAT matching some contexts": + nimgrep "--context:2 --ninContext:CONTEXTPAT PATTERN context_match_filtering" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == dedent""" + context_match_filtering:10 - + context_match_filtering:11 - + context_match_filtering:12: PATTERN + context_match_filtering:13 - + context_match_filtering:14 - + + 1 matches + """ + + + test "`--notinContext` with PAT not matching any of the contexts": + nimgrep "--context:1 --ninc:CONTEXTPAT PATTERN context_match_filtering" + check ngExitCode == 0 + check ngStdErr.len == 0 + check ngStdOut == dedent""" + context_match_filtering:3 - + context_match_filtering:4: PATTERN + context_match_filtering:5 - + + context_match_filtering:11 - + context_match_filtering:12: PATTERN + context_match_filtering:13 - + + 2 matches + """ + + +#========= +# cleanup +#========= + +setCurrentDir previousDir +removeDir testFilesRoot diff --git a/tests/tools/tunused_imports.nim b/tests/tools/tunused_imports.nim index 31d6cf7d7..539608ad6 100644 --- a/tests/tools/tunused_imports.nim +++ b/tests/tools/tunused_imports.nim @@ -1,9 +1,12 @@ discard """ cmd: '''nim c --hint:Processing:off $file''' nimout: ''' -tunused_imports.nim(11, 10) Warning: BEGIN [User] -tunused_imports.nim(36, 10) Warning: END [User] -tunused_imports.nim(34, 8) Warning: imported and not used: 'strutils' [UnusedImport] +tunused_imports.nim(14, 10) Warning: BEGIN [User] +tunused_imports.nim(41, 10) Warning: END [User] +tunused_imports.nim(37, 8) Warning: imported and not used: 'strutils' [UnusedImport] +tunused_imports.nim(38, 13) Warning: imported and not used: 'strtabs' [UnusedImport] +tunused_imports.nim(38, 22) Warning: imported and not used: 'cstrutils' [UnusedImport] +tunused_imports.nim(39, 12) Warning: imported and not used: 'macrocache' [UnusedImport] ''' action: "compile" """ @@ -32,5 +35,7 @@ macro bar(): untyped = bar() import strutils +import std/[strtabs, cstrutils] +import std/macrocache {.warning: "END".} diff --git a/tests/trmacros/tnorewrite.nim b/tests/trmacros/tnorewrite.nim new file mode 100644 index 000000000..e6769246f --- /dev/null +++ b/tests/trmacros/tnorewrite.nim @@ -0,0 +1,20 @@ +block: + proc get(x: int): int = x + + template t{get(a)}(a: int): int = + {.noRewrite.}: + get(a) + 1 + + doAssert get(0) == 1 + +block: + var x: int + + template asgn{a = b}(a: int{lvalue}, b: int) = + let newVal = b + 1 + # ^ this is needed but should it be? + {.noRewrite.}: + a = newVal + + x = 10 + doAssert x == 11, $x diff --git a/tests/trmacros/tor.nim b/tests/trmacros/tor.nim index 087dc0d68..9defc4d1b 100644 --- a/tests/trmacros/tor.nim +++ b/tests/trmacros/tor.nim @@ -1,11 +1,23 @@ discard """ - output: '''0 + output: ''' +3 +30 true -3''' +''' """ + +# bug #798 +template t012{(0|1|2){x}}(x: untyped): untyped = x+1 +let z = 1 +# outputs 3 thanks to fixpoint iteration: +echo z + + template arithOps: untyped = (`+` | `-` | `*`) -template testOr{ (arithOps{f})(a, b) }(a, b, f: untyped): untyped = f(a mod 10, b) +template testOr{ (arithOps{f})(a, b) }(a, b, f: untyped): untyped = + {.noRewrite.}: + f(a mod 10, b) let xx = 10 echo 10*xx @@ -20,9 +32,3 @@ var c = false a = b and a echo a - -# bug #798 -template t012{(0|1|2){x}}(x: untyped): untyped = x+1 -let z = 1 -# outputs 3 thanks to fixpoint iteration: -echo z diff --git a/tests/trmacros/trmacros_various.nim b/tests/trmacros/trmacros_various.nim index 74b248739..8fe51e548 100644 --- a/tests/trmacros/trmacros_various.nim +++ b/tests/trmacros/trmacros_various.nim @@ -33,7 +33,8 @@ block tcse: block hoist: template optPeg{peg(pattern)}(pattern: string{lit}): Peg = - var gl {.global, gensym.} = peg(pattern) + {.noRewrite.}: + var gl {.global, gensym.} = peg(pattern) gl doAssert match("(a b c)", peg"'(' @ ')'") doAssert match("W_HI_Le", peg"\y 'while'") diff --git a/tests/trmacros/trmacros_various2.nim b/tests/trmacros/trmacros_various2.nim index 257ee8ba6..981df4ca6 100644 --- a/tests/trmacros/trmacros_various2.nim +++ b/tests/trmacros/trmacros_various2.nim @@ -70,7 +70,9 @@ block tstar: for i in 1..len(s)-1: result.add s[i] inc calls - template optConc{ `&&` * a }(a: string): string = &&a + template optConc{ `&&` * a }(a: string): string = + {.noRewrite.}: + &&a let space = " " echo "my" && (space & "awe" && "some " ) && "concat" diff --git a/tests/tuples/mnimsconstunpack.nim b/tests/tuples/mnimsconstunpack.nim new file mode 100644 index 000000000..65fafc12f --- /dev/null +++ b/tests/tuples/mnimsconstunpack.nim @@ -0,0 +1,4 @@ +proc foo(): tuple[a, b: string] = + result = ("a", "b") + +const (a, b*) = foo() diff --git a/tests/tuples/t18125_1.nim b/tests/tuples/t18125_1.nim new file mode 100644 index 000000000..74fdfe8f5 --- /dev/null +++ b/tests/tuples/t18125_1.nim @@ -0,0 +1,14 @@ +# issue #18125 solved with type inference + +type + Parent = ref object of RootObj + + Child = ref object of Parent + c: char + +func foo(c: char): (Parent, int) = + # Works if you use (Parent(Child(c: c)), 0) + (Child(c: c), 0) + +let x = foo('x')[0] +doAssert Child(x).c == 'x' diff --git a/tests/tuples/t18125_2.nim b/tests/tuples/t18125_2.nim new file mode 100644 index 000000000..fe0a4a8bb --- /dev/null +++ b/tests/tuples/t18125_2.nim @@ -0,0 +1,20 @@ +discard """ + errormsg: "type mismatch: got <(Child, int)> but expected '(Parent, int)'" + line: 17 +""" + +# issue #18125 solved with correct type relation + +type + Parent = ref object of RootObj + + Child = ref object of Parent + c: char + +func foo(c: char): (Parent, int) = + # Works if you use (Parent(Child(c: c)), 0) + let x = (Child(c: c), 0) + x + +let x = foo('x')[0] +doAssert Child(x).c == 'x' diff --git a/tests/tuples/tnimsconstunpack.nim b/tests/tuples/tnimsconstunpack.nim new file mode 100644 index 000000000..7860fc0a4 --- /dev/null +++ b/tests/tuples/tnimsconstunpack.nim @@ -0,0 +1,8 @@ +discard """ + action: compile + cmd: "nim e $file" +""" + +import mnimsconstunpack + +doAssert b == "b" diff --git a/tests/tuples/ttuples_issues.nim b/tests/tuples/ttuples_issues.nim index 0cc505d28..70defdfce 100644 --- a/tests/tuples/ttuples_issues.nim +++ b/tests/tuples/ttuples_issues.nim @@ -107,6 +107,18 @@ template main() = return (x,y) doAssert bar() == (10, (11,)) + block: # bug #16331 + type T1 = tuple[a, b: int] + + proc p(b: bool): T1 = + var x: T1 = (10, 20) + x = if b: (x.b, x.a) else: (-x.b, -x.a) + x + + doAssert p(false) == (-20, -10) + doAssert p(true) == (20, 10) + + proc mainProc() = # other tests should be in `main` block: diff --git a/tests/tuples/ttuples_various.nim b/tests/tuples/ttuples_various.nim index dc060da1e..e392731d2 100644 --- a/tests/tuples/ttuples_various.nim +++ b/tests/tuples/ttuples_various.nim @@ -171,3 +171,41 @@ block tuple_with_seq: echo s (s, 7) t = test(t.a) + +block: # bug #22049 + type A = object + field: tuple[a, b, c: seq[int]] + + func value(v: var A): var tuple[a, b, c: seq[int]] = + v.field + template get(v: A): tuple[a, b, c: seq[int]] = v.value + + var v = A(field: (@[1], @[2], @[3])) + var (a, b, c) = v.get() + + doAssert a == @[1] + doAssert b == @[2] + doAssert c == @[3] + +block: # bug #22054 + type A = object + field: tuple[a: int] + + func value(v: var A): var tuple[a: int] = + v.field + template get(v: A): tuple[a: int] = v.value + + var v = A(field: (a: 1314)) + doAssert get(v)[0] == 1314 + +block: # tuple unpacking assignment with underscore + var + a = 1 + b = 2 + doAssert (a, b) == (1, 2) + (a, _) = (3, 4) + doAssert (a, b) == (3, 2) + (_, a) = (5, 6) + doAssert (a, b) == (6, 2) + (b, _) = (7, 8) + doAssert (a, b) == (6, 7) diff --git a/tests/typerel/t4799_1.nim b/tests/typerel/t4799_1.nim index 74012190b..03d2a0cfa 100644 --- a/tests/typerel/t4799_1.nim +++ b/tests/typerel/t4799_1.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" targets: "c cpp" outputsub: '''ObjectAssignmentDefect''' exitcode: "1" diff --git a/tests/typerel/t4799_2.nim b/tests/typerel/t4799_2.nim index f97b89622..ef8571f25 100644 --- a/tests/typerel/t4799_2.nim +++ b/tests/typerel/t4799_2.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" targets: "c cpp" outputsub: '''ObjectAssignmentDefect''' exitcode: "1" diff --git a/tests/typerel/t4799_3.nim b/tests/typerel/t4799_3.nim index 6102b69cc..26258b983 100644 --- a/tests/typerel/t4799_3.nim +++ b/tests/typerel/t4799_3.nim @@ -1,4 +1,5 @@ discard """ + matrix: "--mm:refc" targets: "c cpp" outputsub: '''ObjectAssignmentDefect''' exitcode: "1" diff --git a/tests/typerel/t7600_1.nim b/tests/typerel/t7600_1.nim index e9d01bd0d..83f93ae7f 100644 --- a/tests/typerel/t7600_1.nim +++ b/tests/typerel/t7600_1.nim @@ -1,6 +1,6 @@ discard """ errormsg: "type mismatch: got <Thin[system.int]>" -nimout: '''t7600_1.nim(21, 6) Error: type mismatch: got <Thin[system.int]> +nimout: '''t7600_1.nim(21, 1) Error: type mismatch: got <Thin[system.int]> but expected one of: proc test[T](x: Paper[T]) first type mismatch at position: 1 diff --git a/tests/typerel/t7600_2.nim b/tests/typerel/t7600_2.nim index 371707f4c..9488a44bc 100644 --- a/tests/typerel/t7600_2.nim +++ b/tests/typerel/t7600_2.nim @@ -1,6 +1,6 @@ discard """ errormsg: "type mismatch: got <Thin>" -nimout: '''t7600_2.nim(20, 6) Error: type mismatch: got <Thin> +nimout: '''t7600_2.nim(20, 1) Error: type mismatch: got <Thin> but expected one of: proc test(x: Paper) first type mismatch at position: 1 diff --git a/tests/typerel/tnoargopenarray.nim b/tests/typerel/tnoargopenarray.nim deleted file mode 100644 index 9e2b2fb86..000000000 --- a/tests/typerel/tnoargopenarray.nim +++ /dev/null @@ -1,8 +0,0 @@ -discard """ -action: compile -""" - -import db_sqlite - -var db: DbConn -exec(db, sql"create table blabla()") diff --git a/tests/typerel/tproctypeclass.nim b/tests/typerel/tproctypeclass.nim new file mode 100644 index 000000000..e8fab9780 --- /dev/null +++ b/tests/typerel/tproctypeclass.nim @@ -0,0 +1,89 @@ +import std/assertions + +proc main = + iterator closureIter(): int {.closure.} = + yield 1 + yield 2 + iterator inlineIter(): int {.inline.} = + yield 1 + yield 2 + proc procNotIter(): int = 1 + + doAssert closureIter is iterator + doAssert inlineIter is iterator + doAssert procNotIter isnot iterator + + doAssert closureIter isnot proc + doAssert inlineIter isnot proc + doAssert procNotIter is proc + + doAssert typeof(closureIter) is iterator + doAssert typeof(inlineIter) is iterator + doAssert typeof(procNotIter) isnot iterator + + doAssert typeof(closureIter) isnot proc + doAssert typeof(inlineIter) isnot proc + doAssert typeof(procNotIter) is proc + + block: + proc fn1(iter: iterator {.closure.}) = discard + proc fn2[T: iterator {.closure.}](iter: T) = discard + + fn1(closureIter) + fn2(closureIter) + + doAssert not compiles(fn1(procNotIter)) + doAssert not compiles(fn2(procNotIter)) + + doAssert not compiles(fn1(inlineIter)) + doAssert not compiles(fn2(inlineIter)) + + block: # concrete iterator type + proc fn1(iter: iterator(): int) = discard + proc fn2[T: iterator(): int](iter: T) = discard + + fn1(closureIter) + fn2(closureIter) + + doAssert not compiles(fn1(procNotIter)) + doAssert not compiles(fn2(procNotIter)) + + doAssert not compiles(fn1(inlineIter)) + doAssert not compiles(fn2(inlineIter)) + + proc takesNimcall[T: proc {.nimcall.}](p: T) = discard + proc takesClosure[T: proc {.closure.}](p: T) = discard + proc takesAnyProc[T: proc](p: T) = discard + + proc nimcallProc(): int {.nimcall.} = 1 + proc closureProc(): int {.closure.} = 2 + + doAssert nimcallProc is proc {.nimcall.} + takesNimcall(nimcallProc) + doAssert closureProc isnot proc {.nimcall.} + doAssert not compiles(takesNimcall(closureProc)) + + doAssert nimcallProc isnot proc {.closure.} + doAssert not compiles(takesClosure(nimcallProc)) + doAssert closureProc is proc {.closure.} + takesClosure(closureProc) + + doAssert nimcallProc is proc + takesAnyProc(nimcallProc) + doAssert closureProc is proc + takesAnyProc(closureProc) + + block: # supposed to test that sameType works + template ensureNotRedefine(Ty): untyped = + proc foo[T: Ty](x: T) = discard + doAssert not (compiles do: + proc bar[T: Ty](x: T) = discard + proc bar[T: Ty](x: T) = discard) + ensureNotRedefine proc + ensureNotRedefine iterator + ensureNotRedefine proc {.nimcall.} + ensureNotRedefine iterator {.nimcall.} + ensureNotRedefine proc {.closure.} + ensureNotRedefine iterator {.closure.} + +main() diff --git a/tests/typerel/tregionptrs.nim b/tests/typerel/tregionptrs.nim deleted file mode 100644 index 504ec1011..000000000 --- a/tests/typerel/tregionptrs.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - errormsg: "type mismatch: got <BPtr> but expected 'APtr = ptr[RegionA, int]'" - line: 16 -""" - -type - RegionA = object - APtr = RegionA ptr int - RegionB = object - BPtr = RegionB ptr int - -var x,xx: APtr -var y: BPtr -x = nil -x = xx -x = y diff --git a/tests/typerel/tsigmatch.nim b/tests/typerel/tsigmatch.nim new file mode 100644 index 000000000..7541f2028 --- /dev/null +++ b/tests/typerel/tsigmatch.nim @@ -0,0 +1,6 @@ +block: # bug #13618 + proc test(x: Natural or BackwardsIndex): int = + int(x) + + doAssert test(^1) == 1 + doAssert test(1) == 1 diff --git a/tests/typerel/ttynilinstantiation.nim b/tests/typerel/ttynilinstantiation.nim new file mode 100644 index 000000000..303506689 --- /dev/null +++ b/tests/typerel/ttynilinstantiation.nim @@ -0,0 +1,7 @@ +proc foo[T: proc](x: T) = + # old error here: + let y = x + # invalid type: 'typeof(nil)' for let + +foo(nil) #[tt.Error + ^ type mismatch: got <typeof(nil)>]# diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim index 3998a6a5f..8fdcf217e 100644 --- a/tests/typerel/ttypedesc_as_genericparam1.nim +++ b/tests/typerel/ttypedesc_as_genericparam1.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:refc" errormsg: "type mismatch: got <typedesc[int]>" - line: 6 + line: 7 """ # bug #3079, #1146 -echo repr(int) +echo repr(int) \ No newline at end of file diff --git a/tests/typerel/ttypedesc_as_genericparam1_orc.nim b/tests/typerel/ttypedesc_as_genericparam1_orc.nim new file mode 100644 index 000000000..d528a7421 --- /dev/null +++ b/tests/typerel/ttypedesc_as_genericparam1_orc.nim @@ -0,0 +1,5 @@ +discard """ + matrix: "--mm:orc" +""" + +doAssert repr(int) == "int" diff --git a/tests/typerel/ttypedesc_as_genericparam2.nim b/tests/typerel/ttypedesc_as_genericparam2.nim index ea06606f9..882f66584 100644 --- a/tests/typerel/ttypedesc_as_genericparam2.nim +++ b/tests/typerel/ttypedesc_as_genericparam2.nim @@ -1,6 +1,7 @@ discard """ + matrix: "--mm:refc" errormsg: "'repr' doesn't support 'void' type" - line: 9 + line: 10 """ # bug #2879 diff --git a/tests/typerel/ttypelessemptyset.nim b/tests/typerel/ttypelessemptyset.nim index 5f49c33fd..a4b6f003a 100644 --- a/tests/typerel/ttypelessemptyset.nim +++ b/tests/typerel/ttypelessemptyset.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "internal error: invalid kind for lastOrd(tyEmpty)" + errormsg: "statement returns no value that can be discarded" """ var q = false discard (if q: {} else: {}) diff --git a/tests/typerel/tuncheckedarray_eq.nim b/tests/typerel/tuncheckedarray_eq.nim new file mode 100644 index 000000000..c07696b5f --- /dev/null +++ b/tests/typerel/tuncheckedarray_eq.nim @@ -0,0 +1,2 @@ +type p = ptr UncheckedArray[char] +doAssert p is ptr UncheckedArray \ No newline at end of file diff --git a/tests/typerel/typedescs.nim b/tests/typerel/typedescs.nim index 23b9ce64f..faf919e13 100644 --- a/tests/typerel/typedescs.nim +++ b/tests/typerel/typedescs.nim @@ -5,3 +5,18 @@ p(type((5, 6))) # Compiles (type((5, 6))).p # Doesn't compile (SIGSEGV: Illegal storage access.) type T = type((5, 6)) # Doesn't compile (SIGSEGV: Illegal storage access.) +block: # issue #21677 + type + Uints = uint16|uint32 + + template constructor(name: untyped, typ: typedesc[Uints], typ2: typedesc[Uints]) = + type + name = object + data: typ + data2: typ2 + + proc `init name`(data: typ, data2: typ2): name = + result.data = data + result.data2 = data2 + + constructor(Test, uint32, uint16) diff --git a/tests/types/t15836.nim b/tests/types/t15836.nim new file mode 100644 index 000000000..27d3ad0d0 --- /dev/null +++ b/tests/types/t15836.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "type mismatch: got <int literal(1), proc (a: GenericParam): auto>" + line: 11 +""" + +proc takesProc[T](x: T, f: proc(x: T): int) = + echo f(x) + 2 + +takesProc(1, proc (a: int): int = 2) # ok, prints 4 +takesProc(1, proc (a: auto): auto = 2) # ok, prints 4 +takesProc(1, proc (a: auto): auto = "uh uh") # prints garbage diff --git a/tests/types/t15836_2.nim b/tests/types/t15836_2.nim new file mode 100644 index 000000000..6a16e2d22 --- /dev/null +++ b/tests/types/t15836_2.nim @@ -0,0 +1,21 @@ +import std/sugar + +type Tensor[T] = object + x: T + +proc numerical_gradient*[T](input: T, f: (proc(x: T): T), h = T(1e-5)): T {.inline.} = + result = default(T) + +proc numerical_gradient*[T](input: Tensor[T], f: (proc(x: Tensor[T]): T), h = T(1e-5)): Tensor[T] {.noinit.} = + result = default(Tensor[T]) + +proc conv2d*[T](input: Tensor[T]): Tensor[T] {.inline.} = + result = default(Tensor[T]) + +proc sum*[T](arg: Tensor[T]): T = default(T) + +proc sum*[T](arg: Tensor[T], axis: int): Tensor[T] {.noinit.} = default(Tensor[T]) + +let dinput = Tensor[int](x: 1) +let target_grad_input = dinput.numerical_gradient( + x => conv2d(x).sum()) diff --git a/tests/types/t21027.nim b/tests/types/t21027.nim new file mode 100644 index 000000000..3a992177a --- /dev/null +++ b/tests/types/t21027.nim @@ -0,0 +1,5 @@ +discard """ + errormsg: "Invalid usage of cast, cast requires a type to convert to, e.g., cast[int](0d)." +""" +# bug #21027 +let x: uint64 = cast(5) diff --git a/tests/types/t21260.nim b/tests/types/t21260.nim new file mode 100644 index 000000000..90d6613c1 --- /dev/null +++ b/tests/types/t21260.nim @@ -0,0 +1,13 @@ +discard """ + errormsg: "illegal recursion in type 'Foo'" + line: 8 +""" + +type + Kind = enum kA, kB + Foo = object + case k: Kind: + of kA: + foo: Foo + of kB: + discard diff --git a/tests/types/t5648.nim b/tests/types/t5648.nim new file mode 100644 index 000000000..b3bd406b3 --- /dev/null +++ b/tests/types/t5648.nim @@ -0,0 +1,32 @@ +discard """ + output: ''' +ptr Foo +''' +joinable: false +""" +# not joinable because it causes out of memory with --gc:boehm + +# issue #5648 + +import typetraits + +type Foo = object + bar: int + +proc main() = + var f = create(Foo) + f.bar = 3 + echo f.type.name + + discard realloc(f, 0) + + var g = Foo() + g.bar = 3 + +var + mainPtr = cast[pointer](main) + mainFromPtr = cast[typeof(main)](mainPtr) + +doAssert main == mainFromPtr + +main() diff --git a/tests/types/tcyclic.nim b/tests/types/tcyclic.nim new file mode 100644 index 000000000..651394c8b --- /dev/null +++ b/tests/types/tcyclic.nim @@ -0,0 +1,135 @@ +## todo publish the `isCyclic` when it's mature. +proc isCyclic(t: typedesc): bool {.magic: "TypeTrait".} = + ## Returns true if the type can potentially form a cyclic type + +template cyclicYes(x: typed) = + doAssert isCyclic(x) + +template cyclicNo(x: typed) = + doAssert not isCyclic(x) + +# atomic types are not cyclic +cyclicNo(int) +cyclicNo(float) +cyclicNo(string) +cyclicNo(char) +cyclicNo(void) + +type + Object = object + Ref = ref object + +cyclicNo(Object) +cyclicNo(Ref) + +type + Data1 = ref object + Data2 = ref object + id: Data1 + +cyclicNo(Data2) + +type + Cyclone = ref object + data: Cyclone + + Alias = Cyclone + + Acyclic {.acyclic.} = ref object + data: Acyclic + + LinkedNode = object + next: ref LinkedNode + + LinkedNodeWithCursor = object + next {.cursor.} : ref LinkedNodeWithCursor + +cyclicYes(Cyclone) +cyclicYes(Alias) +cyclicNo(seq[Cyclone]) +cyclicNo((Cyclone, )) +cyclicNo(Acyclic) + +cyclicYes(LinkedNode) +cyclicNo(LinkedNodeWithCursor) # cursor doesn't increase rc, cannot form a cycle + +type + ObjectWithoutCycles = object + data: seq[ObjectWithoutCycles] + +cyclicNo(ObjectWithoutCycles) + + +block: + type + Try = object + id: Best + Best = object + name: ref Try + Best2 = ref Best + + cyclicYes(Best) + cyclicYes(Try) + cyclicNo(Best2) + + type + Base = object + data: ref seq[Base] + Base2 = ref Base + + cyclicYes(Base) + cyclicNo(Base2) + + + type + Base3 = ref object + id: Base3 + + Base4 = object + id: ref Base4 + + cyclicYes(Base3) + cyclicYes(Base4) + cyclicYes(ref Base4) + +block: + type Cyclic2 = object + x: ref (Cyclic2, int) + + cyclicYes (Cyclic2, int) + cyclicYes (ref (Cyclic2, int)) + +block: + type + myseq[T] = object + data: ptr UncheckedArray[T] + Node = ref object + kids: myseq[Node] + + cyclicNo(Node) + +block: + type + myseq[T] = object + data: ptr UncheckedArray[T] + Node = ref object + kids: myseq[Node] + + proc `=trace`(x: var myseq[Node]; env: pointer) = discard + + cyclicYes(Node) + +block: + type + Foo = object + id: ptr ref Foo + + cyclicNo(Foo) + +block: + type + InheritableObj = object of RootObj + InheritableRef = ref object of RootObj + + cyclicYes(InheritableObj) + cyclicYes(InheritableRef) diff --git a/tests/types/texportgeneric.nim b/tests/types/texportgeneric.nim new file mode 100644 index 000000000..9e6be2bb6 --- /dev/null +++ b/tests/types/texportgeneric.nim @@ -0,0 +1,8 @@ +discard """ + errormsg: "{.exportc.} not allowed for generic types" + line: 6 +""" + +type Struct[T] {.exportc.} = object + a:int + b: T \ No newline at end of file diff --git a/tests/types/tinheritgenericparameter.nim b/tests/types/tinheritgenericparameter.nim new file mode 100644 index 000000000..d0d313635 --- /dev/null +++ b/tests/types/tinheritgenericparameter.nim @@ -0,0 +1,39 @@ +discard """ + cmd: "nim check --hints:off --warnings:off $file" + action: "reject" + nimout:''' +tinheritgenericparameter.nim(36, 15) Error: Cannot inherit from: 'MyObject' +tinheritgenericparameter.nim(36, 15) Error: Cannot inherit from: 'MyObject' +tinheritgenericparameter.nim(36, 23) Error: object constructor needs an object type [error] +tinheritgenericparameter.nim(36, 23) Error: expression '' has no type (or is ambiguous) +tinheritgenericparameter.nim(37, 15) Error: Cannot inherit from: 'int' +tinheritgenericparameter.nim(37, 15) Error: Cannot inherit from: 'int' +tinheritgenericparameter.nim(37, 23) Error: object constructor needs an object type [error] +tinheritgenericparameter.nim(37, 23) Error: expression '' has no type (or is ambiguous) +''' +""" + +type + MyObject = object + HorzLayout[Base, T] = ref object of Base + data: seq[T] + VertLayout[T, Base] = ref object of Base + data: seq[T] + UiElement = ref object of RootObj + a: int + MyType[T] = ref object of RootObj + data: seq[T] + OtherElement[T] = ref object of T + Child[T] = ref object of HorzLayout[UiElement, T] + Child2[T] = ref object of VertLayout[T, UiElement] + Child3[T] = ref object of HorzLayout[MyObject, T] + Child4[T] = ref object of HorzLayout[int, T] +static: + var a = Child[int](a: 300, data: @[100, 200, 300]) + assert a.a == 300 + assert a.data == @[100, 200, 300] +discard Child2[string]() +discard Child3[string]() +discard Child4[string]() +discard OtherElement[MyType[int]]() + diff --git a/tests/types/tinheritref.nim b/tests/types/tinheritref.nim index b79926356..c03e3bcab 100644 --- a/tests/types/tinheritref.nim +++ b/tests/types/tinheritref.nim @@ -11,10 +11,10 @@ ob = T[int](elem: 23) doAssert ob.elem == 23 type - TTreeIteratorA* {.inheritable.} = ref object - TKeysIteratorA* = ref object of TTreeIteratorA #compiles + TTreeIteratorA* {.inheritable.} = ref object + TTreeIterator* [T,D] {.inheritable.} = ref object TKeysIterator* [T,D] = ref object of TTreeIterator[T,D] #this not diff --git a/tests/types/tisop.nim b/tests/types/tisop.nim deleted file mode 100644 index 5f9cba0d8..000000000 --- a/tests/types/tisop.nim +++ /dev/null @@ -1,48 +0,0 @@ -discard """ - disabled: true -""" - -import typetraits - -type - TRecord = (tuple) or (object) - - TFoo[T, U] = object - x: int - - when T is string: - y: float - else: - y: string - - when U is TRecord: - z: float - - E = enum A, B, C - -macro m(t: typedesc): typedesc = - if t is enum: - result = string - else: - result = int - -var f: TFoo[int, int] -static: doAssert(f.y.type.name == "string") - -when compiles(f.z): - {.error: "Foo should not have a `z` field".} - -proc p(a, b: auto) = - when a.type is int: - static: doAssert false - - var f: TFoo[m(a.type), b.type] - static: - doAssert f.x.type.name == "int" - echo f.y.type.name - doAssert f.y.type.name == "float" - echo f.z.type.name - doAssert f.z.type.name == "float" - -p(A, f) - diff --git a/tests/types/tisopr.nim b/tests/types/tisopr.nim index 67f1ce0c1..c95b63c90 100644 --- a/tests/types/tisopr.nim +++ b/tests/types/tisopr.nim @@ -135,3 +135,37 @@ block: let Q = MyObj[P](y: 2) doAssert($Q == "(y: 2)") +block: # previously tisop.nim + type + TRecord = (tuple) or (object) + TFoo[T, U] = object + x: int + when T is string: + y: float + else: + y: string + when U is TRecord: + z: float + E = enum A, B, C + template m(t: typedesc): typedesc = + when t is enum: + string + else: + int + var f: TFoo[int, int] + static: doAssert(typeof(f.y) is string) + when compiles(f.z): + {.error: "Foo should not have a `z` field".} + proc p(a, b: auto) = + when typeof(a) is int: + static: doAssert false + var f: TFoo[m(a.typeof), b.typeof] + static: + doAssert f.x.typeof is int + doAssert f.y.typeof is float + doAssert f.z.typeof is float + p(A, f) + +block: # issue #22850 + doAssert not (type is int) + doAssert not (typedesc is int) diff --git a/tests/types/tissues_types.nim b/tests/types/tissues_types.nim index 7ed0547bf..6bb1258f4 100644 --- a/tests/types/tissues_types.nim +++ b/tests/types/tissues_types.nim @@ -3,7 +3,6 @@ discard """ true true true -ptr Foo (member: "hello world") (member: 123.456) (member: "hello world", x: ...) @@ -11,10 +10,7 @@ ptr Foo 0 false ''' -joinable: false """ -# not joinable because it causes out of memory with --gc:boehm -import typetraits block t1252: echo float32 isnot float64 @@ -29,29 +25,6 @@ block t5640: var v = vec2([0.0'f32, 0.0'f32]) -block t5648: - type Foo = object - bar: int - - proc main() = - var f = create(Foo) - f.bar = 3 - echo f.type.name - - discard realloc(f, 0) - - var g = Foo() - g.bar = 3 - - var - mainPtr1: pointer = main - mainPtr2 = pointer(main) - mainPtr3 = cast[pointer](main) - - doAssert mainPtr1 == mainPtr2 and mainPtr2 == mainPtr3 - - main() - block t7581: discard int -1 @@ -108,3 +81,38 @@ block: var f1: Foo echo f1.bar + +import macros + +block: # issue #12582 + macro foo(T: type): type = + nnkBracketExpr.newTree(bindSym "array", newLit 1, T) + var + _: foo(int) # fine + type + Foo = object + x: foo(int) # fine + Bar = ref object + x: foo(int) # error + let b = Bar() + let b2 = Bar(x: [123]) + +block: + when true: # bug #14710 + type Foo[T] = object + x1: int + when T.sizeof == 4: discard # SIGSEGV + when sizeof(T) == 4: discard # ok + let t = Foo[float](x1: 1) + doAssert t.x1 == 1 + +block: + template s(d: varargs[typed])=discard + + proc something(x:float)=discard + proc something(x:int)=discard + proc otherthing()=discard + + s(something) + s(otherthing, something) + s(something, otherthing) diff --git a/tests/types/ttopdowninference.nim b/tests/types/ttopdowninference.nim index 296729cd8..765761e99 100644 --- a/tests/types/ttopdowninference.nim +++ b/tests/types/ttopdowninference.nim @@ -193,3 +193,141 @@ block: # templates doAssert a == float(1) doAssert b == byte(2) doAssert c == cstring("abc") + + +proc foo(): set[char] = # bug #11259 + discard "a" + {} + +discard foo() + +block: # bug #11085 + const ok1: set[char] = {} + var ok1b: set[char] = {} + + const ok2: set[char] = block: + {} + + const ok3: set[char] = block: + var x: set[char] = {} + x + var ok3b: set[char] = block: + var x: set[char] = {} + x + + var bad: set[char] = block: + {} + +# bug #6213 +block: + block: + type MyEnum = enum a, b + type MyTuple = tuple[x: set[MyEnum]] + + var myVar: seq[MyTuple] = @[ (x: {}) ] + doAssert myVar.len == 1 + + block: + type + Foo = tuple + f: seq[string] + s: string + + proc e(): seq[Foo] = + return @[ + (@[], "asd") + ] + + doAssert e()[0].f == @[] + +block: # bug #11777 + type S = set[0..5] + var s: S = {1, 2} + doAssert 1 in s + +block: # bug #20807 + var s: seq[string] + template fail = + s = @[] + template test(body: untyped) = + body + proc test(a: string) = discard + test: fail() + doAssert not (compiles do: + let x: seq[int] = `@`[string]([])) + +block: # bug #21377 + proc b[T](v: T): seq[int] = + let x = 0 + @[] + + doAssert b(0) == @[] + +block: # bug #21377 + proc b[T](v: T): seq[T] = + let x = 0 + @[] + + doAssert b(0) == @[] + +block: # bug #21377 + proc b[T](v: T): set[bool] = + let x = 0 + {} + + doAssert b(0) == {} + +block: # bug #21377 + proc b[T](v: T): array[0, int] = + let x = 0 + [] + + doAssert b(0) == [] + +block: # bug #21377 + proc b[T](v: T): array[0, (string, string)] = + let x = 0 + {:} + + doAssert b(0) == {:} + +block: # bug #22180 + type A = object + proc j() = discard + + let x = + if false: + (ref A)(nil) + else: + if false: + quit 1 + else: + if true: + j() + nil # compiles with (ref A)(nil) here + else: + (ref A)(nil) + doAssert x.isNil + + let y = + case true + of false: + (ref A)(nil) + else: + case true + of false: + quit 1 + else: + case true + of true: + j() + nil # compiles with (ref A)(nil) here + else: + (ref A)(nil) + doAssert y.isNil + +block: # issue #24164, related regression + proc foo(x: proc ()) = discard + template bar(x: untyped = nil) = + foo(x) + bar() diff --git a/tests/untestable/gdb/gdb_pretty_printer_test.py b/tests/untestable/gdb/gdb_pretty_printer_test.py index 8f0f88e85..aed0cfeb0 100644 --- a/tests/untestable/gdb/gdb_pretty_printer_test.py +++ b/tests/untestable/gdb/gdb_pretty_printer_test.py @@ -1,11 +1,14 @@ import gdb +import re +import sys # this test should test the gdb pretty printers of the nim # library. But be aware this test is not complete. It only tests the # command line version of gdb. It does not test anything for the # machine interface of gdb. This means if if this test passes gdb # frontends might still be broken. -gdb.execute("source ../../../tools/nim-gdb.py") +gdb.execute("set python print-stack full") +gdb.execute("source ../../../tools/debug/nim-gdb.py") # debug all instances of the generic function `myDebug`, should be 14 gdb.execute("rbreak myDebug") gdb.execute("run") @@ -16,7 +19,7 @@ outputs = [ '"meTwo"', '{meOne, meThree}', 'MyOtherEnum(1)', - '5', + '{MyOtherEnum(0), MyOtherEnum(2)}', 'array = {1, 2, 3, 4, 5}', 'seq(0, 0)', 'seq(0, 10)', @@ -25,16 +28,21 @@ outputs = [ 'seq(3, 3) = {"one", "two", "three"}', 'Table(3, 64) = {[4] = "four", [5] = "five", [6] = "six"}', 'Table(3, 8) = {["two"] = 2, ["three"] = 3, ["one"] = 1}', - '{a = 1, b = "some string"}' + '{a = 1, b = "some string"}', + '("hello", 42)' ] +argRegex = re.compile("^.* = (?:No suitable Nim \$ operator found for type: \w+\s*)*(.*)$") +# Remove this error message which can pop up +noSuitableRegex = re.compile("(No suitable Nim \$ operator found for type: \w+\s*)") + for i, expected in enumerate(outputs): - gdb.write(f"{i+1}) expecting: {expected}: ", gdb.STDLOG) + gdb.write(f"\x1b[38;5;105m{i+1}) expecting: {expected}: \x1b[0m", gdb.STDLOG) gdb.flush() - - functionSymbol = gdb.selected_frame().block().function - assert functionSymbol.line == 41, str(functionSymbol.line) - + currFrame = gdb.selected_frame() + functionSymbol = currFrame.block().function + assert functionSymbol.line == 24, str(functionSymbol.line) + raw = "" if i == 6: # myArray is passed as pointer to int to myDebug. I look up myArray up in the stack gdb.execute("up") @@ -44,10 +52,13 @@ for i, expected in enumerate(outputs): gdb.execute("up") raw = gdb.parse_and_eval("myOtherArray") else: - raw = gdb.parse_and_eval("arg") - + rawArg = re.sub(noSuitableRegex, "", gdb.execute("info args", to_string = True)) + raw = rawArg.split("=", 1)[-1].strip() output = str(raw) - assert output == expected, "{0} : output: ({1}) != expected: ({2})".format(i, output, expected) - gdb.write(f"passed\n", gdb.STDLOG) + if output != expected: + gdb.write(f"\x1b[38;5;196m ({output}) != expected: ({expected})\x1b[0m\n", gdb.STDERR) + gdb.execute("quit 1") + else: + gdb.write("\x1b[38;5;34mpassed\x1b[0m\n", gdb.STDLOG) gdb.execute("continue") diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_output.txt b/tests/untestable/gdb/gdb_pretty_printer_test_output.txt deleted file mode 100644 index 73d26016f..000000000 --- a/tests/untestable/gdb/gdb_pretty_printer_test_output.txt +++ /dev/null @@ -1,3 +0,0 @@ -Loading Nim Runtime support. -NimEnumPrinter: lookup global symbol 'NTI__z9cu80OJCfNgw9bUdzn5ZEzw_ failed for tyEnum_MyOtherEnum__z9cu80OJCfNgw9bUdzn5ZEzw. -8 diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_program.nim b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim index d2acdd282..163c99860 100644 --- a/tests/untestable/gdb/gdb_pretty_printer_test_program.nim +++ b/tests/untestable/gdb/gdb_pretty_printer_test_program.nim @@ -18,23 +18,6 @@ type MyObj = object a*: int b*: string - - # MyVariant = ref object - # id*: int - # case kind*: MyEnum - # of meOne: mInt*: int - # of meTwo, meThree: discard - # of meFour: - # moInt*: int - # babies*: seq[MyVariant] - # after: float - - # MyIntVariant = ref object - # stuff*: int - # case myKind*: range[0..32766] - # of 0: mFloat*: float - # of 2: mString*: string - # else: mBabies*: seq[MyIntVariant] var counter = 0 @@ -97,16 +80,10 @@ proc testProc(): void = var obj = MyObj(a: 1, b: "some string") myDebug(obj) #15 - # var varObj = MyVariant(id: 13, kind: meFour, moInt: 94, - # babies: @[MyVariant(id: 18, kind: meOne, mInt: 7, after: 1.0), - # MyVariant(id: 21, kind: meThree, after: 2.0)], - # after: 3.0) - # myDebug(varObj) #16 - - # var varObjInt = MyIntVariant(stuff: 5, myKind: 2, mString: "this is my sweet string") - # myDebug(varObjInt) #17 + var tup = ("hello", 42) + myDebug(tup) # 16 - echo(counter) + assert counter == 16 testProc() diff --git a/tests/untestable/gdb/gdb_pretty_printer_test_run.sh b/tests/untestable/gdb/gdb_pretty_printer_test_run.sh index 525f54705..411c68435 100644..100755 --- a/tests/untestable/gdb/gdb_pretty_printer_test_run.sh +++ b/tests/untestable/gdb/gdb_pretty_printer_test_run.sh @@ -1,15 +1,13 @@ #!/usr/bin/env bash -# Exit if anything fails set -e -#!/usr/bin/env bash # Compile the test project with fresh debug information. -nim c --debugger:native gdb_pretty_printer_test_program.nim &> /dev/null +nim c --debugger:native --mm:orc --out:gdbNew gdb_pretty_printer_test_program.nim +echo "Running new runtime tests..." # 2>&1 redirects stderr to stdout (all output in stdout) -# <(...) is a bash feature that makes the output of a command into a -# file handle. -# diff compares the two files, the expected output, and the file -# handle that is created by the execution of gdb. -diff ./gdb_pretty_printer_test_output.txt <(gdb -x gdb_pretty_printer_test.py --batch-silent --args gdb_pretty_printer_test_program 2>&1) -# The exit code of diff is forwarded as the exit code of this -# script. So when the comparison fails, the exit code of this script -# won't be 0. So this script should be embeddable in a test suite. +gdb -x gdb_pretty_printer_test.py --batch-silent --args gdbNew 2>&1 + + +# Do it all again, but with old runtime +nim c --debugger:native --mm:refc --out:gdbOld gdb_pretty_printer_test_program.nim &> /dev/null +echo "Running old runtime tests" +gdb -x gdb_pretty_printer_test.py --batch-silent --args gdbOld 2>&1 diff --git a/tests/untestable/thttpclient_ssl_remotenetwork.nim b/tests/untestable/thttpclient_ssl_remotenetwork.nim index d2366d9a9..3cb759516 100644 --- a/tests/untestable/thttpclient_ssl_remotenetwork.nim +++ b/tests/untestable/thttpclient_ssl_remotenetwork.nim @@ -32,65 +32,71 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win good, bad, dubious, good_broken, bad_broken, dubious_broken CertTest = tuple[url:string, category:Category, desc: string] - const certificate_tests: array[0..54, CertTest] = [ - ("https://wrong.host.badssl.com/", bad, "wrong.host"), - ("https://captive-portal.badssl.com/", bad, "captive-portal"), - ("https://expired.badssl.com/", bad, "expired"), - ("https://google.com/", good, "good"), - ("https://self-signed.badssl.com/", bad, "self-signed"), - ("https://untrusted-root.badssl.com/", bad, "untrusted-root"), - ("https://revoked.badssl.com/", bad_broken, "revoked"), - ("https://pinning-test.badssl.com/", bad_broken, "pinning-test"), - ("https://no-common-name.badssl.com/", bad, "no-common-name"), - ("https://no-subject.badssl.com/", bad, "no-subject"), - ("https://sha1-intermediate.badssl.com/", bad, "sha1-intermediate"), - ("https://sha256.badssl.com/", good, "sha256"), - ("https://sha384.badssl.com/", bad, "sha384"), - ("https://sha512.badssl.com/", bad, "sha512"), - ("https://1000-sans.badssl.com/", bad, "1000-sans"), - ("https://10000-sans.badssl.com/", good_broken, "10000-sans"), - ("https://ecc256.badssl.com/", good_broken, "ecc256"), - ("https://ecc384.badssl.com/", good_broken, "ecc384"), - ("https://rsa2048.badssl.com/", good, "rsa2048"), - ("https://rsa8192.badssl.com/", dubious_broken, "rsa8192"), - ("http://http.badssl.com/", good, "regular http"), - ("https://http.badssl.com/", bad_broken, "http on https URL"), # FIXME - ("https://cbc.badssl.com/", dubious, "cbc"), - ("https://rc4-md5.badssl.com/", bad, "rc4-md5"), - ("https://rc4.badssl.com/", bad, "rc4"), - ("https://3des.badssl.com/", bad, "3des"), - ("https://null.badssl.com/", bad, "null"), - ("https://mozilla-old.badssl.com/", bad_broken, "mozilla-old"), - ("https://mozilla-intermediate.badssl.com/", dubious_broken, "mozilla-intermediate"), - ("https://mozilla-modern.badssl.com/", good, "mozilla-modern"), - ("https://dh480.badssl.com/", bad, "dh480"), - ("https://dh512.badssl.com/", bad, "dh512"), - ("https://dh1024.badssl.com/", dubious_broken, "dh1024"), - ("https://dh2048.badssl.com/", good, "dh2048"), - ("https://dh-small-subgroup.badssl.com/", bad_broken, "dh-small-subgroup"), - ("https://dh-composite.badssl.com/", bad_broken, "dh-composite"), - ("https://static-rsa.badssl.com/", dubious, "static-rsa"), - ("https://tls-v1-0.badssl.com:1010/", dubious, "tls-v1-0"), - ("https://tls-v1-1.badssl.com:1011/", dubious, "tls-v1-1"), - ("https://invalid-expected-sct.badssl.com/", bad, "invalid-expected-sct"), - ("https://hsts.badssl.com/", good, "hsts"), - ("https://upgrade.badssl.com/", good, "upgrade"), - ("https://preloaded-hsts.badssl.com/", good, "preloaded-hsts"), - ("https://subdomain.preloaded-hsts.badssl.com/", bad, "subdomain.preloaded-hsts"), - ("https://https-everywhere.badssl.com/", good, "https-everywhere"), - ("https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/", good, - "long-extended-subdomain-name-containing-many-letters-and-dashes"), - ("https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/", good, - "longextendedsubdomainnamewithoutdashesinordertotestwordwrapping"), - ("https://superfish.badssl.com/", bad, "(Lenovo) Superfish"), - ("https://edellroot.badssl.com/", bad, "(Dell) eDellRoot"), - ("https://dsdtestprovider.badssl.com/", bad, "(Dell) DSD Test Provider"), - ("https://preact-cli.badssl.com/", bad, "preact-cli"), - ("https://webpack-dev-server.badssl.com/", bad, "webpack-dev-server"), - ("https://mitm-software.badssl.com/", bad, "mitm-software"), - ("https://sha1-2016.badssl.com/", dubious, "sha1-2016"), - ("https://sha1-2017.badssl.com/", bad, "sha1-2017"), - ] + # badssl certs sometimes expire, set to false when that happens + when true: + const certificate_tests: array[0..54, CertTest] = [ + ("https://wrong.host.badssl.com/", bad, "wrong.host"), + ("https://captive-portal.badssl.com/", bad, "captive-portal"), + ("https://expired.badssl.com/", bad, "expired"), + ("https://google.com/", good, "good"), + ("https://self-signed.badssl.com/", bad, "self-signed"), + ("https://untrusted-root.badssl.com/", bad, "untrusted-root"), + ("https://revoked.badssl.com/", bad_broken, "revoked"), + ("https://pinning-test.badssl.com/", bad_broken, "pinning-test"), + ("https://no-common-name.badssl.com/", bad, "no-common-name"), + ("https://no-subject.badssl.com/", bad, "no-subject"), + ("https://sha1-intermediate.badssl.com/", bad, "sha1-intermediate"), + ("https://sha256.badssl.com/", good, "sha256"), + ("https://sha384.badssl.com/", bad, "sha384"), + ("https://sha512.badssl.com/", bad, "sha512"), + ("https://1000-sans.badssl.com/", bad, "1000-sans"), + ("https://10000-sans.badssl.com/", good_broken, "10000-sans"), + ("https://ecc256.badssl.com/", good_broken, "ecc256"), + ("https://ecc384.badssl.com/", good_broken, "ecc384"), + ("https://rsa2048.badssl.com/", good, "rsa2048"), + ("https://rsa8192.badssl.com/", dubious_broken, "rsa8192"), + ("http://http.badssl.com/", good, "regular http"), + ("https://http.badssl.com/", bad_broken, "http on https URL"), # FIXME + ("https://cbc.badssl.com/", dubious, "cbc"), + ("https://rc4-md5.badssl.com/", bad, "rc4-md5"), + ("https://rc4.badssl.com/", bad, "rc4"), + ("https://3des.badssl.com/", bad, "3des"), + ("https://null.badssl.com/", bad, "null"), + ("https://mozilla-old.badssl.com/", bad_broken, "mozilla-old"), + ("https://mozilla-intermediate.badssl.com/", dubious_broken, "mozilla-intermediate"), + ("https://mozilla-modern.badssl.com/", good, "mozilla-modern"), + ("https://dh480.badssl.com/", bad, "dh480"), + ("https://dh512.badssl.com/", bad, "dh512"), + ("https://dh1024.badssl.com/", dubious_broken, "dh1024"), + ("https://dh2048.badssl.com/", good, "dh2048"), + ("https://dh-small-subgroup.badssl.com/", bad_broken, "dh-small-subgroup"), + ("https://dh-composite.badssl.com/", bad_broken, "dh-composite"), + ("https://static-rsa.badssl.com/", dubious, "static-rsa"), + ("https://tls-v1-0.badssl.com:1010/", dubious, "tls-v1-0"), + ("https://tls-v1-1.badssl.com:1011/", dubious, "tls-v1-1"), + ("https://invalid-expected-sct.badssl.com/", bad, "invalid-expected-sct"), + ("https://hsts.badssl.com/", good, "hsts"), + ("https://upgrade.badssl.com/", good, "upgrade"), + ("https://preloaded-hsts.badssl.com/", good, "preloaded-hsts"), + ("https://subdomain.preloaded-hsts.badssl.com/", bad, "subdomain.preloaded-hsts"), + ("https://https-everywhere.badssl.com/", good, "https-everywhere"), + ("https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/", good, + "long-extended-subdomain-name-containing-many-letters-and-dashes"), + ("https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/", good, + "longextendedsubdomainnamewithoutdashesinordertotestwordwrapping"), + ("https://superfish.badssl.com/", bad, "(Lenovo) Superfish"), + ("https://edellroot.badssl.com/", bad, "(Dell) eDellRoot"), + ("https://dsdtestprovider.badssl.com/", bad, "(Dell) DSD Test Provider"), + ("https://preact-cli.badssl.com/", bad, "preact-cli"), + ("https://webpack-dev-server.badssl.com/", bad, "webpack-dev-server"), + ("https://mitm-software.badssl.com/", bad, "mitm-software"), + ("https://sha1-2016.badssl.com/", dubious, "sha1-2016"), + ("https://sha1-2017.badssl.com/", bad, "sha1-2017"), + ] + else: + const certificate_tests: array[0..0, CertTest] = [ + ("https://google.com/", good, "good") + ] template evaluate(exception_msg: string, category: Category, desc: string) = @@ -190,12 +196,18 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win type NetSocketTest = tuple[hostname: string, port: Port, category:Category, desc: string] - const net_tests:array[0..3, NetSocketTest] = [ - ("imap.gmail.com", 993.Port, good, "IMAP"), - ("wrong.host.badssl.com", 443.Port, bad, "wrong.host"), - ("captive-portal.badssl.com", 443.Port, bad, "captive-portal"), - ("expired.badssl.com", 443.Port, bad, "expired"), - ] + # badssl certs sometimes expire, set to false when that happens + when true: + const net_tests:array[0..3, NetSocketTest] = [ + ("imap.gmail.com", 993.Port, good, "IMAP"), + ("wrong.host.badssl.com", 443.Port, bad, "wrong.host"), + ("captive-portal.badssl.com", 443.Port, bad, "captive-portal"), + ("expired.badssl.com", 443.Port, bad, "expired"), + ] + else: + const net_tests: array[0..0, NetSocketTest] = [ + ("imap.gmail.com", 993.Port, good, "IMAP") + ] # TODO: ("null.badssl.com", 443.Port, bad_broken, "null"), diff --git a/tests/untestable/tpostgres.nim b/tests/untestable/tpostgres.nim index d3397e53a..8b1378917 100644 --- a/tests/untestable/tpostgres.nim +++ b/tests/untestable/tpostgres.nim @@ -1,328 +1 @@ -import db_postgres, strutils - - -let db = open("localhost", "dom", "", "test") -db.exec(sql"DROP TABLE IF EXISTS myTable") -db.exec(sql("""CREATE TABLE myTable ( - id integer PRIMARY KEY, - name varchar(50) not null)""")) -let name = "Dom" -db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)", - name) -doAssert db.getValue(sql"SELECT name FROM myTable") == name -# Check issue #3513 -doAssert db.getValue(sql"SELECT name FROM myTable") == name - - -# issue #3560 -proc addToDb(conn: DbConn, fileId: int, fileName: string): int64 = - result = conn.insertId(sql("INSERT into files (id, filename) VALUES (?, ?)"), fileId, fileName) - -db.exec(sql"DROP TABLE IF EXISTS files") -db.exec(sql"DROP TABLE IF EXISTS fileobjects") -db.exec(sql("""CREATE TABLE FILEOBJECTS( - ID SERIAL PRIMARY KEY, - FILE_SIZE INT, - MD5 CHAR(32) NOT NULL UNIQUE - );""")) - -db.exec(sql("""CREATE TABLE FILES( - ID SERIAL PRIMARY KEY, - OBJECT_ID INT, - FILENAME TEXT NOT NULL, - URI TEXT, - SCHEME CHAR(10), - PUBLIC BOOLEAN DEFAULT FALSE, - CONSTRAINT fk1_fileobjs FOREIGN KEY (object_id) - REFERENCES fileobjects (id) MATCH SIMPLE - ON DELETE CASCADE - );""")) - -let f1 = db.addToDb(1, "hello.tmp") -doAssert f1 == 1 -let f2 = db.addToDb(2, "hello2.tmp") -doAssert f2 == 2 - -# PreparedStmt vs. normal query -try: - echo db.getValue(sql("select * from files where id = $1"), 1) - doAssert false, "Exception expected" -except DbError: - let msg = getCurrentExceptionMsg().normalize - doAssert "expects" in msg - doAssert "?" in msg - doAssert "parameter substitution" in msg - -doAssert db.getValue(sql("select filename from files where id = ?"), 1) == "hello.tmp" - -var first = prepare(db, "one", sql"select filename from files where id = $1", 1) -doAssert db.getValue(first, 1) == "hello.tmp" - -try: - var second = prepare(db, "two", sql"select filename from files where id = ?", 1) - doAssert false, "Exception expected" -except: - let msg = getCurrentExceptionMsg().normalize - doAssert "expects" in msg - doAssert "$1" in msg - doAssert "parameter substitution" in msg - -# issue #3569 -db.exec(SqlQuery("DROP TABLE IF EXISTS tags")) -db.exec(SqlQuery("CREATE TABLE tags(id serial UNIQUE, name varchar(255))")) - -for i in 1..10: - var name = "t" & $i - echo(name) - discard db.getRow( - SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name])) - -# get column details -db.exec(SqlQuery("DROP TABLE IF EXISTS dbtypes;")) -db.exec(SqlQuery("DROP TYPE IF EXISTS custom_enum;")) -db.exec(SqlQuery("CREATE TYPE custom_enum AS ENUM ('1', '2', '3');")) -db.exec(SqlQuery("DROP TYPE IF EXISTS custom_composite;")) -db.exec(SqlQuery("CREATE TYPE custom_composite AS (r double precision, i double precision);")) -db.exec(SqlQuery("""CREATE TABLE dbtypes( - id serial UNIQUE, - bytea_col bytea, - smallint_col smallint, - integer_col integer, - bigint_col bigint, - decimal_col decimal, - numeric_col numeric, - real_col real, - double_precision_col double precision, - smallserial_col smallserial, - serial_col serial, - bigserial_col bigserial, - money_col money, - varchar_col varchar(10), - character_col character(1), - text_col text, - timestamp_col timestamp, - date_col date, - time_col time, - interval_col interval, - bool_col boolean, - custom_enum_col custom_enum, - point_col point, - line_col line, - lseg_col lseg, - box_col box, - path_col path, - polygon_col polygon, - circle_col circle, - cidr_col cidr, - inet_col inet, - macaddr_col macaddr, - bit_col bit, - varbit_col bit(3), - tsvector_col tsvector, - tsquery_col tsquery, - uuid_col uuid, - xml_col xml, - json_col json, - array_col integer[], - custom_composite_col custom_composite, - range_col int4range - );""")) -db.exec(SqlQuery("INSERT INTO dbtypes (id) VALUES(0);")) - -var dbCols : DbColumns = @[] -for row in db.instantRows(dbCols, sql"SELECT * FROM dbtypes"): - doAssert len(dbCols) == 42 - -doAssert dbCols[0].name == "id" -doAssert dbCols[0].typ.kind == DbTypeKind.dbInt -doAssert dbCols[0].typ.name == "int4" -doAssert dbCols[0].typ.size == 4 - -doAssert dbCols[1].name == "bytea_col" -doAssert dbCols[1].typ.kind == DbTypeKind.dbBlob -doAssert dbCols[1].typ.name == "bytea" - -doAssert dbCols[2].name == "smallint_col" -doAssert dbCols[2].typ.kind == DbTypeKind.dbInt -doAssert dbCols[2].typ.name == "int2" -doAssert dbCols[2].typ.size == 2 - -doAssert dbCols[3].name == "integer_col" -doAssert dbCols[3].typ.kind == DbTypeKind.dbInt -doAssert dbCols[3].typ.name == "int4" -doAssert dbCols[3].typ.size == 4 - -doAssert dbCols[4].name == "bigint_col" -doAssert dbCols[4].typ.kind == DbTypeKind.dbInt -doAssert dbCols[4].typ.name == "int8" -doAssert dbCols[4].typ.size == 8 - -doAssert dbCols[5].name == "decimal_col" -doAssert dbCols[5].typ.kind == DbTypeKind.dbDecimal -doAssert dbCols[5].typ.name == "numeric" - -doAssert dbCols[6].name == "numeric_col" -doAssert dbCols[6].typ.kind == DbTypeKind.dbDecimal -doAssert dbCols[6].typ.name == "numeric" - -doAssert dbCols[7].name == "real_col" -doAssert dbCols[7].typ.kind == DbTypeKind.dbFloat -doAssert dbCols[7].typ.name == "float4" - -doAssert dbCols[8].name == "double_precision_col" -doAssert dbCols[8].typ.kind == DbTypeKind.dbFloat -doAssert dbCols[8].typ.name == "float8" - -doAssert dbCols[9].name == "smallserial_col" -doAssert dbCols[9].typ.kind == DbTypeKind.dbInt -doAssert dbCols[9].typ.name == "int2" - -doAssert dbCols[10].name == "serial_col" -doAssert dbCols[10].typ.kind == DbTypeKind.dbInt -doAssert dbCols[10].typ.name == "int4" - -doAssert dbCols[11].name == "bigserial_col" -doAssert dbCols[11].typ.kind == DbTypeKind.dbInt -doAssert dbCols[11].typ.name == "int8" - -doAssert dbCols[12].name == "money_col" -doAssert dbCols[12].typ.kind == DbTypeKind.dbDecimal -doAssert dbCols[12].typ.name == "money" - -doAssert dbCols[13].name == "varchar_col" -doAssert dbCols[13].typ.kind == DbTypeKind.dbVarchar -doAssert dbCols[13].typ.name == "varchar" - -doAssert dbCols[14].name == "character_col" -doAssert dbCols[14].typ.kind == DbTypeKind.dbFixedChar -doAssert dbCols[14].typ.name == "bpchar" - -doAssert dbCols[15].name == "text_col" -doAssert dbCols[15].typ.kind == DbTypeKind.dbVarchar -doAssert dbCols[15].typ.name == "text" - -doAssert dbCols[16].name == "timestamp_col" -doAssert dbCols[16].typ.kind == DbTypeKind.dbTimestamp -doAssert dbCols[16].typ.name == "timestamp" - -doAssert dbCols[17].name == "date_col" -doAssert dbCols[17].typ.kind == DbTypeKind.dbDate -doAssert dbCols[17].typ.name == "date" - -doAssert dbCols[18].name == "time_col" -doAssert dbCols[18].typ.kind == DbTypeKind.dbTime -doAssert dbCols[18].typ.name == "time" - -doAssert dbCols[19].name == "interval_col" -doAssert dbCols[19].typ.kind == DbTypeKind.dbTimeInterval -doAssert dbCols[19].typ.name == "interval" - -doAssert dbCols[20].name == "bool_col" -doAssert dbCols[20].typ.kind == DbTypeKind.dbBool -doAssert dbCols[20].typ.name == "bool" - -doAssert dbCols[21].name == "custom_enum_col" -doAssert dbCols[21].typ.kind == DbTypeKind.dbUnknown -doAssert parseInt(dbCols[21].typ.name) > 0 - -doAssert dbCols[22].name == "point_col" -doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint -doAssert dbCols[22].typ.name == "point" - -doAssert dbCols[23].name == "line_col" -doAssert dbCols[23].typ.kind == DbTypeKind.dbLine -doAssert dbCols[23].typ.name == "line" - -doAssert dbCols[24].name == "lseg_col" -doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg -doAssert dbCols[24].typ.name == "lseg" - -doAssert dbCols[25].name == "box_col" -doAssert dbCols[25].typ.kind == DbTypeKind.dbBox -doAssert dbCols[25].typ.name == "box" - -doAssert dbCols[26].name == "path_col" -doAssert dbCols[26].typ.kind == DbTypeKind.dbPath -doAssert dbCols[26].typ.name == "path" - -doAssert dbCols[27].name == "polygon_col" -doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon -doAssert dbCols[27].typ.name == "polygon" - -doAssert dbCols[28].name == "circle_col" -doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle -doAssert dbCols[28].typ.name == "circle" - -doAssert dbCols[29].name == "cidr_col" -doAssert dbCols[29].typ.kind == DbTypeKind.dbInet -doAssert dbCols[29].typ.name == "cidr" - -doAssert dbCols[30].name == "inet_col" -doAssert dbCols[30].typ.kind == DbTypeKind.dbInet -doAssert dbCols[30].typ.name == "inet" - -doAssert dbCols[31].name == "macaddr_col" -doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress -doAssert dbCols[31].typ.name == "macaddr" - -doAssert dbCols[32].name == "bit_col" -doAssert dbCols[32].typ.kind == DbTypeKind.dbBit -doAssert dbCols[32].typ.name == "bit" - -doAssert dbCols[33].name == "varbit_col" -doAssert dbCols[33].typ.kind == DbTypeKind.dbBit -doAssert dbCols[33].typ.name == "bit" - -doAssert dbCols[34].name == "tsvector_col" -doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar -doAssert dbCols[34].typ.name == "tsvector" - -doAssert dbCols[35].name == "tsquery_col" -doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar -doAssert dbCols[35].typ.name == "tsquery" - -doAssert dbCols[36].name == "uuid_col" -doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar -doAssert dbCols[36].typ.name == "uuid" - -doAssert dbCols[37].name == "xml_col" -doAssert dbCols[37].typ.kind == DbTypeKind.dbXml -doAssert dbCols[37].typ.name == "xml" - -doAssert dbCols[38].name == "json_col" -doAssert dbCols[38].typ.kind == DbTypeKind.dbJson -doAssert dbCols[38].typ.name == "json" - -doAssert dbCols[39].name == "array_col" -doAssert dbCols[39].typ.kind == DbTypeKind.dbArray -doAssert dbCols[39].typ.name == "int4[]" - -doAssert dbCols[40].name == "custom_composite_col" -doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown -doAssert parseInt(dbCols[40].typ.name) > 0 - -doAssert dbCols[41].name == "range_col" -doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite -doAssert dbCols[41].typ.name == "int4range" - -# issue 6571 -db.exec(sql"DROP TABLE IF EXISTS DICTIONARY") -db.exec(sql("""CREATE TABLE DICTIONARY( - id SERIAL PRIMARY KEY, - entry VARCHAR(1000) NOT NULL, - definition VARCHAR(4000) NOT NULL - );""")) -var entry = "あっそ" -var definition = "(int) (See ああそうそう) oh, really (uninterested)/oh yeah?/hmmmmm" -discard db.getRow( - SqlQuery("INSERT INTO DICTIONARY(entry, definition) VALUES(\'$1\', \'$2\') RETURNING id" % [entry, definition])) -doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition -entry = "Format string entry" -definition = "Format string definition" -db.exec(sql"INSERT INTO DICTIONARY(entry, definition) VALUES (?, ?)", entry, definition) -doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition - -echo("All tests succeeded!") - -db.close() diff --git a/tests/varres/tprevent_forloopvar_mutations.nim b/tests/varres/tprevent_forloopvar_mutations.nim index 96bb208c2..c9aeb94d8 100644 --- a/tests/varres/tprevent_forloopvar_mutations.nim +++ b/tests/varres/tprevent_forloopvar_mutations.nim @@ -1,8 +1,8 @@ discard """ errormsg: "type mismatch: got <int>" - nimout: '''tprevent_forloopvar_mutations.nim(16, 7) Error: type mismatch: got <int> + nimout: '''tprevent_forloopvar_mutations.nim(16, 3) Error: type mismatch: got <int> but expected one of: -proc inc[T: Ordinal](x: var T; y = 1) +proc inc[T, V: Ordinal](x: var T; y: V = 1) first type mismatch at position: 1 required type for x: var T: Ordinal but expression 'i' is immutable, not 'var' diff --git a/tests/varstmt/tvardecl.nim b/tests/varstmt/tvardecl.nim index 37bc4bad7..d5ccfafb7 100644 --- a/tests/varstmt/tvardecl.nim +++ b/tests/varstmt/tvardecl.nim @@ -2,6 +2,7 @@ discard """ output: "44" """ # Test the new variable declaration syntax +import std/sequtils var x = 0 @@ -10,3 +11,9 @@ var write(stdout, a) writeLine(stdout, b) #OUT 44 + +proc p() = # bug #18104 + var x, y = newSeqWith(10, newString(3)) + discard (x, y) + +p() diff --git a/tests/views/t19986.nim b/tests/views/t19986.nim new file mode 100644 index 000000000..85a7cf97d --- /dev/null +++ b/tests/views/t19986.nim @@ -0,0 +1,42 @@ +discard """ + cmd: '''nim check --hints:off $file''' + action: reject +nimout: ''' +t19986.nim(19, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it +t19986.nim(28, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it +t19986.nim(37, 7) Error: 'foo' borrows from the immutable location 'a' and attempts to mutate it +''' +""" + +{.experimental: "views".} + +type + Object = object + id: int + +proc foo() = + let a = Object(id: 3) + var foo: var Object = a + + foo.id = 777 + echo a + +foo() + +proc bar() = + let a = "123" + var foo: var string = a + + foo[0] = '7' + echo a + +bar() + +proc main() = + let a = 3 + var foo: var int = a + + foo = 777 + echo a + +main() diff --git a/tests/views/tconst_views.nim b/tests/views/tconst_views.nim index d7f1fc481..a85b03864 100644 --- a/tests/views/tconst_views.nim +++ b/tests/views/tconst_views.nim @@ -24,3 +24,14 @@ proc `$`(x: openArray[int]): string = echo c echo c2.data + +type MyObj = object + data: openarray[char] + +const + val1 = Foo(data: toOpenArray([1, 2, 3], 1, 1)) + val2 = Foo(data: toOpenArray([1, 2, 3], 0, 2)) + val3 = MyObj(data: "Hello".toOpenArray(0, 2)) +assert val1.data == [2] +assert val2.data == [1, 2, 3] +assert val3.data == "Hel" diff --git a/tests/views/tviews1.nim b/tests/views/tviews1.nim index b81b17f30..9785d25e5 100644 --- a/tests/views/tviews1.nim +++ b/tests/views/tviews1.nim @@ -77,3 +77,60 @@ type Inner = object var o = Outer(value: 1234) var v = Inner(owner: o).owner.value doAssert v == 1234 + +block: # bug #21674 + type + Lent = object + data: lent int + + proc foo(s: Lent) = + var m = 12 + discard cast[lent int](m) + + proc main = + var m1 = 123 + var x = Lent(data: m1) + foo(x) + + main() + +block: # bug #22117 + proc main: int = + var a = 10 + defer: discard a # extend a's lifetime + + var aref: var int = a + #└──── 'aref' borrows from location 'a' which does not live long enough + + result = aref + + doAssert main() == 10 + +type + Slice*[T] = object + first, last: int + p: ptr UncheckedArray[T] + +var i = 0 + +converter autoToOpenArray*[T](s: Slice[T]): openArray[T] = + inc i + result = toOpenArray(s.p, s.first, s.last) + +proc acceptOpenArray(s: openArray[byte]) = discard + +proc bug22597 = # bug #22597 + acceptOpenArray(Slice[byte]()) + doAssert i == 1 + +bug22597() + +block: # bug #20048 + type + Test = object + tokens: openArray[string] + + func init(Self: typedesc[Test], tokens: openArray[string]): Self = Self(tokens: tokens) + + let data = Test.init(["123"]) + doAssert @(data.tokens) == @["123"] diff --git a/tests/views/tviews2.nim b/tests/views/tviews2.nim new file mode 100644 index 000000000..29aff76df --- /dev/null +++ b/tests/views/tviews2.nim @@ -0,0 +1,90 @@ +discard """ + targets: "c js" +""" + +{.experimental: "views".} + +block: + type + Foo = object + id: openArray[char] + + proc foo(): Foo = + var source = "1245" + result = Foo(id: source.toOpenArray(0, 1)) + + doAssert foo().id == @['1', '2'] + +block: # bug #15778 + type + Reader = object + data: openArray[char] + current: int + + var count = 0 + + proc read(data: var Reader, length: int): openArray[char] = + inc count + let start = data.current + data.current.inc length + return data.data.toOpenArray(start, data.current-1) + + var data = "hello there" + var reader = Reader(data: data.toOpenArray(0, data.len-1), current: 0) + doAssert @(reader.read(2)) == @['h', 'e'] + doAssert @(reader.read(3)) == @['l', 'l', 'o'] + doAssert count == 2 + +block: # bug #16671 + block: + type X = ref object of RootObj + type Y = ref object of X + field: openArray[int] + + var s: seq[X] + proc f() = + s.add(Y(field: [1])) + + f() + + block: + type X = ref object of RootObj + type Y = ref object of X + field: openArray[int] + + var s: seq[X] + proc f() = + s.add(Y(field: toOpenArray([1, 2, 3], 0, 1))) + + f() + +block: # bug #15746 + type + Reader = object + data: openArray[char] + current: int + + proc initReader(data: openArray[char], offset = 0): Reader = + result = Reader(data: data, current: offset) + + let s = "\x01\x00\x00\x00" + doAssert initReader(s).data[0].int == 1 + +block: + proc foo(x: openArray[char]) = + discard x + + foo("12254") + foo(@['a', 'b']) + + var a1 = "12254" + foo(a1) + + var a2 = @['a', 'b'] + foo(a2) + + var s = "138443" + var ooo: openArray[char] = s + var xxx: openArray[char] = ooo + foo(ooo) + foo(xxx) diff --git a/tests/vm/mscriptcompiletime.nim b/tests/vm/mscriptcompiletime.nim new file mode 100644 index 000000000..ed7e7c029 --- /dev/null +++ b/tests/vm/mscriptcompiletime.nim @@ -0,0 +1,7 @@ +# bug.nim +var bar* {.compileTime.} = 1 + +proc dummy = discard + +static: + inc bar \ No newline at end of file diff --git a/tests/vm/t17121.nim b/tests/vm/t17121.nim new file mode 100644 index 000000000..bf2d6423f --- /dev/null +++ b/tests/vm/t17121.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "cannot 'importc' variable at compile time; c_printf" +""" + +proc c_printf*(frmt: cstring): cint {.importc: "printf", header: "<stdio.h>", varargs, discardable.} = + ## foo bar + runnableExamples: discard +static: + let a = c_printf("abc\n") diff --git a/tests/vm/t18103.nim b/tests/vm/t18103.nim new file mode 100644 index 000000000..8622ab290 --- /dev/null +++ b/tests/vm/t18103.nim @@ -0,0 +1,35 @@ +discard """ + targets: "c cpp" + matrix: "--mm:refc; --mm:arc" +""" + +import base64, complex, sequtils, math, sugar + +type + + FP = float + T = object + index: int + arg: FP + val: Complex[FP] + M = object + alpha, beta: FP + +func a(s: openArray[T], model: M): seq[T] = + let f = (tn: int) => model.alpha + FP(tn) * model.beta; + return mapIt s: + block: + let s = it.val * rect(1.0, - f(it.index)) + T(index: it.index, arg: phase(s), val: s) + +proc b(): float64 = + var s = toSeq(0..10).mapIt(T(index: it, arg: 1.0, val: complex.complex(1.0))) + discard a(s, M(alpha: 1, beta: 1)) + return 1.0 + +func cc(str: cstring, offset: ptr[cdouble]): cint {.exportc.} = + offset[] = b() + return 0 + +static: + echo b() diff --git a/tests/vm/t19075.nim b/tests/vm/t19075.nim new file mode 100644 index 000000000..89ca9cb19 --- /dev/null +++ b/tests/vm/t19075.nim @@ -0,0 +1,19 @@ +discard """ + timeout: 10 + joinable: false +""" + +# bug #19075 +const size = 50_000 + +const stuff = block: + var a: array[size, int] + a + +const zeugs = block: + var zeugs: array[size, int] + for i in 0..<size: + zeugs[i] = stuff[i] + zeugs + +doAssert zeugs[0] == 0 \ No newline at end of file diff --git a/tests/vm/t20746.nim b/tests/vm/t20746.nim new file mode 100644 index 000000000..bfad269ef --- /dev/null +++ b/tests/vm/t20746.nim @@ -0,0 +1,13 @@ +discard """ + timeout: 10 + joinable: false + output: "fine" +""" + +func addString(): string = + let x = newString(1000000) + for i in 0..<1000000: + discard x[i] + +const translationTable = addString() +echo "fine" diff --git a/tests/vm/t21704.nim b/tests/vm/t21704.nim new file mode 100644 index 000000000..27f4f5b06 --- /dev/null +++ b/tests/vm/t21704.nim @@ -0,0 +1,69 @@ +discard """ +matrix: "--hints:off" +nimout: ''' +Found 2 tests to run. +Found 3 benches to compile. + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow +''' +""" +# bug #21704 +import std/strformat + +const testDesc: seq[string] = @[ + "tests/t_hash_sha256_vs_openssl.nim", + "tests/t_cipher_chacha20.nim" +] +const benchDesc = [ + "bench_sha256", + "bench_hash_to_curve", + "bench_ethereum_bls_signatures" +] + +proc setupTestCommand(flags, path: string): string = + return "nim c -r " & + flags & + &" --nimcache:nimcache/{path} " & # Commenting this out also solves the issue + path + +proc testBatch(commands: var string, flags, path: string) = + commands &= setupTestCommand(flags, path) & '\n' + +proc setupBench(benchName: string): string = + var runFlags = if false: " -r " + else: " " # taking this branch is needed to trigger the bug + + echo runFlags # Somehow runflags isn't reset in corner cases + runFlags &= " --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow " + echo runFlags + + return "nim c " & + runFlags & + &" benchmarks/{benchName}.nim" + +proc buildBenchBatch(commands: var string, benchName: string) = + let command = setupBench(benchName) + commands &= command & '\n' + +proc addTestSet(cmdFile: var string) = + echo "Found " & $testDesc.len & " tests to run." + + for path in testDesc: + var flags = "" # This is important + cmdFile.testBatch(flags, path) + +proc addBenchSet(cmdFile: var string) = + echo "Found " & $benchDesc.len & " benches to compile." + for bd in benchDesc: + cmdFile.buildBenchBatch(bd) + +proc task_bug() = + var cmdFile: string + cmdFile.addTestSet() # Comment this out and there is no bug + cmdFile.addBenchSet() + +static: task_bug() diff --git a/tests/vm/t9622.nim b/tests/vm/t9622.nim index 214ab0f19..fada8fe59 100644 --- a/tests/vm/t9622.nim +++ b/tests/vm/t9622.nim @@ -1,6 +1,6 @@ discard """ targets: "c cpp" - matrix: "--gc:refc; --gc:arc" + matrix: "--mm:refc; --mm:arc" """ type diff --git a/tests/cnstseq/tcnstseq.nim b/tests/vm/tcnstseq.nim index 5679a6e37..5679a6e37 100644 --- a/tests/cnstseq/tcnstseq.nim +++ b/tests/vm/tcnstseq.nim diff --git a/tests/vm/tconst.nim b/tests/vm/tconst.nim index c2bcf78b5..5cfe7533e 100644 --- a/tests/vm/tconst.nim +++ b/tests/vm/tconst.nim @@ -42,6 +42,16 @@ template main() = discard (x, increment, a) mytemp() + block: # bug #12334 + block: + const b: cstring = "foo" + var c = b + doAssert c == "foo" + block: + const a = "foo" + const b: cstring = a + var c = b + doAssert c == "foo" static: main() diff --git a/tests/vm/tconstarrayresem.nim b/tests/vm/tconstarrayresem.nim new file mode 100644 index 000000000..6701cfe4d --- /dev/null +++ b/tests/vm/tconstarrayresem.nim @@ -0,0 +1,29 @@ +# issue #23010 + +type + Result[T, E] = object + case oResult: bool + of false: + discard + of true: + vResult: T + + Opt[T] = Result[T, void] + +template ok[T, E](R: type Result[T, E], x: untyped): R = + R(oResult: true, vResult: x) + +template c[T](v: T): Opt[T] = Opt[T].ok(v) + +type + FixedBytes[N: static[int]] = distinct array[N, byte] + + H = object + d: FixedBytes[2] + +const b = default(H) +template g(): untyped = + const t = default(H) + b + +discard c(g()) diff --git a/tests/vm/tconstresem.nim b/tests/vm/tconstresem.nim new file mode 100644 index 000000000..4526cb891 --- /dev/null +++ b/tests/vm/tconstresem.nim @@ -0,0 +1,10 @@ +block: # issue #19849 + type + Vec2[T] = object + x, y: T + Vec2i = Vec2[int] + template getX(p: Vec2i): int = p.x + let x = getX: + const t = Vec2i(x: 1, y: 2) + t + doAssert x == 1 diff --git a/tests/vm/tconstscope1.nim b/tests/vm/tconstscope1.nim new file mode 100644 index 000000000..41c45a28f --- /dev/null +++ b/tests/vm/tconstscope1.nim @@ -0,0 +1,5 @@ +# issue #5395 + +const a = (var b = 3; b) +echo b #[tt.Error + ^ undeclared identifier: 'b']# diff --git a/tests/vm/tconstscope2.nim b/tests/vm/tconstscope2.nim new file mode 100644 index 000000000..d858e96c2 --- /dev/null +++ b/tests/vm/tconstscope2.nim @@ -0,0 +1,5 @@ +const + a = (var x = 3; x) + # should we allow this? + b = x #[tt.Error + ^ undeclared identifier: 'x']# diff --git a/tests/vm/tconsttable.nim b/tests/vm/tconsttable.nim index 64a74a59d..152a33cba 100644 --- a/tests/vm/tconsttable.nim +++ b/tests/vm/tconsttable.nim @@ -17,3 +17,18 @@ x = "ah" echo foo[x] x = "possible." echo foo[x] + +block: # bug #19840 + const testBytes = [byte 0xD8, 0x08, 0xDF, 0x45, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x61] + var tempStr = "__________________" + + tempStr.prepareMutation + copyMem(addr tempStr[0], addr testBytes[0], testBytes.len) + +block: # bug #22389 + func foo(): ptr UncheckedArray[byte] = + const bar = [77.byte] + cast[ptr UncheckedArray[byte]](addr bar[0]) + + doAssert foo()[0] == 77 + diff --git a/tests/vm/tconvaddr.nim b/tests/vm/tconvaddr.nim new file mode 100644 index 000000000..9762a9e59 --- /dev/null +++ b/tests/vm/tconvaddr.nim @@ -0,0 +1,49 @@ +block: # issue #24097 + type Foo = distinct int + proc foo(x: var Foo) = + int(x) += 1 + proc bar(x: var int) = + x += 1 + static: + var x = Foo(1) + int(x) = int(x) + 1 + doAssert x.int == 2 + int(x) += 1 + doAssert x.int == 3 + foo(x) + doAssert x.int == 4 + bar(int(x)) # need vmgen flags propagated for this + doAssert x.int == 5 + type Bar = object + x: Foo + static: + var obj = Bar(x: Foo(1)) + int(obj.x) = int(obj.x) + 1 + doAssert obj.x.int == 2 + int(obj.x) += 1 + doAssert obj.x.int == 3 + foo(obj.x) + doAssert obj.x.int == 4 + bar(int(obj.x)) # need vmgen flags propagated for this + doAssert obj.x.int == 5 + static: + var arr = @[Foo(1)] + int(arr[0]) = int(arr[0]) + 1 + doAssert arr[0].int == 2 + int(arr[0]) += 1 + doAssert arr[0].int == 3 + foo(arr[0]) + doAssert arr[0].int == 4 + bar(int(arr[0])) # need vmgen flags propagated for this + doAssert arr[0].int == 5 + proc testResult(): Foo = + result = Foo(1) + int(result) = int(result) + 1 + doAssert result.int == 2 + int(result) += 1 + doAssert result.int == 3 + foo(result) + doAssert result.int == 4 + bar(int(result)) # need vmgen flags propagated for this + doAssert result.int == 5 + doAssert testResult().int == 5 diff --git a/tests/constr/tconexpr.nim b/tests/vm/tfibconst.nim index cca6dd84f..cca6dd84f 100644 --- a/tests/constr/tconexpr.nim +++ b/tests/vm/tfibconst.nim diff --git a/tests/vm/tgenericcompiletimeproc.nim b/tests/vm/tgenericcompiletimeproc.nim new file mode 100644 index 000000000..08099ebbe --- /dev/null +++ b/tests/vm/tgenericcompiletimeproc.nim @@ -0,0 +1,36 @@ +block: # issue #10753 + proc foo(x: int): int {.compileTime.} = x + const a = foo(123) + doAssert foo(123) == a + + proc bar[T](x: T): T {.compileTime.} = x + const b = bar(123) + doAssert bar(123) == b + const c = bar("abc") + doAssert bar("abc") == c + +block: # issue #22021 + proc foo(x: static int): int {.compileTime.} = x + 1 + doAssert foo(123) == 124 + +block: # issue #19365 + proc f[T](x: static T): T {.compileTime.} = x + x + doAssert f(123) == 246 + doAssert f(1.0) == 2.0 + +block: + # don't fold compile time procs in typeof + proc fail[T](x: T): T {.compileTime.} = + doAssert false + x + doAssert typeof(fail(123)) is typeof(123) + proc p(x: int): int = x + + type Foo = typeof(p(fail(123))) + +block: # issue #24150, related regression + proc w(T: type): T {.compileTime.} = default(ptr T)[] + template y(v: auto): auto = typeof(v) is int + discard compiles(y(w int)) + proc s(): int {.compileTime.} = discard + discard s() diff --git a/tests/vm/tmisc_vm.nim b/tests/vm/tmisc_vm.nim index af09e8871..1ad830b5f 100644 --- a/tests/vm/tmisc_vm.nim +++ b/tests/vm/tmisc_vm.nim @@ -445,3 +445,15 @@ static: needSecondIdentifier.mgetOrPut(firstPart, @[]).add((name, pattern)) doAssert needSecondIdentifier[0] == @[("aaaa", "bbbb"), ("aaaaa", "bbbbb"), ("aaaaaa", "bbbbbb"), ("aaaaaaa", "bbbbbbb"), ("aaaaaaaa", "bbbbb")] + +# bug #17864 +macro transform*(fn: typed) = + quote do: + `fn` + +var map: Table[string, HashSet[string]] +proc publish*(): void {.transform.} = + map["k"] = init_hash_set[string]() + map["k"].incl "d" + +publish() diff --git a/tests/vm/tnilclosurecall.nim b/tests/vm/tnilclosurecall.nim new file mode 100644 index 000000000..449865b9c --- /dev/null +++ b/tests/vm/tnilclosurecall.nim @@ -0,0 +1,8 @@ +discard """ + errormsg: "attempt to call nil closure" + line: 8 +""" + +static: + let x: proc () = nil + x() diff --git a/tests/vm/tnilclosurecallstacktrace.nim b/tests/vm/tnilclosurecallstacktrace.nim new file mode 100644 index 000000000..879060e8e --- /dev/null +++ b/tests/vm/tnilclosurecallstacktrace.nim @@ -0,0 +1,23 @@ +discard """ + action: reject + nimout: ''' +stack trace: (most recent call last) +tnilclosurecallstacktrace.nim(23, 6) tnilclosurecallstacktrace +tnilclosurecallstacktrace.nim(20, 6) baz +tnilclosurecallstacktrace.nim(17, 6) bar +tnilclosurecallstacktrace.nim(14, 4) foo +tnilclosurecallstacktrace.nim(14, 4) Error: attempt to call nil closure +''' +""" + +proc foo(x: proc ()) = + x() + +proc bar(x: proc ()) = + foo(x) + +proc baz(x: proc ()) = + bar(x) + +static: + baz(nil) diff --git a/tests/constr/tnocompiletimefunc.nim b/tests/vm/tnocompiletimefunc.nim index a95648c0f..a95648c0f 100644 --- a/tests/constr/tnocompiletimefunc.nim +++ b/tests/vm/tnocompiletimefunc.nim diff --git a/tests/constr/tnocompiletimefunclambda.nim b/tests/vm/tnocompiletimefunclambda.nim index d134eea40..d134eea40 100644 --- a/tests/constr/tnocompiletimefunclambda.nim +++ b/tests/vm/tnocompiletimefunclambda.nim diff --git a/tests/vm/tnoreturn.nim b/tests/vm/tnoreturn.nim new file mode 100644 index 000000000..d4f8601a9 --- /dev/null +++ b/tests/vm/tnoreturn.nim @@ -0,0 +1,32 @@ +block: # issue #22216 + type + Result[T, E] = object + case oVal: bool + of false: + eVal: E + of true: + vVal: T + + func raiseResultDefect(m: string) {.noreturn, noinline.} = + raise (ref Defect)(msg: m) + + template withAssertOk(self: Result, body: untyped): untyped = + case self.oVal + of false: + raiseResultDefect("Trying to access value with err Result") + else: + body + + func value[T, E](self: Result[T, E]): T {.inline.} = + withAssertOk(self): + self.vVal + + const + x = Result[int, string](oVal: true, vVal: 123) + z = x.value() + + let + xx = Result[int, string](oVal: true, vVal: 123) + zz = x.value() + + doAssert z == zz diff --git a/tests/vm/topenarrays.nim b/tests/vm/topenarrays.nim new file mode 100644 index 000000000..375d2523d --- /dev/null +++ b/tests/vm/topenarrays.nim @@ -0,0 +1,89 @@ +proc mutate(a: var openarray[int]) = + var i = 0 + for x in a.mitems: + x = i + inc i + +proc mutate(a: var openarray[char]) = + var i = 1 + for ch in a.mitems: + ch = 'a' + + +static: + var a = [10, 20, 30] + assert a.toOpenArray(1, 2).len == 2 + + mutate(a) + assert a.toOpenArray(0, 2) == [0, 1, 2] + assert a.toOpenArray(0, 0) == [0] + assert a.toOpenArray(1, 2) == [1, 2] + assert "Hello".toOpenArray(1, 4) == "ello" + var str = "Hello" + str.toOpenArray(2, 4).mutate() + assert str.toOpenArray(0, 4).len == 5 + assert str.toOpenArray(0, 0).len == 1 + assert str.toOpenArray(0, 0).high == 0 + assert str == "Heaaa" + assert str.toOpenArray(0, 4) == "Heaaa" + + var arr: array[3..4, int] = [1, 2] + assert arr.toOpenArray(3, 4) == [1, 2] + assert arr.toOpenArray(3, 4).len == 2 + assert arr.toOpenArray(3, 3).high == 0 + + assert arr.toOpenArray(3, 4).toOpenArray(0, 0) == [1] + + +proc doThing(s: static openArray[int]) = discard + +doThing([10, 20, 30].toOpenArray(0, 0)) + +# bug #19969 +proc f(): array[1, byte] = + var a: array[1, byte] + result[0..0] = a.toOpenArray(0, 0) + +doAssert static(f()) == [byte(0)] + + +# bug #15952 +proc main1[T](a: openArray[T]) = discard +proc main2[T](a: var openArray[T]) = discard + +proc main = + var a = [1,2,3,4,5] + main1(a.toOpenArray(1,3)) + main2(a.toOpenArray(1,3)) +static: main() +main() + +# bug #16306 +{.experimental: "views".} +proc test(x: openArray[int]): tuple[id: int] = + let y: openArray[int] = toOpenArray(x, 0, 2) + result = (y[0],) +template fn= + doAssert test([0,1,2,3,4,5]).id == 0 +fn() # ok +static: fn() + + +block: # bug #22095 + type + StUint = object + limbs: array[4, uint64] + + func shlAddMod(a: var openArray[uint64]) = + a[0] = 10 + + func divRem(r: var openArray[uint64]) = + shlAddMod(r.toOpenArray(0, 3)) + + func fn(): StUint = + divRem(result.limbs) + + const + z = fn() + + doAssert z.limbs[0] == 10 diff --git a/tests/vm/tscriptcompiletime.nims b/tests/vm/tscriptcompiletime.nims new file mode 100644 index 000000000..daec54bf7 --- /dev/null +++ b/tests/vm/tscriptcompiletime.nims @@ -0,0 +1,9 @@ +discard """ + cmd: "nim e $file" +""" + +import mscriptcompiletime + +macro foo = + doAssert bar == 2 +foo() diff --git a/tests/vm/tsignaturehash.nim b/tests/vm/tsignaturehash.nim index 42e0a1571..972ec6fb0 100644 --- a/tests/vm/tsignaturehash.nim +++ b/tests/vm/tsignaturehash.nim @@ -1,7 +1,7 @@ # test sym digest is computable at compile time import macros, algorithm -import md5 +import ../../dist/checksums/src/checksums/md5 macro testmacro(s: typed{nkSym}): string = let s = getMD5(signaturehash(s) & " - " & symBodyHash(s)) diff --git a/tests/vm/ttouintconv.nim b/tests/vm/ttouintconv.nim index ff2187a36..8c43a3adb 100644 --- a/tests/vm/ttouintconv.nim +++ b/tests/vm/ttouintconv.nim @@ -75,3 +75,10 @@ macro foo2() = foo() foo2() + +block: + const neg5VM = block: + let x = -5'i8 + uint64(x) + let y = -5'i8 + doAssert uint64(y) == neg5VM diff --git a/tests/vm/ttypedesc.nim b/tests/vm/ttypedesc.nim new file mode 100644 index 000000000..d799e5adb --- /dev/null +++ b/tests/vm/ttypedesc.nim @@ -0,0 +1,31 @@ +block: # issue #15760 + type + Banana = object + SpecialBanana = object + + proc getName(_: type Banana): string = "Banana" + proc getName(_: type SpecialBanana): string = "SpecialBanana" + + proc x[T](): string = + const n = getName(T) # this one works + result = n + + proc y(T: type): string = + const n = getName(T) # this one failed to compile + result = n + + doAssert x[SpecialBanana]() == "SpecialBanana" + doAssert y(SpecialBanana) == "SpecialBanana" + +import macros + +block: # issue #23112 + type Container = object + foo: string + + proc canBeImplicit(t: typedesc) {.compileTime.} = + let tDesc = getType(t) + doAssert tDesc.kind == nnkObjectTy + + static: + canBeImplicit(Container) diff --git a/tests/vm/tunsupportedintfloatcast.nim b/tests/vm/tunsupportedintfloatcast.nim new file mode 100644 index 000000000..d65f10d86 --- /dev/null +++ b/tests/vm/tunsupportedintfloatcast.nim @@ -0,0 +1,3 @@ +static: + echo cast[int32](12.0) #[tt.Error + ^ VM does not support 'cast' from tyFloat with size 8 to tyInt32 with size 4 due to different sizes]# diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index dfe086d10..6aeac5529 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -1,7 +1,7 @@ -# bug #4462 import macros import os +# bug #4462 block: proc foo(t: typedesc) {.compileTime.} = assert sameType(getType(t), getType(int)) @@ -9,14 +9,14 @@ block: static: foo(int) -# #4412 +# bug #4412 block: proc default[T](t: typedesc[T]): T {.inline.} = discard static: var x = default(type(0)) -# #6379 +# bug #6379 import algorithm static: @@ -28,7 +28,7 @@ static: str.sort(cmp) doAssert str == "abc" -# #6086 +# bug #6086 import math, sequtils, sugar block: @@ -82,8 +82,10 @@ block: doAssert fileExists("MISSINGFILE") == false doAssert dirExists("MISSINGDIR") == false + doAssert fileExists(currentSourcePath()) + doAssert dirExists(currentSourcePath().parentDir) -# #7210 +# bug #7210 block: static: proc f(size: int): int = @@ -91,7 +93,7 @@ block: result = size doAssert f(4) == 4 -# #6689 +# bug #6689 block: static: proc foo(): int = 0 @@ -106,7 +108,7 @@ block: new(x) doAssert(not x.isNil) -# #7871 +# bug #7871 static: type Obj = object field: int @@ -116,11 +118,11 @@ static: o.field = 2 doAssert s[0].field == 0 -# #8125 +# bug #8125 static: let def_iter_var = ident("it") -# #8142 +# bug #8142 static: type Obj = object names: string @@ -136,7 +138,7 @@ static: o.pushName() doAssert o.names == "FOOBARFOOBAR" -# #8154 +# bug #8154 import parseutils static: @@ -149,7 +151,7 @@ static: static: doAssert foo().i == 1 -# #10333 +# bug #10333 block: const encoding: auto = [ @@ -160,7 +162,7 @@ block: ] doAssert encoding.len == 4 -# #10886 +# bug #10886 proc tor(): bool = result = true @@ -229,6 +231,14 @@ block: # bug #15595 static: main() main() +block: # issue #20543 + type F = proc() + const myArray = block: + var r: array[1, F] + r[0] = nil + r + doAssert isNil(myArray[0]) + # bug #15363 import sequtils @@ -291,14 +301,6 @@ block: # bug #10815 const a = P() doAssert $a == "" -when defined osx: # xxx bug https://github.com/nim-lang/Nim/issues/10815#issuecomment-476380734 - block: - type CharSet {.union.} = object - cs: set[char] - vs: array[4, uint64] - const a = Charset(cs: {'a'..'z'}) - doAssert a.repr.len > 0 - import tables block: # bug #8007 @@ -353,7 +355,7 @@ block: # bug #8007 block: # bug #14340 block: proc opl3EnvelopeCalcSin0() = discard - type EnvelopeSinfunc = proc() + type EnvelopeSinfunc = proc() {.nimcall.} # todo: fixme # const EnvelopeCalcSin0 = opl3EnvelopeCalcSin0 # ok const EnvelopeCalcSin0: EnvelopeSinfunc = opl3EnvelopeCalcSin0 # was bug const envelopeSin = [EnvelopeCalcSin0] @@ -361,7 +363,7 @@ block: # bug #14340 envelopeSin[a]() block: - type Mutator = proc() {.noSideEffect, gcsafe, locks: 0.} + type Mutator = proc() {.noSideEffect, gcsafe.} proc mutator0() = discard const mTable = [Mutator(mutator0)] var i=0 @@ -564,11 +566,231 @@ block: block: static: let x = int 1 - echo x.type # Foo + doAssert $(x.type) == "int" # Foo block: static: let x = int 1 let y = x + 1 # Error: unhandled exception: value out of range: -8 notin 0 .. 65535 [RangeDefect] - echo y + doAssert y == 2 + + +type Atom* = object + bar: int + +proc main() = # bug #12994 + var s: seq[Atom] + var atom: Atom + var checked = 0 + for i in 0..<2: + atom.bar = 5 + s.add atom + atom.reset + if i == 0: + checked += 1 + doAssert $s == "@[(bar: 5)]" + else: + checked += 1 + doAssert $s == "@[(bar: 5), (bar: 5)]" + doAssert checked == 2 + +static: main() +main() + +# bug #19201 +proc foo(s: sink string) = doAssert s.len == 3 + +static: + foo("abc") + + +static: + for i in '1' .. '2': # bug #10938 + var s: set[char] + doAssert s == {} + incl(s, i) + + for _ in 0 ..< 3: # bug #13312 + var s: string + s.add("foo") + doAssert s == "foo" + + for i in 1 .. 5: # bug #13918 + var arr: array[3, int] + var val: int + doAssert arr == [0, 0, 0] and val == 0 + for j in 0 ..< len(arr): + arr[j] = i + val = i + +# bug #20985 +let a = block: + var groups: seq[seq[int]] + for i in 0 ..< 3: + var group: seq[int] + for j in 0 ..< 3: + group.add j + groups.add group + groups + +const b = block: + var groups: seq[seq[int]] + for i in 0 ..< 3: + var group: seq[int] + for j in 0 ..< 3: + group.add j + groups.add group + groups + +doAssert a == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] +doAssert b == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] + +macro m1(s: string): int = + var ProcID {.global, compileTime.}: int + inc(ProcID) + result = newLit(ProcID) + +proc macroGlobal = + doAssert m1("Macro argument") == 1 + doAssert m1("Macro argument") == 2 + doAssert m1("Macro argument") == 3 + +static: macroGlobal() +macroGlobal() + +block: # bug #10108 + template reject(x) = + static: doAssert(not compiles(x)) + + static: + let x: int = 2 + proc deliver_x(): int = x + var y2 = deliver_x() + discard y2 + reject: + const c5 = deliver_x() + +block: # bug #7590 + proc doInit[T]():auto= + var a: T + return a + + proc fun2[T](tup1:T)= + const tup0=doInit[T]() + + # var tup=tup0 #ok + const tup=tup0 #causes bug + + doAssert tup is tuple + doAssert tup[0] is tuple + for ai in tup.fields: + doAssert ai is tuple, "BUG2" + + # const c=(foo:(bar1: 0.0)) + const c=(foo:(bar1:"foo1")) + fun2(c) + +block: # bug #21708 + type + Tup = tuple[name: string] + + const X: array[2, Tup] = [(name: "foo",), (name: "bar",)] + + static: + let s = X[0] + doAssert s[0] == "foo" + +block: + proc swap[T](x: var T): T = + result = x + x = default(T) + + proc merge[T](a, b: var openArray[T]) = + a[0] = swap b[0] + + static: + var x = "abc" + var y = "356" + merge(x, y) + doAssert x == "3bc" + +block: # bug #22190 + type + EVMFork = enum + Berlin + Istanbul + Shanghai + + const + Vm2OpAllForks = + {EVMFork.low .. EVMFork.high} + + vm2OpExecBlockData = [(forks: Vm2OpAllForks)] + + proc mkOpTable(selected: EVMFork): bool = + selected notin vm2OpExecBlockData[0].forks + + const + tab = mkOpTable(Berlin) + + doAssert not tab + +block: # issue #22524 + const cnst = cstring(nil) + doAssert cnst.isNil + doAssert cnst == nil + let b = cnst + doAssert b.isNil + doAssert b == nil + + let a = static: cstring(nil) + doAssert a.isNil + + static: + var x: cstring + doAssert x.isNil + doAssert x == nil + doAssert x != "" + +block: # issue #15730 + const s: cstring = "" + doAssert s != nil + + static: + let s: cstring = "" + doAssert not s.isNil + doAssert s != nil + doAssert s == "" + +static: # more nil cstring issues + let x = cstring(nil) + doAssert x.len == 0 + +block: # bug #23925 + type Foo = enum A = -1 + proc foo = + doAssert cast[Foo](-1) == A + doAssert ord(A) == -1 + + static: foo() + foo() + + type E = enum + e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 e10 e11 e12 e13 e14 e15 e16 e17 e18 e19 e20 + e21 e22 e23 e24 e25 e26 e27 e28 e29 e30 e31 e32 e33 e34 e35 e36 e37 e38 + e39 e40 e41 e42 e43 e44 e45 e46 e47 e48 e49 e50 e51 e52 e53 e54 e55 e56 + e57 e58 e59 e60 e61 e62 e63 e64 e65 e66 e67 e68 e69 e70 e71 e72 e73 e74 + e75 e76 e77 e78 e79 e80 e81 e82 e83 e84 e85 e86 e87 e88 e89 e90 e91 e92 + e93 e94 e95 e96 e97 e98 e99 e100 e101 e102 e103 e104 e105 e106 e107 e108 + e109 e110 e111 e112 e113 e114 e115 e116 e117 e118 e119 e120 e121 e122 + e123 e124 e125 e126 e127 e128 + proc bar = + doAssert cast[E](int(e128)) == e128 + + static: bar() + bar() + +static: # bug #21353 + var s: proc () = default(proc ()) + doAssert s == nil diff --git a/tests/vm/tvmopsDanger.nim b/tests/vm/tvmopsDanger.nim new file mode 100644 index 000000000..966feffe6 --- /dev/null +++ b/tests/vm/tvmopsDanger.nim @@ -0,0 +1,13 @@ +discard """ + cmd: "nim c --experimental:vmopsDanger -r $file" +""" +when defined(nimPreviewSlimSystem): + import std/assertions +import std/[times, os] + +const foo = getTime() +let bar = foo +doAssert bar > low(Time) + +static: # bug #23932 + doAssert getCurrentDir().len > 0 diff --git a/tests/vm/tzero_extend.nim b/tests/vm/tzero_extend.nim index 1fed5d419..418dbc486 100644 --- a/tests/vm/tzero_extend.nim +++ b/tests/vm/tzero_extend.nim @@ -5,10 +5,10 @@ proc get_values(): (seq[int8], seq[int16], seq[int32]) = let i8 = -3'i8 let i16 = -3'i16 let i32 = -3'i32 - doAssert i8.ze == 0xFD - doAssert i8.ze64 == 0xFD - doAssert i16.ze == 0xFFFD - doAssert i16.ze64 == 0xFFFD + doAssert int(cast[uint8](i8)) == 0xFD + doAssert int64(cast[uint8](i8)) == 0xFD + doAssert int(cast[uint16](i16)) == 0xFFFD + doAssert int64(cast[uint16](i16)) == 0xFFFD result[0] = @[]; result[1] = @[]; result[2] = @[] diff --git a/tests/whenstmt/t12517.nim b/tests/whenstmt/t12517.nim new file mode 100644 index 000000000..8be0171e1 --- /dev/null +++ b/tests/whenstmt/t12517.nim @@ -0,0 +1,21 @@ +# Test based on issue #12517 + +discard """ + nimout: ''' +nimvm +both +''' + output: ''' +both +''' +""" + +proc test() = + when nimvm: + echo "nimvm" + echo "both" + +static: + test() +test() + diff --git a/tests/whenstmt/t19426.nim b/tests/whenstmt/t19426.nim new file mode 100644 index 000000000..95fb54a9e --- /dev/null +++ b/tests/whenstmt/t19426.nim @@ -0,0 +1,16 @@ +type + MyInt = object + bitWidth: int + +template toRealType*(t: MyInt): typedesc = + when t.bitWidth == 32: int32 + elif t.bitWidth == 64: int64 + else: {.error.} + +proc doFail(T: typedesc): T = default(T) + +proc test = + const myInt = MyInt(bitWidth:32) + discard doFail(toRealType(myInt)) + +test() \ No newline at end of file diff --git a/tests/xml/ttree_add.nim b/tests/xml/ttree_add.nim new file mode 100644 index 000000000..4c6ef6cf9 --- /dev/null +++ b/tests/xml/ttree_add.nim @@ -0,0 +1,51 @@ +discard """ + output: ''' +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocHead = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> +</xml> +""" +var baseDocHeadTree = parseXml(baseDocHead) +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) + +proc test_add() = + var testDoc = baseDocHeadTree + var newBody = newElement("body") + for item in baseDocBodyTree.items(): + newBody.add(item) + + echo $newBody + + testDoc.add(newBody) + echo $testDoc + +test_add() diff --git a/tests/xml/ttree_add1.nim b/tests/xml/ttree_add1.nim new file mode 100644 index 000000000..30ec83c02 --- /dev/null +++ b/tests/xml/ttree_add1.nim @@ -0,0 +1,53 @@ +discard """ + output: ''' +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocHead = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> +</xml> +""" +var baseDocHeadTree = parseXml(baseDocHead) +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) + +proc test_add() = + var testDoc = baseDocHeadTree + var newBody = newElement("body") + var bodyItems: seq[XmlNode] = @[] + for item in baseDocBodyTree.items(): + bodyItems.add(item) + newBody.add(bodyItems) + + echo $newBody + + testDoc.add(newBody) + echo $testDoc + +test_add() diff --git a/tests/xml/ttree_delete.nim b/tests/xml/ttree_delete.nim new file mode 100644 index 000000000..32b477839 --- /dev/null +++ b/tests/xml/ttree_delete.nim @@ -0,0 +1,47 @@ +discard """ + output: ''' +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +let initialDocBase = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <tag> + <div>MORE TEXT </div> + <div>MORE TEXT Some more text</div> + </tag> + <tag> + <div>MORE TEXT </div> + <div>MORE TEXT Some more text</div> + </tag> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +""" +var initialDocBaseTree = parseXml(initialDocBase) + +proc test_delete() = + var testDoc = initialDocBaseTree + + testDoc.delete(1..2) + echo $testDoc + +test_delete() diff --git a/tests/xml/ttree_delete1.nim b/tests/xml/ttree_delete1.nim new file mode 100644 index 000000000..a8442a093 --- /dev/null +++ b/tests/xml/ttree_delete1.nim @@ -0,0 +1,48 @@ +discard """ + output: ''' +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +let initialDocBase = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <tag> + <div>MORE TEXT </div> + <div>MORE TEXT Some more text</div> + </tag> + <tag> + <div>MORE TEXT </div> + <div>MORE TEXT Some more text</div> + </tag> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +""" +var initialDocBaseTree = parseXml(initialDocBase) + +proc test_delete() = + var testDoc = initialDocBaseTree + + testDoc.delete(1) + testDoc.delete(1) + echo $testDoc + +test_delete() diff --git a/tests/xml/ttree_insert.nim b/tests/xml/ttree_insert.nim new file mode 100644 index 000000000..b2941395b --- /dev/null +++ b/tests/xml/ttree_insert.nim @@ -0,0 +1,53 @@ +discard """ + output: ''' +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocHead = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> +</xml> +""" +var baseDocHeadTree = parseXml(baseDocHead) +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) + +proc test_insert() = + var testDoc = baseDocHeadTree + var newBody = newElement("body") + var bodyItems: seq[XmlNode] = @[] + for item in baseDocBodyTree.items(): + bodyItems.insert(item, len(bodyItems)) + newBody.insert(bodyItems, 1) + + echo $newBody + + testDoc.insert(newBody, 1) + echo $testDoc + +test_insert() diff --git a/tests/xml/ttree_insert1.nim b/tests/xml/ttree_insert1.nim new file mode 100644 index 000000000..9aa3faf69 --- /dev/null +++ b/tests/xml/ttree_insert1.nim @@ -0,0 +1,51 @@ +discard """ + output: ''' +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocHead = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> +</xml> +""" +var baseDocHeadTree = parseXml(baseDocHead) +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) + +proc test_insert() = + var testDoc = baseDocHeadTree + var newBody = newElement("body") + for item in baseDocBodyTree.items(): + newBody.insert(item, len(newBody)) + + echo $newBody + + testDoc.insert(newBody, 1) + echo $testDoc + +test_insert() diff --git a/tests/xml/ttree_replace.nim b/tests/xml/ttree_replace.nim new file mode 100644 index 000000000..97d2db638 --- /dev/null +++ b/tests/xml/ttree_replace.nim @@ -0,0 +1,46 @@ +discard """ + output: ''' +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) +let initialDocBase = """ +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body before replace </div> + <div>Some more text in body before replace </div> + </body> +</xml> +""" +var initialDocBaseTree = parseXml(initialDocBase) + +proc test_replace() = + var testDoc = initialDocBaseTree + + testDoc.replace(1, @[baseDocBodyTree]) + echo $testDoc + +test_replace() diff --git a/tests/xml/ttree_replace1.nim b/tests/xml/ttree_replace1.nim new file mode 100644 index 000000000..059ce2085 --- /dev/null +++ b/tests/xml/ttree_replace1.nim @@ -0,0 +1,53 @@ +discard """ + output: ''' +<xml> + <head> + <div>Some text</div> + <div>Some more text </div> + </head> + <body> + <div>Some text in body</div> + <div>Some more text in body </div> + </body> +</xml> +''' +""" + +# Test xmltree add/insert/delete/replace operations +import xmlparser +import xmltree +var baseDocHead = """ + <head> + <div>Some text</div> + <div>Some more text </div> + </head> +""" +var baseDocHeadTree = parseXml(baseDocHead) +var baseDocBody = """ +<body> + <div>Some text in body</div> + <div>Some more text in body </div> +</body> +""" +var baseDocBodyTree = parseXml(baseDocBody) +let initialDocBase = """ +<xml> + <head> + <div>Some text before replace </div> + <div>Some more text before replace </div> + </head> + <body> + <div>Some text in body before replace </div> + <div>Some more text in body before replace </div> + </body> +</xml> +""" +var initialDocBaseTree = parseXml(initialDocBase) + +proc test_replace() = + var testDoc = initialDocBaseTree + + testDoc.replace(0..1, @[baseDocHeadTree, baseDocBodyTree]) + echo $testDoc + +test_replace() |