Compare commits

...

44 Commits

Author SHA1 Message Date
ringabout
10564f25b3 fixes #24719; improves order of destruction (#25060)
fixes #24719

(cherry picked from commit 8e57a9f623)
2025-07-19 08:22:53 +02:00
narimiran
fbc7e54e95 revert Atlas commit to the one compatible with 2.0.x 2025-07-14 09:48:48 +02:00
Juan M Gómez
7f3dbd5656 Updates nimble commit (#25036)
(cherry picked from commit 370ee61f6d)
2025-07-08 16:23:45 +02:00
ringabout
71f3e100b6 provides a $ function for Path (#23617)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 4e7c70fd7d)
2025-07-02 09:59:38 +02:00
ringabout
d2cb099e44 fixes #24881; build_all.sh koch tools fails to build atlas (#24884)
fixes #24881

To test: `nim c koch.nim` + delete the `dist` directory

(cherry picked from commit af9219ada7)
2025-07-01 14:23:58 +02:00
Miran
7e51e48cac update the tooling versions (#24878)
(cherry picked from commit 11e4bd668c)
2025-06-30 14:10:33 +02:00
ringabout
19c89622ca fixes #23564; hasCustomPragma skips alises types (#24994)
fixes #23564

perhaps handle generic aliases (tyGenericInst for aliases types) if
needed

(cherry picked from commit 7e6fa9e2d6)
2025-06-27 13:47:24 +02:00
Jacek Sieka
b1d9af4d5f Ensure that gc interface remains non-raising (#25006)
GC_fullCollect in particular has an annoying `Exception` effect

(cherry picked from commit aba9361510)
2025-06-18 16:15:42 +02:00
metagn
c467532484 don't set sym of generic param type value to generic param sym (#24995)
fixes #23713

`linkTo` normally sets the sym of the type as well as the type of the
sym, but this is not wanted for custom pragmas as it would look up the
definition of the generic param and not the definition of its value. I
don't see a practical use for this either.

(cherry picked from commit 7701b3c7e6)
2025-06-16 11:17:19 +02:00
Eugene Kabanov
114d0b8bdc Fix FreeBSD getThreadId() should use different syscall definition for 64bit platforms. (#24977)
(cherry picked from commit 7a53db6874)
2025-06-06 08:33:38 +02:00
Alfred Morgan
f8ce7ddd6d Patch 24922 (#24923)
(cherry picked from commit b61a614e8a)
2025-06-03 07:38:25 +02:00
Andreas Rumpf
cd6dbbd7f3 fixes #4851 [backport] (#24954)
(cherry picked from commit 1e602490e9)
2025-05-19 17:54:43 +02:00
narimiran
acac0bc1f2 bump NimVersion to 2.0.17 2025-04-22 16:26:30 +02:00
narimiran
82f3a57612 bump NimVersion to 2.0.16 2025-04-21 19:10:44 +02:00
metagn
7e589bcbe4 add bit type overloads of $ and repr (#24865)
fixes #24864

(cherry picked from commit 97d819a251)
2025-04-14 10:56:41 +02:00
metagn
dbed9310ba ignore typeof in closure iterators (#24861)
fixes #24859

(cherry picked from commit f58cd51fc4)
2025-04-14 10:54:56 +02:00
ringabout
9524edec60 fixes #24850; macro-generated if/else and when/else statements have m… (#24852)
…ismatched indentation with repr

fixes #24850

(cherry picked from commit 29a2e25d1e)
2025-04-09 07:57:52 +02:00
metagn
574db65396 make fillObjectFields recur over base type (#24854)
fixes #24847

Object constructors call `fillObjectFields` when a field inside the
constructor does not have a location, however when the field is from a
base type this does not process it. Now `fillObjectFields` also calls
itself for the base type to fix this but not sure if this is a good
solution as `fillObjectFields` is used in other places too.

(cherry picked from commit a625fab098)
2025-04-09 07:57:39 +02:00
ringabout
e2bf3a6f70 bump to windows 2025 (#24853)
(cherry picked from commit 052ceca3c1)
2025-04-09 07:55:26 +02:00
Miran
6f2dbc105e test stint more thoroughly (#24832)
(cherry picked from commit 10c9ebad93)
2025-04-09 07:55:20 +02:00
ringabout
63151568b4 fixes #24801; Invalid C codegen generated when destroying distinct seq types (#24835)
fixes #24801

Because distinct `seq` types match `proc `=destroy`*[T](x: var T)
{.inline, magic: "Destroy".}`. But the Nim compiler generates lifted seq
types for corresponding distinct types. So we skip the address for
distinct types.

Related to https://github.com/nim-lang/Nim/pull/22207 I had a hard time
finding the other place where generic destructors get replaced by
attachedDestructors

(cherry picked from commit 4352fa2ef0)
2025-04-04 10:18:00 +02:00
ringabout
4610c2b314 fixes #10625; setjmp on linux mangles ebp leading to early collection (#24787)
fixes #10625

(cherry picked from commit 7c5d005510)
2025-03-25 09:45:23 +01:00
ringabout
d01002d8f8 fixes #24770; Thread local not registed as GC root when =destroy exists (#24776)
fixes #24770

e.g. `seq[(ObjectWithDestructors, string)]`/ For refc, a seq with
elements that have destructors will have `hasAsgn` flags. The flag is
the criteria whether a seq is thought as `containsGarbageCollectedRef`.
i.e. whether to `registerTraverseProc` for the type.
The culprit seems to be that `searchTypeForAux` doesn't consider the
element type of sequence, even it contains a string that should belong
to `GarbageCollectedRef`.

With this PR:

It now generates

```
nimRegisterThreadLocalMarker(TM__mSF73dT1lSI7DG58StKHLQ_5);
```

in refc

(cherry picked from commit dfa482e292)
2025-03-13 12:24:29 +01:00
ringabout
bc2fa6fe32 fixes #24147; Copy hook causes an incompatible-pointer-types (#24149)
fixes #24147

(cherry picked from commit 5c843d3d60)
2025-03-11 08:58:37 +01:00
ringabout
41637db18f fixes ORC memory leaks; marks hooks with optQuirky (#24701)
closes https://github.com/nim-lang/Nim/pull/24686
closes #24693

```nim
# v.nim
import std/[json]

var test: seq[string]
var testData: JsonNode
try:
  ## Fails
  testData = parseJson("""[{"id": 1"}, {"id": "2"}]""")

  ## Works
  # testdata = parseJson("""[{"id": "1"}, {"id": "2"}]""")

  ## Fails
  # let stream = newStringStream("""[{"id": 1"}, {"id": "2"}]""")
  # testData = parseJson(stream, "input", false, false)
  # stream.close()

except:
  testData = %* []
for t in testData:
  test.add(t["id"].getStr())
echo $test
```

With this PR:

```
==66425== LEAK SUMMARY:
==66425==    definitely lost: 0 bytes in 0 blocks
==66425==    indirectly lost: 0 bytes in 0 blocks
==66425==      possibly lost: 0 bytes in 0 blocks
==66425==    still reachable: 16,512 bytes in 2 blocks
==66425==         suppressed: 0 bytes in 0 blocks
==66425== Reachable blocks (those to which a pointer was found) are not shown.
==66425== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==66425==
==66425== For lists of detected and suppressed errors, rerun with: -s
==66425== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
```

(cherry picked from commit f0b5bf359e)
2025-02-20 10:26:12 +01:00
ringabout
b7eefc31d8 implements quirky for functions (#24700)
ref https://github.com/nim-lang/Nim/pull/24686

With this PR

```nim
import std/streams

proc foo() =
  var name = newStringStream("2r2")
  raise newException(ValueError, "sh")

try:
  foo()
except:
 discard

echo 123
```
this example no longer leaks

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 510ac84518)
2025-02-18 17:51:21 +01:00
metagn
5df3bf467e retry thttpclient_ssl twice (#24467)
Flaky on linux_amd64

(cherry picked from commit 652edb229a)
2025-02-17 21:16:14 +01:00
metagn
ac44139084 add retries to testament, use it for GC tests (#24279)
Testament now retries a test by a specified amount if it fails in any
way other than an invalid spec. This is to deal with the flaky GC tests
on Windows CI that fail in many different ways, from the linker randomly
erroring, segfaults, etc.

Unfortunately I couldn't do this cleanly in testament's current code.
The proc `addResult`, which is the "final" proc called in a test run's
lifetime, is now wrapped in a proc `finishTest` that returns a bool
`true` if the test failed and has to be retried. This result is
propagated up from `cmpMsgs` and `compilerOutputTests` until it reaches
`testSpecHelper`, which handles these results by recursing if the test
has to be retried. Since calling `testSpecHelper` means "run this test
with one given configuration", this means every single matrix
option/target etc. receive an equal amount of retries each.

The result of `finishTest` is ignored in cases where it's known that it
won't be retried due to passing, being skipped, having an invalid spec
etc. It's also ignored in `testNimblePackages` because it's not
necessary for those specific tests yet and similar retry behavior is
already implemented for part of it.

This was a last resort for the flaky GC tests but they've been a problem
for years at this point, they give us more work to do and turn off
contributors. Ideally GC tests failing should mark as "needs review" in
the CI rather than "failed" but I don't know if Github supports
something like this.

(cherry picked from commit 720d0aee5c)
2025-02-17 21:16:13 +01:00
metagn
ac882ea696 disable all badssl tests indefinitely (#24403)
Flaky not just due to recent ubuntu 24/GCC 14 upgrades, windows fails as
well, assuming the issue is with badssl or it's just not worth testing
here.

(cherry picked from commit 5f056f87b2)
2025-02-17 17:11:42 +01:00
ringabout
56f9559c69 adds a ubuntu 24.04 matrix with gcc 14 for tests (#23673)
ref https://forum.nim-lang.org/t/11587

(cherry picked from commit 6336d2681b)
2025-02-17 15:37:45 +01:00
ringabout
c08c32a1ed fixes #5901 #21211; don't fold cast function types because of gcc 14 (#23683)
follow up https://github.com/nim-lang/Nim/pull/6265

fixes #5901
fixes #21211

It causes many problems with gcc14 if we fold the cast function types.
Let's check what it will break

(cherry picked from commit 2d1533f34f)
2025-02-17 13:25:35 +01:00
narimiran
03491904a0 update CI to Ubuntu 24.04 2025-02-17 09:27:37 +01:00
metagn
57f84c5376 track introduced locals in vmgen for eval check (#24674)
fixes #8758, fixes #10828, fixes #12172, fixes #21610, fixes #23803,
fixes #24633, fixes #24634, succeeds #24085

We simply track the symbol ID of every traversed `var`/`let` definition
in `vmgen`, then these symbols are always considered evaluable in the
current `vmgen` context. The set of symbols is reset before every
generation, but both tests worked properly without doing this including
the nested `const`, so maybe it's already done in some way I'm not
seeing.

(cherry picked from commit a5cc33c1d3)
2025-02-17 08:23:51 +01:00
ringabout
1df4debbf1 fixes bugs on the Nim manual (#24669)
ref https://en.cppreference.com/w/cpp/error/exception/what

> Pointer to a null-terminated string with explanatory information. The
pointer is guaranteed to be valid at least until the exception object
from which it is obtained is destroyed, or until a non-const member
function on the exception object is called.

The pointer is only valid before `CStdException as e` is destroyed

Old examples are broken on macOS arm64

```
/Users/blue/Desktop/nimony/test4.nim(38) test4
/Users/blue/Desktop/nimony/test4.nim(26) fn
/Users/blue/.choosenim/toolchains/nim-#devel/lib/std/assertions.nim(41) failedAssertImpl
/Users/blue/.choosenim/toolchains/nim-#devel/lib/std/assertions.nim(36) raiseAssert
/Users/blue/.choosenim/toolchains/nim-#devel/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: /Users/blue/Desktop/nimony/test4.nim(26, 3) `$b == "foo2"`  [AssertionDefect]
```

(cherry picked from commit e6f6c369ff)
2025-02-10 17:11:50 +01:00
metagn
1ff69eae17 don't mark captured field sym in template as fully used (#24660)
fixes #24657

(cherry picked from commit 647c6687f1)
2025-01-31 09:36:33 +01:00
metagn
4fa122eb44 don't try to transform objconstr/cast type nodes (#24636)
fixes #24631

[Object
constructors](793baf34ff/compiler/semobjconstr.nim (L462)),
[casts](793baf34ff/compiler/semexprs.nim (L494))
and [type
conversions](793baf34ff/compiler/semexprs.nim (L419))
copy their type nodes verbatim instead of producing semchecked type
nodes. This causes a crash in transf when an untyped expression in the
type node has `nil` type. To deal with this, don't try to transform the
type node in these expressions at all. I couldn't reproduce the problem
with type conversion nodes though so those are unchanged in transf.

(cherry picked from commit 6d59680217)
2025-01-27 09:30:11 +01:00
Tomohiro
53782b1404 Fix parseBiggestUInt to detect overflow (#24649)
With some inputs larger than `BiggestUInt.high`, `parseBiggestUInt` proc
in `parseutils.nim` fails to detect overflow and returns random value.
This is because `rawParseUInt` try to detects overflow with `if prev >
res:` but it doesn't detects the overflow from multiplication.
It is possible that `x *= 10` causes overflow and resulting value is
larger than original value.
Here is example values larger than `BiggestUInt.high` but
`parseBiggestUInt` returns without detecting overflow:
```
22751622367522324480000000
41404969074137497600000000
20701551093035827200000000000000000
22546225502460313600000000000000000
204963831854661632000000000000000000
```

Following code search for values larger than `BiggestUInt.high` and
`parseBiggestUInt` cannot detect overflow:
```nim
import std/[strutils]

const
  # Increase this to extend search range
  NBits = 34'u
  NBitsMax1 = 1'u shl NBits
  NBitsMax = NBitsMax1 - 1'u

  # Increase this when there are too many results and want to see only larger result.
  MinMultiply10 = 14

var nfound = 0
for i in (NBitsMax div 10'u + 1'u) .. NBitsMax:
  var
    x = i
    n10 = 0
  for j in 0 ..< NBits:
    let px = x
    x = (x * 10'u) and NBitsMax
    if x < px:
      break
    inc n10
  if n10 >= MinMultiply10:
    echo "i =   ", i
    echo "uint: ", (i shl (64'u - NBits)), '0'.repeat n10
    inc nfound
    if nfound > 15:
      break

echo "found: ", nfound
```

(cherry picked from commit 95b1dda1db)
2025-01-27 08:51:04 +01:00
ringabout
cafe1284ac fixes #24623; fixes #23692; size pragma only allowed for imported types and enum types (#24640)
fixes #24623
fixes #23692

ref
https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-size-pragma

confines `size` pragma to `enums` and imported `objects` for now

The `typeDefLeftSidePass` carries out the check for pragmas, but the
type is not complete yet. So the `size` pragma checking is postponed at
the final pass.

(cherry picked from commit d6d28a9c79)
2025-01-24 05:13:03 +01:00
ringabout
e2ae7d5f43 fixes #24630; static openArray backed by seq cannot be passed to another function (#24638)
fixes #24630

(cherry picked from commit 2f402fcb82)
2025-01-24 05:12:26 +01:00
metagn
772ebe6715 disable sfml test on osx (#24615)
Tried installing sfml 2 in #24614 but didn't work

(cherry picked from commit d83ff81695)
2025-01-22 09:56:31 +01:00
ringabout
32c99651fc ci: update to ubuntu 22.04 (#24608)
(cherry picked from commit 41c447b5f4)
2025-01-22 06:58:51 +01:00
metagn
2eac7941ff stricter skip for conversions in array indices in transf (#24424)
fixes #17958

In `transf`, conversions in subscript expressions are skipped (with
`skipConv`'s rules). This is because array indexing can produce
conversions to the range type that is the array's index type, which
causes a `RangeDefect` rather than an `IndexDefect` (and also
`--rangeChecks` and `--indexChecks` are both considered). However this
causes problems when explicit conversions are used, between types of
different bitsizes, because those also get skipped.

To fix this, we only skip the conversion if:

* it's a hidden (implicit) conversion
* it's a range check conversion (produces `nkChckRange`)
* the subscript is on an array type and the result type of the
conversion has the same bounds as the array index type

And `skipConv` rules also still apply (int/float classification).

Another idea would be to prevent the implicit conversion to the array
index type from being generated. But there is no good way to do this:
matching to the base type instead prevents types like `uint32` from
implicitly converting (i.e. it can convert to `range[0..3]` but not
`int`), and analyzing whether this is an array bound check is easier in
`transf`, since `sigmatch` just produces a type conversion.

The rules for skipping the conversion could also receive some other
tweaks: We could add a rule that changing bitsizes also doesn't skip the
conversion, but this breaks the `uint32` case. We could simplify it to
only removing implicit skips to specifically fix #17958, but this is
wrong in general.

We could also add something like `nkChckIndex` that generates index
errors instead but this is weird when it doesn't have access to the
collection type and it might be overkill.

(cherry picked from commit 76c5f16ac5)
2025-01-22 06:56:48 +01:00
metagn
cedcb7881d generate destructor in nodestroy proc for explicit destructor call (#24627)
fixes #24626

`createTypeboundOps` in sempass2 is called when generating destructors
for types including for explicit destructor calls, however it blocks
destructors from getting generated in a `nodestroy` proc. This causes
issues when a destructor is explicitly called in a `nodestroy` proc. To
fix this, allow destructors to get generated only for explicit
destructor calls in nodestroy procs.

(cherry picked from commit 793baf34ff)
2025-01-22 06:45:40 +01:00
narimiran
117b913458 bump NimVersion to 2.0.15 2025-01-22 06:39:41 +01:00
106 changed files with 976 additions and 216 deletions

View File

@@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
os: [ubuntu-24.04]
cpu: [amd64]
name: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}

View File

@@ -43,7 +43,7 @@ jobs:
target: [linux, windows, osx]
include:
- target: linux
os: ubuntu-20.04
os: ubuntu-22.04
- target: windows
os: windows-2019
- target: osx

76
.github/workflows/ci_gcc14.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: GCC 14
on:
pull_request:
push:
branches:
- 'devel'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04]
cpu: [amd64]
name: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
timeout-minutes: 60 # refs bug #18178
steps:
- name: 'Checkout'
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo apt update -qq
sudo apt remove needrestart
DEBIAN_FRONTEND='noninteractive' \
sudo apt install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
valgrind libc6-dbg libblas-dev xorg-dev
- name: 'Install dependencies (Linux amd64 gcc 14)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo add-apt-repository universe
sudo apt update -qq
sudo apt install -y gcc-14 g++-14 libpcre3 liblapack-dev
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml gtk+3
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
set -e
. ci/funs.sh
nimInternalInstallDepsWindows
echo_run echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
- name: 'NIM_TESTAMENT_DISABLE_SSL'
shell: bash
run: echo "NIM_TESTAMENT_DISABLE_SSL=1" >> $GITHUB_ENV
- name: 'System information'
shell: bash
run: . ci/funs.sh && nimCiSystemInfo
- name: 'Build csourcesAny'
shell: bash
run: . ci/funs.sh && nimBuildCsourcesIfNeeded CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'koch, Run CI'
shell: bash
run: . ci/funs.sh && nimInternalBuildKochAndRunCI

View File

@@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-13]
os: [ubuntu-22.04, macos-13]
cpu: [amd64]
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'

View File

@@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
os: [ubuntu-22.04]
cpu: [amd64]
name: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
@@ -21,10 +21,10 @@ jobs:
with:
fetch-depth: 2
- name: 'Install node.js 20.x'
- name: 'Install node.js'
uses: actions/setup-node@v4
with:
node-version: '20.x'
node-version: ''
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
@@ -34,17 +34,6 @@ jobs:
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
valgrind libc6-dbg libblas-dev xorg-dev
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml gtk+3
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
set -e
. ci/funs.sh
nimInternalInstallDepsWindows
echo_run echo "${{ github.workspace }}/dist/mingw64/bin" >> "${GITHUB_PATH}"
- name: 'Add build binaries to PATH'
shell: bash

View File

@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-20.04'
vmImage: 'ubuntu-24.04'
CPU: amd64
# regularly breaks, refs bug #17325
# Linux_i386:
@@ -36,16 +36,16 @@ jobs:
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64_batch0_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
# see also: `NIM_TEST_PACKAGES`
NIM_TESTAMENT_BATCH: "0_3"
Windows_amd64_batch1_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
NIM_TESTAMENT_BATCH: "1_3"
Windows_amd64_batch2_3:
vmImage: 'windows-2019'
vmImage: 'windows-2025'
CPU: amd64
NIM_TESTAMENT_BATCH: "2_3"
@@ -80,10 +80,12 @@ jobs:
- bash: |
set -e
. ci/funs.sh
echo_run sudo apt-fast update -qq
echo_run sudo add-apt-repository universe
echo_run sudo apt-get update -qq
DEBIAN_FRONTEND='noninteractive' \
echo_run sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
echo_run sudo apt-get install --no-install-recommends -yq \
gcc-14 g++-14 libpcre3 liblapack-dev libpcre3 liblapack-dev libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
echo_run sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
displayName: 'Install dependencies (amd64 Linux)'
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
@@ -100,12 +102,12 @@ jobs:
Pin-Priority: 1001
EOF
# echo_run sudo apt-fast update -qq
echo_run sudo apt-fast update -qq || echo "failed, see bug #17343"
# echo_run sudo apt-get update -qq
echo_run sudo apt-get update -qq || echo "failed, see bug #17343"
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
# `could not load: libffi.so` during dynamic loading.
DEBIAN_FRONTEND='noninteractive' \
echo_run sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
echo_run sudo apt-get install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 libffi-dev:i386

View File

@@ -19,6 +19,11 @@
slots when enlarging a sequence.
- Added `hasDefaultValue` to `std/typetraits` to check if a type has a valid default value.
- Added Viewport API for the JavaScript targets in the `dom` module.
- Added `toSinglyLinkedRing` and `toDoublyLinkedRing` to `std/lists` to convert from `openArray`s.
- ORC: To be enabled via `nimOrcStats` there is a new API called `GC_orcStats` that can be used to query how many
objects the cyclic collector did free. If the number is zero that is a strong indicator that you can use `--mm:arc`
instead of `--mm:orc`.
- A `$` template is provided for `Path` in `std/paths`.
[//]: # "Deprecations:"

View File

@@ -18,7 +18,7 @@ proc registerTraverseProc(p: BProc, v: PSym) =
var traverseProc = ""
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcRefc} and
optOwnedRefs notin p.config.globalOptions and
containsGarbageCollectedRef(v.loc.t):
containsManagedMemory(v.loc.t):
# we register a specialized marked proc here; this has the advantage
# that it works out of the box for thread local storage then :-)
traverseProc = genTraverseProcForGlobal(p.module, v, v.info)

View File

@@ -768,6 +768,8 @@ proc fillObjectFields*(m: BModule; typ: PType) =
# this fact here.
var check = initIntSet()
discard getRecordFields(m, typ, check)
if typ.baseClass != nil:
fillObjectFields(m, typ.baseClass.skipTypes(skipPtrs))
proc mangleDynLibProc(sym: PSym): Rope

View File

@@ -163,7 +163,7 @@ type
const
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt, nkMixinStmt, nkBindStmt} + procDefs
nkCommentStmt, nkMixinStmt, nkBindStmt, nkTypeOfExpr} + procDefs
proc newStateAccess(ctx: var Ctx): PNode =
if ctx.stateVarSym.isNil:

View File

@@ -452,6 +452,11 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
result = conf.compileOptions
if (conf.cCompiler == ccGcc or conf.cCompiler == ccCLang) and
conf.selectedGC == gcRefc:
# bug #10625
addOpt(result, "-fno-omit-frame-pointer")
for option in conf.compileOptionsCmd:
if strutils.find(result, option, 0) < 0:
addOpt(result, option)

View File

@@ -39,7 +39,7 @@ template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink)
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym
info: TLineInfo; idgen: IdGenerator): PSym
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
idgen: IdGenerator)
@@ -217,17 +217,38 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool,
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
c.filterDiscriminator = oldfilterDiscriminator
of nkRecList:
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
# destroys in reverse order #24719
if c.kind == attachedDestructor:
for i in countdown(n.len-1, 0):
fillBodyObj(c, n[i], body, x, y, enforceDefaultOp, enforceWasMoved)
else:
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
else:
illFormedAstLocal(n, c.g.config)
proc fillBodyObjTImpl(c: var TLiftCtx; t: PType, body, x, y: PNode) =
if t.len > 0 and t[0] != nil:
let obj = newNodeIT(nkHiddenSubConv, c.info, t[0])
obj.add newNodeI(nkEmpty, c.info)
obj.add x
fillBody(c, skipTypes(t[0], abstractPtrs), body, obj, y)
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
template fillBase =
if t.len > 0 and t[0] != nil:
let dest = newNodeIT(nkHiddenSubConv, c.info, t[0])
dest.add newNodeI(nkEmpty, c.info)
dest.add x
var src = y
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
src = newNodeIT(nkHiddenSubConv, c.info, t[0])
src.add newNodeI(nkEmpty, c.info)
src.add y
fillBody(c, skipTypes(t[0], abstractPtrs), body, dest, src)
template fillFields =
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
if c.kind == attachedDestructor:
# destroys in reverse order #24719
fillFields()
fillBase()
else:
fillBase()
fillFields()
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
var hasCase = isCaseObj(t.n)
@@ -1036,9 +1057,7 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
assert typ.kind == tyDistinct
let baseType = typ[0]
if getAttachedOp(g, baseType, kind) == nil:
# TODO: fixme `isDistinct` is a fix for #23552; remove it after
# `-d:nimPreviewNonVarDestructor` becomes the default
discard produceSym(g, c, baseType, kind, info, idgen, isDistinct = true)
discard produceSym(g, c, baseType, kind, info, idgen)
result = getAttachedOp(g, baseType, kind)
setAttachedOp(g, idgen.module, typ, kind, result)
@@ -1077,7 +1096,7 @@ proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttache
incl result.flags, sfGeneratedOp
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false; isDistinct = false): PSym =
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false): PSym =
if kind == attachedDup:
return symDupPrototype(g, typ, owner, kind, info, idgen)
@@ -1087,7 +1106,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
idgen, result, info)
if kind == attachedDestructor and g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
((g.config.isDefined("nimPreviewNonVarDestructor") and not isDiscriminant) or (typ.kind in {tyRef, tyString, tySequence} and not isDistinct)):
((g.config.isDefined("nimPreviewNonVarDestructor") and not isDiscriminant) or (typ.kind in {tyRef, tyString, tySequence})):
dest.typ = typ
else:
dest.typ = makeVarType(typ.owner, typ, idgen)
@@ -1129,13 +1148,13 @@ proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add newAsgnStmt(xx, yy)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym =
info: TLineInfo; idgen: IdGenerator): PSym =
if typ.kind == tyDistinct:
return produceSymDistinctType(g, c, typ, kind, info, idgen)
result = getAttachedOp(g, typ, kind)
if result == nil:
result = symPrototype(g, typ, typ.owner, kind, info, idgen, isDistinct = isDistinct)
result = symPrototype(g, typ, typ.owner, kind, info, idgen)
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType: typ, idgen: idgen,
fn: result)
@@ -1179,6 +1198,8 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
result.ast[pragmasPos].add newTree(nkExprColonExpr,
newIdentNode(g.cache.getIdent("raises"), info), newNodeI(nkBracket, info))
if kind == attachedDestructor:
incl result.options, optQuirky
completePartialOp(g, idgen.module, typ, kind, result)

View File

@@ -1295,8 +1295,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
pragmaProposition(c, it)
of wEnsures:
pragmaEnsures(c, it)
of wEnforceNoRaises, wQuirky:
of wEnforceNoRaises:
sym.flags.incl sfNeverRaises
of wQuirky:
sym.flags.incl sfNeverRaises
if sym.kind in {skProc, skMethod, skConverter, skFunc, skIterator}:
sym.options.incl optQuirky
of wSystemRaisesDefect:
sym.flags.incl sfSystemRaisesDefect
of wVirtual:

View File

@@ -557,8 +557,16 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkIfExpr:
result = lsub(g, n[0][0]) + lsub(g, n[0][1]) + lsons(g, n, 1) +
len("if_:_")
of nkElifExpr: result = lsons(g, n) + len("_elif_:_")
of nkElseExpr: result = lsub(g, n[0]) + len("_else:_") # type descriptions
of nkElifExpr, nkElifBranch:
if isEmptyType(n[1].typ):
result = lsons(g, n) + len("elif_:_")
else:
result = lsons(g, n) + len("_elif_:_")
of nkElseExpr, nkElse:
if isEmptyType(n[0].typ):
result = lsub(g, n[0]) + len("else:_")
else:
result = lsub(g, n[0]) + len("_else:_") # type descriptions
of nkTypeOfExpr: result = (if n.len > 0: lsub(g, n[0]) else: 0)+len("typeof()")
of nkRefTy: result = (if n.len > 0: lsub(g, n[0])+1 else: 0) + len("ref")
of nkPtrTy: result = (if n.len > 0: lsub(g, n[0])+1 else: 0) + len("ptr")
@@ -601,8 +609,6 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkCommentStmt: result = n.comment.len
of nkOfBranch: result = lcomma(g, n, 0, - 2) + lsub(g, lastSon(n)) + len("of_:_")
of nkImportAs: result = lsub(g, n[0]) + len("_as_") + lsub(g, n[1])
of nkElifBranch: result = lsons(g, n) + len("elif_:_")
of nkElse: result = lsub(g, n[0]) + len("else:_")
of nkFinally: result = lsub(g, n[0]) + len("finally:_")
of nkGenericParams: result = lcomma(g, n) + 2
of nkFormalParams:
@@ -1459,15 +1465,30 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
putWithSpace(g, tkColon, ":")
if n.len > 0: gsub(g, n[0], 1)
gsons(g, n, emptyContext, 1)
of nkElifExpr:
putWithSpace(g, tkElif, " elif")
gcond(g, n[0])
putWithSpace(g, tkColon, ":")
gsub(g, n, 1)
of nkElseExpr:
put(g, tkElse, " else")
putWithSpace(g, tkColon, ":")
gsub(g, n, 0)
of nkElifExpr, nkElifBranch:
if isEmptyType(n[1].typ):
optNL(g)
putWithSpace(g, tkElif, "elif")
gsub(g, n, 0)
putWithSpace(g, tkColon, ":")
gcoms(g)
gstmts(g, n[1], c)
else:
putWithSpace(g, tkElif, " elif")
gcond(g, n[0])
putWithSpace(g, tkColon, ":")
gsub(g, n, 1)
of nkElseExpr, nkElse:
if isEmptyType(n[0].typ):
optNL(g)
put(g, tkElse, "else")
putWithSpace(g, tkColon, ":")
gcoms(g)
gstmts(g, n[0], c)
else:
put(g, tkElse, " else")
putWithSpace(g, tkColon, ":")
gsub(g, n, 0)
of nkTypeOfExpr:
put(g, tkType, "typeof")
put(g, tkParLe, "(")
@@ -1729,19 +1750,6 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkMixinStmt:
putWithSpace(g, tkMixin, "mixin")
gcomma(g, n, c)
of nkElifBranch:
optNL(g)
putWithSpace(g, tkElif, "elif")
gsub(g, n, 0)
putWithSpace(g, tkColon, ":")
gcoms(g)
gstmts(g, n[1], c)
of nkElse:
optNL(g)
put(g, tkElse, "else")
putWithSpace(g, tkColon, ":")
gcoms(g)
gstmts(g, n[0], c)
of nkFinally, nkDefer:
optNL(g)
if n.kind == nkFinally:

View File

@@ -1345,7 +1345,9 @@ proc readTypeParameter(c: PContext, typ: PType,
# This seems semantically correct and then we'll be able
# to return the section symbol directly here
let foundType = makeTypeDesc(c, def[2].typ)
return newSymNode(copySym(def[0].sym, c.idgen).linkTo(foundType), info)
let s = copySym(def[0].sym, c.idgen)
s.typ = foundType
return newSymNode(s, info)
of nkConstSection:
for def in statement:
@@ -1370,7 +1372,9 @@ proc readTypeParameter(c: PContext, typ: PType,
return c.graph.emptyNode
else:
let foundTyp = makeTypeDesc(c, rawTyp)
return newSymNode(copySym(tParam.sym, c.idgen).linkTo(foundTyp), info)
let s = copySym(tParam.sym, c.idgen)
s.typ = foundTyp
return newSymNode(s, info)
return nil

View File

@@ -757,7 +757,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
of nkCast:
var a = getConstExpr(m, n[1], idgen, g)
if a == nil: return
if n.typ != nil and n.typ.kind in NilableTypes:
if n.typ != nil and n.typ.kind in NilableTypes and
not (n.typ.kind == tyProc and a.typ.kind == tyProc):
# we allow compile-time 'cast' for pointer types:
result = a
result.typ = n.typ

View File

@@ -11,7 +11,7 @@ import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
wordrecg, strutils, options, guards, lineinfos, semfold, semdata,
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling, tables,
semstrictfuncs
semstrictfuncs, lowerings
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -89,10 +89,11 @@ const
errXCannotBeAssignedTo = "'$1' cannot be assigned to"
errLetNeedsInit = "'let' symbol requires an initialization"
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
if typ == nil or sfGeneratedOp in tracked.owner.flags:
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo; explicit = false) =
if typ == nil or (sfGeneratedOp in tracked.owner.flags and not explicit):
# don't create type bound ops for anything in a function with a `nodestroy` pragma
# bug #21987
# unless this is an explicit call, bug #24626
return
when false:
let realType = typ.skipTypes(abstractInst)
@@ -926,10 +927,17 @@ proc trackCall(tracked: PEffects; n: PNode) =
# rebind type bounds operations after createTypeBoundOps call
let t = n[1].typ.skipTypes({tyAlias, tyVar})
if a.sym != getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind)):
createTypeBoundOps(tracked, t, n.info)
createTypeBoundOps(tracked, t, n.info, explicit = true)
let op = getAttachedOp(tracked.graph, t, TTypeAttachedOp(opKind))
if op != nil:
n[0].sym = op
if TTypeAttachedOp(opKind) == attachedDestructor and
op.typ.len == 2 and op.typ.firstParamType.kind != tyVar:
if n[1].kind == nkSym and n[1].sym.kind == skParam and
n[1].typ.kind == tyVar:
n[1] = genDeref(n[1])
else:
n[1] = skipAddr(n[1])
if op != nil and op.kind == tyProc:
for i in 1..<min(n.safeLen, op.len):

View File

@@ -1719,6 +1719,17 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
# check the style here after the pragmas have been processed:
styleCheckDef(c, s)
# compute the type's size and check for illegal recursions:
if a[0].kind == nkPragmaExpr:
let pragmas = a[0][1]
for i in 0 ..< pragmas.len:
if pragmas[i].kind == nkExprColonExpr and
pragmas[i][0].kind == nkIdent and
whichKeyword(pragmas[i][0].ident) == wSize:
if s.typ.kind != tyEnum and sfImportc notin s.flags:
# EventType* {.size: sizeof(uint32).} = enum
# AtomicFlag* {.importc: "atomic_flag", header: "<stdatomic.h>", size: 1.} = object
localError(c.config, pragmas[i].info, "size pragma only allowed for enum types and imported types")
if a[1].kind == nkEmpty:
var x = a[2]
if x.kind in nkCallKinds and nfSem in x.flags:

View File

@@ -66,7 +66,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
if not isField or sfGenSym notin s.flags:
result = newSymNode(s, info)
markUsed(c, info, s)
if isField:
# possibly not final field sym
incl(s.flags, sfUsed)
markOwnerModuleAsUsed(c, s)
else:
markUsed(c, info, s)
onUse(info, s)
else:
result = n

View File

@@ -107,6 +107,13 @@ proc transformSons(c: PTransf, n: PNode, noConstFold = false): PNode =
for i in 0..<n.len:
result[i] = transform(c, n[i], noConstFold)
proc transformSonsAfterType(c: PTransf, n: PNode, noConstFold = false): PNode =
result = newTransNode(n)
assert n.len != 0
result[0] = copyTree(n[0])
for i in 1..<n.len:
result[i] = transform(c, n[i], noConstFold)
proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PNode; isFirstWrite: bool): PNode =
result = newTransNode(kind, ri.info, 2)
result[0] = le
@@ -835,9 +842,18 @@ proc transformArrayAccess(c: PTransf, n: PNode): PNode =
if n[0].kind == nkSym and n[0].sym.kind == skType:
result = n
else:
result = newTransNode(n)
for i in 0..<n.len:
result[i] = transform(c, skipConv(n[i]))
result = transformSons(c, n)
if n.len >= 2 and result[1].kind in {nkChckRange, nkChckRange64} and
n[1].kind in {nkHiddenStdConv, nkHiddenSubConv}:
# implicit conversion, was transformed into range check
# remove in favor of index check if conversion to array index type
# has to be done here because the array index type needs to be relaxed
# i.e. a uint32 index can implicitly convert to range[0..3] but not int
let arr = skipTypes(n[0].typ, abstractVarRange)
if arr.kind == tyArray and
firstOrd(c.graph.config, arr) == getOrdValue(result[1][1]) and
lastOrd(c.graph.config, arr) == getOrdValue(result[1][2]):
result[1] = result[1].skipConv
proc getMergeOp(n: PNode): PSym =
case n.kind
@@ -1058,6 +1074,9 @@ proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = transformConv(c, n)
of nkObjConstr, nkCast:
# don't try to transform type node
result = transformSonsAfterType(c, n)
of nkDiscardStmt:
result = n
if n[0].kind != nkEmpty:

View File

@@ -12,7 +12,7 @@
import semmacrosanity
import
std/[strutils, tables, parseutils],
std/[strutils, tables, intsets, parseutils],
msgs, vmdef, vmgen, nimsets, types,
parser, vmdeps, idents, trees, renderer, options, transf,
gorgeimpl, lineinfos, btrees, macrocacheimpl,
@@ -1837,7 +1837,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen)
else:
stackTrace(c, tos, pc, "node has no type")
else:
of 3:
# getTypeImpl opcode:
ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
@@ -1846,6 +1846,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen)
else:
stackTrace(c, tos, pc, "node has no type")
else:
# getTypeInstSkipAlias opcode:
ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen, skipAlias = true)
elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen, skipAlias = true)
else:
stackTrace(c, tos, pc, "node has no type")
of opcNGetSize:
decodeBImm(rkInt)
let n = regs[rb].node
@@ -2375,8 +2384,11 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator;
setupGlobalCtx(module, g, idgen)
var c = PCtx g.vm
let oldMode = c.mode
let oldLocals = c.locals
c.mode = mode
c.locals = initIntSet()
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
c.locals = oldLocals
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
assert c.code[start].opcode != opcEof
when debugEchoCode: c.echoCode start

View File

@@ -10,7 +10,7 @@
## This module contains the type definitions for the new evaluation engine.
## An instruction is 1-3 int32s in memory, it is a register based VM.
import std/[tables, strutils]
import std/[tables, strutils, intsets]
import ast, idents, options, modulegraphs, lineinfos
@@ -270,6 +270,7 @@ type
templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst
vmstateDiff*: seq[(PSym, PNode)] # we remember the "diff" to global state here (feature for IC)
procToCodePos*: Table[int, int]
locals*: IntSet
PStackFrame* = ref TStackFrame
TStackFrame* {.acyclic.} = object

View File

@@ -40,7 +40,7 @@ proc atomicTypeX(s: PSym; info: TLineInfo): PNode =
result.info = info
proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator;
inst=false; allowRecursionX=false): PNode
inst=false; allowRecursionX=false; skipAlias = false): PNode
proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo;
idgen: IdGenerator;
@@ -68,7 +68,7 @@ proc objectNode(cache: IdentCache; n: PNode; idgen: IdGenerator): PNode =
proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
idgen: IdGenerator;
inst=false; allowRecursionX=false): PNode =
inst=false; allowRecursionX=false; skipAlias = false): PNode =
var allowRecursion = allowRecursionX
template atomicType(name, m): untyped = atomicTypeX(cache, name, m, t, info, idgen)
template atomicType(s): untyped = atomicTypeX(s, info)
@@ -89,7 +89,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
id
template newIdentDefs(s): untyped = newIdentDefs(s, s.typ)
if inst and not allowRecursion and t.sym != nil:
if inst and not allowRecursion and t.sym != nil and
not (skipAlias and t.kind == tyAlias):
# getTypeInst behavior: return symbol
return atomicType(t.sym)
@@ -122,7 +123,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
if t.base != nil:
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
result.add atomicType("typeDesc", mTypeDesc)
result.add mapTypeToAst(t.base, info)
result.add mapTypeToAstX(cache, t.base, info, idgen, inst, skipAlias = skipAlias)
else:
result = atomicType("typeDesc", mTypeDesc)
of tyGenericInvocation:
@@ -151,7 +152,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
else:
result = mapTypeToAst(t.lastSon, info)
of tyAlias:
result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion)
result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion, skipAlias = skipAlias)
of tyOrdinal:
result = mapTypeToAst(t.lastSon, info)
of tyDistinct:
@@ -316,8 +317,9 @@ proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGene
# the "Inst" version includes generic parameters in the resulting type tree
# and also tries to look like the corresponding Nim type declaration
proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode =
result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false)
proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; skipAlias = false): PNode =
# skipAlias: skips aliases and typedesc
result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false, skipAlias = skipAlias)
# the "Impl" version includes generic parameters in the resulting type tree
# and also tries to look like the corresponding Nim type implementation

