diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim index ddf9c2704c..52f0bed2bb 100644 --- a/compiler/closureiters.nim +++ b/compiler/closureiters.nim @@ -727,7 +727,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode = n[0] = ex result.add(n) - of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv, + of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv, nkObjUpConv, nkDerefExpr, nkHiddenDeref: var ns = false for i in ord(n.kind == nkCast)..= how.len: + raise newException(ValueError, "Syntax error in format string at " & $i) + if how[i + 1] == '$': val.add('$') i += 2 @@ -27,7 +30,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = i += 1 var id {.inject.} = 0 while i < how.len and how[i] in {'0'..'9'}: - id += (id * 10) + (ord(how[i]) - ord('0')) + id = (id * 10) + (ord(how[i]) - ord('0')) i += 1 val.add(idgetter) lastNum = id + 1 @@ -44,6 +47,8 @@ template formatStr*(howExpr, namegetter, idgetter): untyped = while i < how.len and how[i] != '}': name.add(how[i]) i += 1 + if i >= how.len or how[i] != '}': + raise newException(ValueError, "Syntax error in format string at " & $i) i += 1 val.add(namegetter) else: diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 004cc9bcfe..70d94b023e 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -1946,9 +1946,14 @@ proc withTimeout*[T](fut: Future[T], timeout: int): owned(Future[bool]) = retFuture.fail(fut.error) else: retFuture.complete(true) + # Timeout side lost; drop its callback to avoid retaining closures/futures. + timeoutFuture.clearCallbacks() timeoutFuture.callback = proc () = - if not retFuture.finished: retFuture.complete(false) + if not retFuture.finished: + retFuture.complete(false) + # Wrapped future side lost; drop its callback to avoid retaining closures/futures. + fut.clearCallbacks() return retFuture proc accept*(socket: AsyncFD, diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index 5eb16a8c17..7d422ff4fe 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -16,9 +16,9 @@ ## stream interface. ## ## .. warning:: Due to the use of `pointer`, the `readData`, `peekData` and -## `writeData` interfaces are not available on the compile-time VM, and must -## be cast from a `ptr string` on the JS backend. However, `readDataStr` is -## available generally in place of `readData`. +## `writeData` interfaces are not available on the compile-time VM, and must +## be cast from a `ptr string` on the JS backend. However, `readDataStr` is +## available generally in place of `readData`. ## ## Basic usage ## =========== diff --git a/lib/std/sysatomics.nim b/lib/std/sysatomics.nim index cc6000c206..ac5acf76e6 100644 --- a/lib/std/sysatomics.nim +++ b/lib/std/sysatomics.nim @@ -219,16 +219,16 @@ elif someVcc: elif mem == ATOMIC_ACQ_REL: fence() elif mem == ATOMIC_SEQ_CST: fence() - proc atomicStoreN*[T: AtomType](p: ptr T, val: T, mem: static[AtomMemModel]) = + proc atomicStoreN*[T: AtomType](p: ptr T, val: T, mem: static[AtomMemModel]) {.enforcenoraises.} = barrier(mem) p[] = val - proc atomicLoadN*[T: AtomType](p: ptr T, mem: static[AtomMemModel]): T = + proc atomicLoadN*[T: AtomType](p: ptr T, mem: static[AtomMemModel]): T {.enforcenoraises.} = result = p[] barrier(mem) proc atomicCompareExchangeN*[T: ptr](p, expected: ptr T, desired: T, - weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool = + weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.enforcenoraises.} = when sizeof(T) == 8: interlockedCompareExchange64(p, cast[int64](desired), cast[int64](expected[])) == cast[int64](expected[]) @@ -236,7 +236,7 @@ elif someVcc: interlockedCompareExchange32(p, cast[int32](desired), cast[int32](expected[])) == cast[int32](expected[]) - proc atomicExchangeN*[T: ptr](p: ptr T, val: T, mem: AtomMemModel): T = + proc atomicExchangeN*[T: ptr](p: ptr T, val: T, mem: AtomMemModel): T {.enforcenoraises.} = when sizeof(T) == 8: cast[T](interlockedExchange64(p, cast[int64](val))) elif sizeof(T) == 4: diff --git a/tests/generics/tpointerprocs.nim b/tests/generics/tpointerprocs.nim index 29c4f2954f..ba99044645 100644 --- a/tests/generics/tpointerprocs.nim +++ b/tests/generics/tpointerprocs.nim @@ -3,7 +3,7 @@ cmd: "nim check $options --hints:off $file" action: "reject" nimout:''' tpointerprocs.nim(22, 11) Error: 'foo' doesn't have a concrete type, due to unspecified generic parameters. -tpointerprocs.nim(34, 14) Error: type mismatch: got +tpointerprocs.nim(34, 14) Error: type mismatch: got but expected one of: proc foo(x: int | float; y: int or string): float first type mismatch at position: 2 in generic parameters diff --git a/tests/iter/tclosureiter_objupconv_methodawait.nim b/tests/iter/tclosureiter_objupconv_methodawait.nim new file mode 100644 index 0000000000..671f70f923 --- /dev/null +++ b/tests/iter/tclosureiter_objupconv_methodawait.nim @@ -0,0 +1,12 @@ +discard """ + cmd: "nim c $file" +""" + +import std/asyncdispatch + +type + A {.inheritable.} = ref object + B = ref object of A + +method a(x: A): Future[A] {.async, base.} = + B(await a(B())) diff --git a/tests/stdlib/nre/replace.nim b/tests/stdlib/nre/replace.nim index 5cf659f213..290892bc4e 100644 --- a/tests/stdlib/nre/replace.nim +++ b/tests/stdlib/nre/replace.nim @@ -14,9 +14,15 @@ block: # replace check("123".replace(re"(\d)(\d)", "$#$#") == "123") check("123".replace(re"(?\d)(\d)", "$foo$#$#") == "1123") check("123".replace(re"(?\d)(\d)", "${foo}$#$#") == "1123") + check("abcdefghijklm".replace(re"(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)", "$12") == "l") block: # replacing missing captures should throw instead of segfaulting expect IndexDefect: discard "ab".replace(re"(a)|(b)", "$1$2") expect IndexDefect: discard "b".replace(re"(a)?(b)", "$1$2") expect KeyError: discard "b".replace(re"(a)?", "${foo}") expect KeyError: discard "b".replace(re"(?a)?", "${foo}") + + block: # malformed replacement syntax should throw instead of OOB crash + expect ValueError: discard "a".replace(re"a", "$") + expect ValueError: discard "a".replace(re"a", "x$") + expect ValueError: discard "a".replace(re"a", "${foo") diff --git a/tests/typerel/t25262.nim b/tests/typerel/t25262.nim new file mode 100644 index 0000000000..182561dde3 --- /dev/null +++ b/tests/typerel/t25262.nim @@ -0,0 +1,13 @@ +discard """ + errormsg: "type mismatch" + output: ''' +t25262.nim(13, 5) Error: type mismatch: got <> +but expected one of: +proc v[T: typedesc]() + +expression: v[0]() +''' +""" + +proc v[T: typedesc]() = discard +v[0]() \ No newline at end of file diff --git a/tests/types/tlent_var.nim b/tests/types/tlent_var.nim index 73b5bef9b4..715567d2d1 100644 --- a/tests/types/tlent_var.nim +++ b/tests/types/tlent_var.nim @@ -23,3 +23,18 @@ proc varProc(x: var int) = doAssert: not compiles(test_lent(x) = 1) doAssert: not compiles(varProc(test_lent(x))) +type X = tuple[a: int, b: int] + +type ArrayBuf*[N: static int, T] = object + buf*: array[N, T] + +var v: ArrayBuf[32, X] + + +# proc `[]`*[N, T](b: var ArrayBuf[N, T], i: BackwardsIndex): lent T = # works +# b.buf[i] + +template `[]`*[N, T](b: var ArrayBuf[N, T], i: BackwardsIndex): lent T = + b.buf[i] + +doAssert $v[^4] == "(a: 0, b: 0)"