Merge branch 'devel' into pr_remove_macros

This commit is contained in:
ringabout
2024-08-14 15:17:53 +08:00
committed by GitHub
251 changed files with 6721 additions and 10708 deletions

54
tests/alloc/tmembug.nim Normal file
View File

@@ -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()

58
tests/alloc/tmembug2.nim Normal file
View File

@@ -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()

View File

@@ -136,4 +136,38 @@ proc main2 =
doAssert a.len == 2
doAssert b.len == 0
main2()
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

View File

@@ -1,5 +1,6 @@
discard """
output: '''
Destructor for TestTestObj
=destroy called
123xyzabc
destroyed: false
@@ -36,9 +37,33 @@ 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
@@ -46,13 +71,12 @@ type
len: int
data: ptr UncheckedArray[float]
proc `=destroy`*(m: var MyObj) =
proc `=destroy`*(m: MyObj) =
echo "=destroy called"
if m.data != nil:
deallocShared(m.data)
m.data = nil
type
MyObjDistinct = distinct MyObj
@@ -104,7 +128,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 =
@@ -158,7 +182,7 @@ type
B = ref object of A
x: int
proc `=destroy`(x: var AObj) =
proc `=destroy`(x: AObj) =
close(x.io)
echo "closed"
@@ -742,3 +766,26 @@ block: # bug #23524
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

View File

@@ -338,3 +338,29 @@ block:
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"))]"""

View File

@@ -68,3 +68,19 @@ block:
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)

View File

@@ -4,6 +4,7 @@ discard """
# Test the new ``emit`` pragma:
{.emit: """
#include <stdio.h>
static int cvariable = 420;
""".}

View File

@@ -3,4 +3,5 @@ func test*(input: var openArray[int32], start: int = 0, fin: int = input.len - 1
var someSeq = @[1'i32]
test(someSeq)
test(someSeq)
# bug with gcc 14

View File

@@ -24,7 +24,10 @@ type
fulfilled: Atomic[bool]
var x: Pledge
when defined(gcRefc):
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]"
elif not defined(cpp): # fixme # bug #20081
else: # fixme # bug #20081
doAssert x.repr == "Pledge(p: nil)"

25
tests/ccgbugs/t23796.nim Normal file
View File

@@ -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)

View File

@@ -4,6 +4,7 @@ success
M1 M2
ok
'''
matrix: "--mm:refc;--mm:orc"
"""
type
@@ -133,3 +134,30 @@ proc foo = # bug #23280
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

View File

@@ -5,11 +5,11 @@ discard """
ccodecheck: "'_ZN14titaniummangle8testFuncE6stringN14titaniummangle3FooE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3int7varargsI6stringE'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle3BooE'"
ccodecheck: "'_ZN8testFunc8testFuncE8typeDescIN14titaniummangle17EnumAnotherSampleEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE8typeDescIN14titaniummangle17EnumAnotherSampleEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI14uncheckedArrayI3intEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3setIN14titaniummangle10EnumSampleEE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE4procI6string6stringE'"
ccodecheck: "'_ZN8testFunc8testFuncE3intN10Comparable10ComparableE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3intN10Comparable10ComparableE'"
ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'"
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'"
@@ -37,7 +37,6 @@ type
Comparable = concept x, y
(x < y) is bool
type
Foo = object
a: int32
b: int32
@@ -45,8 +44,10 @@ type
FooTuple = tuple
a: int
b: int
Container[T] = object
data: T
data: T
Container2[T, T2] = object
data: T
data2: T2

View File

@@ -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", "genericsOpenSym")
doAssert compileOption("experimental", "vtables")

View File

@@ -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", "genericsOpenSym")
switch("experimental", "vtables")

View File

@@ -45,3 +45,4 @@ switch("define", "nimPreviewNonVarDestructor")
switch("warningAserror", "UnnamedBreak")
switch("legacy", "verboseTypeMismatch")
switch("experimental", "vtables")
switch("experimental", "genericsOpenSym")

View File

@@ -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()

4
tests/cpp/fam.h Normal file
View File

@@ -0,0 +1,4 @@
struct Test{
~Test() {
}
};

54
tests/cpp/t23657.nim Normal file
View File

@@ -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

View File

@@ -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
doAssert t.len == 2

7
tests/cpp/tfam.nim Normal file
View File

@@ -0,0 +1,7 @@
discard """
targets: "cpp"
"""
type
Test {.importcpp, header: "fam.h".} = object
let test = newSeq[Test]()

View File

@@ -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

View File

@@ -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()

View File

@@ -0,0 +1,8 @@
discard """
matrix: "-u:nimPreviewNonVarDestructor;"
"""
type DistinctSeq* = distinct seq[int]
# `=destroy`(cast[ptr DistinctSeq](0)[])
var x = @[].DistinctSeq
`=destroy`(x)

View File

@@ -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

View File

@@ -14,3 +14,11 @@ proc foo = # bug #23359
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)

View File

@@ -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'; routine: main"
errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b0'; routine: main"
line: 48
"""