View File

@@ -1324,7 +1324,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
of "getType": 0
of "typeKind": 1
of "getTypeInst": 2
else: 3 # "getTypeImpl"
of "getTypeImpl": 3 # "getTypeImpl"
else: 4 # getTypeInstSkipAlias
c.gABC(n, opcNGetType, dest, tmp, rc)
c.freeTemp(tmp)
#genUnaryABC(c, n, dest, opcNGetType)
@@ -1559,6 +1560,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
# are in the right scope:
if sfGenSym in s.flags and c.prc.sym == nil: discard
elif s.kind == skParam and s.typ.kind == tyTypeDesc: discard
elif s.kind in {skVar, skLet} and s.id in c.locals: discard
else: cannotEval(c, n)
elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags:
@@ -1948,7 +1950,7 @@ proc genVarSection(c: PCtx; n: PNode) =
c.gen(lowerTupleUnpacking(c.graph, a, c.idgen, c.getOwner))
elif a[0].kind == nkSym:
let s = a[0].sym
checkCanEval(c, a[0])
c.locals.incl(s.id)
if s.isGlobal:
let runtimeAccessToCompileTime = c.mode == emRepl and
sfCompileTime in s.flags and s.position > 0
@@ -2013,7 +2015,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
let intType = getSysType(c.graph, n.info, tyInt)
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
let seqType = n.typ.skipTypes(abstractVar+{tyStatic}-{tyTypeDesc})
if seqType.kind == tySequence:
var tmp = c.getTemp(intType)
c.gABx(n, opcLdImmInt, tmp, n.len)

