Commit Graph

23039 Commits

Author SHA1 Message Date
ringabout
f1ff8b6d9e fixes #25849; fixes #25872; Iteration on elements of array (#25860)
fixes #25849
fixes https://github.com/nim-lang/Nim/issues/25872
2026-06-06 07:58:19 +02:00
Ryan McConnell
46259cd0b8 fix sortVTableDispatchers KeyError on re-entrant method registration via when isMainModule (#25856)
Encountered in realistic scenario. Didn't really look at this one. AI
one shot it lol

When a module defines method-bearing types and a when isMainModule
block imports additional modules that also define methods on the same
type hierarchy, sortVTableDispatchers crashes with:

Error: unhandled exception: key not found: (module: N, item: M)
[KeyError]

Root cause: the itemTable built during vtable sorting is populated
from g.objectTree[baseType], which only contains types from the
current compilation pass. When when isMainModule triggers re-import
of method-bearing modules, the method bucket contains types from both
passes. Types from the first pass have ItemIds not present in the
second pass's object tree, so itemTable[obj.itemId] raises KeyError
at line 155.

Fix: if obj.itemId is missing from itemTable, create an empty slot
array of the correct length. The entry is a local temporary — the
second loop in sortVTableDispatchers only calls setMethodsPerType
for types in the current object tree, so types from the prior pass
retain their already-established dispatch. The entry exists solely to
prevent the KeyError during the assignment loop.

The methodIndexLen used for the new entry is the bucket's slot count,
which is correct for any type in the hierarchy.

Added test tests/method/tvtable_reentry.nim that defines methods
across three types in two compilation passes and verifies dispatch
correctness for all three.
2026-06-05 16:37:00 +02:00
ringabout
4b374eb0a6 stop a temp register from being freed if addressed for lent (#25861)
ref https://github.com/nim-lang/Nim/issues/25849

The important part is in compiler/vmgen.nim:1838: when the VM lowers
a[i] or a.b as an address-producing operation, it emits opcLdArrAddr /
opcLdObjAddr. That returns an alias into the storage owned by the source
register. Before the patch, that source register could still betreated
as a normal temporary and later reclaimed or reused by the allocator.
Once that happened, the address result was still live, but the backing
temp was no longer guaranteed to exist, which is what led to the
nil/illegal-storage crash.

The fix is to pin that source temp by changing its slot kind to
slotTempPerm right after emitting the address load. You can see the same
lifetime rule already existed for the generic addr(...) path around
compiler/vmgen.nim:1551: if the source is a temporary and we take its
address, the compiler marks it permanent so freeTemp won’t recycle it.
The patch extends that exact rule to array and object address loads:

- compiler/vmgen.nim:1843
- compiler/vmgen.nim:1861

slotTempPerm is outside the normal freeTemp range in
compiler/vmgen.nim:248, so once a temp is upgraded to permanent, the VM
allocator stops treating it as reusable. That is the actual root-cause
fix: it preserves the backing storage for the address result until the
surrounding evaluation is done.

The regression test in tests/vm/t25849.nim:8 forces exactly that path
with a local lent iterator over an array and a static VM evaluation.
2026-06-04 13:29:48 +02:00
Corey Leavitt
c8e805a2fa fixes #25595; cursor inference: a recorded mutation extends the variable's liveness (#25864)
fixes #25595

## Bug

A `let` bound to a field of a value-type **case object** with a `ref`
field is inferred as a non-owning cursor, but the cursor's source can be
mutated through the cursor's own ref during a call, freeing the ref
while the borrow still reads it. Use-after-free under arc/orc (refc is
unaffected, it has no cursor inference):

```nim
var destroyed = false
type
  O = ref object
    value: int
    home: H
  W = object
    case k: bool
    of true: r: O
    of false: discard
  H = ref object
    w: W
proc `=destroy`(o: var typeof(O()[])) =
  destroyed = true
proc clear(o: O): int =
  o.home.w = W()             # overwrites h.w via the back-reference -> frees the ref
  doAssert not destroyed     # fails: the element was destroyed during the call
  result = o.value
proc go(h: H): int =
  let c = h.w                # inferred cursor (borrow of h.w)
  result = clear(c.r)
proc main =
  let h = H()
  let o = O(value: 42)
  o.home = h
  h.w = W(k: true, r: o)
  doAssert go(h) == 42
main()
```

The `not destroyed` assert fails: the element is destroyed during the
call, so the following `o.value` read is a use-after-free. The same code
with the `=destroy` guard removed (so the freed `o.value` is actually
read) is reported as `heap-use-after-free` by ASan under `-d:useMalloc
-fsanitize=address`. Longstanding (reproduces back to 2.2.0).
`--cursorInference:off` is a workaround.

## Root cause

Cursor inference (`varpartitions.computeCursors`) cursors `let c = h.w`
unless `dangerousMutation` finds a mutation of `c`'s graph within `c`'s
alive range `aliveStart..aliveEnd`. Here the mutation (the `clear(c.r)`
call) *is* connected to `c`'s graph and *is* recorded with `isMutated`,
but it is recorded at an `abstractTime` just past `c.aliveEnd`, so the
range check misses it.

The gap is timing. `aliveEnd` is set from the last `nkSym` use of `c`. A
call records its argument's mutation *after* traversing the whole
argument subtree (`potentialMutationViaArg`). When the argument is `c.r`
on a case object it is an `nkCheckedFieldExpr` (the discriminant check),
whose extra nodes advance `abstractTime` past `c`'s last `nkSym`. A
plain `nkDotExpr` has no such gap, so the bug needs a case object.

## Fix

In `potentialMutation`, extend the mutated variable's liveness to the
mutation time:

```nim
v.s[id].aliveEnd = max(v.s[id].aliveEnd, v.abstractTime)
```

A variable mutated at time T is provably alive at T, so this only
completes the liveness computation that `dangerousMutation` relies on.
The worst case is an extra copy, never an unsound cursor.

## Note on the locus

The fix is conservative by mechanism (it runs at every recorded
mutation) but perf-neutral in practice: it only suppresses a cursor
where the corrected liveness proves the borrow unsafe (cursor counts are
unchanged on the suites). I can scope it to call arguments if you'd
prefer it narrower.

## Test

`tests/arc/t25595.nim`, matrix `--mm:orc; --mm:arc; --mm:refc`: the
repro above as a `doAssert`. Fails (UAF) on arc/orc before the fix and
passes after. refc passes throughout.

## Checks

- repro passes on orc/arc after the fix. The guard-removed variant
(which reads the freed value) is ASan-clean after the fix and was
heap-use-after-free before. refc unaffected.
- testament `destructor` 90/90, `arc` 120/120. `views` 5/6, same as
stock (the one failure is environmental and pre-exists this change).
- perf-neutral: inferred-cursor count is identical stock vs fix across
the `arc` and `destructor` test files under `--mm:orc` (322 vs 322).
2026-06-03 07:25:33 +02:00
Corey Leavitt
73986c03a1 fixes #25857; don't treat typeof(result) as a use-before-init of result (#25858)
fixes #25857

## Bug

`typeof(result)` inside the expression that builds `result` gets counted
as a read
of `result` before it's set. On a `{.requiresInit.}` return type that's
a hard error
("'result' requires explicit initialization"). `typeof` never evaluates
its operand,
so it's a false positive. On 2.2.4 it compiles, but the same line still
emits a bogus
`ProveInit` warning, so no released version gets it right.

Regression from #25151. That PR made a used-before-init `requiresInit`
result a hard
error instead of a warning, which is correct on its own. The side effect
was that
this old false-positive warning became a build error.

## Root cause

`track` in `compiler/sempass2.nim` has no arm for `nkTypeOfExpr`, so it
hits the
default that recurses into every child, reaches the `result` `nkSym`
inside the
`typeof`, and calls `useVar`. `sizeof`/`compiles`/`declared` don't hit
this because
they fold to a constant before `track` runs. A `typeof(result)` typedesc
argument
survives into `track`.

## Fix

Skip `nkTypeOfExpr` in `track`. Its operand is never evaluated, so it
isn't a
definite-assignment use. After the patch there's no error and no warning
here, even
with `--warnings:on`. The #25151 check is untouched: a real use of
`result` before
init is a plain `nkSym`, not inside a `typeof`, so it still reaches
`useVar`.

## Test

`tests/init/t25857.nim`, a positive test that compiles and prints `1`.

## Checks

- Repro compiles and runs on patched 2.2.6 and patched devel.
- `tests/errmsgs/t25117.nim` still fails as expected. A real
`xxx(result)` before
  init still errors.
- `testament cat init` and `testament cat errmsgs` green on patched
devel (55 tests,
  0 failures), including the `--warningAsError:ProveInit` tests.
- Bisect: parent `1ab68797` good, `576c4018` (#25151) bad.
2026-06-02 07:07:44 +02:00
ringabout
88a18de44f fixes #25851; ensure --panics:on does not skip nimErr_ check after closure calls (#25855)
fixes #25851

## Summary: `--panics:on` drops `nimErr_` check after closure calls
(#25851)

### Bug

With `--exceptions:goto` and `--panics:on`, the compiler skipped the
`nimErr_` check after indirect closure calls whose result flows directly
into another call (e.g., `result.add elem(src)`). A raise inside the
closure was silently swallowed — the loop continued, and the next
`raise` hit the already-set `nimInErrorMode` flag, overflowing its
`bool` storage into `OverflowDefect`.

### Root Cause

**ast.nim** — `canRaise` checked `fn.typ.n[0].len < effectListLen` first
(false after the expansion) and then `exceptionEffects != nil` (also
false, nil), so it returned `false` — meaning "cannot raise." The C
codegen trusted this and omitted the `nimErr_` check.

### Fix

**ast.nim** — `canRaise` now treats `nil` `exceptionEffects` as "unknown
→ can raise" (`exceptionEffects == nil` as an additional true
condition). This is defense-in-depth: even if some other path expands
the list but leaves `exceptionEffects` nil (e.g., a type with `{.tags.}`
but no `{.raises.}`), the error check is still emitted.

### Test

tclosure_err_panic_goto.nim — exercises the double-trigger pattern
(`drawBool` sets the error flag → closure call must propagate it) with
`matrix: "; --panics:on"` covering both exception modes.
2026-06-01 16:21:37 +02:00
Andreas Rumpf
7813bd8b92 fixes #25693 (#25842) 2026-05-29 08:08:42 +02:00
ringabout
645e131739 fixes #25796; fixes procParamTypeRel to ensure backend type consistency (#25798)
fixes #25796

This pull request addresses a subtle type-matching issue in the Nim
compiler related to backend type compatibility, particularly for
procedures returning `lent` types. It also adds new test cases to ensure
correct handling of these scenarios.

**Compiler type-checking fix:**

* Updated `procParamTypeRel` in `compiler/sigmatch.nim` to skip wrappers
like `tyVar`, `tyLent`, `tySink`, and `tyOwned` before comparing backend
types, ensuring more accurate type equivalence checks for procedure
parameters and return types.

**Test coverage improvements:**

* Added multiple blocks in `tests/proc/tproc.nim` to test procedure
types returning `lent` objects, including cases with constants,
variables, and union parameter types, verifying that the compiler now
correctly handles these cases.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 07:58:23 +02:00
puffball1567
7d2f28b046 fixes ReraiseDefect after typeless except: + finally: (cpp backend) (#25777)
## Bug

A bare `except:` followed by a `finally:` block raises a spurious
`ReraiseDefect: no exception to reraise` when compiled with `nim cpp`:

```nim
proc test() =
  try:
    raise newException(CatchableError, "x")
  except:
    discard
  finally:
    echo "finally"

test()
echo "after"
```

Expected output:
```
finally
after
```

Actual output:
```
finally
fatal.nim(53)            sysFatal
Error: unhandled exception: no exception to reraise [ReraiseDefect]
```

This reproduces on every memory manager (`--mm:arc`, `--mm:orc`,
`--mm:refc`).

## Root cause

`genTryCpp` emits `try { ... } catch (Exception* T_) { ... }` followed
by a finally block that ends with `if (T_) std::rethrow_exception(T_);`.
In the *typed* except branches the codegen explicitly sets `T_ =
nullptr;` once the exception is handled, so the rethrow check in the
finally is a no-op.

The typeless `except:` branch (the `if t[i].len == 1` arm) emitted only
`popCurrentException()` and forgot to clear `T_`. After the handler body
finished, `T_` still pointed at the original exception, so the trailing
`if (T_) std::rethrow_exception(T_);` rethrew it. By that point Nim's
current-exception stack had already been popped, and the rethrow
surfaced as `ReraiseDefect`.

## Fix

Emit `T_ = nullptr;` at the start of the typeless `except:` handler
body, mirroring what is already done for the typed branches. This is the
same one-line treatment that fixed the analogous typed-except case for
#5871.

## Tests

Adds `tests/exception/treraise_typeless_except_finally.nim`, exercising
the bug pattern on `--mm:arc`, `--mm:orc`, and `--mm:refc`.

Locally:
- `tests/exception/` — 43 PASS, 0 FAIL, 3 SKIP
- new test passes on all three memory managers

## Backport

Tagged `[backport]` in the commit message — the same bug exists in
`version-2-2` and the fix applies cleanly there.

## Related

Independent of, but in the same family as, #25775 (also currently open).
Both are silent-finally / cpp-backend exception handling fixes; they
touch different lines of `genTryCpp` and don't conflict.

Co-authored-by: puffball1567 <17452514+puffball1567@users.noreply.github.com>
2026-05-29 07:53:37 +02:00
Antonis Geralis
f4dd00c4cc Scan until next special char (", \, \0, \c, \L) and append that slice once. (#25498)
Benchmark comparison (-d:danger --mm:arc --debugger:native -d:useMalloc,
  OpenAI file benchmark, 5 runs):

- Before: 0.196674934, 0.189423191, 0.198763300, 0.197125584,
0.205015032
- After: 0.182827130, 0.183330852, 0.174878542, 0.174360811, 0.181704921
  - Median before: 0.197125584s
  - Median after: 0.181704921s
  - Improvement: 7.82% faster

  Callgrind comparison (same build flags):

  - Total Ir before: 3,219,477,120
  - Total Ir after: 2,449,556,167
  - Total Ir reduction: 23.91%

  parseString hotspot:

  - Before: 1,343,343,723 Ir
  - After: 573,423,735 Ir
  - Reduction: 57.31%
2026-05-27 23:31:39 +02:00
ringabout
3e2cea21ed fixes #22791; ProveField warning with nested case object (#25774)
fixes #22791

This pull request introduces a minor improvement to the handling of
immutable variables in the compiler and adds a new test case for nested
case objects. The most important changes are:

### Compiler improvements

* Updated the `isLet` guard in `compiler/guards.nim` to recognize
`skConst` symbols as immutable variables, ensuring that constants are
correctly identified alongside lets and other immutable types.

### Test coverage

* Added a new test in `tests/objvariant/tcorrectcheckedfield.nim` for
bug #22791, verifying correct pattern matching and field access in
nested `case` objects with constants.
2026-05-27 23:29:27 +02:00
ringabout
cfa769fefc fixes #22950; Poor error message on cast effect violation (#25839)
fixes #22950

This pull request improves the tracking and reporting of effect
annotations (such as `raises`, `tags`, and `forbids`) in pragma blocks,
particularly when using the `cast` pragma. It ensures that the source of
these effect annotations is correctly preserved and referenced, which
improves error reporting and effect analysis. Additionally, a new test
was added to check for violations when using `cast` with effect
annotations.

Effect annotation source tracking and propagation:

* Added new fields (`excSource`, `tagsSource`, `forbidsSource`) to the
`PragmaBlockContext` type to store the original source node for each
effect annotation.
* Updated `castBlock` to set these new source fields when processing
`raises`, `tags`, and `forbids` pragmas, ensuring the source node is
preserved for later error reporting.
* Modified `unapplyBlockContext` to use the stored source node (if
available) when calling `addRaiseEffect`, `addTag`, and `addNotTag`,
improving the accuracy of effect tracking and diagnostics.

Pragma handling improvements:

* Changed the call to `castBlock` in the main pragma processing loop to
pass the entire pragma node, enabling access to the original source for
effect annotations.

Testing:

* Added a new test (`tests/effects/tcast_effect_violation.nim`) to
verify that using `cast(raises: ValueError)` inside a procedure with
`.raises: [].` correctly triggers an error message about an unlisted
exception.
2026-05-27 23:28:27 +02:00
ringabout
8771451701 closes #25294; adds a test case (#25833)
closes #25294
2026-05-22 10:32:14 +08:00
ringabout
43ac102ca8 fixes #25800; move now uses its declaration for overridden =wasMoved (#25809)
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`.
2026-05-21 13:42:38 +02:00
Rybnikov Alex
393d27b57d fix(stdlib): use first-element flag in $ for collections (#18583) (#25832)
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>
2026-05-21 13:40:35 +02:00
Andreas Rumpf
9f5c193c1d fixes #25814 (#25816) 2026-05-19 23:28:13 +02:00
Pedro Batista
4f6b727d9e pegs: accept UTF-8 bytes in bare identifier terminals (#25829)
## 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.
2026-05-19 23:27:48 +02:00
ringabout
f9647276d8 fixes #25821; unary minus off by one mistake [backport] (#25823)
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`.
2026-05-18 07:55:33 +02:00
vip892766gma
2c946950f4 fix: duplicated "to" in alloc.nim comments (#25813)
Two one-line typo fixes for duplicated "to" in `lib/system/alloc.nim`:
- "# set 'used' to to true:" → "# set 'used' to true:" (occurs twice,
lines ~694 and ~711)

No code/behavior change.

Co-authored-by: Aiden Park <275402320+vip892766gma@users.noreply.github.com>
2026-05-14 08:02:36 +02:00
oab24413gmai
bbc5bbdcc7 fix: duplicated words in manual.md and gc_common.nim comment (#25812)
Two one-line typo fixes for duplicated words:
- `doc/manual.md` — "if the the type was marked as `bycopy`" → "if the
type was marked as `bycopy`"
- `lib/system/gc_common.nim` — "## thread stack is is returned." → "##
thread stack is returned."

No code/behavior change.

Co-authored-by: Mira Sato <275437409+oab24413gmai@users.noreply.github.com>
2026-05-14 08:02:11 +02:00
Andreas Rumpf
6204e48ba5 SSO strings: bugfix (#25810) 2026-05-12 23:20:10 +02:00
Nils-Hero Lindemann
f0c60b06e5 Update outdated string representation in example (#25802)
See
[here](https://nim-lang.github.io/Nim/tut1.html#internal-type-representation).
2026-05-09 08:55:39 +02:00
Ryan McConnell
4c8052a45b fix: implicit imports drop std/ prefix (#25780)
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]`
2026-05-08 06:50:13 +02:00
Nils-Hero Lindemann
7295f57833 Write all variables italic in section "About this document" (#25797)
Makes more sense. One variable was already written italic.
2026-05-08 06:48:48 +02:00
Andreas Rumpf
f0077a12b2 fixes DOS via malformed HTTP protocol (#25793)
refs https://github.com/nim-lang/Nim/pull/25568
2026-05-06 19:48:08 +08:00
ringabout
568eccd7f8 fixes #25617; handle backend type aliasing in procParamTypeRel (#25692)
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.
2026-05-06 08:44:09 +02:00
ringabout
f2e4ae0016 fixes lent tuple codegen error (#25782)
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.
2026-05-06 08:42:36 +02:00
Andreas Rumpf
df7a114d7a IC: use the newer nif27 format (#25792) 2026-05-06 08:41:59 +02:00
ringabout
e9a0c9634e fixes #25784; Object default field initialized with an object constructor (#25785)
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>
2026-05-05 21:05:17 +02:00
ringabout
b73908a361 fix #25789; improve handling of distinct types (#25791)
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.
2026-05-05 20:21:37 +02:00
puffball1567
cbe02aa9de fixes finally being skipped when except T as e re-raises (cpp backend) (#25775)
## 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>
2026-05-05 21:27:33 +08:00
Andreas Rumpf
4bcb706d49 IC: added support for conditional dependencies (#25770) 2026-04-28 18:48:41 +02:00
ringabout
92d0c097e5 fixes #25140; Cannot resolve pragmas when new type is defined from typeof expression (#25764)
fixes #25140
2026-04-27 18:47:45 +02:00
Andreas Rumpf
49b5e66d3a SSO: better switch to enable it (#25772) 2026-04-27 18:00:29 +02:00
Zoom
cbe8ce59ed fix string setLenUninit growth without realloc for refc (#25767)
`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.
2026-04-25 12:27:13 +02:00
Jake Leahy
148e82f418 Add Nix certificate path to ssl_certs.nim (#25763)
This makes it easier to run Nix built containers for Nim programs since
by default Nim doesn't search environment variables for SSL certs so its
a little annoying having to move around files

-
10e7ad5bbc/pkgs/by-name/ca/cacert/package.nix (L85)
2026-04-24 14:04:30 +02:00
Tomohiro
8b44b9d9ae fixes #23668; Create a new std/nre2 module using Nim Regex replaces re and nre (#25696)
std/nre2 is implemented using https://github.com/nitely/nim-regex.
std/nre2 has almost same features as std/nre but some regular
expressions supported by std/nre are not supported.
The syntax of regular expressions of Nim Regex is explained in:
https://nitely.github.io/nim-regex/regex.html
2026-04-22 08:06:03 +02:00
ringabout
efacf1f390 Fix typo in getContentType function in cgi.nim (#25757)
This pull request fixes a typo in the `getContentType` function in
`lib/pure/cgi.nim`, ensuring it retrieves the correct `CONTENT_TYPE`
environment variable.

> Exact spelling matters: It is CONTENT_TYPE, not CONTENT_Type or
Content-Type. Environment variables in CGI are case-sensitive.
2026-04-21 16:38:56 +02:00
ringabout
60bb9c75cc fixes #25650; nim ic import std/strbasics (#25760)
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
2026-04-21 16:38:33 +02:00
Bojun Chai
de3d61f15b Fix invalid Mac OS X minimum version in README (#25758)
**Repo:** nim-lang/Nim ( 16000)
**Type:** docs
**Files changed:** 1
**Lines:** +1/-1

## What
Correct the supported platform table in the top-level README by changing
the Mac OS X minimum version from `10.04` to `10.4`.

## Why
`10.04` is not a valid Mac OS X release number, so the existing text is
misleading for anyone reading the build and platform support guidance.
Fixing it keeps the README accurate without changing project behavior or
widening scope.

## Testing
Verified the README diff locally and confirmed the corrected `Mac OS X
(10.4 or greater)` entry appears in `readme.md`. No code or test suite
changes were needed for this docs-only patch.

## Risk
Low / documentation-only change with no runtime impact.

Co-authored-by: Bojun Chai <bojunchai@microsoft.com>
2026-04-21 08:50:13 +08:00
Tomohiro
ba4e12fb65 fixes #25753 (#25754) 2026-04-20 20:13:06 +02:00
Andreas Rumpf
f236e6a210 fixes #25695 (#25756) 2026-04-20 09:17:12 +02:00
Tomohiro
317bc10824 Makes containsOrIncl*[A](s: var PackedSet[A], key: A) proc faster (#25755)
This PR makes it faster when a number of elements is less than 34
I used following code to compare the speed of `containsOrIncl` proc.
It calls `isRecursiveStructuralType` proc defined in compiler/types.nim
that calls `containsOrIncl` with `IntSet`(= `PackedSet[int]`).
```nim
import std/[tables, monotimes, times, strformat]
import "$nim"/compiler/[astdef, ast, idents, types]

var idgen = IdGenerator(module: 0, symId: 0, typeId: 0, disambTable: initCountTable[PIdent]())

proc newType(kind: TTypeKind; son: sink PType = nil): PType =
  result = newType(kind, idgen, nil, son)

proc genNoRecursPType(len: int): PType =
  assert len > 1
  let intTyp = newType(tyInt)
  result = newType(tyRef, intTyp)
  for i in 0..<(len - 2):
    result = newType(tyRef, result)

proc test =
  var noRecursPType = genNoRecursPType(4)
  assert not isRecursiveStructuralType(noRecursPType)

test()

template measure(label: string; body: untyped): untyped =
  let
    loop = 2000
    sampling = 200
  block:
    var r {.inject.} = false
    var minT = initDuration(hours = 1)
    for i in 0 ..< sampling:
      let start = getMonoTime()
      for j in 0 ..< loop:
        body
      let finish = getMonoTime()
      minT = min(finish - start, minT)
    echo ($r)[0], ' ', label, minT div loop

proc benchNoRecurs(len: int) =
  echo fmt"No recursive: length: {len}"
  var noRecursPType = genNoRecursPType(len)
  measure("IntSet: "):
    r = isRecursiveStructuralType(noRecursPType)

proc bench =
  benchNoRecurs(30)

bench()
```

Output before changing code:
```
f IntSet: 1 microsecond and 262 nanoseconds
```
Output after change:
```
f IntSet: 833 nanoseconds
```

Why this PR make it faster:
```nim
proc containsOrIncl*[A](s: var PackedSet[A], key: A): bool =
  ...
  if s.elems <= s.a.len:
    for i in 0..<s.elems:
      if s.a[i] == ord(key):
        return true
    # `incl` scans `s.a` again
    incl(s, key)
    result = false
```

```nim
proc containsOrIncl*[A](s: var PackedSet[A], key: A): bool =
  ...
  if s.elems <= s.a.len:
    for i in 0..<s.elems:
      if s.a[i] == ord(key):
        return true
    if s.elems < s.a.len:
      # put `key` in `s.a` instead of calling `incl(s, key)`
      s.a[s.elems] = ord(key)
      inc(s.elems)
    else:
      incl(s, key)
    result = false
```
2026-04-20 09:21:46 +08:00
ringabout
5948dbbeed fixes #25718; setLenUnit slow (#25743)
fixes #25718

This pull request optimizes sequence allocation in the Nim standard
library by introducing a way to create uninitialized sequence payloads
for element types that don't require zero-initialization. The changes
allow for more efficient memory allocation when initializing sequences
with types that have no references, avoiding unnecessary zeroing of
memory.

Sequence allocation and initialization improvements:

* Added the `newSeqUninitRaw` procedure to create sequence payloads with
a specified length without forcing zero-initialization for element types
marked as `ntfNoRefs`. (`lib/system/sysstr.nim`,
[lib/system/sysstr.nimR277-R292](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eR277-R292))
* Modified the `extendCapacityRaw` procedure and the `setLengthSeqImpl`
template to use `newSeqUninitRaw` when zero-initialization is not
required, controlled by the `doInit` static parameter.
(`lib/system/sysstr.nim`,
[[1]](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eR277-R292)
[[2]](diffhunk://#diff-bcaa1967f436ad03877f353823c08a8b4a719fe387629d33aab4bddf16534b5eL316-R335)
2026-04-19 20:12:01 +02:00
ringabout
98131a9fa1 fixes #25751; JS backend crashes when returning Option[T] with custom =destroy (#25752)
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.
2026-04-18 09:40:55 +02:00
Ryan McConnell
f98578ea35 fix 25667; Generic forward type confusion (#25737)
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>
2026-04-18 08:52:31 +02:00
dependabot[bot]
e6e00a74a3 Bump actions/github-script from 8 to 9 (#25748)
Bumps [actions/github-script](https://github.com/actions/github-script)
from 8 to 9.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/github-script/releases">actions/github-script's
releases</a>.</em></p>
<blockquote>
<h2>v9.0.0</h2>
<p><strong>New features:</strong></p>
<ul>
<li><strong><code>getOctokit</code> factory function</strong> —
Available directly in the script context. Create additional
authenticated Octokit clients with different tokens for multi-token
workflows, GitHub App tokens, and cross-org access. See <a
href="https://github.com/actions/github-script#creating-additional-clients-with-getoctokit">Creating
additional clients with <code>getOctokit</code></a> for details and
examples.</li>
<li><strong>Orchestration ID in user-agent</strong> — The
<code>ACTIONS_ORCHESTRATION_ID</code> environment variable is
automatically appended to the user-agent string for request
tracing.</li>
</ul>
<p><strong>Breaking changes:</strong></p>
<ul>
<li><strong><code>require('@actions/github')</code> no longer works in
scripts.</strong> The upgrade to <code>@actions/github</code> v9
(ESM-only) means <code>require('@actions/github')</code> will fail at
runtime. If you previously used patterns like <code>const { getOctokit }
= require('@actions/github')</code> to create secondary clients, use the
new injected <code>getOctokit</code> function instead — it's available
directly in the script context with no imports needed.</li>
<li><code>getOctokit</code> is now an injected function parameter.
Scripts that declare <code>const getOctokit = ...</code> or <code>let
getOctokit = ...</code> will get a <code>SyntaxError</code> because
JavaScript does not allow <code>const</code>/<code>let</code>
redeclaration of function parameters. Use the injected
<code>getOctokit</code> directly, or use <code>var getOctokit =
...</code> if you need to redeclare it.</li>
<li>If your script accesses other <code>@actions/github</code> internals
beyond the standard <code>github</code>/<code>octokit</code> client, you
may need to update those references for v9 compatibility.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Add ACTIONS_ORCHESTRATION_ID to user-agent string by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/695">actions/github-script#695</a></li>
<li>ci: use deployment: false for integration test environments by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/712">actions/github-script#712</a></li>
<li>feat!: add getOctokit to script context, upgrade
<code>@​actions/github</code> v9, <code>@​octokit/core</code> v7, and
related packages by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/github-script/pull/700">actions/github-script#700</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Copilot"><code>@​Copilot</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/github-script/pull/695">actions/github-script#695</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/github-script/compare/v8.0.0...v9.0.0">https://github.com/actions/github-script/compare/v8.0.0...v9.0.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3a2844b7e9"><code>3a2844b</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/github-script/issues/700">#700</a>
from actions/salmanmkc/expose-getoctokit + prepare re...</li>
<li><a
href="ca10bbdd1a"><code>ca10bbd</code></a>
fix: use <code>@​octokit/core/</code>types import for v7
compatibility</li>
<li><a
href="86e48e20ac"><code>86e48e2</code></a>
merge: incorporate main branch changes</li>
<li><a
href="c1084728b5"><code>c108472</code></a>
chore: rebuild dist for v9 upgrade and getOctokit factory</li>
<li><a
href="afff112e4f"><code>afff112</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/github-script/issues/712">#712</a>
from actions/salmanmkc/deployment-false + fix user-ag...</li>
<li><a
href="ff8117e5b7"><code>ff8117e</code></a>
ci: fix user-agent test to handle orchestration ID</li>
<li><a
href="81c6b78760"><code>81c6b78</code></a>
ci: use deployment: false to suppress deployment noise from integration
tests</li>
<li><a
href="3953caf885"><code>3953caf</code></a>
docs: update README examples from <a
href="https://github.com/v8"><code>@​v8</code></a> to <a
href="https://github.com/v9"><code>@​v9</code></a>, add getOctokit docs
and v9 brea...</li>
<li><a
href="c17d55b90d"><code>c17d55b</code></a>
ci: add getOctokit integration test job</li>
<li><a
href="a047196d9a"><code>a047196</code></a>
test: add getOctokit integration tests via callAsyncFunction</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/github-script/compare/v8...v9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/github-script&package-manager=github_actions&previous-version=8&new-version=9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-17 19:14:36 +08:00
ringabout
c22819ef17 fixes #25732; semStaticExpr and semStaticStmt to handle errors (#25742)
fix #25732
2026-04-17 10:00:00 +02:00
ringabout
2b2872928b fixes #25469; Conversion from distinct in for forces a copy of underlying instance (#25746)
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.
2026-04-17 09:59:22 +02:00
Andreas Rumpf
b4d4028afa fixes whitespace related endless loop in renderer.nim (#25750) 2026-04-16 09:44:58 +02:00