12
tests/discard/t23677.nim Normal file
View File

@@ -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")

View File

@@ -5,6 +5,7 @@ tdiscardable
1
something defered
something defered
hi
'''
"""
@@ -110,3 +111,65 @@ block:
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()

View File

@@ -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)]#

View File

@@ -184,3 +184,84 @@ block: # bug #12589
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)

View File

@@ -0,0 +1,10 @@
discard """
errormsg: "duplicate value in enum 'd'"
"""
type
unordered_enum = enum
a = 1
b = 0
c
d = 2

9
tests/errmsgs/t22852.nim Normal file
View File

@@ -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]

View File

@@ -7,7 +7,7 @@ block:
when false:
let x = 123
else:
template x: untyped = 456
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()

View File

@@ -2,16 +2,18 @@ discard """
cmd: "nim check --hints:off $file"
action: "reject"
nimout: '''
tmetaobjectfields.nim(24, 5) Error: 'array' is not a concrete type
tmetaobjectfields.nim(28, 5) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(32, 5) Error: 'set' is not a concrete type
tmetaobjectfields.nim(35, 3) Error: 'sink' is not a concrete type
tmetaobjectfields.nim(37, 3) Error: 'lent' is not a concrete type
tmetaobjectfields.nim(54, 16) Error: 'seq' is not a concrete type
tmetaobjectfields.nim(58, 5) Error: 'ptr' is not a concrete type
tmetaobjectfields.nim(59, 5) Error: 'ref' is not a concrete type
tmetaobjectfields.nim(60, 5) Error: 'auto' is not a concrete type
tmetaobjectfields.nim(61, 5) Error: 'UncheckedArray' is not a concrete type
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
'''
"""
@@ -59,3 +61,15 @@ type
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

View File

@@ -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

View File

@@ -0,0 +1,16 @@
{.experimental: "genericsOpenSym".}
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"

14
tests/generics/t23790.nim Normal file
View File

@@ -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)

91
tests/generics/t23853.nim Normal file
View File

@@ -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()

View File

@@ -186,3 +186,11 @@ block:
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

View File

@@ -113,3 +113,62 @@ block: # issue #22605, original complex example
"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"

View File

@@ -1,3 +1,7 @@
discard """
matrix: "--skipParentCfg --filenames:legacyRelProj"
"""
type Xxx = enum
error
value
@@ -42,8 +46,13 @@ proc f(): Result[int, cstring] =
proc g(T: type): string =
let x = f().valueOr:
{.push warningAsError[GenericsIgnoredInjection]: on.}
# test spurious error
discard true
let _ = f
{.pop.}
return $error #[tt.Warning
^ a new symbol 'error' has been injected during instantiation of g, however 'error' [enumField declared in tmacroinjectedsymwarning.nim(2, 3)] captured at the proc declaration will be used instead; either enable --experimental:genericsOpenSym to use the injected symbol or `bind` this captured symbol explicitly [GenericsIgnoredInjection]]#
^ a new symbol 'error' has been injected during instantiation of g, however 'error' [enumField declared in tmacroinjectedsymwarning.nim(6, 3)] captured at the proc declaration will be used instead; either enable --experimental:genericsOpenSym to use the injected symbol or `bind` this captured symbol explicitly [GenericsIgnoredInjection]]#
"ok"

View File

@@ -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")

View File

@@ -0,0 +1,5 @@
# issue #23386
import mopensymimport2
doAssert g(int) == "f"

View File

@@ -140,3 +140,26 @@ block: # issue #1771
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

View File

@@ -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

View File

@@ -1,3 +1,7 @@
discard """
targets: "c cpp"
"""
doAssert typeOf(1.int64 + 1.int) is int64
doAssert typeOf(1.uint64 + 1.uint) is uint64
doAssert int64 is SomeNumber
@@ -12,3 +16,34 @@ 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

View File

@@ -1,6 +1,5 @@
discard """
matrix: "; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
targets: "c js"
matrix: "; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
output: '''
0 0
0 0
@@ -8,7 +7,6 @@ Success'''
"""
# Test the different integer operations
# TODO: fixme --backend:js cannot change targets!!!
import std/private/jsutils

View File

@@ -504,3 +504,26 @@ block: # void iterator
except:
discard
var a = it
block: # 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)

17
tests/js/tdanger.nim Normal file
View File

@@ -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()

View File

@@ -1,4 +1,5 @@
discard """
matrix: "--legacy:jsnolambdalifting;"
output: '''
3
2

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--jsbigint64:off; --jsbigint64:on"
matrix: "--jsbigint64:off -d:nimStringHash2; --jsbigint64:on"
"""
import std/private/jsutils

37
tests/lookups/t23749.nim Normal file
View File

@@ -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()

View File

@@ -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]

View File

@@ -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

View File

@@ -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

23
tests/macros/t23547.nim Normal file
View File

@@ -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)

157
tests/macros/t23784.nim Normal file
View File

@@ -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.

View File

@@ -365,3 +365,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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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 = [

View File

@@ -121,7 +121,7 @@ template main {.dirty.} =
rVal: R = default(R) # Works fine
objVal = default(Obj)
doAssert rVal == 0 # it should be 1
doAssert rVal == 1
doAssert objVal.r == 1
block: # bug #16744
@@ -134,7 +134,7 @@ template main {.dirty.} =
rVal: R = default(R) # Works fine
objVal = Obj()
doAssert rVal == 0 # it should be 1
doAssert rVal == 1 # it should be 1
doAssert objVal.r == 1
block: # bug #3608
@@ -745,5 +745,19 @@ template main {.dirty.} =
doAssert b.list[North] == 1
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()
static: main()
main()

View File

@@ -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()

View File

@@ -0,0 +1,33 @@
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
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)

62
tests/overload/t23755.nim Normal file
View File

@@ -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)

View File

@@ -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]"

View File

@@ -77,27 +77,30 @@ testPred(1)
# bug #6526
type
BaseObj = ref object of RootObj
DerivedObj = ref object of BaseObj
OtherDerivate = ref object of BaseObj
block: # 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
proc p[T](a: T, b: T): bool =
assert false
let a = DerivedObj()
let b = DerivedObj()
echo a == b
proc p[T1, T2: BaseObj](a: T1, b: T2): bool =
echo "baseobj =="
return true
proc `==`*[T1, T2: OtherDerivate](a: T1, b: T2): bool =
echo "even better! =="
return true
let a = DerivedObj()
let b = DerivedObj()
echo p(a,b)
let a2 = OtherDerivate()
let b2 = OtherDerivate()
echo a2 == b2
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)

View File

@@ -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

View File

@@ -1,18 +1,10 @@
discard """
output: '''ob2 @[]
ob @[]
ob3 @[]
3
ob2 @[]
ob @[]
ob3 @[]
'''
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