View File

@@ -5096,22 +5096,22 @@ caught by reference. Example:
proc fn() =
let a = initRuntimeError("foo")
doAssert $a.what == "foo"
var b: cstring
var b = ""
try: raise initRuntimeError("foo2")
except CStdException as e:
doAssert e is CStdException
b = e.what()
doAssert $b == "foo2"
b = $e.what()
doAssert b == "foo2"
try: raise initStdException()
except CStdException: discard
try: raise initRuntimeError("foo3")
except CRuntimeError as e:
b = e.what()
b = $e.what()
except CStdException:
doAssert false
doAssert $b == "foo3"
doAssert b == "foo3"
fn()
```

View File

@@ -11,13 +11,13 @@
const
# examples of possible values for repos: Head, ea82b54
NimbleStableCommit = "123f97a5e4ee9ba35720c0869e19a047c43c797e" # 0.16.4
NimbleStableCommit = "6a2486b597132340ea7422b078c769b58f21d16d" # 0.20.0
AtlasStableCommit = "5faec3e9a33afe99a7d22377dd1b45a5391f5504"
ChecksumsStableCommit = "bd9bf4eaea124bf8d01e08f92ac1b14c6879d8d3"
ChecksumsStableCommit = "f8f6bd34bfa3fe12c64b919059ad856a96efcba0" # 2.0.1
SatStableCommit = "faf1617f44d7632ee9601ebc13887644925dcc01"
# examples of possible values for fusion: #head, #ea82b54, 1.2.3
FusionStableHash = "#372ee4313827ef9f2ea388840f7d6b46c2b1b014"
FusionStableHash = "#562467452b32cb7a97410ea177f083e6d8405734"
HeadHash = "#head"
when not defined(windows):
const

View File

@@ -1574,10 +1574,13 @@ proc extractTypeImpl(n: NimNode): NimNode =
result = n[2]
else: error("Invalid node to retrieve type implementation of: " & $n.kind)
proc getTypeInstSkipAlias(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
proc customPragmaNode(n: NimNode): NimNode =
expectKind(n, {nnkSym, nnkDotExpr, nnkBracketExpr, nnkTypeOfExpr, nnkType, nnkCheckedFieldExpr})
let
typ = n.getTypeInst()
let typ = n.getTypeInstSkipAlias()
if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy:
return typ[1][1]

View File

@@ -215,6 +215,11 @@ when defined(osx): # 2001 POSIX evidently does not concern Apple
# present size & has no good reason to call this unless it is growing.
if fcntl(a1, F_PREALLOCATE, fst.addr) != cint(-1): ftruncate(a1, a2 + a3)
else: cint(-1)
elif defined(openbsd):
proc posix_fallocate*(a1: cint, a2, a3: Off): cint =
# above assumption: "has no good reason to call this unless it is growing."
# man ftruncate "it will be extended as if by writing bytes with the value zero."
return ftruncate(a1, a2 + a3)
else:
proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
importc, header: "<fcntl.h>".}

View File

@@ -514,7 +514,6 @@ proc parseSaturatedNatural*(s: openArray[char], b: var int): int {.
proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
var
res = 0.BiggestUInt
prev = 0.BiggestUInt
i = 0
if i < s.len - 1 and s[i] == '-' and s[i + 1] in {'0'..'9'}:
integerOutOfRangeError()
@@ -522,8 +521,11 @@ proc rawParseUInt(s: openArray[char], b: var BiggestUInt): int =
if i < s.len and s[i] in {'0'..'9'}:
b = 0
while i < s.len and s[i] in {'0'..'9'}:
prev = res
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
if res > BiggestUInt.high div 10: # Highest value that you can multiply 10 without overflow
integerOutOfRangeError()
res = res * 10
let prev = res
res += (ord(s[i]) - ord('0')).BiggestUInt
if prev > res:
integerOutOfRangeError()
inc(i)

View File

@@ -25,6 +25,9 @@ export ReadDirEffect, WriteDirEffect
type
Path* = distinct string
template `$`*(x: Path): string =
string(x)
func `==`*(x, y: Path): bool {.inline.} =
## Compares two paths.
##

View File

@@ -14,6 +14,8 @@ at offset 0 then. The ``ref`` object header is independent from the
runtime type and only contains a reference count.
]#
{.push raises: [].}
when defined(gcOrc):
const
rcIncrement = 0b10000 # so that lowest 4 bits are not touched
@@ -72,6 +74,9 @@ else:
template count(x: Cell): untyped =
x.rc shr rcShift
when not defined(nimHasQuirky):
{.pragma: quirky.}
proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
let hdrSize = align(sizeof(RefHeader), alignment)
let s = size + hdrSize
@@ -173,7 +178,7 @@ proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} =
template `=dispose`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
#proc dispose*(x: pointer) = nimRawDispose(x)
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, quirky, raises: [].} =
let rti = cast[ptr PNimTypeV2](p)
if rti.destructor != nil:
cast[DestructorProc](rti.destructor)(p)
@@ -236,3 +241,5 @@ template tearDownForeignThreadGc* =
proc isObjDisplayCheck(source: PNimTypeV2, targetDepth: int16, token: uint32): bool {.compilerRtl, inl.} =
result = targetDepth <= source.depth and source.display[targetDepth] == token
{.pop.} # raises: []

View File

@@ -252,12 +252,12 @@ iterator elementsExcept(t, s: CellSet): PCell {.inline.} =
var r = t.head
while r != nil:
let ss = cellSetGet(s, r.key)
var i:uint = 0
var i = 0'u
while int(i) <= high(r.bits):
var w = r.bits[i]
if ss != nil:
w = w and not ss.bits[i]
var j:uint = 0
var j = 0'u
while w != 0:
if (w and 1) != 0:
yield cast[PCell]((r.key shl PageShift) or

View File

@@ -10,7 +10,7 @@ const
## is the minor number of Nim's version.
## Odd for devel, even for releases.
NimPatch* {.intdefine.}: int = 14
NimPatch* {.intdefine.}: int = 17
## is the patch number of Nim's version.
## Odd for devel, even for releases.

View File

@@ -62,8 +62,8 @@ const
colorMask = 0b011
type
TraceProc = proc (p, env: pointer) {.nimcall, benign.}
DisposeProc = proc (p: pointer) {.nimcall, benign.}
TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].}
DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].}
template color(c): untyped = c.rc and colorMask
template setColor(c, col) =

View File

@@ -13,17 +13,24 @@ when not defined(nimPreviewSlimSystem):
## Outplace version of `addFloat`.
result.addFloat(x)
proc `$`*(x: int): string {.raises: [].} =
## Outplace version of `addInt`.
result.addInt(x)
template addIntAlias(T: typedesc) =
proc `$`*(x: T): string {.raises: [].} =
## Outplace version of `addInt`.
result = ""
result.addInt(x)
proc `$`*(x: int64): string {.raises: [].} =
## Outplace version of `addInt`.
result.addInt(x)
# need to declare for bit types as well to not clash with converters:
addIntAlias int
addIntAlias int8
addIntAlias int16
addIntAlias int32
addIntAlias int64
proc `$`*(x: uint64): string {.raises: [].} =
## Outplace version of `addInt`.
addInt(result, x)
addIntAlias uint
addIntAlias uint8
addIntAlias uint16
addIntAlias uint32
addIntAlias uint64
# same as old `ctfeWhitelist` behavior, whether or not this is a good idea.
template gen(T) =

View File

@@ -60,6 +60,7 @@ comparisons).
]#
{.push profiler:off.}
{.push raises: [].}
const
CycleIncrease = 2 # is a multiplicative increase
@@ -595,7 +596,13 @@ proc sweep(gch: var GcHeap) =
if isCell(x):
# cast to PCell is correct here:
var c = cast[PCell](x)
if c notin gch.marked: freeCyclicCell(gch, c)
if c notin gch.marked:
# Don't free objects that have the ZctFlag set (created in finalizers)
if (c.refcount and ZctFlag) == 0:
freeCyclicCell(gch, c)
else:
# Clear the ZctFlag for the next collection cycle
c.refcount = c.refcount and not ZctFlag
proc markS(gch: var GcHeap, c: PCell) =
gcAssert isAllocatedPtr(gch.region, c), "markS: foreign heap root detected A!"
@@ -906,4 +913,5 @@ when not defined(useNimRtl):
result.add "[GC] stack bottom: " & gch.stack.bottom.repr
result.add "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
{.pop.} # raises: []
{.pop.} # profiler: off, stackTrace: off

View File

@@ -25,33 +25,33 @@ when hasAlloc and not defined(js) and not usesDestructors:
proc GC_enable*() {.rtl, inl, benign, raises: [].}
## Enables the GC again.
proc GC_fullCollect*() {.rtl, benign.}
proc GC_fullCollect*() {.rtl, benign, raises: [].}
## Forces a full garbage collection pass.
## Ordinary code does not need to call this (and should not).
proc GC_enableMarkAndSweep*() {.rtl, benign.}
proc GC_disableMarkAndSweep*() {.rtl, benign.}
proc GC_enableMarkAndSweep*() {.rtl, benign, raises: [].}
proc GC_disableMarkAndSweep*() {.rtl, benign, raises: [].}
## The current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and
## sweep phase may take a long time and is not needed if the application
## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC.
proc GC_getStatistics*(): string {.rtl, benign.}
proc GC_getStatistics*(): string {.rtl, benign, raises: [].}
## Returns an informative string about the GC's activity. This may be useful
## for tweaking.
proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.}
proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.}
proc GC_ref*(x: string) {.magic: "GCref", benign.}
proc GC_ref*[T](x: ref T) {.magic: "GCref", benign, raises: [].}
proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign, raises: [].}
proc GC_ref*(x: string) {.magic: "GCref", benign, raises: [].}
## Marks the object `x` as referenced, so that it will not be freed until
## it is unmarked via `GC_unref`.
## If called n-times for the same object `x`,
## n calls to `GC_unref` are needed to unmark `x`.
proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.}
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.}
proc GC_unref*(x: string) {.magic: "GCunref", benign.}
proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign, raises: [].}
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign, raises: [].}
proc GC_unref*(x: string) {.magic: "GCunref", benign, raises: [].}
## See the documentation of `GC_ref <#GC_ref,string>`_.
proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign, raises: [].}

