Commit Graph

34 Commits

Author SHA1 Message Date
araq
467c911dc5 IC testing: compare against nim c, and run the real corpus under nim ic
Every invariant `tests/ic` checked was IC-against-IC — clean == incremental, a
no-op edit changes nothing, a body edit moves no interface cookie. An IC that is
*consistently* wrong satisfies all of them, and that is exactly how two silent
miscompilations survived. `koch bootic` has the same blind spot: it proves the
compiler reproduces itself, not that it agrees with the reference backend.

Two mechanisms, at different scales.

**The oracle, in the metamorphic runner.** Every successful step is now also
compiled with `nim c` and run, and the two outputs must agree. Unlike the
hand-written `expect:` strings this needs no foresight from the test author: it
compares everything the program does, not only what someone thought to print,
which is what a silently-skipped destructor evades. `no-oracle` opts out.

The format also grew the expressiveness the recent bug hunt showed was missing —
every one of these described a state the suite could not reach:

* `#!DELETE <file>` removes a module. Deleting a still-imported file moves no
  mtime, so nothing re-fires.
* `#!FLAGS <switches>` changes the compiler switches between steps. A config
  change is not a file either.
* `fails: <substring>` asserts that BOTH compilers reject the program with that
  text. Previously every step had to succeed, so the whole error path — and
  recovery from it — was untested.

Six regression tests cover the eight bugs the last round fixed.
`testament r <file>` now dispatches metamorphic tests like `testament cat ic`.

**`testament --ic` runs the whole corpus through the incremental compiler**, so
IC inherits ~10k programs with expected output instead of 30 bespoke tests.
Two things had to change for that to mean anything:

* `nimcacheDir` now keys on the `matrix:` entry too. Two matrix variants of one
  file are two different compilations; sharing a cache meant each run
  invalidated what the previous left — harmless for a backend that caches only
  object files, useless for an incremental one.
* About half the corpus overrides the command wholesale (`cmd: "nim c --gc:arc
  $file"`), bypassing both `$target` and `$options`. Those are rewritten to `ic`
  and given a private cache.

**Warm cache, hastur-style.** A generated warmup program pulling in `system` and
the most-imported stdlib modules is compiled once per distinct compile
configuration into `nimcache/ic_warmup_<hash>`, and each test's empty cache is
seeded from it with mtimes preserved (nifmake compares output-mtime >
input-mtime, so stamping the copies "now" re-fires the whole graph). Only
program-independent artifacts are copied: the frontend NIFs and cookies plus the
per-module `lower`/`cg` output. The `.c`/`.o` are left behind on purpose — the
merge decision is whole-program, so they are re-rendered for every program
anyway.

`tests/destructor` (97 runs): `nim c` 35s cold / 32s warm; `nim ic` ~3m30 cold /
**9.8s warm**.

Compiler changes this required or uncovered:

* `merge` read the live-module list from a manifest the driver writes instead of
  globbing `*.c.nif` off the nimcache. Globbing absorbed artifacts belonging to
  any other program sharing the directory — which is what made a prefilled cache
  produce undefined symbols at link.
* The build-arg signature no longer includes `--icproject:`/`--icPreparsedConfig:`
  (they name where a build lives, not what it produces, so two caches holding
  identical artifacts got different signatures). The precompiled config still
  counts, by content hash, minus its `(nimcache …)` line.
* `.s.deps` seeding is speculative and runs before the prune, so a sidecar entry
  that has gone stale (an import that a `when` no longer takes) can be dropped
  instead of lingering forever; a pruned module's scan artifacts are deleted so
  an edit-accumulated cache still matches a clean one.
* A failed nifmake run no longer prints an `Error:` of its own. The children have
  already reported; adding a build-system status as the LAST error hid the
  compiler's real message from anything reading the final error — every
  reject-style test under `nim ic` said "nifmake failed with exit code: 1".
* `--mm:hooks` fed the mm mode to an on/off switch and failed outright with
  "'on' or 'off' expected, but 'hooks' found". Pre-existing and unrelated to IC;
  only reachable through the explicit switch, since `--newruntime` sets
  `selectedGC` directly.