View File

@@ -99,3 +99,28 @@ block: # bug #23019
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.}

26
tests/proc/t23874.nim Normal file
View File

@@ -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.}

View File

@@ -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

26
tests/refc/tsinkbug.nim Normal file
View File

@@ -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)

View File

@@ -84,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)

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off"
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
@@ -31,7 +31,8 @@ block hashes:
doAssert hashWangYi1(123) == wy123
const wyNeg123 = hashWangYi1(-123)
doAssert wyNeg123 != 0
doAssert hashWangYi1(-123) == wyNeg123
when not defined(js): # TODO: fixme it doesn't work for JS
doAssert hashWangYi1(-123) == wyNeg123
# "hashIdentity value incorrect at 456"
@@ -45,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)
@@ -92,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):

View File

@@ -53,9 +53,9 @@ 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)
when false: # occasionally does not give success code
resp = await client.request("https://google.com/")
@@ -115,9 +115,9 @@ 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)
when false: # occasionally does not give success code
resp = client.request("https://google.com/")

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --backend:cpp --mm:refc; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
matrix: "; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
"""
@@ -51,7 +51,7 @@ for i in 0 .. 10000:
except:
discard
# memory diff should less than 4M
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024) # todo fixme doesn;t work for ORC
doAssert(abs(getOccupiedMem() - startMemory) < 4 * 1024 * 1024)
# test `$`

View File

@@ -19,5 +19,10 @@ template main() =
# 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()

View File

@@ -99,3 +99,14 @@ block: # With this included, static: test() crashes the compiler (from a
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

View File

@@ -6,15 +6,12 @@ import std/paths
import std/assertions
import pathnorm
from std/private/ospaths2 {.all.} import joinPathImpl
import std/sugar
import std/[sugar, sets]
proc normalizePath*(path: Path; dirSep = DirSep): Path =
result = Path(pathnorm.normalizePath(path.string, dirSep))
func `==`(x, y: Path): bool =
x.string == y.string
func joinPath*(parts: varargs[Path]): Path =
var estimatedLen = 0
var state = 0
@@ -231,4 +228,11 @@ block ospaths:
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
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

View File

@@ -1,6 +1,6 @@
discard """
joinable: false # to avoid messing with global rand state
matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
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]
@@ -297,6 +297,9 @@ block: # bug #22360
inc fc
when defined(js):
doAssert (tc, fc) == (483, 517), $(tc, fc)
when compileOption("jsbigint64"):
doAssert (tc, fc) == (517, 483), $(tc, fc)
else:
doAssert (tc, fc) == (515, 485), $(tc, fc)
else:
doAssert (tc, fc) == (510, 490), $(tc, fc)

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
"""
import std/strutils
@@ -527,9 +527,9 @@ template main() =
block: # toHex
doAssert(toHex(100i16, 32) == "00000000000000000000000000000064")
doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
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")

View File

@@ -4,7 +4,7 @@ discard """
"""
import stdtest/testutils
import std/assertions
import std/[assertions, formatfloat]
# TODO: in future work move existing `system` tests here, where they belong
@@ -83,24 +83,36 @@ 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:
type
X = object
a: string
b: int
var y = X(b: 1314)
reset(y)
doAssert y.b == 0
var x = 2
var y = move x
doAssert y == 2
doAssert x == 0
reset y
doAssert y == 0
block:
type
@@ -170,3 +182,19 @@ block: # bug #20516
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"

View File

@@ -523,3 +523,39 @@ block:
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

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off"
matrix: "--mm:refc; --mm:orc; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off -d:nimStringHash2"
"""
import times, strutils, unittest
@@ -71,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,
@@ -770,3 +770,15 @@ block: # ttimes
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