View File

@@ -14,6 +14,8 @@
# R.D. Lins / Information Processing Letters 109 (2008) 7178
#
{.push raises: [].}
include cellseqs_v2
const
@@ -27,8 +29,8 @@ const
logOrc = defined(nimArcIds)
type
TraceProc = proc (p, env: pointer) {.nimcall, benign.}
DisposeProc = proc (p: pointer) {.nimcall, benign.}
TraceProc = proc (p, env: pointer) {.nimcall, benign, raises: [].}
DisposeProc = proc (p: pointer) {.nimcall, benign, raises: [].}
template color(c): untyped = c.rc and colorMask
template setColor(c, col) =
@@ -520,3 +522,5 @@ proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerR
dec cell.rc, rcIncrement
#if cell.color == colPurple:
rememberCycle(result, cell, desc)
{.pop.} # raises: []

View File

@@ -14,21 +14,26 @@ proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".}
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
proc repr*(x: int): string =
## Same as $x
$x
template dollarAlias(T: typedesc) =
proc repr*(x: T): string {.noSideEffect.} =
## Same as $x
$x
proc repr*(x: int64): string =
## Same as $x
$x
# need to declare for bit types as well to not clash with converters:
dollarAlias int
dollarAlias int8
dollarAlias int16
dollarAlias int32
dollarAlias int64
proc repr*(x: uint64): string {.noSideEffect.} =
## Same as $x
$x
dollarAlias uint
dollarAlias uint8
dollarAlias uint16
dollarAlias uint32
dollarAlias uint64
proc repr*(x: float): string =
## Same as $x
$x
dollarAlias float
dollarAlias float32
proc repr*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## repr for a boolean argument. Returns `x`

