Compare commits

..

84 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
narimiran
bf4de6a394 bump NimVersion to 2.0.14 2024-12-23 08:07:41 +01:00
ringabout
86f1a2785a remove zippy data from tarballs (#24551)
fixes https://github.com/nim-lang/nightlies/issues/95

(cherry picked from commit 63c884038d)
2024-12-23 06:59:22 +01:00
ringabout
c7d057d7f9 fixes #24536; fixes nightlies regression caused by nimble update (#24542)
follow up #24537

Because `nimble` is a bundled repo so it is bundled in the tarballs

i.e.
82421fd705/.github/workflows/nightlies.yml (L264)
has bundled `dist/nimble`, but it only copies the data without `.git`.
So in this PR, we ignore bundled nimble repo.

(cherry picked from commit 70b3232d3a)
2024-12-23 06:58:25 +01:00
Juan M Gómez
8f44c40b6b Adds skipParentCfg back. Bump nimble to a commit where it doesnt rely in the parent config (#24545)
(cherry picked from commit 8ce58fab26)
2024-12-20 15:51:57 +01:00
Juan M Gómez
76935b4c34 (cherry picked from commit 556f217b4c) 2024-12-20 15:49:40 +01:00
Juan M Gómez
30abe60cda Bumps nimble v0.16.4 (#24437)
(cherry picked from commit be4d19e562)
2024-12-20 15:48:29 +01:00
ringabout
14dfabb230 fixes #24472; let symbol created by template is reused in nimvm branch (#24473)
fixes #24472

Excluding variables which are initialized in the nimvm branch so that
they won't interfere the other branch

(cherry picked from commit e7f48cdd5c)
2024-12-20 07:52:00 +01:00
ringabout
5fb4662ab1 fixes #18081; fixes #18079; fixes #18080; nested ref/deref'd types (#24335)
fixes #18081;
fixes https://github.com/nim-lang/Nim/issues/18080
fixes #18079

reverts https://github.com/nim-lang/Nim/pull/20738

It is probably more reasonable to use the type node from `nkObjConstr`
since it is barely changed unlike the external type, which is
susceptible to code transformation e.g. `addr(deref objconstr)`.

(cherry picked from commit aa90d00caf)
2024-12-20 05:33:40 +01:00
metagn
535556875e fix logic for dcEqIgnoreDistinct in sameType (#24197)
fixes #22523

There were 2 problems with the code in `sameType` for
`dcEqIgnoreDistinct`:

1. The code that skipped `{tyDistinct, tyGenericInst}` only ran if the
given types had different kinds. This is fixed by always performing this
skip.
2. The code block below that checks if `tyGenericInst`s have different
values still ran for `dcEqIgnoreDistinct` since it checks if the given
types are generic insts, not the skipped types (and also only the 1st
given type). This is fixed by only invoking this block for `dcEq`;
`dcEqOrDistinctOf` (which is unused) also skips the first given type.
Arguably there is another issue here that `skipGenericAlias` only ever
skips 1 type.

These combined fix the issue (`T` is `GenericInst(V, 1, distinct int)`
and `D[0]` is `GenericInst(D, 0, distinct int)`).

(cherry picked from commit b0e6d28782)
2024-12-20 05:30:27 +01:00
metagn
95fa7f0f12 make distinct conversions addressable in VM (#24124)
fixes #24097

For `nkConv` addresses where the conversion is between 2 types that are
equal between backends, treat assignments the same as assignments to the
argument of the conversion. In the VM this seems to be in `genAsgn` and
`genAsgnPatch`, as evidenced by the special logic for `nkDerefExpr` etc.

This doesn't handle ranges after #24037 because `sameBackendType` is
used and not `sameBackendTypeIgnoreRange`. This is so this is
backportable without #24037 and another PR can be opened that implements
it for ranges and adds tests as well. We can also merge
`sameBackendTypeIgnoreRange` with `sameBackendType` since it doesn't
seem like anything that uses it would be affected (only cycle checks and
the VM), but then we still have to add tests.

(cherry picked from commit 1fbb67ffe9)
2024-12-20 05:21:18 +01:00
bptato
6bcb078476 Fix exitnow signature, mark as .noreturn (#24533)
Like quit, this function never returns.

Also, "code" was marked as "int", even though POSIX _exit takes a C int.

(cherry picked from commit f485973459)
2024-12-17 15:58:34 +01:00
metagn
5c58e7d201 fix crash with tyBuiltInTypeClass matching itself (#24462)
fixes #24449

The standalone `seq` type is a `tyBuiltInTypeClass` with a single child
of kind `tySequence`, which itself has no children. This is also the
case for most other `tyBuiltInTypeClass` kinds. However this can cause a
crash in sigmatch when calling `isEmptyContainer` on this child type,
which expects the sequence type to have children. This check was added
in #5557 to prevent empty collections like `@[]` from matching their
respective typeclass, but it's not useful when matching against another
typeclass (which is done here to resolve an ambiguity). So to avoid the
crash, this empty container check is disabled when matching against
another typeclass.

(cherry picked from commit 96043bdbb7)
2024-12-17 15:58:33 +01:00
metagn
5327498547 gensym anonymous proc symbols (#24422)
fixes #14067, fixes #15004, fixes #19019

Anonymous procs are [added to
scope](8091d76306/compiler/semstmts.nim (L2466))
with the name `:anonymous`. This means that if they have the same
signature in a scope, they can consider each other as redefinitions. To
prevent this, mark their symbols as `sfGenSym` so they do not get added
to scope or cause any name conflicts. The commented out `and not isAnon`
check wouldn't work because `isAnon` would not be true if the proc is
being resemmed, in which case the name field in the proc AST would have
the symbol of the anonymous proc rather than being empty.

There is a separate problem of default values in generic/normal procs
not opening new scopes which is partially responsible for #19019.

(cherry picked from commit 3e47725c08)
2024-12-17 14:38:42 +01:00
ringabout
d84d41dc95 fixes #24371; incorrect importc wrapper incompatible with gcc 14 on Windows (#24388)
fixes #24371

(cherry picked from commit 74df699ff1)
2024-12-17 14:38:32 +01:00
ringabout
693b35b59f fixes #23545; C compiler error when default initializing an object field function (#24375)
fixes #23545

(cherry picked from commit 815bbf0e73)
2024-12-17 14:38:23 +01:00
bptato
c1bb144fdc Fix broken poll and nfds_t bindings (#24331)
This fixes several cases of the Nim binding of nfds_t being inconsistent
with the target platform signedness and/or size.

Additionally, it fixes poll's third argument (timeout) being set to Nim
"int" when it should have been "cint".

The former is the same issue that #23045 had attempted to fix, but
failed because it only considered Linux. (Also, it was only applied to
version 2.0, so the two branches now have incompatible versions of the
same bug.)

Notes:

* SVR4's original "unsigned long" definition is cloned by Linux and
Haiku. Nim got this right for Haiku and Linux-amd64, but it was wrong on
non-amd64 Linux.
* Zephyr does not have nfds_t, but simply uses (signed) "int". This was
already correctly reflected by Nim.
* OpenBSD poll.h uses "unsigned int", and other BSD derivatives follow
suit. This being the most commonly copied definition, the fallback case
now returns cuint. (This also seems to be correct for the OS X headers I
could find on the web.)
* This changes Nintendo Switch nfds_t to cuint from culong. It is
purportedly a FreeBSD derivative, so I *think* this is correct, but I
can't tell because I don't have access to the Nintendo Switch headers.

I have also moved the platform-specific Tnfds to posix.nim so that we
can reuse the fallback logic on all platforms. (e.g. specifying the size
in posix_linux_amd64 only to then use when defined(linux) in posix_other
seems redundant.)

(cherry picked from commit 67442471ae)
2024-12-17 14:35:25 +01:00
ringabout
1f38c3cea8 fixes #24319; move doesn't work well with (deref (var array)) (#24321)
fixes #24319

`byRefLoc` (`mapType`) requires the Loc `a` to have the right type.
Without `lfEnforceDeref`, it produces the wrong type for `deref (var
array)`, which may come from `mitems`.

(cherry picked from commit 0347536ff2)
2024-12-17 14:34:27 +01:00
metagn
f45ca4fdf4 only generate first field for default value of union (#24303)
fixes #20653

(cherry picked from commit 6df050d6d2)
2024-12-16 17:42:19 +01:00
metagn
5cbc7a6d1b fix regression with generic params in static type (#24075)
Caught in https://github.com/metagn/applicates, I'm not sure which
commit causes this but it's also in the 2.0 branch (but not 2.0.2), so
it's not any recent PRs.

If a proc has a static parameter with type `static Foo[T]`, then another
parameter with type `static Bar[T, U]`, the generic instantiation for
`Bar` doesn't match `U` which has type `tyGenericParam`, but matches `T`
since it has type `tyTypeDesc`. The reason is that `concreteType`
returns the type itself for `tyTypeDesc` if `c.isNoCall` (i.e. matching
a generic invocation), but returns `nil` for `tyGenericParam`. I'm
guessing `tyGenericParam` is received here because of #22618, but that
doesn't explain why `T` is still `tyTypeDesc`. I'm not sure.

Regardless, we can just copy the behavior for `tyTypeDesc` to
`tyGenericParam` and also return the type itself when `c.isNoCall`. This
feels like it defeats the purpose of `concreteType` but the way it's
used doesn't make sense without it (generic param can't match another
generic param?). Alternatively we could loosen the `if concrete == nil:
return isNone` checks in some places for specific conditions, whether
`c.isNoCall` or `c.inGenericContext == 0` (though this would need

(cherry picked from commit 24e5b21c90)
2024-12-16 15:11:47 +01:00
metagn
56e7c75e03 fix int32's that should be uint32 on BSD & OSX (#24078)
fixes #24076

As described in #24076, misannotating these types causes codegen errors.
Sources for the types are https://github.com/openbsd/src/blob/master/sys
for BSD and https://opensource.apple.com/source/Libinfo/Libinfo-391/ and
[_types.h](https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/sys/_types.h.auto.html)
for OSX.

(cherry picked from commit 7de4ace949)
2024-12-16 15:11:03 +01:00
metagn
d51236e9cc fix string literal assignment with different lengths on ARC (#24083)
fixes #24080

(cherry picked from commit cd22560af5)
2024-12-16 15:10:58 +01:00
metagn
4d0d848235 fix undeclared identifier in templates in generics (#24069)
fixes #13979

Fixes templates in generics that use identifiers that aren't defined
yet, giving an early `undeclared identifier` error, by just marking
template bodies as in a mixin context in `semgnrc`.

(cherry picked from commit bf865fa75a)
2024-12-16 15:10:46 +01:00
ringabout
8859f1ddf7 fixes #24034; fixes lent types after taking implicit address (#24035)
fixes #24034

(cherry picked from commit 11ead19bc1)
2024-12-16 15:09:57 +01:00
metagn
0e2b34ce35 fix subscript magic giving unresolved generic param type (#23988)
fixes #19737

As in the diff, `semResolvedCall` sets the return type of a call to a
proc to the type of the call. But in the case of the [subscript
magic](https://nim-lang.org/docs/system.html#%5B%5D%2CT%2CI), this type
is the first generic param which is also supposed to be the type of the
first argument, but this is invalid, the correct type is the element
type eventually given by `semSubscript`. Some lines above also [prevent
the subscript magics from instantiating their
params](dda638c1ba/compiler/semcall.nim (L699))
so this type ends up being an unresolved generic param.

Since the type of the node is not `nil`, `prepareOperand` doesn't try to
type it again, and this unresolved generic param type ends up being the
final type of the node. To prevent this, we just never set the type of
the node if we encountered a subscript magic.

Maybe we could also rename the generic parameters of the subscript
magics to stuff like `DummyT`, `DummyI` if we want this to be easier to
debug in the future.

(cherry picked from commit 04da0a6028)
2024-12-16 15:09:00 +01:00
metagn
ba516c8eb5 include generic bodies in allowMetaTypes (#23968)
fixes #19848

Not sure why this wasn't the case already. The `if cl.allowMetaTypes:
return` line below for `tyFromExpr` [was added 10 years
ago](d5798b43de).
Hopefully it was just negligence?

(cherry picked from commit 1befb8d4a3)
2024-12-16 15:07:47 +01:00
metagn
009a5b0684 bypass constraints for tyFromExpr in generic bodies (#23863)
fixes #19819, fixes #23339

Since #22029 `tyFromExpr` does not match anything in overloading, so
generic bodies can know which call expressions to delay until the type
can be evaluated. However generic type invocations also run overloading
to check for generic constraints even in generic bodies. To prevent them
from failing early from the overload not matching, pretend that
`tyFromExpr` matches. This mirrors the behavior of the compiler in more
basic cases like:

```nim
type
  Foo[T: int] = object
    x: T
  Bar[T] = object
    y: Foo[T]
```

Unfortunately this case doesn't respect the constraint (#21181, some
other bugs) but `tyFromExpr` should easily use the same principle when
it does.

(cherry picked from commit 31ee75f10e)
2024-12-16 15:06:10 +01:00
SirOlaf
c786415eef Set type of object constructor during annotateType (#23852)
Fix https://github.com/nim-lang/Nim/issues/23547

Tested locally with the included test, the test from constantine and the
original issue.

(cherry picked from commit f765898a75)
2024-12-16 15:06:00 +01:00
Yuriy Glukhov
33dc54c573 Check for nil in cstringArrayToSeq (#23747)
This fixes crashes in some specific network configurations (as
`cstringArrayToSeq` is used extensively in `nativesockets`).

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 2c83f94544)
2024-12-16 15:03:09 +01:00
Marius Andra
6a1d1a8c2b fixes 12381, HttpClient socket handle leak (#23575)
## Bug

Fixes https://github.com/nim-lang/Nim/issues/12381 - HttpClient socket
handle leak

To replicate the bug, run the following code in a loop:

```nim
import httpclient
while true:
    echo "New loop"
    var client = newHttpClient(timeout = 1000)
    try:
        let response = client.request("http://10.44.0.4/bla", httpMethod = HttpPost, body = "boo")
        echo "HTTP " & $response.status
    except CatchableError as e:
        echo "Error sending logs: " & $e.msg
    finally:
        echo "Finally"
        client.close()
```

Note the IP address as the hostname. I'm directly connecting to a
plausible local IP, but one that does not resolve, as I have everything
under 10.4.x.x.

The output looks like this to me:

```
New loop
Error sending logs: Operation timed out
Finally
New loop
Error sending logs: Operation timed out
Finally
New loop
...
```

In Nim 2.0.4, running the code above leaks the socket:

<img width="944" alt="Screenshot 2024-05-05 at 22 00 13"
src="https://github.com/nim-lang/Nim/assets/53387/ddac67db-d7df-45e6-b7a5-3d42f79775ea">

## Fix

With the added line of code, each old socket is cleanly removed:

<img width="938" alt="Screenshot 2024-05-05 at 21 54 18"
src="https://github.com/nim-lang/Nim/assets/53387/5b0b4b2d-d4f0-4e74-a9cf-74aec0c50d2e">

I believe the line below, `closeUnusedFds(ord(domain))` was supposed to
clean up the failed connection attempts, but it failed to do so for the
last one, assuming it succeeded. Yet it didn't. This fix makes sure
failed connections are closed immediately.

## Tests

I don't have a test with this PR. When testing locally, the
`connect(lastFd, ..)` call on line 2032 blocks for ~75 seconds, ignoring
the http timeout. I fear any test I could add would either 1) take way
too long, 2) one day run in an environment where my randomly chosen IP
is real, yielding in weird flakes.

The only bug i can imagine is if running `lastFd.close()` twice is a bad
idea. I tested by actually running it twice, and... no crash/op? So
seems safe? I'm hoping the CI run will be green, and this will be
enough. However I'm happy to take feedback on how I should test this,
and do the necessary changes.

~Edit: looks like a test does fail, so moving to a draft while I figure
this out.~ Attempt 2 fixed it.

(cherry picked from commit e6f66e4d13)
2024-12-16 15:02:56 +01:00
ringabout
0c426e7875 fixes #23295; don't expand constants for complex structures (#23297)
fixes #23295

(cherry picked from commit 39f2df1972)
2024-12-16 15:02:23 +01:00
ringabout
4e1b5ee702 fixes #18104; tranform one liner var decl before templates expansion (#23294)
fixes #18104

(cherry picked from commit 1e9a3c438b)
2024-12-16 15:01:45 +01:00
ringabout
3a334e09ea fixes #23233; Regression when using generic type with Table/OrderedTable (#23235)
fixes #23233

(cherry picked from commit 720021908d)
2024-12-16 14:59:51 +01:00
narimiran
dbe9c724a0 Revert "Bumps nimble v0.16.4 (#24437)"
This reverts commit 1778b8354a.
2024-12-16 14:02:04 +01:00
narimiran
9620d206b9 Revert "(cherry picked from commit 556f217b4c)"
This reverts commit 9e5cdc43a6.
2024-12-16 14:01:53 +01:00
Juan M Gómez
9e5cdc43a6 (cherry picked from commit 556f217b4c) 2024-12-16 08:07:55 +01:00
Juan M Gómez
1778b8354a Bumps nimble v0.16.4 (#24437)
(cherry picked from commit be4d19e562)
2024-12-13 19:22:23 +01:00
ringabout
f6f72722bb fixes #22153; UB calling allocCStringArray([""]) with --mm:refc (#24529)
fixes #22153

It's a problem for refc because you cannot index a nil string: i.e.
`[""]` is `{((NimStringDesc*) NIM_NIL)}` which cannot be indexed

(cherry picked from commit 9bb7e53e7f)
2024-12-12 12:27:10 +01:00
metagn
90993aeff6 install older version of nimcuda for arraymancer (#24496)
Attempt to fix CI failure, refs
https://github.com/nim-lang/Nim/pull/24495#issuecomment-2511299112,
alternative is to use a commit version like
bc65375ff5

(cherry picked from commit 33dc2367e7)
2024-12-09 09:11:30 +01:00
ringabout
15e5ddc675 fixes #24504; fixes ensureMove for refs (#24505)
fixes #24504

(cherry picked from commit d0288d3b57)
2024-12-08 19:18:30 +01:00
narimiran
9f43f9fa6e bump NimVersion to 2.0.13 2024-12-08 19:18:30 +01:00
155 changed files with 1656 additions and 365 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

@@ -24,6 +24,6 @@ if not exist %nim_csources% (
cd ..
copy /y bin\nim.exe %nim_csources%
)
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
koch tools --skipUserCfg --skipParentCfg --hints:off
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
koch tools --skipUserCfg --skipParentCfg --hints:off

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

@@ -2362,7 +2362,7 @@ proc genWasMoved(p: BProc; n: PNode) =
proc genMove(p: BProc; n: PNode; d: var TLoc) =
var a: TLoc
initLocExpr(p, n[1].skipAddr, a)
initLocExpr(p, n[1].skipAddr, a, {lfEnforceDeref})
if n.len == 4:
# generated by liftdestructors:
var src: TLoc
@@ -3118,16 +3118,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkObjConstr: genObjConstr(p, n, d)
of nkCast: genCast(p, n, d)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d)
of nkHiddenAddr:
if n[0].kind == nkDerefExpr:
# addr ( deref ( x )) --> x
var x = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
x.typ = n.typ
expr(p, x, d)
return
genAddr(p, n, d)
of nkAddr: genAddr(p, n, d)
of nkAddr, nkHiddenAddr: genAddr(p, n, d)
of nkBracketExpr: genBracketExpr(p, n, d)
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d)
of nkDotExpr: genRecordField(p, n, d)
@@ -3312,8 +3303,12 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
isConst: bool, info: TLineInfo) =
case obj.kind
of nkRecList:
let isUnion = tfUnion in t.flags
for it in obj.sons:
getNullValueAux(p, t, it, constOrNil, result, count, isConst, info)
if isUnion:
# generate only 1 field for default value of union
return
of nkRecCase:
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
var res = ""

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

@@ -795,15 +795,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
result = passCopyToSink(n, c, s)
elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
nkCallKinds + nkLiterals:
if n.kind in nkCallKinds and n[0].kind == nkSym:
if n[0].sym.magic == mEnsureMove:
inc c.inEnsureMove
result = p(n[1], c, s, sinkArg)
dec c.inEnsureMove
else:
result = p(n, c, s, consumed)
else:
result = p(n, c, s, consumed)
result = p(n, c, s, consumed)
elif ((n.kind == nkSym and isSinkParam(n.sym)) or isAnalysableFieldAccess(n, c.owner)) and
isLastRead(n, c, s) and not (n.kind == nkSym and isCursor(n)):
# Sinked params can be consumed only once. We need to reset the memory
@@ -878,12 +870,6 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
if mode == normal and (isRefConstr or hasCustomDestructor(c, t)):
result = ensureDestruction(result, n, c, s)
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
inc c.inEnsureMove
result = p(n[1], c, s, sinkArg)
dec c.inEnsureMove
return
let inSpawn = c.inSpawn
if n[0].kind == nkSym and n[0].sym.magic == mSpawn:
c.inSpawn.inc
@@ -900,13 +886,19 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
isDangerous = true
result = shallowCopy(n)
for i in 1..<n.len:
if i < L and isCompileTimeOnly(parameters[i]):
result[i] = n[i]
elif i < L and (isSinkTypeForParam(parameters[i]) or inSpawn > 0):
result[i] = p(n[i], c, s, sinkArg)
else:
result[i] = p(n[i], c, s, normal)
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
inc c.inEnsureMove
result[1] = p(n[1], c, s, sinkArg)
dec c.inEnsureMove
else:
for i in 1..<n.len:
if i < L and isCompileTimeOnly(parameters[i]):
result[i] = n[i]
elif i < L and (isSinkTypeForParam(parameters[i]) or inSpawn > 0):
result[i] = p(n[i], c, s, sinkArg)
else:
result[i] = p(n[i], c, s, normal)
when false:
if isDangerous:

View File

@@ -1519,15 +1519,8 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
of nkObjDownConv:
gen(p, n[0], r)
of nkHiddenDeref:
of nkHiddenDeref, nkDerefExpr:
gen(p, n[0], r)
of nkDerefExpr:
var x = n[0]
if n.kind == nkHiddenAddr:
x = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
x.typ = n.typ
gen(p, x, r)
of nkHiddenAddr:
gen(p, n[0], r)
of nkConv:

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

@@ -662,7 +662,8 @@ proc semResolvedCall(c: PContext, x: TCandidate,
instGenericConvertersSons(c, result, x)
markConvertersUsed(c, result)
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
result.typ = finalCallee.typ[0]
if finalCallee.magic notin {mArrGet, mArrPut}:
result.typ = finalCallee.typ[0]
updateDefaultParams(result)
proc canDeref(n: PNode): bool {.inline.} =

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
@@ -1850,6 +1854,8 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
else:
localError(c.config, n.info, errExprHasNoAddress)
result = newNodeIT(nkHiddenAddr, n.info, if n.typ.kind in {tyVar, tyLent}: n.typ else: makePtrType(c, n.typ))
if n.typ.kind in {tyVar, tyLent}:
n.typ = n.typ.elementType
result.add(n)
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =

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

@@ -577,7 +577,8 @@ proc semGenericStmt(c: PContext, n: PNode,
else:
body = getBody(c.graph, s)
else: body = n[bodyPos]
n[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
let bodyFlags = if n.kind == nkTemplateDef: flags + {withinMixin} else: flags
n[bodyPos] = semGenericStmtScope(c, body, bodyFlags, ctx)
closeScope(c)
of nkPragma, nkPragmaExpr: discard
of nkExprColonExpr, nkExprEqExpr:

View File

@@ -51,6 +51,7 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
of nkObjConstr:
let x = t.skipTypes(abstractPtrs)
n.typ = t
n[0].typ = t
for i in 1..<n.len:
var j = i-1
let field = x.ithField(j)

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)
@@ -177,6 +178,7 @@ proc varDecl(a: PEffects; n: PNode) {.inline.} =
proc skipHiddenDeref(n: PNode): PNode {.inline.} =
result = if n.kind == nkHiddenDeref: n[0] else: n
proc initVar(a: PEffects, n: PNode; volatileCheck: bool) =
let n = skipHiddenDeref(n)
if n.kind != nkSym: return
@@ -925,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):
@@ -1144,7 +1153,12 @@ proc track(tracked: PEffects, n: PNode) =
let last = lastSon(child)
track(tracked, last)
of nkCaseStmt: trackCase(tracked, n)
of nkWhen, nkIfStmt, nkIfExpr: trackIf(tracked, n)
of nkWhen: # This should be a "when nimvm" node.
let oldState = tracked.init.len
track(tracked, n[0][1])
tracked.init.setLen(oldState)
track(tracked, n[1][0])
of nkIfStmt, nkIfExpr: trackIf(tracked, n)
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n[1])
of nkWhileStmt:
# 'while true' loop?

View File

@@ -780,6 +780,24 @@ proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSy
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode
result = copyNode(n)
# transform var x, y = 12 into var x = 12; var y = 12
# bug #18104; transformation should be finished before templates expansion
# TODO: move warnings for tuple here
var transformed = copyNode(n)
for i in 0..<n.len:
var a = n[i]
if a.kind == nkIdentDefs and a.len > 3 and a[^1].kind != nkEmpty:
for j in 0..<a.len-2:
var b = newNodeI(nkIdentDefs, a.info)
b.add a[j]
b.add a[^2]
b.add copyTree(a[^1])
transformed.add b
else:
transformed.add a
let n = transformed
for i in 0..<n.len:
var a = n[i]
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
@@ -1701,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:
@@ -2253,6 +2282,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
of nkEmpty:
s = newSym(kind, c.cache.idAnon, c.idgen, c.getCurrOwner, n.info)
s.flags.incl sfUsed
s.flags.incl sfGenSym
n[namePos] = newSymNode(s)
of nkSym:
s = n[namePos].sym

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

@@ -228,6 +228,22 @@ proc isRecursiveType(t: PType, cycleDetector: var IntSet): bool =
else:
return false
proc annotateClosureConv(n: PNode) =
case n.kind
of {nkNone..nkNilLit}:
discard
of nkTupleConstr:
if n.typ.kind == tyProc and n.typ.callConv == ccClosure and
n[0].typ.kind == tyProc and n[0].typ.callConv != ccClosure:
# restores `transf.generateThunk`
n[0] = newTreeIT(nkHiddenSubConv, n[0].info, n.typ,
newNodeI(nkEmpty, n[0].info), n[0])
n.transitionSonsKind(nkClosure)
n.flags.incl nfTransf
else:
for i in 0..<n.len:
annotateClosureConv(n[i])
proc fitDefaultNode(c: PContext, n: PNode): PType =
inc c.inStaticContext
let expectedType = if n[^2].kind != nkEmpty: semTypeNode(c, n[^2], nil) else: nil
@@ -243,6 +259,7 @@ proc fitDefaultNode(c: PContext, n: PNode): PType =
# `changeType` to infer types for constant values
# that's also the reason why we don't use `semExpr` to check
# the type since two overlapping error messages might be produced
annotateClosureConv(n)
result = n[^1].typ
else:
result = n[^1].typ

View File

@@ -578,6 +578,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
result.kind = tyUserTypeClassInst
of tyGenericBody:
if cl.allowMetaTypes: return
localError(
cl.c.config,
cl.info,
@@ -651,7 +652,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
for i in 0..<result.len:
if result[i] != nil:
if result[i].kind == tyGenericBody:
if result[i].kind == tyGenericBody and not cl.allowMetaTypes:
localError(cl.c.config, if t.sym != nil: t.sym.info else: cl.info,
"cannot instantiate '" &
typeToString(result[i], preferDesc) &

View File

@@ -379,6 +379,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
else: result = t
of tyGenericParam, tyAnything, tyConcept:
result = t
if c.isNoCall: return
while true:
result = PType(idTableGet(c.bindings, t))
if result == nil:
@@ -1220,10 +1221,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyFromExpr:
if c.c.inGenericContext > 0:
# generic type bodies can sometimes compile call expressions
# prevent expressions with unresolved types from
# being passed as parameters
return isNone
if not c.isNoCall:
# generic type bodies can sometimes compile call expressions
# prevent expressions with unresolved types from
# being passed as parameters
return isNone
else:
# Foo[templateCall(T)] shouldn't fail early if Foo has a constraint
# and we can't evaluate `templateCall(T)` yet
return isGeneric
else: discard
case f.kind
of tyEnum:
@@ -1743,9 +1749,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let target = f[0]
let targetKind = target.kind
var effectiveArgType = reduceToBase(a)
# the skipped child of tyBuiltInTypeClass can be structured differently,
# newConstraint constructs them with no children
let typeClassArg = effectiveArgType.kind == tyBuiltInTypeClass
effectiveArgType = effectiveArgType.skipTypes({tyBuiltInTypeClass})
if targetKind == effectiveArgType.kind:
if effectiveArgType.isEmptyContainer:
if not typeClassArg and effectiveArgType.isEmptyContainer:
return isNone
if targetKind == tyProc:
if target.flags * {tfIterator} != effectiveArgType.flags * {tfIterator}:

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
@@ -497,7 +504,17 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false)
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
else:
if n[0].kind in kinds:
if n[0].kind in kinds and
not (n[0][0].kind == nkSym and n[0][0].sym.kind == skForVar and
n[0][0].typ.skipTypes(abstractVar).kind == tyTuple
) and not (n[0][0].kind == nkSym and n[0][0].sym.kind == skParam and
n.typ.kind == tyVar and
n.typ.skipTypes(abstractVar).kind == tyOpenArray and
n[0][0].typ.skipTypes(abstractVar).kind == tyString) and
not (isAddr and n.typ.kind == tyVar and n[0][0].typ.kind == tyRef and
n[0][0].kind == nkObjConstr)
: # elimination is harmful to `for tuple unpack` because of newTupleAccess
# it is also harmful to openArrayLoc (var openArray) for strings
# addr ( deref ( x )) --> x
result = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
@@ -825,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
@@ -1035,9 +1061,7 @@ proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
of nkBreakStmt: result = transformBreak(c, n)
of nkCallKinds:
result = transformCall(c, n)
of nkHiddenAddr:
result = transformAddrDeref(c, n, {nkHiddenDeref}, isAddr = true)
of nkAddr:
of nkAddr, nkHiddenAddr:
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref}, isAddr = true)
of nkDerefExpr:
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
@@ -1050,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

@@ -213,8 +213,7 @@ proc stupidStmtListExpr*(n: PNode): bool =
proc dontInlineConstant*(orig, cnst: PNode): bool {.inline.} =
# symbols that expand to a complex constant (array, etc.) should not be
# inlined, unless it's the empty array:
result = orig.kind != cnst.kind and
cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
result = cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket, nkObjConstr} and
cnst.len > ord(cnst.kind == nkObjConstr)
proc isRunnableExamples*(n: PNode): bool =

View File

@@ -1226,16 +1226,16 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
b = skipTypes(b[^1], {tyAlias})
assert(a != nil)
assert(b != nil)
if a.kind != b.kind:
case c.cmp
of dcEq: return false
of dcEqIgnoreDistinct:
a = a.skipTypes({tyDistinct, tyGenericInst})
b = b.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
a = a.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
case c.cmp
of dcEq:
if a.kind != b.kind: return false
of dcEqIgnoreDistinct:
a = a.skipTypes({tyDistinct, tyGenericInst})
b = b.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
a = a.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
#[
The following code should not run in the case either side is an generic alias,
@@ -1243,11 +1243,12 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
objects ie `type A[T] = SomeObject`
]#
# this is required by tunique_type but makes no sense really:
if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
if c.cmp == dcEq and x.kind == tyGenericInst and
IgnoreTupleFields notin c.flags and tyDistinct != y.kind:
let
lhs = x.skipGenericAlias
rhs = y.skipGenericAlias
if rhs.kind != tyGenericInst or lhs.base != rhs.base:
if rhs.kind != tyGenericInst or lhs.base != rhs.base or rhs.kidsLen != lhs.kidsLen:
return false
for i in 1..<lhs.len - 1:
let ff = rhs[i]

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

@@ -698,6 +698,9 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
let dest = c.genx(le, {gfNodeAddr})
c.gABC(le, opcWrDeref, dest, 0, value)
c.freeTemp(dest)
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
if sameBackendType(le.typ, le[1].typ):
genAsgnPatch(c, le[1], value)
else:
discard
@@ -866,7 +869,7 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
genBinaryABC(c, n, dest, opc)
c.genNarrow(n, dest)
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest, flags: TGenFlags = {}; opc=opcConv) =
let t2 = n.typ.skipTypes({tyDistinct})
let targ2 = arg.typ.skipTypes({tyDistinct})
@@ -878,7 +881,7 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
return true
if implicitConv():
gen(c, arg, dest)
gen(c, arg, dest, flags)
return
let tmp = c.genx(arg)
@@ -1040,7 +1043,7 @@ proc whichAsgnOpc(n: PNode; requiresCopy = true): TOpcode =
else:
(if requiresCopy: opcAsgnComplex else: opcFastAsgnComplex)
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMagic) =
case m
of mAnd: c.genAndOr(n, opcFJmp, dest)
of mOr: c.genAndOr(n, opcTJmp, dest)
@@ -1179,7 +1182,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(size*8))
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n[1], dest)
genConv(c, n, n[1], dest, flags)
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
of mEqCString: genBinaryABC(c, n, dest, opcEqCString)
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
@@ -1321,7 +1324,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
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)
@@ -1556,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:
@@ -1645,6 +1650,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
c.freeTemp(cc)
else:
gen(c, ri, dest)
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
if sameBackendType(le.typ, le[1].typ):
genAsgn(c, le[1], ri, requiresCopy)
else:
let dest = c.genx(le, {gfNodeAddr})
genAsgn(c, dest, ri, requiresCopy)
@@ -1942,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
@@ -2007,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)
@@ -2155,7 +2163,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
if n[0].kind == nkSym:
let s = n[0].sym
if s.magic != mNone:
genMagic(c, n, dest, s.magic)
genMagic(c, n, dest, flags, s.magic)
elif s.kind == skMethod:
localError(c.config, n.info, "cannot call method " & s.name.s &
" at compile time")
@@ -2212,11 +2220,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
unused(c, n, dest)
gen(c, n[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
genConv(c, n, n[1], dest)
genConv(c, n, n[1], dest, flags)
of nkObjDownConv:
genConv(c, n, n[0], dest)
genConv(c, n, n[0], dest, flags)
of nkObjUpConv:
genConv(c, n, n[0], dest)
genConv(c, n, n[0], dest, flags)
of nkVarSection, nkLetSection:
unused(c, n, dest)
genVarSection(c, n)
@@ -2249,7 +2257,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
of nkCast:
if allowCast in c.features:
genConv(c, n, n[1], dest, opcCast)
genConv(c, n, n[1], dest, flags, opcCast)
else:
genCastIntFloat(c, n, dest)
of nkTypeOfExpr:

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 = "46e2ae13eeb95619a371a74d16efc5aff30ea371" # 0.16.2
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
@@ -156,13 +156,12 @@ proc bundleNimbleExe(latest: bool, args: string) =
let commit = if latest: "HEAD" else: NimbleStableCommit
cloneDependency(distDir, "https://github.com/nim-lang/nimble.git",
commit = commit, allowBundled = true)
cloneDependency(distDir / "nimble" / distDir, "https://github.com/nim-lang/checksums.git",
commit = ChecksumsStableCommit, allowBundled = true) # or copy it from dist?
cloneDependency(distDir / "nimble" / distDir, "https://github.com/nim-lang/sat.git",
commit = SatStableCommit, allowBundled = true)
# installer.ini expects it under $nim/bin
updateSubmodules(distDir / "nimble", allowBundled = true)
nimCompile("dist/nimble/src/nimble.nim",
options = "-d:release -d:nimNimbleBootstrap --mm:refc --noNimblePath " & args)
options = "-d:release --mm:refc --noNimblePath " & args)
const zippyTests = "dist/nimble/vendor/zippy/tests"
if dirExists(zippyTests):
removeDir(zippyTests)
proc bundleAtlasExe(latest: bool, args: string) =
let commit = if latest: "HEAD" else: AtlasStableCommit

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>".}
@@ -503,7 +508,7 @@ proc pthread_spin_unlock*(a1: ptr Pthread_spinlock): cint {.
proc pthread_testcancel*() {.importc, header: "<pthread.h>".}
proc exitnow*(code: int) {.importc: "_exit", header: "<unistd.h>".}
proc exitnow*(code: cint) {.importc: "_exit", header: "<unistd.h>", noreturn.}
proc access*(a1: cstring, a2: cint): cint {.importc, header: "<unistd.h>".}
proc alarm*(a1: cint): cint {.importc, header: "<unistd.h>".}
proc chdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
@@ -1095,7 +1100,21 @@ proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
when not defined(lwip):
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
# Linux and Haiku emulate SVR4, which used unsigned long.
# Meanwhile, BSD derivatives had used unsigned int; we will use this
# for the else case, because it is more widely cloned than SVR4's
# behavior.
when defined(linux) or defined(haiku):
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
elif defined(zephyr):
type
Tnfds* = distinct cint
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cuint
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {.
importc, header: "<poll.h>", sideEffect.}
proc realpath*(name, resolved: cstring): cstring {.

View File

@@ -519,8 +519,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -563,8 +563,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -125,7 +125,7 @@ type
Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
Id* {.importc: "id_t", header: "<sys/types.h>".} = int
Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
Key* {.importc: "key_t", header: "<sys/types.h>".} = int
@@ -167,7 +167,7 @@ type
Trace_event_set* {.importc: "trace_event_set_t",
header: "<sys/types.h>".} = int
Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
Utsname* {.importc: "struct utsname",
@@ -462,9 +462,9 @@ type
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
sin6_family*: TSa_Family ## AF_INET6.
sin6_port*: InPort ## Port number.
sin6_flowinfo*: int32 ## IPv6 traffic class and flow information.
sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information.
sin6_addr*: In6Addr ## IPv6 address.
sin6_scope_id*: int32 ## Set of interfaces for a scope.
sin6_scope_id*: uint32 ## Set of interfaces for a scope.
Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
header: "<netinet/in.h>".} = object ## struct ipv6_mreq
@@ -491,7 +491,7 @@ type
## alternative network names, terminated by a
## null pointer.
n_addrtype*: cint ## The address type of the network.
n_net*: int32 ## The network number, in host byte order.
n_net*: uint32 ## The network number, in host byte order.
Protoent* {.importc: "struct protoent", pure, final,
header: "<netdb.h>".} = object ## struct protoent
@@ -529,8 +529,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -484,8 +484,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -134,7 +134,7 @@ type
Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
Id* {.importc: "id_t", header: "<sys/types.h>".} = int
Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
Key* {.importc: "key_t", header: "<sys/types.h>".} = int
@@ -171,7 +171,7 @@ type
Trace_event_set* {.importc: "trace_event_set_t",
header: "<sys/types.h>".} = int
Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
Utsname* {.importc: "struct utsname",
@@ -446,9 +446,9 @@ type
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
sin6_family*: TSa_Family ## AF_INET6.
sin6_port*: InPort ## Port number.
sin6_flowinfo*: int32 ## IPv6 traffic class and flow information.
sin6_flowinfo*: uint32 ## IPv6 traffic class and flow information.
sin6_addr*: In6Addr ## IPv6 address.
sin6_scope_id*: int32 ## Set of interfaces for a scope.
sin6_scope_id*: uint32 ## Set of interfaces for a scope.
Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
header: "<netinet/in.h>".} = object ## struct ipv6_mreq
@@ -475,7 +475,7 @@ type
## alternative network names, terminated by a
## null pointer.
n_addrtype*: cint ## The address type of the network.
n_net*: int32 ## The network number, in host byte order.
n_net*: uint32 ## The network number, in host byte order.
Protoent* {.importc: "struct protoent", pure, final,
header: "<netdb.h>".} = object ## struct protoent
@@ -513,8 +513,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -604,13 +604,6 @@ when not defined(lwip):
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
when defined(zephyr):
type
Tnfds* = distinct culong
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -231,7 +231,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
verifySelectParams(timeout)
s.withPollLock():
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), timeout)
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), cint(timeout))
if count < 0:
result = 0
let err = osLastError()

View File

@@ -211,7 +211,7 @@ when defined(nimHasStyleChecks):
when defined(posix) and not defined(lwip):
from posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int =
template monitorPollEvent(x: var SocketHandle, y, timeout: cint): int =
var tpollfd: TPollfd
tpollfd.fd = cast[cint](x)
tpollfd.events = y
@@ -222,14 +222,14 @@ proc timeoutRead(fd: var SocketHandle, timeout = 500): int =
var fds = @[fd]
selectRead(fds, timeout)
else:
monitorPollEvent(fd, POLLIN or POLLPRI, timeout)
monitorPollEvent(fd, POLLIN or POLLPRI, cint(timeout))
proc timeoutWrite(fd: var SocketHandle, timeout = 500): int =
when defined(windows) or defined(lwip):
var fds = @[fd]
selectWrite(fds, timeout)
else:
monitorPollEvent(fd, POLLOUT or POLLWRBAND, timeout)
monitorPollEvent(fd, POLLOUT or POLLWRBAND, cint(timeout))
proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode,
@@ -2040,8 +2040,10 @@ proc dial*(address: string, port: Port,
if success:
result = newSocket(lastFd, domain, sockType, protocol, buffered)
elif lastError != 0.OSErrorCode:
lastFd.close()
raiseOSError(lastError)
else:
lastFd.close()
raise newException(IOError, "Couldn't resolve address: " & address)
proc connect*(socket: Socket, address: string,

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

@@ -19,9 +19,8 @@ template volatileLoad*[T](src: ptr T): T =
when defined(js):
src[]
else:
var res: T
{.emit: [res, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
res
result = default(T)
{.emit: [result, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
template volatileStore*[T](dest: ptr T, val: T) =
## Generates a volatile store into the container `dest` of the value

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

@@ -2054,12 +2054,14 @@ when not defined(js):
proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
## of length `len`.
if a == nil: return @[]
newSeq(result, len)
for i in 0..len-1: result[i] = $a[i]
proc cstringArrayToSeq*(a: cstringArray): seq[string] =
## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
## terminated by `nil`.
if a == nil: return @[]
var L = 0
while a[L] != nil: inc(L)
result = cstringArrayToSeq(a, L)
@@ -2074,7 +2076,7 @@ when not defined(js) and declared(alloc0) and declared(dealloc):
let x = cast[ptr UncheckedArray[string]](a)
for i in 0 .. a.high:
result[i] = cast[cstring](alloc0(x[i].len+1))
copyMem(result[i], addr(x[i][0]), x[i].len)
copyMem(result[i], x[i].cstring, x[i].len)
proc deallocCStringArray*(a: cstringArray) =
## Frees a NULL terminated cstringArray.

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 = 12
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

@@ -166,7 +166,7 @@ proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} =
s.len = newLen
proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
if a.p == b.p: return
if a.p == b.p and a.len == b.len: return
if isLiteral(b):
# we can shallow copy literals:
frees(a)

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

@@ -449,14 +449,9 @@ type
SockLen* = cuint
when defined(cpp):
type
Timeval* {.importc: "timeval", header: "<time.h>".} = object
tv_sec*, tv_usec*: int32
else:
type
Timeval* = object
tv_sec*, tv_usec*: int32
type
Timeval* {.importc: "struct timeval", header: "<time.h>".} = object
tv_sec*, tv_usec*: int32
var
SOMAXCONN* {.importc, header: "winsock2.h".}: cint

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

@@ -30,12 +30,12 @@ type NimblePackage* = object
var packages*: seq[NimblePackage]
proc pkg(name: string; cmd = "nimble test"; url = "", useHead = true, allowFailure = false) =
proc pkg(name: string; cmd = "nimble test -l"; url = "", useHead = true, allowFailure = false) =
packages.add NimblePackage(name: name, cmd: cmd, url: url, useHead: useHead, allowFailure: allowFailure)
pkg "alea"
pkg "argparse"
pkg "arraymancer", "nim c tests/tests_cpu.nim"
pkg "arraymancer", "nimble install -y; nimble uninstall -i -y nimcuda; nimble install nimcuda@0.2.1; nim c tests/tests_cpu.nim"
pkg "ast_pattern_matching", "nim c -r tests/test1.nim"
pkg "asyncftpclient", "nimble compileExample"
pkg "asyncthreadpool", "nimble test --mm:refc"
@@ -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

View File

@@ -0,0 +1,17 @@
discard """
matrix: "--mm:arc; --mm:orc"
"""
block: # issue #24080
var a = (s: "a")
var b = "a"
a.s.setLen 0
b = a.s
doAssert b == ""
block: # issue #24080, longer string
var a = (s: "abc")
var b = "abc"
a.s.setLen 2
b = a.s
doAssert b == "ab"

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

@@ -31,3 +31,39 @@ elif defined(gcRefc):
doAssert x.repr == "[p = nil]"
else: # fixme # bug #20081
doAssert x.repr == "Pledge(p: nil)"
block:
block: # bug #18081
type
Foo = object
discard
Bar = object
x: Foo
proc baz(state: var Bar) =
state.x = Foo()
baz((ref Bar)(x: (new Foo)[])[])
block: # bug #18079
type
Foo = object
discard
Bar = object
x: Foo
proc baz(state: var Bar) = discard
baz((ref Bar)(x: (new Foo)[])[])
block: # bug #18080
type
Foo = object
discard
Bar = object
x: Foo
proc baz(state: var Bar) = discard
baz((ref Bar)(x: Foo())[])

View File

@@ -0,0 +1,32 @@
# issue #20653
type
EmptySeq* {.bycopy.} = object
ChoiceWithEmptySeq_d* {.bycopy.} = object
a*: bool
INNER_C_UNION* {.bycopy, union.} = object
a*: char
b*: EmptySeq
c*: byte
d*: ChoiceWithEmptySeq_d
ChoiceWithEmptySeq_selection* = enum
ChoiceWithEmptySeq_NONE,
ChoiceWithEmptySeq_a_PRESENT,
ChoiceWithEmptySeq_b_PRESENT,
ChoiceWithEmptySeq_c_PRESENT,
ChoiceWithEmptySeq_d_PRESENT
ChoiceWithEmptySeq* {.bycopy.} = object
kind*: ChoiceWithEmptySeq_selection
u*: INNER_C_UNION
Og_Context* {.bycopy.} = object
state*: int
init_done*: bool
ch*: ChoiceWithEmptySeq
em*: EmptySeq
var context* : Og_Context = Og_Context(init_done: false)

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

@@ -16,3 +16,16 @@ block:
doAssert s == 2
foo()
import std/deques
block: # bug #24319
var queue = initDeque[array[32, byte]]()
for i in 0 ..< 5:
let element: array[32, byte] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1,
]
queue.addLast(element)
doAssert queue.popLast[^1] == byte(1)

View File

@@ -1,6 +1,6 @@
discard """
valgrind: true
cmd: '''nim c -d:nimAllocStats --gc:arc -d:useMalloc $file'''
cmd: '''nim c -d:nimAllocStats --mm:arc -d:useMalloc $file'''
output: '''
@[(input: @["KXSC", "BGMC"]), (input: @["PXFX"]), (input: @["WXRQ", "ZSCZD"])]
14
@@ -252,3 +252,48 @@ proc main =
main()
block:
block:
type
JsonNode = ref object
proc foo(d: JsonNode) =
discard
proc test_something()=
var a = JsonNode()
foo ensureMove(a)
test_something()
block:
type
JsonNode = object
data: int
proc foo(d: JsonNode) =
discard
proc test_something()=
var a = JsonNode()
foo ensureMove(a)
test_something()
block:
type
JsonNode = object
data: int
proc `=destroy`(x: JsonNode) = discard
proc foo(d: JsonNode) =
discard
proc test_something()=
var a = JsonNode()
foo ensureMove(a)
test_something()

View File

@@ -0,0 +1,21 @@
# issue #22523
from std/typetraits import distinctBase
type
V[p: static int] = distinct int
D[p: static int] = distinct int
T = V[1]
proc f(y: var T) = discard
var a: D[0]
static:
doAssert distinctBase(T) is distinctBase(D[0])
doAssert distinctBase(T) is int
doAssert distinctBase(D[0]) is int
doAssert T(a) is T
f(cast[ptr T](addr a)[])
f(T(a))

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

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