View File

@@ -74,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()

View File

@@ -57,6 +57,7 @@ doAssert isAlpha("r")
doAssert isAlpha("α")
doAssert isAlpha("ϙ")
doAssert isAlpha("")
doAssert isAlpha("")
doAssert(not isAlpha("$"))
doAssert(not isAlpha(""))
@@ -66,6 +67,7 @@ doAssert isAlpha("𐌼𐌰𐌲𐌲𐌻𐌴𐍃𐍄𐌰𐌽")
doAssert isAlpha("ὕαλονϕαγεῖνδύναμαιτοῦτοοὔμεβλάπτει")
doAssert isAlpha("Јамогујестистаклоитоминештети")
doAssert isAlpha("Կրնամապակիուտեևինծիանհանգիստչըներ")
doAssert isAlpha("编程语言")
doAssert(not isAlpha("$Foo"))
doAssert(not isAlpha("⠙⠕⠑⠎⠝⠞"))

View File

@@ -33,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) =

View File

@@ -1,5 +1,5 @@
discard """
matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
matrix: "--mm:refc; --mm:orc; --backend:cpp; --backend:js --jsbigint64:off -d:nimStringHash2; --backend:js --jsbigint64:on"
"""
#[
@@ -109,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

View File

@@ -219,3 +219,9 @@ proc bug23223 = # bug #23223
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

87
tests/template/t13426.nim Normal file
View File

@@ -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)

View File

@@ -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()

51
tests/threads/tmembug.nim Normal file
View File

@@ -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()

View File

@@ -0,0 +1,2 @@
type p = ptr UncheckedArray[char]
doAssert p is ptr UncheckedArray

View File

@@ -124,3 +124,13 @@ proc bug22597 = # bug #22597
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"]

90
tests/views/tviews2.nim Normal file
View File

@@ -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)

View File

@@ -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

View File

@@ -67,3 +67,23 @@ 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

Some files were not shown because too many files have changed in this diff Show More