8838 Commits

Author SHA1 Message Date
ringabout
4734c2f5d7 fixes #26024; sink + no-copy type copies type in refc 2026-07-28 21:00:24 +08:00
Ryan McConnell
2d81149294 unwrap typedesc in semSet to enable stuff like set[T.distinctBase] (#25924)
`distinctBase` results in typedesc, so `set[T.distinctBase]` received
`typedesc[range[...]]` as its element type, which `isOrdinalType`
rejects. Strip the wrapper in `semSet` before storing the element type
and checking ordinality.

Also add `tyFromExpr` to the deferred-check set so the error doesn't
fire prematurely inside generic bodies - same pattern already used by
`semArray`.
2026-07-26 18:08:44 +02:00
ringabout
99a696e0c4 fixes #26010; Double destroy with {.cursor.} (#26031)
fixes #26010

Cursors do not own their values and therefore cannot transfer ownership
through move.
Reject move(cursor) during semantic analysis and share the
cursor-location check
between semantic analysis and destructor injection.
2026-07-24 14:07:15 +02:00
cryo2010
8e8f8de1ab fix: exception leak in closure iterator typed except branches (#23615) (#26034)
Fixes #23615

## Root cause

The leak does not require async at all -- this minimal closure iterator
leaks the exception and its stacktrace seq under ARC/ORC:

```nim
iterator it(): int {.closure.} =
  try:
    yield 1                              # try spanning a yield => closureiters transform
    raise newException(ValueError, "x")
  except ValueError:                     # typed except => generated `of` check
    discard
  yield 2
```

A bare `except:` does not leak; a *typed* `except` does:

1. `collectExceptState` in `compiler/closureiters.nim` generates the
except-branch type check as `of(getCurrentException(), T)`, using the
raw generic magic sym from `getSysMagic("of", mOf)`.
2. `injectdestructors` skips call arguments whose *formal* parameter
type is `isCompileTimeOnly`, and the raw generic `of` sym's formal
params are `tyGenericParam` so both arguments of the generated `of` call
are never processed.
3. `getCurrentException()` increfs `currException` via `=copy` into its
result. Since the arc pass never wraps that owned temp in a destroy
(`--expandArc` shows the condition left untouched, while a user-written
`if f() of ValueError` in the same iterator gets a `:tmpD` +
`=destroy`), the caught exception's refcount stays +1 forever.

Every `try: await x() except SomeError` in async code has this shape, so
each caught async exception leaked once.

## Fix

The state-machine wrapper already stores the active exception in the
`:curExc` env field before jumping to the except landing state, and
`currException == :curExc` on every path into that state. The generated
condition now references the env field via `ctx.newCurExcAccess()`
instead of calling `getCurrentException()` again -- no ownership
transfer, no temp to destroy, one fewer runtime call.

Note: the underlying `injectdestructors` behavior (skipping args of
calls whose formal params are raw `tyGenericParam`, e.g. from
`getSysMagic`) is a separate latent gap that could affect other
compiler-generated code; it is intentionally left untouched here.

## Valgrind, before and after

Exact code and command from the issue, on Linux (Valgrind 3.19):

```
nim c -d:danger --mm:orc --debugger:native --threads:off -d:useMalloc bug.nim
valgrind --leak-check=full --show-leak-kinds=all ./bug
```

Before (devel):

```
==14663== HEAP SUMMARY:
==14663==     in use at exit: 136 bytes in 2 blocks
==14663==   total heap usage: 22 allocs, 20 frees, 116,466 bytes allocated
==14663==
==14663== 56 bytes in 1 blocks are indirectly lost in loss record 1 of 2
==14663==    at 0x488A1C4: realloc (vg_replace_malloc.c:1437)
==14663==    by 0x10C663: prepareSeqAddUninit (seqs_v2.nim:212)
==14663==    by 0x10CF6F: raiseExceptionEx (excpt.nim:538)
==14663==    by 0x11661F: amain::amainX20X28AsyncX29_(Future<void>) (bug.nim:10)
==14663==    ...
==14663==
==14663== 136 (80 direct, 56 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==14663==    at 0x48850C8: malloc (vg_replace_malloc.c:381)
==14663==    by 0x10C8E3: nimNewObj (arc.nim:122)
==14663==    by 0x115403: err::errX20X28AsyncX29_(Future<void>) (asyncmacro.nim:274)
==14663==    by 0x116027: err::errNimAsyncContinue(Future<void>, ClosureIt<void>) (asyncmacro.nim:44)
==14663==    by 0x1163D3: bug::err (bug.nim:3)
==14663==    ...
==14663==
==14663== LEAK SUMMARY:
==14663==    definitely lost: 80 bytes in 1 blocks
==14663==    indirectly lost: 56 bytes in 1 blocks
==14663==      possibly lost: 0 bytes in 0 blocks
==14663==    still reachable: 0 bytes in 0 blocks
==14663== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```

After (this PR):

```
==14675== HEAP SUMMARY:
==14675==     in use at exit: 0 bytes in 0 blocks
==14675==   total heap usage: 22 allocs, 22 frees, 116,466 bytes allocated
==14675==
==14675== All heap blocks were freed -- no leaks are possible
==14675==
==14675== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
```

## Testing

- New `tests/async/t23615.nim` (modeled on `t23212.nim`: `valgrind:
true` + alloc-stats assertion) covers both the pure closure-iterator
form and the async form from the issue, with the caught exception looped
50x so the leak blows well past the slack threshold. It passes with this
PR and fails against devel.
- Testament categories `async`, `arc`, `iter`, `exception` all pass with
the patched compiler (323 tests).
- Behavior is unchanged on a sanity program covering multi-branch
dispatch, `as e` binding, nested try, and re-raise across yields: output
is byte-identical to devel; the patched build just frees 2 more blocks
per caught exception.
2026-07-24 14:06:27 +02:00
Andreas Rumpf
cd3e9a46b2 run async tests under --mm:yrc (#26033) 2026-07-24 14:04:45 +02:00
ringabout
0cf1bc3835 fixes #26019; deepCopy should not be allowed for non-copyable type (#26030)
fixes #26019
2026-07-22 12:36:48 +02:00
Jaremy Creechley
adda34bcb8 add --genBif for semantic BIF output on non-IC builds (#26001)
## Summary

Adds `--genBif:on|off`, allowing regular compiler builds to generate
per-module semantic BIF artifacts in `nimcache`.

This reuses the semantic artifact format produced by incremental
compilation without enabling IC or changing the normal code-generation
and linking pipeline.

In comparison to `nim check --compress ...` this new flag `nim c
--genBif:on --compileOnly yourlib.nim` is considerably more useful for
tooling.

That produced full semantic proc declarations, Nim visibility,
signatures, overload disambiguators, and pragmas. For a proc that was
actually code-generated, it also recorded the exact backend name, for
example.

## Motivation

External tools such as language servers, debuggers, and binding
generators can benefit from resolved symbol and type information
produced during an ordinary build. Previously, these semantic BIF
artifacts were tied to the incremental compiler workflow.

## Details

With the option enabled:

```sh
nim c --genBif:on project.nim
```

the compiler writes semantic `.s.bif` files and their supporting
sidecars for each semantically checked module while continuing with the
requested backend normally.

The option:

- Works with non-IC builds.
- Does not enable incremental compilation.
- Does not change generated program behavior.
- Does not enable or introduce native ABI exports.
- Does not generate `.abi.nif` manifests.
- Is ignored for NimScript compilation.

The `genBif` name follows existing artifact-generation options such as
`genScript`, `genMapping`, and `genCDeps`.

## Testing

Added a focused C backend test that runs a regular build with
`--genBif:on` and verifies that semantic `.s.bif` artifacts are
generated.

A release-mode temporary compiler build and the focused Testament test
both pass.
2026-07-20 13:01:30 +02:00
ringabout
2915691515 fixes #26000; Cannot add members to enum-indexed array of seqs at com… (#26013)
…pile time

fixes #26000


vm: preserve lvalues for mutations of broadcast array elements

Load in-place mutation targets through their address so mutations don't
operate on detached copies of broadcast defaults. This also preserves
nested lvalues and evaluates indexed destinations only once.

Cover sequence, string, and set mutations through direct, nested, field,
enum-indexed, and range-indexed array elements.
2026-07-20 12:59:18 +02:00
Andreas Rumpf
fa66510f7a IC: bugfix (#25982) 2026-07-10 14:07:35 +02:00
ringabout
4b1444e728 fix #25976: treat proc-type forbids as an empty tag set (#25980)
fix #25976

Initialize tagEffects for proc types that declare .forbids but omit
.tags,
so they behave like explicit tags: [] during indirect-call effect
tracking.
Add a regression for the nested callback assignment case.
2026-07-10 07:39:32 +02:00
Andreas Rumpf
1dc079b723 nim-track: make include files work (#25977) 2026-07-09 22:13:39 +02:00
Mamy Ratsimbazafy
e50fafc971 Fix #25883 tuple sighash collision (#25889)
fixes #25886
fixes #25883

See #25883 

Tuples only hash leaves so if 2 tuples have the same flattened
representation they collide in the C codegen.

Fix by hashing the length as well to disambiguate nesting levels.

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2026-07-09 15:47:58 +02:00
Andreas Rumpf
b290be8d83 nim-track: dedup outputs; make --defusages work (#25975) 2026-07-09 10:16:30 +02:00
Andreas Rumpf
ccc2372884 nim-track: bugfixes (#25974) 2026-07-09 00:20:57 +02:00
Andreas Rumpf
f5cf44d7d5 nim track: oneshot nimsuggest (#25971) 2026-07-08 15:39:40 +02:00
ringabout
c70a4502d2 fix #25608; improve implicit range conversion checks (#25838)
fix #25608

This pull request improves how the compiler handles warnings for
implicit range conversions, ensuring that only non-constant values
trigger downsizing warnings. It also adds new test cases to verify that
assignments and function calls involving compile-time constants do not
produce unnecessary warnings.

Improvements to range conversion warnings:

* Updated the logic in `compiler/sempass2.nim` to skip implicit range
conversion warnings for compile-time constants by checking if an
expression is constant with `getConstExpr`. Now, only non-constant
values will trigger the warning.

Testing enhancements:

* Added new test cases in `tests/range/timplicitrangedownsizing.nim` to
confirm that assignments and function calls with constant enum and
integer values do not trigger downsizing warnings.
2026-07-06 14:26:14 +02:00
Andreas Rumpf
0bfb59f6d4 IC: final tweaks (#25958) 2026-07-04 10:13:39 +02:00
Andreas Rumpf
1c61307692 IC related bugfixes (#25946) 2026-07-03 15:52:41 +02:00
Savant
c7ea004ca9 js: cursor inference to elide nimCopy for safe value aliases (#25948) 2026-07-03 09:55:58 +02:00
ringabout
985b1125b1 fixes genMagicExpr: handle mAsgn for Isolated[T] with primitive types in tuple assignment (#25955)
Explicit `=sink` calls such as `Isolated[T].=sink` can delegate to a
field type like `float`, which has no attached sink op. In that case
`replaceHookMagic` leaves the builtin `mAsgn` call in place.
`genMagicExpr` did not lower that shape, which caused the regression.
Mapping `=sink` to `nkSinkAsgn` and other builtin assignment hooks to
`nkAsgn`.
2026-07-02 19:51:08 +02:00
ringabout
d77f5bcd0f fixes #25803: add genCppConstructorExpr for full type-prefixed expression (#25817)
fixes #25803

This pull request introduces a new approach for generating C++
constructor expressions in the Nim compiler's C++ backend, ensuring that
type-prefixed construction is used when needed (such as in assignments),
rather than just braced initializer lists. It also adds a new test case
(with corresponding C++ header) to verify correct behavior when
assigning to types with overloaded assignment operators and
constructors.

**C++ code generation improvements:**

* Added `genCppConstructorExpr` in `ccgtypes.nim`, which generates a
full type-prefixed constructor expression (e.g., `Foo(a, b)`) for C++
code generation, as opposed to just a braced initializer list. This is
important for contexts like assignments where the type must be explicit.
* Updated `resetLoc` in `cgen.nim` to use `genCppConstructorExpr`
instead of `genCppInitializer` when initializing imported C++ types,
ensuring correct code generation for assignments.

**Testing:**

* Added a new C++ header file, `tcpp_default_ctor_assignment.h`,
defining a struct `AmbiguousAssign` with overloaded assignment operators
and constructors to test ambiguous assignment scenarios.
* Added a corresponding Nim test, `tcpp_default_ctor_assignment.nim`,
which exercises construction and assignment for the imported C++ type,
ensuring the new code generation logic works as intended.
2026-07-02 12:04:43 +02:00
ringabout
a0e44d7aca fixes #25945; cannot map the empty seq type to a C type (#25954)
fixes #25945

When `@[]` appears inside a nested `if` expression that also contains
statements, the AST wraps it in `nkStmtListExpr` nodes. The empty
container's `tyEmpty` element type was never resolved to a concrete
type, causing the C codegen to ICE with "cannot map the empty seq type
to a C type".

Walk through nested statement-list/block expressions in
`fitNodePostMatch` to find the innermost value node and propagate the
formal type to empty containers.
2026-07-02 12:02:16 +02:00
ringabout
3b9100178e fixes #25949; nimvm + staticRead code executed in runtime context (#25950)
fixes #25949

track still walks both branches of preserved when nimvm, but it now sets
a small inNimvmBranch flag while visiting the VM branch, and trackCall
skips sfCompileTime marking only when that flag is set.
2026-07-02 12:02:00 +02:00
Andreas Rumpf
58a5b9e27e IC: move to BIF / nifcore APIs (#25943) 2026-06-29 18:24:49 +02:00
ringabout
6828effd13 Improve effect propagation by skipping hooks in trackCall (#25940)
ref https://github.com/nim-lang/Nim/pull/25731
don't propagate effects for assignment hooks without effect lists
2026-06-26 19:57:03 +02:00
Andreas Rumpf
5688a122f1 IC refactor (#25927) 2026-06-25 23:20:34 +02:00
ringabout
056eeeae30 fixes #25931; type N {.importc: "const void *".} = pointer creates order-dependent compilation failure (#25936)
fixes #25931

This fix addresses bug #25931 — a signature hash collision with
importc-aliased pointer/cstring types.
The problem: In compiler/sighashes.nim, the hashType procedure
canonicalizes types for signature hashing. Integral types
(tyInt..tyUInt64, etc.) were excluded from canonicalization so that
types like pid_t (an importc alias) keep their backend spelling. But
pointer and cstring types with importc annotations were not excluded —
meaning a type like:
type N {.importc: "const void *".} = pointer
...would be collapsed to just pointer in the signature hash, causing
collisions when N and pointer are both used in procedure types within
the same compilation unit.
The fix (compiler/sighashes.nim:193): Adds tyPointer and tyCstring to
the list of types that skip canonicalization, right alongside the
integral types. The comment is updated to clarify this applies to
"builtin scalar-ish / pointer-like types".
The test (tests/ccgbugs/tsighash_typename_regression.nim:33-42): Adds a
regression test exercising the exact scenario — an importc pointer alias
used in both an object field type and a proc parameter type.
2026-06-25 10:19:13 +02:00
Andreas Rumpf
4998affe70 fixes #25925 (#25926) 2026-06-25 01:04:01 +02:00
Andreas Rumpf
4e1dd0b9fc use IC for nimsuggest (#25915) 2026-06-24 21:58:51 +02:00
ringabout
6eef0cc2d5 fixes #25908; resolves lent enum disambiguation (#25929)
fixes #25908

When an enum identifier is resolved as an `nkSymChoice`, one of the
candidates may come from a loop-local view and carry `tyVar` or
`tyLent`.

Enum disambiguation should compare the underlying enum type only.
Otherwise a pure-enum field can win incorrectly even though the intended
symbol is already present in the choice set.

Keep the `includePureEnum` lookup path for enum-typed expectations so
#23976 still works, but normalize `var`/`lent` only at the symchoice
selection point.
2026-06-23 12:22:29 +02:00
Ryan McConnell
f8e470eb57 fix: {.cast(uncheckedAssign).} ineffective across yield in closure iterators (#25916)
closureiters.nim splits a stmt list at yield points, moving post-yield
code into a new state body. When that stmt list was inside a pragma
block like `{.cast(uncheckedAssign).}`, the new state's body was created
as a bare nkStmtList without the wrapper.

Fix: track the enclosing pragma block in the transform context, and wrap
newly-created state bodies in a copy of it when the split occurs inside
one. Added an explicit `nkPragmaBlock` case to
`transformClosureIteratorBody` that saves/restores `ctx.enclosingPragma`
around its body.
2026-06-16 19:15:16 +02:00
Andreas Rumpf
f5d9e7a207 IC: bugfixes (#25914) 2026-06-15 23:33:16 +02:00
Andreas Rumpf
acb9b3a4f1 IC: precompiled configs and bugfixes (#25913) 2026-06-15 21:20:09 +02:00
Andreas Rumpf
7171e6f01f IC: progress (#25879) 2026-06-14 22:35:06 +02:00
ringabout
587f90a816 fixes #22122; Unclear error message for raise of a complex expression (#25899)
fixes  #22122

The commit fixes a bug in Nim's effects checker where raise statements
with case/if expressions (commonly from template expansion) failed to
track exception types from individual branches.
Problem: addRaiseEffect only saw the outermost expression. When a
template like getTransportError(err) expanded to a case expression
raising 3 different exception types, the compiler only registered the
top-level call — missing the branch-level exceptions.
Fix (2 files):
- compiler/sempass2.nim: Added skipHiddenConv to strip implicit type
coercion nodes (nkHiddenStdConv/nkHiddenSubConv) that hide the control
flow structure. Added addRaiseEffectsFromExpr that recursively walks
into case/if/block/stmtlist expressions to find raise effects in each
branch body. Changed the nkRaiseStmt handler to use this new function.
- tests/effects/tcase_raises.nim: Test with templates that expand to
case expressions raising different exception types, verified via
{.raises: [].} pragma.
2026-06-13 10:17:59 +02:00
ringabout
8ad1d106ec fixes #25885; incompleteStruct ignored without importc (#25898)
fixes #25885
2026-06-13 10:17:44 +02:00
ringabout
67707a54b5 fixes #18367 and #21222; using quote inside static block (#25907)
fixes #18367
fixes #21222


1. In vmdef.nim:304, newCtx now sets templInstCounter: new int when it
builds TCtx.
2. vm.nim:1490 — During VM execution of templates, c.templInstCounter is
passed to evalTemplate
3. evaltempl.nim:204 — instID: instID[] dereferences the ref int
4. With a nil templInstCounter, this would crash
5. The same initialization already exists on the semantic side in
sem.nim:787, so this change makes the VM path consistent with the rest
of the compiler.
2026-06-13 07:04:17 +02:00
ringabout
0f751695e4 fixes #25903 and #25904; add closure iterators with error handling (#25905)
fixes #25903
fixes #25904


`nkExceptBranch` can have variable structure depending on the exception
types and it should handle the last node of the `nkExceptBranch`
2026-06-13 07:03:28 +02:00
WyattBlue
b44d373b7d adds wasm64 (Memory64) as a first-class target (#25900)
This pull request allows setting `--cpu:wasm64`, allowing wasm64 as a
first class target. This avoids having to set `-cpu:riscv64` as a
workaround. Sane defaults for the emscripten toolchain are also
provided.
2026-06-11 23:49:50 +02:00
Jacek Sieka
13d152a4d1 fix state array constant types (#25893)
else there's a mismatch in the AST for the bracket constructor
2026-06-11 16:12:28 +02:00
Jacek Sieka
c620adcfce astyaml: formatting fixes (#25897)
fix missing indent and newlines here and there
2026-06-11 14:10:42 +02:00
Ryan McConnell
0448557bfe fix 25778; concept coerces incompatible types (#25781)
I don't like it, but seems like this is correct. Concept type classes
have to behave like other "named" type classes and participate in "bind
once" mechanics or require some weird semantics. As a side note I'm
pretty sure the `tuple` example in the manual explaining this is either
wrong now or has regressed, but I don't think it matters because I doubt
anyone thinks about this feature much.
#25778
2026-06-11 08:17:35 +02:00
Tomohiro
48621c217f adds modifierMode parameter to typeof (#25815)
This PR adds 3 modes to `typeof` to specify how to handle type modifiers
`var`, `sink` and `lent`.

- typeOfModCompatible
Remove or keep type modifiers in the same way as old typeof. That means
keep `sink` but remove `var` and `lent`.
- typeOfModRemoveModifier
  Remove type modifiers.
- typeOfModKeepModifier
  Keep type modifiers.

Related to https://github.com/nim-lang/Nim/pull/25779
https://github.com/nim-lang/Nim/issues/25786
2026-06-09 20:55:30 +02:00
ringabout
4d0663096c Revert "fixes #22122; raise effects for complex expressions" (#25888)
Reverts nim-lang/Nim#25845

```nim
case ecode
of ECONNABORTED, EPERM, ETIMEDOUT, ENOTCONN:
  getConnectionAbortedError(ecode)
of EMFILE, ENFILE, ENOBUFS, ENOMEM:
  getTransportTooManyError(ecode)
else:
  (ref TransportOsError)(code: ecode,
                         msg: "(" & $int(ecode) & ") " & osErrorMsg(ecode))
```

The compiler inserts a hidden conv for the case expression. Perhaps we
can skip hidden convs to inspect the types that are actually raised
2026-06-09 14:46:48 +02:00
ringabout
e942da94b5 fixes #22122; raise effects for complex expressions (#25845)
fixes #22122

The root cause is in the effect tracker: raise was recording the whole
conditional expression as one exception source, so semantic checking
only saw the widened common base type instead of the concrete exception
classes from each branch.
2026-06-08 22:59:16 +02:00
Andreas Rumpf
7a5e35c83e fixes #25693; continues the bugfix story (#25876) 2026-06-08 22:54:03 +02:00
Andreas Rumpf
d9e28aac8e parser: concept of (#25878)
Co-authored-by: Gerke Max Preussner <gmpreussner@headcrash.industries>
2026-06-08 11:32:04 +02:00
ringabout
1d7510dff0 fixes #22936; Generic inheritance matching gives type mismatch when object has members (#25836)
fixes #22936

This pull request improves the compiler's handling of generic type
constraints, specifically for subtypes of generics, and adds a test to
cover this behavior. The main changes are an enhancement to the type
relationship logic in the compiler and a new test case for generic
subtyping with `Future`.

### Compiler improvements for generic subtyping

* Updated `typeRel` in `compiler/sigmatch.nim` to allow generic
constraints (like `F: Future`) to accept not just direct instantiations
but also descendants of the generic family, ensuring more flexible and
correct overload resolution. Inheritance depth is now considered for
overload ranking, making deeper descendants slightly less preferred,
consistent with other inheritance-based matches.

### New test coverage

* Added a test in `tests/typerel/t8905.nim` to verify that generic
constraints correctly accept subtypes of `Future`, including a custom
`B[T, E] = ref object of Future[T]` type, and that overloads like
`take`, `takeMany`, and the macro `checkFutures` work as expected with
these types.
2026-06-08 09:12:00 +02:00
Tomohiro
9b80b2e868 fixes-25655; defining >= operator generates compile error (#25787)
Fixes https://github.com/nim-lang/Nim/issues/25655

---------

Co-authored-by: Andreas Rumpf <araq4k@proton.me>
2026-06-08 09:00:00 +02:00
ringabout
f5930d0bb3 fixes #20811; Nested proc with inner being generic cannot access parameters of outer proc (#25837)
fixes  #20811

This pull request addresses issues with parameter capture in nested
generic procedures and templates, ensuring that outer parameters are
correctly visible and accessible within nested scopes. The main changes
include a fix in the semantic analysis logic and the addition of
targeted regression tests.

### Semantic analysis improvements:
* Updated `semGenericStmtSymbol` in `compiler/semgnrc.nim` to ensure
that parameters from outer scopes are preserved and accessible in nested
generic procedures, fixing visibility issues with captured parameters.

### Added regression tests:
* Added `tests/generics/t20811.nim` to verify that both generic and
plain inner procedures can access parameters from their enclosing
procedure.
* Extended `tests/template/topensym.nim` with a new block for issue
#20811 to test that template-injected parameters are correctly captured
and visible in nested generic procedures.
2026-06-08 08:55:37 +02:00