Running `tests/destructor` under `--ic` currently leaves 10 failures. They are
genuine IC defects, not harness noise (all 97 pass under `nim c`) — the clearest
is `tglobaldestructor`: `graph.globalDestructors` is accumulated while injecting
destructors into a module's top level, but the main module's `cg` — which emits
the teardown — is a different process, so a module-level `var` with a `=destroy`
is never destroyed. Same shape as the init/datInit metas, and it wants the same
fix: record it in the `.c.nif` head.

Validation: `koch bootic` reaches its byte-identical fixed point; `tests/ic` is
36/36; arc, destructor, macros, template, iter, closure, ccg, codegen, types and
effects pass under `nim c`, with generics showing only its pre-existing failure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 21:00:13 +02:00
Andreas Rumpf
8ca7b75b8b refactoring: better IC + no unique Id (#26137) 2026-08-25 11:59:19 +02:00
Andreas Rumpf
fa66510f7a IC: bugfix (#25982) 2026-07-10 14:07:35 +02:00
Andreas Rumpf
1c61307692 IC related bugfixes (#25946) 2026-07-03 15:52:41 +02:00
Andreas Rumpf
5688a122f1 IC refactor (#25927) 2026-06-25 23:20:34 +02:00
Andreas Rumpf
f5d9e7a207 IC: bugfixes (#25914) 2026-06-15 23:33:16 +02:00
Andreas Rumpf
acb9b3a4f1 IC: precompiled configs and bugfixes (#25913) 2026-06-15 21:20:09 +02:00
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
ringabout
e39272eaa8 fixes #25637; nim ic with destructors (#25723)
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)
2026-04-10 15:29:20 +02:00
ringabout
8076fb40b8 fixes transf cannot handle bare sym for nim ic (#25664)
```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
2026-03-31 09:49:55 +02:00
ringabout
c48f487780 fixes: replace ensureMutable with backendEnsureMutable in ccgtypes (#25640) 2026-03-24 11:49:06 +08:00
ringabout
8bb63b475b fixes global tuple unpacking for nim ic (#25624)
This pull request includes a few targeted changes across the codebase,
primarily focusing on improving symbol locality detection in the
compiler, adding a utility function for integer division and modulus,
and simplifying a test case.

- **Compiler Improvements**
* Improved the `isLocalSym` function in `compiler/ast2nif.nim` to more
accurately determine if a symbol is local by checking that the symbol's
owner is not a module.

- **Utility Function Addition**
* Added a new `divmod` procedure in `tests/ic/tmiscs.nim` that returns
both the quotient and remainder of integer division, along with a usage
example.

- **Test Simplification**
* Simplified the `showMeters` test in `tests/ic/tconverter.nim` by
removing a floating-point assertion, leaving only an output statement.



------------------------------------------------------------------------------------------------------------------

```nim
proc divmod(a, b: int): (int, int) =
  (a div b, a mod b)


let (q, r) = divmod(17, 5)
echo q
echo r
```

gives `Error: unhandled exception: local symbol 'tmpTuple.0' not found
in localSyms. [AssertionDefect]`

`makeVarTupleSection` uses a temp of which the globalness and localness
is not specified. Turning it a global variable for top level scope broke
some Nim programs. So I think it's better to check the owner of the
symbol

```nim
if useTemp:
  # use same symkind for compatibility with original section
  let temp = newSym(symkind, getIdent(c.cache, "tmpTuple"), c.idgen, getCurrOwner(c), n.info)
```
2026-03-23 09:35:30 +01:00
ringabout
a4a482b5ef fixes #25620; typekey skips incorrectly the base type of seqs etc. types for nim ic (#25621)
fixes #25620

This pull request includes a fix to the type key generation logic in the
compiler and updates to a test file to cover additional language
features. The most important changes are summarized below:

### Compiler logic fix

* In `compiler/typekeys.nim`, the `typeKey` procedure was updated to
iterate over all elements in `t.sonsImpl` starting from index 0 instead
of 1, ensuring that all type sons are considered during type key
generation.

### Test suite improvements

* The test file `tests/ic/tenum.nim` was renamed to
`tests/ic/tmiscs.nim`, and its output expectations were updated to
reflect the new test cases.
* Added new test cases to `tests/ic/tmiscs.nim` to cover sink and move
semantics, including the definition of a `BigObj` type and a `consume`
procedure that demonstrates moving and consuming large objects.

```nim
# Sink and move semantics
type
  BigObj = object
    data: seq[int]

proc consume(x: sink BigObj) =
  echo x.data.len

var b = BigObj(data: @[1, 2, 3, 4, 5])
consume(move b)
```

gives

```
error: passing 'tySequence__qwqHTkRvwhrRyENtudHQ7g' (aka 'struct tySequence__qwqHTkRvwhrRyENtudHQ7g') to parameter of incompatible type 'tySequence__cTyVHeHOWk5jStsToosJ8Q' (aka 'struct tySequence__cTyVHeHOWk5jStsToosJ8Q')
   84 |         eqdestroy___sysma2dyk_u75((*dest_p0).data);
```

follows up https://github.com/nim-lang/Nim/pull/25614
2026-03-20 07:07:26 +01:00
ringabout
197633dc8b fixes empty tag for nim ic (#25615)
`writeNode` writes `(empty flags type (empty))`, but it should have been
`(empty flags type)` instead

```nim
type
  Meters = distinct float
  Feet = distinct float

converter toMeters(f: Feet): Meters =
  Meters(float(f) * 0.3048)

proc showMeters(m: Meters) =
  echo float(m)

showMeters(Feet(10.0))
```
gives `[NIF decoder] expected: {ParRi} but got:
ParLe14,152,/Users/blue/.choosenim/toolchains/nim-\23devel/lib/std/private/dragonbox.nim(empty)`

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-19 07:36:09 +01:00
ringabout
a7e0065056 implements EnumToStrEntry for nim ic (#25614)
```nim
type
  NodeKind = enum
    nkInt, nkStr, nkAdd

  Node = object
    case kind: NodeKind
    of nkInt: intVal: int
    of nkStr: strVal: string
    of nkAdd: left, right: ref Node

proc newInt(v: int): ref Node =
  new(result)
  result[] = Node(kind: nkInt, intVal: v)

let n = newInt(42)
echo n.intVal
```

gives `unhandled exception: key not found: (module: 68, item: 3)
[KeyError]`
2026-03-19 07:35:24 +01:00
Andreas Rumpf
469e1377cd IC: progress (#25453) 2026-01-24 06:07:41 +01:00
Andreas Rumpf
86a4ddc847 IC: remember which modules are from the NIF cache (#25443) 2026-01-22 04:26:20 +01:00
Andreas Rumpf
01eedd916c IC: progress (#25420) 2026-01-09 13:10:04 +01:00
Andreas Rumpf
d3be5e5e13 IC: need a more recent Nimony for its improved Nifler tool (#25412) 2026-01-06 00:16:19 +01:00
Juan M Gómez
e6ca13ec85 Instantiates generics in the module that uses it (#22513)
Attempts to move the generic instantiation to the module that uses it.
This should decrease re-compilation times as the source module where the
generic lives doesnt need to be recompiled

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-09-09 10:34:20 +02:00
ringabout
512517c223 fixes #18146; fixes #19372; disable tlsEmulation on windows; static link pthreads with mingw (#21668)
* fixes #18146; disable tlsEmulation on windows; static link libwinthreads DLL

* whatever
2023-04-14 22:52:35 +02:00
ringabout
7739e23420 defaults to ORC (#19972)
* defaults to Orc

* bootstrap using refc

* use gc

* init orc defines

* unregister orc

* fix gc

* fix commands

* add prepareMutation for orc

* enable deepcopy for orc

* prepareMutation

* more fixes

* some cases

* bug #20081

* partial fixes

* partial fixes

* fixes command line

* more fixes

* build Nim with refc

* use gc

* more fixes

* rstore

* orc doesn't support threadpool

* more shallowCopy

* more fixes

* fixes unsafeNew

* workarounds

* small

* more fixes

* fixes some megatest

* tcodegenbugs1 refc

* fxies megatest

* build nimble with refc

* workaround tensordsl tests

* replace shallowCopy with move

* fixes action

* workaround

* add todo

* fixes important packages

* unpublic unregisterArcOrc

* fixes cpp

* enable windows

Co-authored-by: xflywind <43030857+xflywind@users.noreply.github.com>
2022-09-23 13:05:05 +02:00
ringabout
2e8c016799 disable tlsEmulation for ic tests (#20345) 2022-09-14 12:06:05 +08:00
flywind
430a179307 default threads on (#19368)
* default threads on

* make rst gcsafe

* ignore threads option for nimscript

* threads off

* use createShared for threads

* test without threads

* avr threds off

* avr threads off

* async threads off

* threads off

* fix ci

* restore option

* make CI pleased

* fix ic tests

* Update config.nims

* add changelog

* Update changelog.md

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
2022-07-06 13:06:41 +02:00
Andreas Rumpf
7b6ab5109f IC exposes typedesc implementation shenanigans (#17759)
* IC exposes typedesc implementation shenanigans; so I change system.default's definition to what it should have been to begin with
* Update lib/system.nim

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
2021-04-18 07:27:03 +02:00
Timothee Cour
8161b02897 import foo {.all.} reboot (#17706) 2021-04-16 09:16:39 +02:00
Andreas Rumpf
cae1839154 IC: added tcompiletime_counter test case (#17698) 2021-04-11 21:41:24 +02:00
Andreas Rumpf
1822ed384a IC: added converter test case (#17688)
* IC: added converter test case

* IC: make converter example work
2021-04-09 16:41:49 +02:00
Andreas Rumpf
13b958eb45 IC: added basic test case for methods (#17679)
* IC: added basic test case for methods

* IC: better methods test
2021-04-09 06:59:25 +02:00
Andreas Rumpf
e3e9742143 added a 'koch ic' command for easier adhoc testing of IC (#17508)
* added a 'koch ic' command for easier adhoc testing of IC
* IC: progress
* IC: enable generics test
* make tests green
2021-03-26 08:52:26 +01:00
Andreas Rumpf
6c1c8f51b3 IC: green tests (#17311)
* IC: renamed to_packed_ast module to ic module

* IC: don't store the --forceBuild flag, makes it easier to test

* IC: enable hello world test

* Codegen: refactorings for IC; changed the name mangling algorithm

* fixed the HCR regressions

* life is too short for HCR

* tconvexhull is now allowed to use deepCopy

* IC exposed a stdlib bug, required a refactoring

* codegen: code cleanups

* IC: even if a module is outdated, its dependencies might come from disk

* IC: progress

* IC: better name mangling, module IDs are not stable

* IC: another refactoring helping with --ic:on --gc:arc

* disable arraymancer on Windows for the time being

* disable arraymancer altogether

* IC: make basic test work with 'nim cpp'

* IC: progress on --ic:on --gc:arc

* wip; name mangling for type info
2021-03-19 16:53:38 +01:00
Andreas Rumpf
fb80d2ff85 IC: bugfixes (WIP) (#16836)
* minor improvements
* IC: added the required logic for compilerProcs
* LazySym ftw
* we need this testing logic
* reimplement the old way we use for module package creation
* fixes a regression; don't pick module names if you can avoid it
2021-02-02 19:24:55 +01:00
Juan Carlos
f1d165adf2 Testament small fixes (#16788)
* ReSync with Devel

* ReSync

* Fix Deprecations, Convertion to itself, code style, etc

* Fix Deprecations, Convertion to itself, code style, etc
2021-01-22 07:50:28 +01:00
Andreas Rumpf
c8cffaf420 Incremental compilation (IC): Improvements (#11881)
* IC: C codegen is aware of IC
* manual: minor change to make VSCode's RST plugin render it properly
* IC: minor refactoring
* testament: code refactorings
* rodutils: removed dead code
* IC: always build the compiler with the IC feature
* IC: C codegen improvements
* IC: implement the undocumented -d:nimMustCache option for testing purposes
* IC: added first basic tests
* IC: extensive testing of the deserialization feature
* testament: refactoring; better IC tests
* IC: removes 'nimMustCache' flag; readonly does the same
* testament: minor refactoring
* update Nimble version
* testament: removed dead code and imports; IC: added simple test
* IC: progress
2019-08-08 08:41:05 +02:00