fixes#25800
closes https://github.com/nim-lang/Nim/pull/25807
ref https://github.com/nim-lang/Nim/issues/25800
This pull request improves the handling of move semantics and the
`=wasMoved` hook in the Nim compiler, especially for C++ code generation
and user-defined types. It refactors the move operation logic to better
support custom hooks, adds new tests for edge cases, and ensures that
the `move` operation is safer and more predictable.
**Move semantics and `=wasMoved` handling:**
* Refactored the move operation in `compiler/ccgexprs.nim` by
introducing helper procs (`canGenMoveCall`, `genMoveCall`,
`genWasMovedCall`, `genMoveWithWasMoved`) to better handle cases with
user-defined `=wasMoved` hooks, especially for generics and C++ interop.
The logic now distinguishes between simple assignments and when to call
custom hooks, improving correctness and maintainability.
[[1]](diffhunk://#diff-4509107d295d7d32b1887c8993cd0f56113ae60f36113e7d8778646dabd92ebcL2818-R2851)
[[2]](diffhunk://#diff-4509107d295d7d32b1887c8993cd0f56113ae60f36113e7d8778646dabd92ebcL2841-R2882)
* Updated the `move` proc in `lib/system.nim` to include the `nodestroy`
pragma, preventing double destruction and making move semantics safer.
**Testing and validation:**
* Added a new test (`tests/ccgbugs2/t25800.nim`) to ensure that
user-defined `=wasMoved` hooks with `{.importcpp.}` are correctly
generated and invoked in C++ code, addressing a specific bug with
invalid preprocessor directives.
* Expanded `tests/destructor/twasmoved.nim` with additional test cases
for objects with and without custom `=wasMoved` hooks, including
multithreaded scenarios using `threadpool`, to verify correct behavior
in a variety of contexts.
**Minor cleanup:**
* Added a blank line for code style consistency in
`compiler/semmagic.nim`.
Fixes#18583.
## Problem
Several stdlib collection types compute the separator for `$` using
`result.len > 1`, where `result` starts as the opening bracket (`"["` or
`"{"`). This breaks when a collection element type has a `$` that
returns an empty string: `result.len` stays at 1 after the first item
contributes nothing, so the separator is never inserted for subsequent
items.
```nim
import std/deques
type Test = object
proc `$`(x: Test): string = ""
echo [Test(), Test()].toDeque # prints [] — expected [, ]
```
## Fix
Replace the length check with an explicit `first` flag in all affected
modules: `deques`, `heapqueue`, `lists`, `critbits`, and `strtabs`.
## Tests
Regression tests added to `tdeques`, `theapqueue`, and `tlists` using a
local type whose `$` returns `""`. All three test files pass with `nim c
-r`.
## Notes
I work with Claude as a co-processor. I'm 56, came to programming late,
and this is genuinely how I learn and contribute. I understand what I'm
submitting, but I didn't write it alone. If your project prefers
human-only contributions, just say so and I'll close without friction.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary
- Fixes `std/pegs` lexing for bare UTF-8 terminals such as `\i café`.
- The lexer previously stopped at the first non-ASCII byte, so
`pkTerminalIgnoreCase` never saw the full term despite its rune-aware
`fastRuneAt`/`toLower` matching.
- This now keeps non-ASCII bytes in identifier-style terminals while
ASCII non-ident characters still terminate the symbol.
## Behavior
Before: `match("CAFÉ", peg"\i café")` failed because the terminal was
lexed as `caf`.
After: `match("CAFÉ", peg"\i café")`, `match("Café", peg"\i café")`, and
`findAll` over mixed-case occurrences pass.
`std/pegs` documents `useUnicode = true` as proper UTF-8 support, and
quoted terminals already preserved the same bytes; this makes bare
terminals consistent with that path.
I did not find an existing relevant issue or PR in searches for
pegs/unicode/utf8/getSymbol/pkTerminalIgnoreCase.
fixes#25821
This pull request includes a minor bug fix in the lexer and adds new
test cases for string formatting with binary operators in interpolated
expressions.
Lexer bug fix:
* Fixed an off-by-one error in the unary minus detection logic in the
`rawGetTok` procedure in `lexer.nim`, ensuring that the start-of-buffer
condition is correctly checked.
Testing improvements:
* Added tests to `tstrformat.nim` to verify that binary operators (such
as subtraction) work correctly inside interpolated string expressions
using both `&` and `fmt`.
Preserves implicit imports instead of always storing the resolved
absolute filename. That lets the later StdPrefix warning check see the
original std/objectdollar spelling.
This is for situations where in cfg or cli warnings are enabled for the
prefix. Essentially a niche combination of compiler switches don't get
along e.g.
`-d:nimPreviewSlimSystem --warning:StdPrefix:on
--warningAsError:StdPrefix:on --import:std/objectdollar`
will cause:
`Error: objectdollar needs the 'std' prefix [StdPrefix]`
fixes#25617
This pull request introduces a stricter check for parameter type
relations in the `procParamTypeRel` procedure. Specifically, it ensures
that two types are not only structurally equal but also have the same
backend type, taking type aliases into account.
Type relation checks:
*
[`compiler/sigmatch.nim`](diffhunk://#diff-251afcd01d239369019495096c187998dd6695b6457528953237a7e4a10f7138R787-R789):
In `procParamTypeRel`, added a check to ensure that if two types are
considered equal (`isEqual`), they must also have the same backend type
(using `sameBackendTypePickyAliases`). If not, the result is set to
`isNone`, preventing false positives when type aliases differ.
ref https://github.com/nim-lang/Nim/pull/25783
This pull request addresses an issue with addressability of tuple
elements of type `lent` or `var` in Nim, ensuring that expressions
involving these types are handled correctly during type changes. The
main changes introduce a check to prevent attempting to change the type
of tuple elements that are views (`var` or `lent`), and a new test is
added to verify the correct error is raised when trying to take the
address of such elements.
Type system and semantic analysis improvements:
* Added the `isViewTarget` template in `semexprs.nim` to check if a type
is a view (`var` or `lent`), and updated `changeType` to skip type
changes for tuple elements that are views. This prevents invalid
addressability operations on these types.
[[1]](diffhunk://#diff-539da3a63df08fa987f1b0c67d26cdc690753843d110b6bf0805a685eeaffd40R655-R657)
[[2]](diffhunk://#diff-539da3a63df08fa987f1b0c67d26cdc690753843d110b6bf0805a685eeaffd40R686-R693)
Testing:
* Added a new test `tlent_tuple_address.nim` to verify that attempting
to take the address of tuple elements of type `lent` correctly produces
an "expression has no address" error.
fixes#25784
This pull request addresses the handling of forward object types during
type determination in the Nim compiler and adds new test cases to ensure
correct default value initialization for objects with forward
references. The main focus is to allow forward object types to remain
unresolved during the initial type analysis, deferring their resolution
to a later compilation phase. This helps support object constructors
with default values involving forward types.
**Compiler improvements:**
* Updated `semObjConstr` in `compiler/semobjconstr.nim` to allow forward
object types (`tyForward`) to remain unresolved during determine-type
analysis. This avoids premature errors and ensures that such types are
resolved later, supporting delayed field-default resolution.
**Testing enhancements:**
* Added new test cases in `tests/objects/mobject_default_value.nim` to
verify that objects with default fields referencing forward types are
correctly initialized, and that their default values are properly set.
---------
Co-authored-by: Copilot <copilot@github.com>
fix#25789
This pull request addresses an issue with the `distinctBase` trait in
the Nim compiler, ensuring it correctly handles types with generic
parameters and static parameters. Additionally, it adds a new test to
cover this scenario. The most important changes are:
### Compiler logic improvements
* Updated the `evalTypeTrait` implementation for the `distinctBase`
trait in `compiler/semmagic.nim` to properly skip all relevant type
wrappers, including those with generic and static parameters, when
unwrapping distinct types. This fixes incorrect handling of types like
`distinct L[int, 100]`.
### Test coverage
* Added a new test block for bug #25789 in
`tests/metatype/ttypetraits.nim` that defines a distinct type over a
generic type with a static parameter, verifies conversions, and checks
that the `distinctBase` trait returns the correct type.
## Bug
When an `except T as e:` handler in the cpp backend raises a new
exception, the enclosing `finally` block is silently dropped under
`--mm:arc` and `--mm:orc`:
```nim
proc main() =
try:
try:
raise newException(CatchableError, "orig")
except CatchableError as e:
echo "inner: ", e.msg
raise newException(CatchableError, "re:" & e.msg)
finally:
echo "finally"
except CatchableError as outer:
echo "outer: ", outer.msg
main()
```
Expected output:
```
inner: orig
finally
outer: re:orig
```
Actual output on `nim cpp --mm:arc` (and `--mm:orc`):
```
inner: orig
outer: re:orig
```
The `finally` line is missing. The bug is specific to memory managers
that use destructor injection (arc/orc); under `--mm:refc` the original
code path works correctly because no destructor wrapper is injected.
## Root cause
When the body of `except T as e:` is processed under ARC/ORC, the
destructor injection pass injects a compiler-generated `nkHiddenTryStmt`
wrapper around the handler body to call `=destroy` on `e` when it goes
out of scope. That wrapper sits at the top of `p.nestedTryStmts` with
`inExcept = false`.
`finallyActions` (which inlines the user-finally body before a raise
propagates) only inspected the topmost entry of `nestedTryStmts`.
Because the wrapper has `inExcept = false`, the check short-circuited
and the user's finally was never inlined.
After the raise, C++'s rule that sibling catch clauses do not catch each
other's throws means the surrounding `catch(...)/finally` emitted by
`genTryCpp` never runs either, so the user's finally is silently
dropped.
## Fix
- Add an `isHidden` flag to `nestedTryStmts` entries, set to `t.kind ==
nkHiddenTryStmt` so compiler-injected try wrappers can be distinguished
from user-written ones.
- In `finallyActions`, walk past `isHidden` wrappers but stop at the
first user try. If that user try is in its except branch with a finally,
inline the finally body before the raise; otherwise leave the raise
untouched (the raise will be caught by that user try's own except
branches and the inner finally will run via normal unwinding, which is
what already happens correctly under refc).
Walking past wrappers fixes the `as e` case under arc/orc. Stopping at
user trys preserves the existing correct behaviour for nested
try/except/finally constructs (e.g. `tests/exception/tfinally.nim`'s
`nested_finally`), which would otherwise see the outer finally inlined
too eagerly when an inner raise is processed.
## Tests
Adds `tests/exception/tcpp_handler_raise_finally.nim` covering:
- `except T as e:` re-raise + outer finally
- typeless `except:` re-raise + outer finally
- try/finally without except (exception propagation through finally)
The test runs on `--mm:arc`, `--mm:orc`, and `--mm:refc`.
Locally verified on both `devel` and `version-2-2`:
- `tests/exception/` — 42 PASS, 0 FAIL, 3 SKIP
- `tests/destructor/` — all PASS
- `tests/cpp/` — all PASS (single unrelated failure: `tasync_cpp.nim`
needs the `jester` package)
- `megatest` — PASS for both `--mm:arc` and `--mm:refc`, including the
previously regressing `tfinally.nim`'s `nested_finally`
## Backport
Tagged `[backport]` in the commit message for inclusion in
`version-2-2`.
---------
Co-authored-by: puffball1567 <17452514+puffball1567@users.noreply.github.com>
`setLenUninit(string)` was broken on the legacy refc backend when
growing within existing spare capacity.
`setLengthStrUninit` in `lib/system/sysstr.nim` only updated len when it
had to reallocate or when shrinking.
If oldLen < newLen <= capacity, it returned early without finalizing:
```nim
var s = newStringOfCap(10)
s.add("abc")
s.setLenUninit(6)
doAssert s.len == 6 # used to fail, len stayed 3
```
This escaped `tests/stdlib/tstring.nim` because the testing routine
`checkSetLenUninit` mostly resizes strings created at **exact**
length/capacity, so growth usually took the reallocating branch.
The new regression test covers the missing edge case.
So sorry for catching this only on the day of the stable release! In my
defense, the original PR hung in limbo for quite a while and it didn't
spend enough time in devel after the merge.
fixes#25650
This pull request refactors and improves the dependency resolution logic
in the Nim compiler, The most important changes are grouped below:
### Dependency Resolution Refactor
* Replaced the `resolveFile` procedure with two more specialized
procedures: `resolveImport` (which uses the compiler's module lookup
rules for imports) and `resolveInclude` (which resolves includes
relative to the including file or search paths). Updated all usages
accordingly, improving clarity and correctness of dependency handling.
[[1]](diffhunk://#diff-1203947eecb9ef641ce7ee029677f875eb983de050b82c65ca286517feed00e6L82-R94)
[[2]](diffhunk://#diff-1203947eecb9ef641ce7ee029677f875eb983de050b82c65ca286517feed00e6L106-R103)
[[3]](diffhunk://#diff-1203947eecb9ef641ce7ee029677f875eb983de050b82c65ca286517feed00e6L121-R118)
* Removed the unused `strutils` import from `compiler/deps.nim` for
cleaner dependencies.
### Testing Improvements
* Added `import std/strbasics` to `tests/ic/tmiscs.nim` to ensure
required symbols are available for tests.
I tried to improve `resolveFile`, which is harder because either we need
to add `lib/std` to search path and all of other nested directory to
`--path` in `config/nim.cfg`. So I choose toi reuse `findModule` for
imports
fixes#25751
This pull request improves the JavaScript backend code generation and
expands test coverage, particularly around temporary and loop variables,
as well as object destruction behavior. The main changes include
updating the code generator to handle more symbol kinds and adding tests
to ensure proper destruction and option handling.
**JavaScript code generation improvements:**
* Updated `genSymAddr` in `compiler/jsgen.nim` to support additional
symbol kinds, specifically `skTemp` and `skForVar`, ensuring correct
address generation for temporaries and loop variables.
**Test suite enhancements:**
* Added tests in `tests/js/test2.nim` to verify correct behavior of
option types, object destruction (`=destroy`), and to check for
backend-specific crashes. This includes printing results of
option-returning functions and confirming destruction messages.
* Updated expected output in `tests/js/test2.nim` to include results
from new tests and destruction messages, ensuring the test suite
reflects the latest code behavior.
ref: #25667
drain deferred reification in a loop until there is no more work to do.
Could potentially evaluate the same deferred work more than once.
---------
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
fixes#25469
This pull request introduces an important fix to argument handling in
the compiler's transformation logic and adds a new test to verify
correct behavior with distinct types and ARC memory management.
### Compiler transformation improvements
* Updated `putArgInto` in `compiler/transf.nim` to handle
`nkHiddenStdConv`, `nkHiddenSubConv`, and `nkConv` nodes more
accurately. Now, if the types match (ignoring distinctness and shallow
range differences), the argument is recursively processed; otherwise, it
falls back to a fast assignment. This prevents incorrect assignments
when dealing with type conversions and distinct types.
### Testing for distinct types and ARC
* Added a new test `tdistinct_for_nodup.nim` to ensure correct iteration
and memory management for distinct sequences of large arrays under ARC.
The test checks that the sequence length remains unchanged during
iteration, helping catch regressions related to ARC and distinct types.
fixes#25735
This pull request updates how string-to-C-string conversions are handled
when the `nimsso` configuration flag is enabled, and adds a new system
test to validate the behavior. The main changes focus on switching from
using `addrLoc` to `byRefLoc` for argument preparation, which likely
improves correctness or compatibility with the `nimsso` mode.
**Code generation improvements for `nimsso` mode:**
* In both `compiler/ccgcalls.nim` (`genArgStringToCString`) and
`compiler/ccgexprs.nim` (`convStrToCStr`), replaced the use of `addrLoc`
with `byRefLoc` when preparing arguments for string-to-C-string
conversions under the `nimsso` configuration flag. This change ensures
that references are handled appropriately according to the requirements
of `nimsso`.
[[1]](diffhunk://#diff-42181cc6f4202af843e7835ea514df2efe85e4faae3bc797a39a0c422547b558L373-R373)
[[2]](diffhunk://#diff-4509107d295d7d32b1887c8993cd0f56113ae60f36113e7d8778646dabd92ebcL2739-R2739)
**Testing:**
* Added a new system test `tests/system/tnimsso.nim` that runs with the
`-d:nimsso` flag on both C and C++ targets, checking that
string-to-C-string conversion works as expected in `nimsso` mode.
Adds `system.setLenUninit` for the `string` type. Allows setting length
without initializing new memory on growth.
- Required for a follow-up to #15951
- Accompanies #22767 (ref #19727) but for strings
- Expands `stdlib/tstring` with tests for `setLen` and `setLenUninit`
---------
Co-authored-by: Andreas Rumpf <araq4k@proton.me>
Follow up PR to #25700
@demotomohiro
This doesn't seem to mirror your suggested approach completely. I still
went with a recursive walk. Could probably add some kind of "clean
types" and "dirty types" cache through this to minimize the recursions,
but that seems like a little much.
fixes#25730
As mentioned in the issue this results in less optimized output, it
always generates the explicitly called hook as a proc rather than an
inline assignment. But maybe this is a reasonable trade since it only
happens on explicit `=sink`/`=copy` calls.
Any way to optimize it requires detecting either the type or the found
hook as a trivial assignment. I am not sure how to do these, the hook
isn't like destructors that propagate empty statements in
`liftdestructors` (which is what `isTrivial` checks for), it needs to
propagate simple assignments instead. And there is no logic for the
type, `tfHasAsgn` is misleading since it only checks if the destructor
is trivial, because there is no check for a trivial assignment.
Did not mark as backported but the only issue I can think of is the
performance issue above, otherwise it would be more correct if anything.
fixes#25727, regression from #24627 which was backported to 2.2.2 and
2.0.16
Instead of calling `createTypeBoundOps` for explicit hook calls and when
generating default hooks, only the called destructor is generated at a
time. This allows defining more than 1 hook for recursive types.
`=sink` for `useSeqOrStrOp` and also `atomicRefOp` always need a
`=destroy` hook generated so that is also generated separately. There
might be more that I missed, only the atomicRefOp one failed `trtree` in
CI, and it was just from a compiler assert that got triggered, otherwise
it would still have functioned.
fixes#25724
This pull request introduces a small but important fix in the compiler
and adds a new test case related to iterators. The main change in the
compiler ensures that lambda-like constructs are handled consistently
with other procedure definitions, while the new test in the suite covers
a previously untested scenario.
**Compiler improvements:**
* Updated `introduceNewLocalVars` in `compiler/transf.nim` to handle all
`nkLambdaKinds` in addition to `nkProcDef`, `nkFuncDef`, `nkMethodDef`,
and `nkConverterDef`, ensuring consistent transformation of all
lambda-like constructs.
**Testing:**
* Added a block to `tests/iter/titer_issues.nim` to test iterator
behavior in both compile-time and run-time contexts, addressing bug
#25724.
fixes#25637
This pull request refactors the way the `sfInjectDestructors` flag is
set on symbols during lambda lifting in the Nim compiler. The main
change is the introduction of a helper procedure to encapsulate the
logic for marking symbols that require destructor injection, improving
code clarity and maintainability.
Refactoring and code quality improvements:
* Introduced the `markInjectDestructors` procedure to encapsulate the
logic for marking a symbol with the `sfInjectDestructors` flag, ensuring
that `backendEnsureMutable` is always called before modifying the
symbol's flags.
* Replaced direct flag manipulation (`owner.incl sfInjectDestructors`
and `prc.incl sfInjectDestructors`) with calls to the new
`markInjectDestructors` procedure in multiple locations, including
`makeClosure`, `createTypeBoundOpsLL`, and `rawClosureCreation`.
[[1]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L231-R235)
[[2]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L243-R247)
[[3]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L639-R643)
fixes#25697
This pull request improves the handling of borrowed routines in the
compiler transformation phase, making the code more robust and
maintainable. The main change is the introduction of a helper function
to properly resolve borrowed routine symbols, which is then used in
multiple places to ensure correct symbol resolution. Additionally, a new
test case is added to cover a previously reported bug related to
borrowed iterators on distinct types.
**Compiler improvements:**
* Added `resolveBorrowedRoutineSym` helper function to follow borrow
aliases and retrieve the underlying implementation symbol for borrowed
routines. This centralizes and clarifies the logic for resolving
borrowed symbols.
* Updated `transformSymAux` and `transformFor` to use the new helper
function, replacing duplicated logic and improving correctness when
handling borrowed routines.
[[1]](diffhunk://#diff-c7b80f51fb685eb22c5b56ee2f320d6c708706f3ae7293478ecd104a2b5b8096L139-R154)
[[2]](diffhunk://#diff-c7b80f51fb685eb22c5b56ee2f320d6c708706f3ae7293478ecd104a2b5b8096L788-R795)
**Testing:**
* Added a test case for bug #25697 to `tests/distinct/tborrow.nim`,
ensuring that iteration over a distinct type with a borrowed iterator
works as expected.
#25713
```nim
type
K = enum
k1,k2
Variant = object
case kind: K
of k1:
discard
of k2:
discard
proc a(x: var K) = discard
proc b(x: ptr K) = discard
var x = Variant(kind: k1)
{.cast(uncheckedAssign).}:
# must be within uncheckedAssign to work
a(x.kind)
# doesn't work out of or under uncheckedAssign
b(addr x.kind)
```
Nested transformBody/liftLambdas passes used a fresh DetectionPass, so
getEnvTypeForOwner could allocate a duplicate PType for the same owner
while :envP already referenced the inner pass type. When addClosureParam
saw cp.typ != t, it errored.
If both types are env objects for the same routine owner, reuse cp.typ
and sync ownerToType.
Adds regression test tests/iter/t21242_nested_closure_in_iter.nim.
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.
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.
```nim
template compute(body: untyped): int =
block:
body
let x = compute:
var sum = 0
for i in 1..10: sum += i
sum
echo x
```
supersedes https://github.com/nim-lang/Nim/pull/25653
which in
02893e2f4c
```nim
of nkSym:
genSingleVar(p, it.sym, newSymNode(it.sym), it.sym.astdef)
```
A new branch for `nkSym` is added, though more changes might be needed
if `nkSym` is handled specifically
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.
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.