View File

@@ -61,15 +61,25 @@ elif defined(netbsd):
result = threadId
elif defined(freebsd):
proc syscall(arg: cint, arg0: ptr cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
var SYS_thr_self {.importc:"SYS_thr_self", header:"<sys/syscall.h>".}: cint
when defined(amd64) or defined(i386):
const SYS_thr_self = 432
else:
var SYS_thr_self {.importc:"SYS_thr_self", header:"<sys/syscall.h>".}: cint
when defined(cpu64):
type
Off {.importc: "off_t", header: "<sys/types.h>".} = int64
Quad {.importc: "quad_t", header: "<sys/types.h>".} = int64
proc syscall(arg: Quad): Off {.varargs, importc: "__syscall", header: "<unistd.h>".}
else:
proc syscall(arg: cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
proc getThreadId*(): int =
## Gets the ID of the currently running thread.
var tid = 0.cint
var tid = when defined(cpu64): Off(0) else: cint(0)
if threadId == 0:
discard syscall(SYS_thr_self, addr tid)
threadId = tid
threadId = int(tid)
result = threadId
elif defined(macosx):

View File

@@ -83,7 +83,7 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string, isOrc =
if "boehm" notin options and not isOrc:
# hcr tests
testSpec r, makeTest("tests/dll/nimhcr_basic.nim", options & " --threads:off --forceBuild --hotCodeReloading:on " & rpath, cat)
# force build required - see the comments in the .nim file for more details
@@ -162,6 +162,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
test "stackrefleak"
test "cyclecollector"
testWithoutBoehm "trace_globals"
test "tfinalizers"
# ------------------------- threading tests -----------------------------------
@@ -446,7 +447,7 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
if pkg.allowFailure:
inc r.passed
inc r.failedButAllowed
addResult(r, test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
discard r.finishTest(test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
continue
outp
@@ -462,21 +463,21 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
discard tryCommand(cmds[i], maxRetries = 3)
discard tryCommand(cmds[^1], reFailed = reBuildFailed)
inc r.passed
r.addResult(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
discard r.finishTest(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
errors = r.total - r.passed
if errors == 0:
r.addResult(packageFileTest, targetC, "", "", "", reSuccess)
discard r.finishTest(packageFileTest, targetC, "", "", "", reSuccess)
else:
r.addResult(packageFileTest, targetC, "", "", "", reBuildFailed)
discard r.finishTest(packageFileTest, targetC, "", "", "", reBuildFailed)
except JsonParsingError:
errors = 1
r.addResult(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
discard r.finishTest(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
raise
except ValueError:
errors = 1
r.addResult(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
discard r.finishTest(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
raise # bug #18805
finally:
if errors == 0: removeDir(packagesDir)
@@ -565,6 +566,7 @@ proc isJoinableSpec(spec: TSpec): bool =
spec.err != reDisabled and
not spec.unjoinable and
spec.exitCode == 0 and
spec.retries == 0 and
spec.input.len == 0 and
spec.nimout.len == 0 and
spec.nimoutFull == false and

View File

@@ -152,7 +152,7 @@ pkg "sim"
pkg "smtp", "nimble compileExample"
pkg "snip", "nimble test", "https://github.com/genotrance/snip"
pkg "stew"
pkg "stint", "nim c stint.nim"
pkg "stint", "nimble test_internal"
pkg "strslice"
pkg "strunicode", "nim c -r --mm:refc src/strunicode.nim"
pkg "supersnappy"

View File

@@ -66,6 +66,11 @@ template enableRemoteNetworking*: bool =
## a `nim` invocation (possibly via additional intermediate processes).
getEnv("NIM_TESTAMENT_REMOTE_NETWORKING") == "1"
template disableSSLTesting*: bool =
## TODO: workaround for GitHub Action gcc 14 matrix; remove this
## matrix and the flag after Azure agent supports ubuntu 24.04
getEnv("NIM_TESTAMENT_DISABLE_SSL") == "1"
template whenRuntimeJs*(bodyIf, bodyElse) =
##[
Behaves as `when defined(js) and not nimvm` (which isn't legal yet).

View File

@@ -56,6 +56,7 @@ type
reJoined, # test is disabled because it was joined into the megatest
reSuccess # test was successful
reInvalidSpec # test had problems to parse the spec
reRetry # test is being retried
TTarget* = enum
targetC = "c"
@@ -102,6 +103,7 @@ type
# but don't rely on much precision
inlineErrors*: seq[InlineError] # line information to error message
debugInfo*: string # debug info to give more context
retries*: int # number of retry attempts after the test fails
proc getCmd*(s: TSpec): string =
if s.cmd.len == 0:
@@ -478,6 +480,8 @@ proc parseSpec*(filename: string): TSpec =
result.timeout = parseFloat(e.value)
except ValueError:
result.parseErrors.addLine "cannot interpret as a float: ", e.value
of "retries":
discard parseInt(e.value, result.retries)
of "targets", "target":
try:
result.targets.incl parseTargets(e.value)

View File

@@ -272,16 +272,13 @@ proc testName(test: TTest, target: TTarget, extraOptions: string, allowFailure:
name.strip()
proc addResult(r: var TResults, test: TTest, target: TTarget,
extraOptions, expected, given: string, successOrig: TResultEnum,
extraOptions, expected, given: string, success: TResultEnum, duration: float,
allowFailure = false, givenSpec: ptr TSpec = nil) =
# instead of `ptr TSpec` we could also use `Option[TSpec]`; passing `givenSpec` makes it easier to get what we need
# instead of having to pass individual fields, or abusing existing ones like expected vs given.
# test.name is easier to find than test.name.extractFilename
# A bit hacky but simple and works with tests/testament/tshould_not_work.nim
let name = testName(test, target, extraOptions, allowFailure)
let duration = epochTime() - test.startTime
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
else: successOrig
let durationStr = duration.formatFloat(ffDecimal, precision = 2).align(5)
if backendLogging:
@@ -342,6 +339,18 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
discard waitForExit(p)
close(p)
proc finishTest(r: var TResults, test: TTest, target: TTarget,
extraOptions, expected, given: string, successOrig: TResultEnum,
allowFailure = false, givenSpec: ptr TSpec = nil): bool =
result = false
let duration = epochTime() - test.startTime
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
else: successOrig
if test.spec.retries > 0 and success notin {reSuccess, reDisabled, reJoined, reInvalidSpec}:
return true
else:
addResult(r, test, target, extraOptions, expected, given, success, duration, allowFailure, givenSpec)
proc toString(inlineError: InlineError, filename: string): string =
result.add "$file($line, $col) $kind: $msg" % [
"file", filename,
@@ -370,23 +379,23 @@ proc nimoutCheck(expected, given: TSpec): bool =
result = false
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest,
target: TTarget, extraOptions: string) =
target: TTarget, extraOptions: string): bool =
if not checkForInlineErrors(expected, given) or
(not expected.nimoutFull and not nimoutCheck(expected, given)):
r.addResult(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
result = r.finishTest(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
elif strip(expected.msg) notin strip(given.msg):
r.addResult(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
result = r.finishTest(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
elif not nimoutCheck(expected, given):
r.addResult(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
result = r.finishTest(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
elif extractFilename(expected.file) != extractFilename(given.file) and
"internal error:" notin expected.msg:
r.addResult(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
result = r.finishTest(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
elif expected.line != given.line and expected.line != 0 or
expected.column != given.column and expected.column != 0:
r.addResult(test, target, extraOptions, $expected.line & ':' & $expected.column,
result = r.finishTest(test, target, extraOptions, $expected.line & ':' & $expected.column,
$given.line & ':' & $given.column, reLinesDiffer)
else:
r.addResult(test, target, extraOptions, expected.msg, given.msg, reSuccess)
result = r.finishTest(test, target, extraOptions, expected.msg, given.msg, reSuccess)
inc(r.passed)
proc generatedFile(test: TTest, target: TTarget): string =
@@ -425,7 +434,7 @@ proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var st
echo getCurrentExceptionMsg()
proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
given: var TSpec, expected: TSpec; r: var TResults) =
given: var TSpec, expected: TSpec; r: var TResults): bool =
var expectedmsg: string = ""
var givenmsg: string = ""
if given.err == reSuccess:
@@ -440,7 +449,7 @@ proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
else:
givenmsg = "$ " & given.cmd & '\n' & given.nimout
if given.err == reSuccess: inc(r.passed)
r.addResult(test, target, extraOptions, expectedmsg, givenmsg, given.err)
result = r.finishTest(test, target, extraOptions, expectedmsg, givenmsg, given.err)
proc getTestSpecTarget(): TTarget =
if getEnv("NIM_COMPILE_TO_CPP", "false") == "true":
@@ -456,31 +465,38 @@ proc equalModuloLastNewline(a, b: string): bool =
proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
target: TTarget, extraOptions: string, nimcache: string) =
test.startTime = epochTime()
template maybeRetry(x: bool) =
if x:
test.spec.err = reRetry
dec test.spec.retries
testSpecHelper(r, test, expected, target, extraOptions, nimcache)
return
if test.spec.err != reRetry:
test.startTime = epochTime()
if testName(test, target, extraOptions, false) in skips:
test.spec.err = reDisabled
if test.spec.err in {reDisabled, reJoined}:
r.addResult(test, target, extraOptions, "", "", test.spec.err)
discard r.finishTest(test, target, extraOptions, "", "", test.spec.err)
inc(r.skipped)
return
var given = callNimCompiler(expected.getCmd, test.name, test.options, nimcache, target, extraOptions)
case expected.action
of actionCompile:
compilerOutputTests(test, target, extraOptions, given, expected, r)
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
of actionRun:
if given.err != reSuccess:
r.addResult(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
maybeRetry r.finishTest(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
else:
let isJsTarget = target == targetJS
var exeFile = changeFileExt(test.name, if isJsTarget: "js" else: ExeExt)
if not fileExists(exeFile):
r.addResult(test, target, extraOptions, expected.output,
maybeRetry r.finishTest(test, target, extraOptions, expected.output,
"executable not found: " & exeFile, reExeNotFound)
else:
let nodejs = if isJsTarget: findNodeJs() else: ""
if isJsTarget and nodejs == "":
r.addResult(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
maybeRetry r.finishTest(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
reExeNotFound)
else:
var exeCmd: string
@@ -512,19 +528,19 @@ proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
buf
if exitCode != expected.exitCode:
given.err = reExitcodesDiffer
r.addResult(test, target, extraOptions, "exitcode: " & $expected.exitCode,
maybeRetry r.finishTest(test, target, extraOptions, "exitcode: " & $expected.exitCode,
"exitcode: " & $exitCode & "\n\nOutput:\n" &
bufB, reExitcodesDiffer)
elif (expected.outputCheck == ocEqual and not expected.output.equalModuloLastNewline(bufB)) or
(expected.outputCheck == ocSubstr and expected.output notin bufB):
given.err = reOutputsDiffer
r.addResult(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
compilerOutputTests(test, target, extraOptions, given, expected, r)
maybeRetry r.finishTest(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
of actionReject:
# Make sure its the compiler rejecting and not the system (e.g. segfault)
cmpMsgs(r, expected, given, test, target, extraOptions)
maybeRetry cmpMsgs(r, expected, given, test, target, extraOptions)
if given.exitCode != QuitFailure:
r.addResult(test, target, extraOptions, "exitcode: " & $QuitFailure,
maybeRetry r.finishTest(test, target, extraOptions, "exitcode: " & $QuitFailure,
"exitcode: " & $given.exitCode & "\n\nOutput:\n" &
given.nimout, reExitcodesDiffer)
@@ -532,7 +548,7 @@ proc targetHelper(r: var TResults, test: TTest, expected: TSpec, extraOptions: s
for target in expected.targets:
inc(r.total)
if target notin gTargets:
r.addResult(test, target, extraOptions, "", "", reDisabled)
discard r.finishTest(test, target, extraOptions, "", "", reDisabled)
inc(r.skipped)
elif simulate:
inc count
@@ -546,7 +562,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) =
var expected = test.spec
if expected.parseErrors.len > 0:
# targetC is a lie, but a parameter is required
r.addResult(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
discard r.finishTest(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
inc(r.total)
return

View File

@@ -0,0 +1,20 @@
discard """
retries: 1
"""
import os
const tempFile = "tnotenoughretries_temp"
if not fileExists(tempFile):
writeFile(tempFile, "abc")
quit(1)
else:
let content = readFile(tempFile)
if content == "abc":
writeFile(tempFile, "def")
quit(1)
else:
# success
removeFile(tempFile)
discard

View File

@@ -160,3 +160,16 @@ block:
testCase()
main()
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)

View File

@@ -0,0 +1,39 @@
discard """
output: '''
destroying d
destroying c
destroying a 2
destroying d
destroying c
destroying a 1
'''
joinable: false
"""
type
Aaaa {.inheritable.} = object
vvvv: int
Bbbb = object of Aaaa
c: Cccc
d: Dddd
Cccc = object
Dddd = object
Holder = object
member: ref Aaaa
proc `=destroy`(v: Cccc) =
echo "destroying c"
proc `=destroy`(v: Dddd) =
echo "destroying d"
proc `=destroy`(v: Aaaa) =
echo "destroying a ", v.vvvv
func makeHolder(vvvv: int): ref Holder =
(ref Holder)(member: (ref Bbbb)(vvvv: vvvv))
block:
var v = makeHolder(1)
var v2 = makeHolder(2)

View File

@@ -0,0 +1,20 @@
# issue #24626
proc arrayWith2[T](y: T, size: static int): array[size, T] {.noinit, nodestroy, raises: [].} =
## Creates a new array filled with `y`.
for i in 0..size-1:
when defined(nimHasDup):
result[i] = `=dup`(y)
else:
wasMoved(result[i])
`=copy`(result[i], y)
proc useArray(x: seq[int]) =
var a = arrayWith2(x, 2)
proc main =
let x = newSeq[int](100)
for i in 0..5:
useArray(x)
main()

View File

@@ -9,7 +9,8 @@ var
try:
x_cursor = ("hi", 5)
if cond:
x_cursor = ("different", 54) else:
x_cursor = ("different", 54)
else:
x_cursor = ("string here", 80)
echo [
:tmpD = `$$`(x_cursor)

View File

@@ -128,7 +128,8 @@ if dirExists(this.value):
var :tmpD
par = (dir:
:tmpD = `=dup`(this.value)
:tmpD, front: "") else:
:tmpD, front: "")
else:
var
:tmpD_1
:tmpD_2

16
tests/arc/tvalgrind.nim Normal file
View File

@@ -0,0 +1,16 @@
discard """
cmd: "nim c --mm:orc -d:useMalloc $file"
valgrind: "true"
"""
import std/streams
proc foo() =
var name = newStringStream("2r2")
raise newException(ValueError, "sh")
try:
foo()
except:
discard

View File

@@ -0,0 +1,4 @@
block: # issue #17958
var mem: array[uint8, uint8]
let val = 0xffff'u16
discard mem[uint8 val] # Error: unhandled exception: index 65535 not in 0 .. 255 [IndexDefect]

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "index 2 not in 0 .. 1"
errormsg: "conversion from int literal(2) to range 0..1(int) is invalid"
line: 18
"""
block:

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "index 3 not in 0 .. 1"
errormsg: "conversion from int literal(3) to range 0..1(int) is invalid"
line: 9
"""

View File

@@ -1,6 +1,4 @@
discard """
# doesn't work on macos 13 seemingly due to libc++ linking issue https://stackoverflow.com/a/77375947
disabled: osx
targets: cpp
"""
@@ -18,21 +16,21 @@ proc initStdException(): CStdException {.importcpp: "std::exception()", construc
proc fn() =
let a = initRuntimeError("foo")
doAssert $a.what == "foo"
var b: cstring
var b = ""
try: raise initRuntimeError("foo2")
except CStdException as e:
doAssert e is CStdException
b = e.what()
doAssert $b == "foo2"
b = $e.what()
doAssert b == "foo2"
try: raise initStdException()
except CStdException: discard
try: raise initRuntimeError("foo3")
except CRuntimeError as e:
b = e.what()
b = $e.what()
except CStdException:
doAssert false
doAssert $b == "foo3"
doAssert b == "foo3"
fn()

View File

@@ -1,5 +1,6 @@
discard """
output: '''----1
output: '''
----1
myobj constructed
myobj destroyed
----2
@@ -14,8 +15,8 @@ mygeneric3 constructed
mygeneric1 destroyed
----5
mydistinctObj constructed
myobj destroyed
mygeneric2 destroyed
myobj destroyed
------------------8
mygeneric1 destroyed
----6

View File

@@ -6,3 +6,26 @@ type DistinctSeq* = distinct seq[int]
# `=destroy`(cast[ptr DistinctSeq](0)[])
var x = @[].DistinctSeq
`=destroy`(x)
import std/options
# bug #24801
type
B[T] = object
case r: bool
of false:
v: ref int
of true:
x: T
E = distinct seq[int]
U = ref object of RootObj
G = ref object of U
proc a(): E = default(E)
method c(_: U): seq[E] {.base.} = discard
proc p(): seq[E] = c(default(U))
method c(_: G): seq[E] = discard E(newSeq[seq[int]](1)[0])
method y(_: U) {.base.} =
let s = default(B[tuple[f: B[int], w: B[int]]])
discard some(s.x)

View File

@@ -1,3 +1,7 @@
discard """
retries: 2
"""
# -*- nim -*-
import os, strutils

View File

@@ -1,6 +1,7 @@
discard """
outputsub: "true"
disabled: "32bit"
retries: 2
"""
type

View File

@@ -1,3 +1,6 @@
discard """
retries: 2
"""
# Program to detect bug #1796 reliably

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
type

View File

@@ -6,6 +6,7 @@ Hello from thread
Hello from thread
'''
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
retries: 2
"""
# Copied from stdlib
import strutils

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "Success!"
retries: 2
"""
# This is adapted from a benchmark written by John Ellis and Pete Kovac

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "77\n77"
retries: 2
"""
## Check how GC/Alloc works in Emscripten

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
when defined(GC_setMaxPause):

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
when defined(GC_setMaxPause):

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
when defined(GC_setMaxPause):

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
type

View File

@@ -1,5 +1,6 @@
discard """
output: "success"
retries: 2
"""
import os, times

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "finished"
retries: 2
"""
# Test the garbage collector.

View File

@@ -1,3 +1,7 @@
discard """
retries: 2
"""
import std/[cgi, strtabs]
proc handleRequest(query: string): StringTableRef =

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
type

View File

@@ -1,5 +1,6 @@
discard """
outputsub: "no leak: "
retries: 2
"""
type

View File

@@ -1,5 +1,6 @@
discard """
joinable: false
retries: 2
"""
import std/asyncdispatch

19
tests/gc/tfinalizers.nim Normal file
View File

@@ -0,0 +1,19 @@
type
PNode = ref TNode
TNode = object
le: PNode
proc finalizeNode(n: PNode) =
var s = @[0]
proc returnTree() =
var cycle: PNode
new(cycle, finalizeNode)
cycle.le = cycle
for i in 1..100:
returnTree()
GC_fullCollect()
GC_fullCollect()

View File

@@ -8,6 +8,7 @@ Performing Loop Recognition
Another 3 iterations...
...
Found 1 loops (including artificial root node) (3)'''
retries: 2
"""
# bug #3184

View File

@@ -1,5 +1,6 @@
discard """
output: '''Success'''
retries: 2
"""
# bug #3793

View File

@@ -3,6 +3,7 @@ discard """
10000000
10000000
10000000'''
retries: 2
"""
# bug #17085

View File

@@ -4,6 +4,7 @@ discard """
finalized
finalized
'''
retries: 2
"""
proc finish(o: RootRef) =

View File

@@ -1,5 +1,6 @@
discard """
output: "true"
retries: 2
"""
import intsets

View File

@@ -0,0 +1,7 @@
# issue #24859
template u(): int =
yield 0
0
iterator s(): int {.closure.} = discard default(typeof(u()))
let _ = s

View File

@@ -5,5 +5,6 @@ discard """
"""
var s = ['a']
let z = s[10000] == 'a'
echo z
let i = 10000
let z = s[i] == 'a'
echo z

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

@@ -14,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)
@@ -29,4 +33,5 @@ proc main =
block: # SSL certificate check integration tests
runCmd fmt"{nim} r {options} -d:ssl --threads:on --mm:refc {testsDir}/untestable/thttpclient_ssl_remotenetwork.nim"
main()
when not disableSSLTesting():
main()

View File

@@ -1,6 +1,7 @@
discard """
action: compile
disabled: "windows"
disabled: osx
"""
import sfml, os

30
tests/objects/t24847.nim Normal file
View File

@@ -0,0 +1,30 @@
# issue #24847
block: # original issue test
type
R[C] = ref object of RootObj
b: C
K[S] = ref object of R[S]
W[J] = object
case y: bool
of false, true: discard
proc e[T]() = discard K[T]()
iterator h(): int {.closure.} = e[W[int]]()
let _ = h
type U = distinct int
e[W[U]]()
block: # simplified
type
R[C] = ref object of RootObj
b: C
K[S] = ref object of R[S]
W[J] = object
case y: bool
of false, true: discard
type U = distinct int
discard K[W[int]]()
discard K[W[U]]()

View File

@@ -531,3 +531,13 @@ block:
check(a)
check(b)
block:
template p {.pragma.}
func foo[T0](v: T0): bool =
type T = T0
T.hasCustomPragma(p)
type X {.p.} = object
doAssert foo(X())

View File

@@ -0,0 +1,13 @@
# issue #23713
import std/macros
template p {.pragma.}
type
X {.p.} = object
Y[T] = object
t: T
doAssert Y[X].T.hasCustomPragma(p)

View File

@@ -1,6 +1,7 @@
discard """
cmd: "nim $target --mm:refc -d:ssl $options $file"
disabled: "openbsd"
retries: 2
"""
# Nim - Basic SSL integration tests
@@ -13,7 +14,10 @@ discard """
## Test with:
## ./bin/nim c -d:ssl -p:. --threads:on -r tests/stdlib/thttpclient_ssl.nim
when not defined(windows):
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

View File

@@ -6,6 +6,54 @@ import unittest, strutils
block: # parseutils
check: parseBiggestUInt("0") == 0'u64
check: parseBiggestUInt("1") == 1'u64
check: parseBiggestUInt("2") == 2'u64
check: parseBiggestUInt("10") == 10'u64
check: parseBiggestUInt("11") == 11'u64
check: parseBiggestUInt("99") == 99'u64
check: parseBiggestUInt("123") == 123'u64
check: parseBiggestUInt("9876") == 9876'u64
check: parseBiggestUInt("1_234") == 1234'u64
check: parseBiggestUInt("123__4") == 1234'u64
for i in 1.BiggestUInt .. 9.BiggestUInt:
var x = i
for j in 1 .. 19:
check parseBiggestUInt((i + '0'.uint).char.repeat j) == x
x *= 10
x += i
check: parseBiggestUInt("18446744073709551609") == 0xFFFF_FFFF_FFFF_FFF9'u64
check: parseBiggestUInt("18446744073709551610") == 0xFFFF_FFFF_FFFF_FFFA'u64
check: parseBiggestUInt("18446744073709551611") == 0xFFFF_FFFF_FFFF_FFFB'u64
check: parseBiggestUInt("18446744073709551612") == 0xFFFF_FFFF_FFFF_FFFC'u64
check: parseBiggestUInt("18446744073709551613") == 0xFFFF_FFFF_FFFF_FFFD'u64
check: parseBiggestUInt("18446744073709551614") == 0xFFFF_FFFF_FFFF_FFFE'u64
check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
expect(ValueError):
discard parseBiggestUInt("18446744073709551616")
expect(ValueError):
discard parseBiggestUInt("18446744073709551617")
expect(ValueError):
discard parseBiggestUInt("18446744073709551618")
expect(ValueError):
discard parseBiggestUInt("18446744073709551619")
expect(ValueError):
discard parseBiggestUInt("18446744073709551620")
expect(ValueError):
discard parseBiggestUInt("18446744073709551621")
expect(ValueError):
discard parseBiggestUInt("18446744073709551622")
expect(ValueError):
discard parseBiggestUInt("18446744073709551623")
expect(ValueError):
for i in 0 .. 999:
discard parseBiggestUInt("18446744073709552" & intToStr(i, 3))
expect(ValueError):
discard parseBiggestUInt("22751622367522324480000000")
expect(ValueError):
discard parseBiggestUInt("41404969074137497600000000")
expect(ValueError):
discard parseBiggestUInt("20701551093035827200000000000000000")
expect(ValueError):
discard parseBiggestUInt("225462255024603136000000000000000000")
expect(ValueError):
discard parseBiggestUInt("204963831854661632000000000000000000")

View File

@@ -326,3 +326,27 @@ do:
static: main()
main()
import std/macros
# bug #24850
macro a() =
let
y = quote do: discard
b = nnkIfStmt.newTree(
nnkElifExpr.newTree(ident "true", y), nnkElseExpr.newTree(y))
d = nnkWhenStmt.newTree(
nnkElifExpr.newTree(ident "true", y), nnkElseExpr.newTree(y))
doAssert repr(b) == """
if true:
discard
else:
discard"""
doAssert repr(d) == """
when true:
discard
else:
discard"""
a()

View File

@@ -0,0 +1,5 @@
# issue #24864
type S = distinct uint16
converter d(field: uint8 | uint16): S = discard
discard (repr(0'u16), repr(0'u8))

View File

@@ -0,0 +1,9 @@
# issue #24657
proc g() {.error.} = discard
type T = object
g: int
template B(): untyped = typeof(T.g)
type _ = B()

View File

@@ -0,0 +1,15 @@
discard """
matrix: "--skipParentCfg"
"""
# issue #24631
type
V[d: static bool] = object
l: int
template y(): V[false] = V[false](l: 0)
discard y()
template z(): V[false] = cast[V[false]](V[false](l: 0))
discard z()

View File

@@ -0,0 +1,20 @@
discard """
retries: 2
"""
import os
const tempFile = "tretries_temp"
if not fileExists(tempFile):
writeFile(tempFile, "abc")
quit(1)
else:
let content = readFile(tempFile)
if content == "abc":
writeFile(tempFile, "def")
quit(1)
else:
# success
removeFile(tempFile)
discard

View File

@@ -24,6 +24,8 @@ FAIL: tests/shouldfail/tnimout.nim
Failure: reMsgsDiffer
FAIL: tests/shouldfail/tnimoutfull.nim
Failure: reMsgsDiffer
FAIL: tests/shouldfail/tnotenoughretries.nim
Failure: reExitcodesDiffer
FAIL: tests/shouldfail/toutput.nim
Failure: reOutputsDiffer
FAIL: tests/shouldfail/toutputsub.nim
@@ -43,7 +45,7 @@ import stdtest/testutils
proc main =
const nim = getCurrentCompilerExe()
let testamentExe = "bin/testament"
let testamentExe = "testament/testament"
let cmd = fmt"{testamentExe} --directory:testament --colors:off --backendLogging:off --nim:{nim} category shouldfail"
let (outp, status) = execCmdEx(cmd)
doAssert status == 1, $status

View File

@@ -9,7 +9,8 @@
## nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:nimDisableCertificateValidation -d:ssl -p:. tests/untestable/thttpclient_ssl_disabled.nim
from stdtest/testutils import enableRemoteNetworking
when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(openbsd)):
# badssl tests disabled indefinitely
when false and enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(openbsd)):
import httpclient, net, unittest
const expired = "https://expired.badssl.com/"

View File

@@ -19,7 +19,6 @@ from net import newSocket, newContext, wrapSocket, connect, close, Port,
from strutils import contains
const
expired = "https://expired.badssl.com/"
good = "https://google.com/"
@@ -56,12 +55,13 @@ suite "SSL certificate check":
var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars)
ctx.wrapSocket(sock)
checkpoint("Socket created")
try:
sock.connect("expired.badssl.com", 443.Port)
fail()
except:
sock.close
check getCurrentExceptionMsg().contains("certificate verify failed")
when false: # badssl tests disabled indefinitely
try:
sock.connect("expired.badssl.com", 443.Port)
fail()
except:
sock.close
check getCurrentExceptionMsg().contains("certificate verify failed")
elif existsEnv("SSL_CERT_DIR"):
var sock = newSocket()

View File

@@ -33,7 +33,8 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win
CertTest = tuple[url:string, category:Category, desc: string]
# badssl certs sometimes expire, set to false when that happens
when true:
# badssl now disabled indefinitely
when false:
const certificate_tests: array[0..54, CertTest] = [
("https://wrong.host.badssl.com/", bad, "wrong.host"),
("https://captive-portal.badssl.com/", bad, "captive-portal"),
@@ -197,7 +198,7 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win
type NetSocketTest = tuple[hostname: string, port: Port, category:Category, desc: string]
# badssl certs sometimes expire, set to false when that happens
when true:
when false:
const net_tests:array[0..3, NetSocketTest] = [
("imap.gmail.com", 993.Port, good, "IMAP"),
("wrong.host.badssl.com", 443.Port, bad, "wrong.host"),

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