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.
fixes#25886fixes#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>
I was updating nim to 2.2.10 in nixpkgs
https://github.com/NixOS/nixpkgs/pull/538469
and without this change the fail build, because add(string, cstring) is
not defined. I think it's caused by a change of position of the includes
in system, but with this it works fine.
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
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.
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`.
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.
The emscripten branch cast the descriptor address to the value type
EmscriptenMMapBlock instead of the pointer alias PEmscriptenMMapBlock,
so osAllocPages stored realSize/realPointer in a discarded local and
osDeallocPages reinterpreted the address integer as the descriptor
instead of dereferencing it -- calling munmap() with garbage that fails,
so freed pages are never returned. Freed huge chunks are also dropped
from the free list, leaking permanently. Affects wasm32 and wasm64.
Cast to PEmscriptenMMapBlock so both accesses go through memory.
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.
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.
This PR implements `expandSymlink` on Windows with POSIX readlink
semantics: it expands exactly one hop and returns the stored link target
without resolving the full chain.
The main design question was whether Windows symlink expansion should be
built on path-finalization APIs such as `GetFinalPathNameByHandleW`, or
on direct reparse-point inspection. Current `expandSymlink` is a
single-hop "what target is stored in this link object?" operation and
most of other ways to resolve symlinks on Windows actually try to answer
the "final true file location" question in various slightly-incompatible
ways.
The full final-path resolution on Windows is substantially more complex
than readlink and is planned as a follow-up.
## Implementation choice
Implements Windows `expandSymlink` by:
- opening the path with `FILE_FLAG_OPEN_REPARSE_POINT`
- calling `DeviceIoControl(FSCTL_GET_REPARSE_POINT)`
- parsing the reparse payload for `IO_REPARSE_TAG_SYMLINK` and
`IO_REPARSE_TAG_MOUNT_POINT`
- decoding the UTF-16 slice referenced by the payload
- returning the stored target
This is the right primitive for the API:
- does not depend on whole-path finalization
- works for both symlinks and junctions
- matches the existing Linux behaviour
`widestrs` changes allow using WideCString views without temporary
allocations.
Windows prohibits symlink creation without admin rights, so,
unfortunately, the tests are conditionally skipped by default. Manually
running `testament` in an admin console is required.
## Behaviour:
- One hop only
- Relative symlink targets are returned unchanged
- Absolute Windows targets are converted from stored NT-style prefixes
to usable Win32 forms when applicable
- Non-links, malformed payloads, and unsupported reparse tags raise
`OSError`
## Future work
Path canonicalization, i.e. "final true file location". Which is, BTW,
different from `absolutePath`, which works on paths only and doesn't hit
the underlying FS. So this needs to be an API extension.
I'd like to follow-up with this when I sort through the docs, for now
you can resolve symlinks in a loop.
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
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.
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.
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.
Companion to readRawData whose pointer stays valid across moves/copies
of the string. Under --strings:sso it promotes a small inline string to
its heap representation; under refc/v2 the data is already heap-resident
so it aliases readRawData.
Uniform `var string` signature on every backend so code can prepare for
--strings:sso without `when declared`.
Fixes#19240.
The Manual's "Delegating bind statements" example didn't compile (module
B didn't import A, type `O` wasn't exported, and `x: T` couldn't bind to
`var O`), and once those were fixed it compiled *without* the `bind`
statement — so it didn't demonstrate delegating bind at all.
This replaces it with a minimal example that genuinely requires `bind
init`: `module main` imports A and B but not C, so `init` is not in
scope at the final instantiation of `genericA`; the open `mixin` symbol
fails to resolve without `bind init` forwarding it from module B.
Verified to fail without `bind` and compile with `bind` under Nim
2.2.10.
---
Disclosure: I work with Claude as a co-processor. I understand what I'm
submitting and I verified the example against the compiler myself. If
you prefer human-only contributions, just say so and I'll close without
friction.
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.
fixes#18367fixes#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.
fixes#25903fixes#25904
`nkExceptBranch` can have variable structure depending on the exception
types and it should handle the last node of the `nkExceptBranch`
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.