fixes#25687
This pull request introduces an optimization for sequence (`seq`)
assignments and copies in the Nim compiler, enabling bulk memory copying
for sequences whose element types are trivially copyable (i.e., no GC
references or destructors). This can significantly improve performance
for such types by avoiding per-element loops.
Key changes:
* Added the `elemSupportsCopyMem` function in
`compiler/liftdestructors.nim` to detect if a sequence's element type is
trivially copyable (no GC refs, no destructors).
* Updated the `fillSeqOp` procedure to use a new `genBulkCopySeq` code
path for eligible element types, generating a call to
`nimCopySeqPayload` for efficient bulk copying. Fallback to the
element-wise loop remains for non-trivial types.
[[1]](diffhunk://#diff-456118dde9a4e21f1b351fd72504d62fc16e9c30354dbb9a3efcb95a29067863R665-R670)
[[2]](diffhunk://#diff-456118dde9a4e21f1b351fd72504d62fc16e9c30354dbb9a3efcb95a29067863R623-R655)
* Introduced the `nimCopySeqPayload` procedure in
`lib/system/seqs_v2.nim`, which performs the actual bulk memory copy of
sequence data using `copyMem`. This is only used for types that are safe
for such an operation.
These changes collectively improve the efficiency of sequence operations
for simple types, while maintaining correctness for complex types.
refc: 3.52s user 0.02s system 99% cpu 3.538 total
orc (after change): 3.46s user 0.01s system 99% cpu 3.476 total
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit 854c1f15ba)
This fixes type resolution for `iterable[T]`.
I want to proceed with RFC
[#562](https://github.com/nim-lang/RFCs/issues/562) and this is the main
blocker for composability.
Fixes#22098 and, arguably, #19206
```nim
import std/strutils
template collect[T](it: iterable[T]): seq[T] =
block:
var res: seq[T] = @[]
for x in it:
res.add x
res
const text = "a b c d"
let words = text.split.collect()
doAssert words == @[ "a", "b", "c", "d" ]
```
In cases like `strutils.split`, where both proc and iterator overload
exists, the compiler resolves to the `func` overload causing a type
mismatch.
The old mode resolved `text.split` to `seq[string]` before the
surrounding `iterable[T]` requirement was applied, so the argument no
longer matched this template.
It should be noted that, compared to older sequtils templates,
composable chains based on `iterable[T]` require an iterator-producing
expression, e.g. `"foo".items.iterableTmpl()` rather than just
`"foo".iterableTmpl()`. This is actually desirable: it keeps the
iteration boundary explicit and makes iterable-driven templates
intentionally not directly interchangeable with older
untyped/loosely-typed templates like those in `sequtils`, whose internal
iterator setup we have zero control over (e.g. hard-coding adapters like
`items`).
Also, I noticed in `semstmts` that anonymous iterators are always
`closure`, which is not that surprising if you think about it, but still
I added a paragraph to the manual.
Regarding implementation:
From what I gathered, the root cause is that `semOpAux` eagerly
pre-types all arguments with plain flags before overload resolution
begins, so by the time `prepareOperand` processes `split` against the
`iterable[T]`, the wrong overload has already won.
The fix touches a few places:
- `prepareOperand` in `sigmatch.nim`:
When `formal.kind == tyIterable` and the argument was already typed as
something else, it's re-semchecked with the
`efPreferIteratorForIterable` flag. The recheck is limited to direct
calls (`a[0].kind in {nkIdent, nkAccQuoted, nkSym, nkOpenSym}`) to avoid
recursing through `semIndirectOp`/`semOpAux` again.
- `iteratorPreference` field `TCandidate`, checked before
`genericMatches` in `cmpCandidates`, gives the iterator overload a win
without touching the existing iterator heuristic used by `for` loops.
**Limitations:**
The implementation is still flag-driven rather than purely
formal-driven, so the behaviour is a bit too broad `efWantIterable` can
cause iterator results to be wrapped as `tyIterable` in
iterable-admitting contexts, not only when `iterable[T]` match is being
processed.
`iterable[T]` still does not accept closure iterator values such
as`iterator(): T {.closure.}`. It only matches the compiler's internal
`tyIterable`, not arbitrary iterator-typed values.
The existing iterator-preference heuristic is still in place, because
when I tried to remove it, some loosely-related regressions happened. In
particular, ordinary iterator-admitting contexts and iterator chains
still rely on early iterator preference during semchecking, before the
compiler has enough surrounding context to distinguish between
value/iterator producing overloads. Full heuristic removal would require
a broader refactor of dot-chain/intermediate-expression semchecking,
which is just too much for me ATM. This PR narrows only the
tyIterable-specific cases.
**Future work:**
Rework overload resolution to preserve additional information of
matching iterator overloads for calls up to the point where the
iterator-requiring context is established, to avoid re-sem in
`prepareOperand`.
Currently there's no good channel to store that information. Nodes can
get rewritten, TCandidate doesn't live long enough, storing in Context
or some side-table raises the question how to properly key that info.
(cherry picked from commit be29bcd402)
fixes#25682
This pull request introduces a fix to the Nim compiler's assignment code
generation logic to better handle statement list expressions, and adds
regression tests to ensure correct behavior when assigning to object
fields via templates. The changes address a specific bug (#25682)
related to assignments using templates with side effects in static
contexts.
**Compiler code generation improvements:**
* Updated the `genAsgn` procedure in `compiler/vmgen.nim` to properly
handle assignments where the left-hand side is a `nkStmtListExpr`
(statement list expression), ensuring all statements except the last are
executed before the assignment occurs.
**Regression tests for assignment semantics:**
* Added new test blocks in `tests/vm/tvmmisc.nim` to verify that
template-based assignments to object fields work as expected in static
contexts, specifically testing for bug #25682.
(cherry picked from commit 9c07bb94c1)
fixes#25632fixes#25631fixes#25630
This pull request introduces a compatibility check between the
`{.error.}` and `{.exportc.}` pragmas in procedure declarations.
Specifically, it prevents a procedure from being marked with both
pragmas at the same time, as this combination is now considered invalid.
Pragma compatibility enforcement:
* Added a check in `semProcAux` (in `compiler/semstmts.nim`) to emit a
local error if a procedure is declared with both `{.error.}` and
`{.exportc.}` pragmas, preventing their incompatible usage.
(cherry picked from commit fb31e86537)
time_t should be a 64-bit type on all relevant windows CRT versions
including mingw-w64 - MSDN recommends against using the 32-bit version
which only is happens when `_USE_32BIT_TIME_T` is explicitly defined -
instead of guessing (and guessing wrong, as happens with recent mingw
versions), we can simply use the 64-bit version always.
(cherry picked from commit e53058dee0)
fixes#25677;
fixes#25678
This pull request introduces both a bug fix to the type checking logic
in the compiler and new test cases for lent types involving procedures
and tables. The most significant change is a refinement in how type
flags are handled for procedure and function types in the compiler,
which improves correctness in type allowance checks. Additionally, the
test suite is expanded to cover more complex scenarios with lent types
and table lookups.
**Compiler improvements:**
* Refined the handling of type flags in `typeAllowedAux` for procedure
and function types by introducing `innerFlags`, which removes certain
flags (`taObjField`, `taTupField`, `taIsOpenArray`) before recursing
into parameter and return types. This ensures more accurate type
checking and prevents inappropriate flag propagation.
**Testing enhancements:**
* Added new test blocks in `tests/lent/tlents.nim` to cover lent
procedure types stored in objects and used as table values, including a
function that retrieves such procedures from a table by key.
* Introduced a test case for an object containing a lent procedure
field, ensuring correct behavior when accessing and using these fields.
(cherry picked from commit 7a82c5920c)
Fixes bug #25674.
`replace` read `s[i+1]` for a CRLF pair without ensuring `i+1 <
s.len()`, so a value ending in a lone `\\c` (quoted in `writeConfig`)
raised `IndexDefect`.
- Fix: only treat `\\c\\l` when the following character exists.
- Test: `tests/stdlib/tparsecfg.nim` block bug #25674 — fails before
fix, passes after.
(cherry picked from commit 78282b241f)
Fixes bug #25670.
The second argument to `max` in `cmpDecimalsIgnoreCase` used `limitB -
iA` instead of `limitB - iB`, which could mis-order numeric segments
when sorting doc index entries.
(cherry picked from commit 5c86c1eda9)
Fixes bug #25671.
The previous condition `not value > 0` was parsed as `(not value) > 0`,
not `not (value > 0)`, so the check did not reliably enforce a positive
`--maxLoopIterationsvm` limit. Align with `--maxcalldepthvm` by using
`value <= 0`.
(cherry picked from commit 7f6b76b34c)
Even on nimscript, the `else` branch of the `when nimvm` below compiles
and gives an "undeclared identifier: copyMem" error. Regression since
#25064.
(cherry picked from commit 6f85d348f4)
fixes#25626
This pull request introduces a small change to the `mapIt` template in
`sequtils.nim`. The update adds the `used` pragma to the injected `it`
variable, which can help suppress unused variable warnings in certain
cases.
- Added the `used` pragma to the injected `it` variable in the `mapIt`
template to prevent unused variable warnings.
or it should give a better warning or something if `it` is not used
(cherry picked from commit fb6fa96979)
Documents environment variable substitution.
Didn't find it mentioned anywhere, even though it's used widely by the
compiler docs.
(cherry picked from commit c33df006c5)
- Small optimizations for mobile, makes code render slightly tighter.
- `font-stretch: semi-condensed;` for pre works if the user's font
provides such a face, shouldn’t change the rendering with the default.
- Removes an excessive page break after the page header when printing.
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 446d903fc1)
Small changes to the default html template and the `nimdoc.css`.
Adds a burger button to show the navigation panel when on narrow
screens/mobile. Displayed when the panel gets hidden.
Second element click or click on the dimmed background ides the panel.
# Demo:

(cherry picked from commit 57e15cd9a4)
mainly to fix `Uninit` warnings for projects that elevate it to an
error. Other changes are stylistic about redundancy or white-space
consistency.
(cherry picked from commit 4414b5a396)
It seems in dispute whether changes to code induced to avoid this new
warning firing are worthwhile.
Until either the analyzer is better or a palatable way to adjust stdlib
code not warn is found, verbosity=1 should not include the warning.
Possibly higher levels, too, but this PR is conservative and only takes
it out at the 2->1 transition.
(cherry picked from commit 4bf44ca47f)
I've been wondering why the inline code was rendered wrapped with no
regards to words/whitespace for a while.
Partially reverts 8b82f5 (#24927)
- `word-break: break-all;` This is seriously wrong, replaced with
`overflow-wrap: break-word;`
- `white-space: normal;` -> `pre-wrap;` to preserve whitespace in code
spans.
- Added `display: block;` and `overflow-x: auto;` to tables. This
contains wide tables with their own scrollbars without stretching the
whole doc.
- `overflow-x: hidden;` just clips content and possibly conflicts with
navbar's `sticky` attribute. Removed.
(cherry picked from commit b494147310)
Follows up #25269, refs #25265.
I hit the same bug as #25265 for my own project but #25269 does not fix
it, I think because the type in my case is a `tyGenericInst` which does
not trigger the generation here. First I thought of skipping abstract
type kinds instead of checking for a raw `tyObject`, which fixes my
problem. But in general this could maybe also be encountered for
`tyTuple` and `tySequence` etc. So I figured it might just be safest to
not filter on specific type kinds, ~~which is done now~~ (edit: broke
CI). Maybe this has a slight cost on codegen performance though.
Edit: Allowing all types failed CI for some reason as commented below,
trying skipped type version again.
(cherry picked from commit 1a1586a5fb)
This fixes autogenerated references within the same-module for types,
variables and constants for custom output file names. Previously, the
module name was baked-in, now intra-module links omit the page name in
href.
In short, fixes symbol anchors for `-o:index.html`
Expected test results updated.
(cherry picked from commit 2db13e05ac)
`getTypeImpl` and friends were always putting `nkEmpty` in the default
value field which meant the default values couldn't be introspected.
This copies the default AST so it can be seen in the returned object
(cherry picked from commit edbb32e4c4)
On simple code like:
```nim
type Foo = object
case x: range[0..7]
of 0..2:
a: string
else:
b: string
var foo = Foo()
{.cast(uncheckedAssign).}:
foo.x = 5
```
The compiler tries to generate a destructor for the variant fields by
checking if the discrim is equal to the old one, but the type is not
skipped when looking for an `==` operator in system, so any
discriminator with type `range`/`distinct`/etc crashes with:
```
(10, 9) Error: can't find magic equals operator for type kind tyRange
```
This is fixed by just skipping abstract types.
(cherry picked from commit 7a87e7d199)
This fixes highlighter's tokenization of char literals inside
parentheses and brackets.
The Nim syntax highlighter in `docutils/highlite.nim` incorrectly
tokenizes character literals that appear after punctuation characters,
such as all kinds of brackets.
For `echo('v', "hello")`, the tokenizer treated the first `'` as
punctuation because the preceding token was punctuation `(`. As a
result, the second `'` (after `v`) was interpreted as the start of a
character literal and the literal incorrectly extended to the end of the
line.
See other examples in the screenshot:
<img width="508" height="266" alt="Screenshot 2026-03-04 at 16-09-06
_y_test"
src="https://github.com/user-attachments/assets/94d991ae-79d2-4208-a046-6ed4ddcb5c34"
/>
This regression originates from a condition added in PR #23015 that
prevented opening a `gtCharLit` token when the previous token kind was
punctuation. Nim syntax allows character literals after punctuation such
as `(`, `[`, `{`, `:`, `;`, or `,`, of course. The only case mentioned
in the manual explicitly that actually requires special handling is
stroped proc declaration for literals (see the [last paragraph
here](https://nim-lang.github.io/Nim/manual.html#lexical-analysis-character-literals)):
```nim
proc `'customLiteral`(s: string)
```
This PR narrows the conditional to not entering charlit only after
backticks.
(cherry picked from commit 269a1c1fec)
So the problem is that Nim Language Server won't show procs like \`+\`
and \`==\` in the Document Symbols or Workspace Symbols lists. Which is
really annoying given they are regular procs just named a bit
differently.
Initially, I thought the problem was with nim-lang/langserver and opened
an issue there: https://github.com/nim-lang/langserver/issues/380
But after an investigation, it turned out the issue is fixed on the
nimsuggest side.
Strangely enough, calling `outline foo.nim:0:0` in nimsuggest manually
does show \`+\` as well as regular procs (e.g. `foo`) but when
nimsuggest is invoked from lsp only `foo` would be there.
Anyway, with this fix all procs appear on the symbol lists.
(cherry picked from commit 2290c75f12)
withTimeout currently leaves the “losing” callback installed:
- when fut finishes first, timeout callback remains until timer fires,
- when timeout fires first, fut callback remains on the wrapped future.
Under high-throughput use with large future payloads, this retains
closures/future references longer than needed and causes large transient
RSS growth.
This patch clears the opposite callback immediately once outcome is
decided, reducing retention without changing API behavior.
(cherry picked from commit 9ed4077d9a)
The rest of the body must be indented in order to fall under the warning
admonition. Right now, only the first part of the warning is inside the
admonition, see [std/streams](https://nim-lang.org/docs/streams.html).
(cherry picked from commit e69d672354)
fixes#25262
```nim
if constraint != nil and constraint.kind == tyTypeDesc:
n[i].typ = e.typ
else:
n[i].typ = e.typ.skipTypes({tyTypeDesc})
```
at least when `constraint` is a typedesc, it should not skip
`tyTypeDesc`
```nim
if arg.kind != tyTypeDesc:
arg = makeTypeDesc(m.c, arg)
```
Wrappers literals into typedesc, which can cause problems. Though, it
doesn't seem to be necessary
(cherry picked from commit bd709f9b4c)
While fixing a few things in the tutorial, I found a few other typos
lingering in the `doc/` directory.
---------
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
(cherry picked from commit a2db2af5b6)
This corrects the example used to describe `std/pegs` sequence notion.
It incorrectly used `Z` whereas `C` was expected.
(cherry picked from commit c36617c490)
1. A trailing `$` at the end of a replacement string could read out of
bounds via `how[i + 1]`; this now raises `ValueError` instead.
2. Numeric capture parsing used `id += (id * 10) + digit` instead of `id
= (id * 10) + digit`, so multi-digit refs were parsed incorrectly (e.g.
`$12` resolved as capture 13 instead of 12).
4. Unterminated named replacement syntax (e.g. `${foo)` is now rejected
with ValueError instead of being accepted and parsed inconsistently.
Found and fixed by GPT 5.3 Codex.
(cherry picked from commit 9b2b286baf)
The `enforcenoraises` pragma prevents generation of exception checking
code for atomic... functions when compiling with Microsoft Visual C++ as
backend.
Fixes#25445
Without this change, the following test program:
```nim
import std/sysatomics
var x: ptr uint64 = cast[ptr uint64](uint64(0))
var y: ptr uint64 = cast[ptr uint64](uint64(42))
let z = atomicExchangeN(addr x, y, ATOMIC_ACQ_REL)
let a = atomicCompareExchangeN(addr x, addr y, y, true, ATOMIC_ACQ_REL, ATOMIC_ACQ_REL)
var v = 42
atomicStoreN(addr v, 43, ATOMIC_ACQ_REL)
let w = atomicLoadN(addr v, ATOMIC_ACQ_REL)
```
... generates this C code when compiling with `--cc:vcc`:
```c
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
NU64* T1_;
NIM_BOOL T2_;
NI T3_;
NIM_BOOL* nimErr_;
nimfr_("testexcept", "/tmp/testexcept.nim");
nimErr_ = nimErrorFlag();
nimlf_(7, "/tmp/testexcept.nim");T1_ = ((NU64*) 0);
T1_ = atomicExchangeN__testexcept_u4((&x__testexcept_u2), y__testexcept_u3, ((int) 4));
if (NIM_UNLIKELY((*nimErr_))) {
goto BeforeRet_;
}
z__testexcept_u32 = T1_;
nimln_(9);T2_ = ((NIM_BOOL) 0);
T2_ = atomicCompareExchangeN__testexcept_u33((&x__testexcept_u2), (&y__testexcept_u3), y__testexcept_u3, NIM_TRUE, ((int) 4), ((int) 4));
if (NIM_UNLIKELY((*nimErr_))) {
goto BeforeRet_;
}
a__testexcept_u45 = T2_;
nimln_(12);atomicStoreN__testexcept_u47(((&v__testexcept_u46)), ((NI) 43));
if (NIM_UNLIKELY((*nimErr_))) {
goto BeforeRet_;
}
nimln_(13);T3_ = ((NI) 0);
T3_ = atomicLoadN__testexcept_u53(((&v__testexcept_u46)));
if (NIM_UNLIKELY((*nimErr_))) {
goto BeforeRet_;
}
w__testexcept_u59 = T3_;
BeforeRet_: ;
nimTestErrorFlag();
popFrame();
}
}
```
Note the repeated checks for `*nimErr_`.
With this PR applied, the checks vanish:
```c
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
nimfr_("testexcept", "/tmp/testexcept.nim");
nimlf_(7, "/tmp/testexcept.nim");z__testexcept_u32 = atomicExchangeN__testexcept_u4((&x__testexcept_u2), y__testexcept_u3, ((int) 4));
nimln_(9);a__testexcept_u45 = atomicCompareExchangeN__testexcept_u33((&x__testexcept_u2), (&y__testexcept_u3), y__testexcept_u3, NIM_TRUE, ((int) 4), ((int) 4));
nimln_(12);atomicStoreN__testexcept_u47(((&v__testexcept_u46)), ((NI) 43));
nimln_(13);w__testexcept_u59 = atomicLoadN__testexcept_u53(((&v__testexcept_u46)));
nimTestErrorFlag();
popFrame();
}
}
```
For reference, with gcc as backend the generated code looks as follows:
```c
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
nimfr_("testexcept", "/tmp/testexcept.nim");
nimlf_(7, "/tmp/testexcept.nim");z__testexcept_u9 = __atomic_exchange_n((&x__testexcept_u2), y__testexcept_u3, __ATOMIC_ACQ_REL);
nimln_(9);a__testexcept_u18 = __atomic_compare_exchange_n((&x__testexcept_u2), (&y__testexcept_u3), y__testexcept_u3, NIM_TRUE, __ATOMIC_ACQ_REL, __ATOMIC_ACQ_REL);
nimln_(12);__atomic_store_n(((&v__testexcept_u19)), ((NI) 43), __ATOMIC_ACQ_REL);
nimln_(13);w__testexcept_u29 = __atomic_load_n(((&v__testexcept_u19)), __ATOMIC_ACQ_REL);
nimTestErrorFlag();
popFrame();
}
}
```
With this PR the program from #25445 yields the correct output `Error:
unhandled exception: index 4 not in 0 .. 3 [IndexDefect]` instead of
crashing with a SIGSEGV.
PS: Unfortunately, I did not find out how to run the tests with MSVC.
`./koch tests --cc:vcc` doesn't use MSVC.
(cherry picked from commit 49961a54dd)
From the Standard Library Style Guide:
> Type identifiers should be in PascalCase. All other identifiers should
> be in camelCase with the exception of constants which may use
> PascalCase but are not required to.
(cherry picked from commit 358d9b4497)