Files
Nim/doc
Zoom 5df28ab02a Fix iterable resolution, prefer iterator overloads (#25679)
This fixes type resolution for `iterable[T]`.

I want to proceed with RFC
[#562](https://github.com/nim-lang/RFCs/issues/562) and this is the main
blocker for composability.

Fixes #22098 and, arguably, #19206

```nim
import std/strutils

template collect[T](it: iterable[T]): seq[T] =
  block:
    var res: seq[T] = @[]
    for x in it:
      res.add x
    res

const text = "a b c d"

let words = text.split.collect()
doAssert words == @[ "a", "b", "c", "d" ]
```

In cases like `strutils.split`, where both proc and iterator overload
exists, the compiler resolves to the `func` overload causing a type
mismatch.

The old mode resolved `text.split` to `seq[string]` before the
surrounding `iterable[T]` requirement was applied, so the argument no
longer matched this template.

It should be noted that, compared to older sequtils templates,
composable chains based on `iterable[T]` require an iterator-producing
expression, e.g. `"foo".items.iterableTmpl()` rather than just
`"foo".iterableTmpl()`. This is actually desirable: it keeps the
iteration boundary explicit and makes iterable-driven templates
intentionally not directly interchangeable with older
untyped/loosely-typed templates like those in `sequtils`, whose internal
iterator setup we have zero control over (e.g. hard-coding adapters like
`items`).

Also, I noticed in `semstmts` that anonymous iterators are always
`closure`, which is not that surprising if you think about it, but still
I added a paragraph to the manual.

Regarding implementation:

From what I gathered, the root cause is that `semOpAux` eagerly
pre-types all arguments with plain flags before overload resolution
begins, so by the time `prepareOperand` processes `split` against the
`iterable[T]`, the wrong overload has already won.

The fix touches a few places:

- `prepareOperand` in `sigmatch.nim`:
When `formal.kind == tyIterable` and the argument was already typed as
something else, it's re-semchecked with the
`efPreferIteratorForIterable` flag. The recheck is limited to direct
calls (`a[0].kind in {nkIdent, nkAccQuoted, nkSym, nkOpenSym}`) to avoid
recursing through `semIndirectOp`/`semOpAux` again.

- `iteratorPreference` field `TCandidate`, checked before
`genericMatches` in `cmpCandidates`, gives the iterator overload a win
without touching the existing iterator heuristic used by `for` loops.

**Limitations:**

The implementation is still flag-driven rather than purely
formal-driven, so the behaviour is a bit too broad `efWantIterable` can
cause iterator results to be wrapped as `tyIterable` in
iterable-admitting contexts, not only when `iterable[T]` match is being
processed.

`iterable[T]` still does not accept closure iterator values such
as`iterator(): T {.closure.}`. It only matches the compiler's internal
`tyIterable`, not arbitrary iterator-typed values.

The existing iterator-preference heuristic is still in place, because
when I tried to remove it, some loosely-related regressions happened. In
particular, ordinary iterator-admitting contexts and iterator chains
still rely on early iterator preference during semchecking, before the
compiler has enough surrounding context to distinguish between
value/iterator producing overloads. Full heuristic removal would require
a broader refactor of dot-chain/intermediate-expression semchecking,
which is just too much for me ATM. This PR narrows only the
tyIterable-specific cases.

**Future work:**

Rework overload resolution to preserve additional information of
matching iterator overloads for calls up to the point where the
iterator-requiring context is established, to avoid re-sem in
`prepareOperand`.

Currently there's no good channel to store that information. Nodes can
get rewritten, TCandidate doesn't live long enough, storing in Context
or some side-table raises the question how to properly key that info.

(cherry picked from commit be29bcd402)
2026-04-02 08:34:34 +02:00
..
2025-01-15 10:21:20 +01:00
2023-09-27 05:49:17 +02:00
2024-01-12 20:50:20 +08:00
2026-03-02 10:56:11 +01:00
2025-11-07 12:33:33 +01:00
2022-06-04 07:03:03 +02:00
2026-03-02 10:56:11 +01:00
2023-02-07 16:15:44 +08:00
2026-03-02 10:56:11 +01:00
2023-07-02 22:36:05 +02:00
2023-07-02 22:36:05 +02:00

============================
Nim's documentation system
============================

This folder contains Nim's documentation. The documentation
is written in a format called *Markdown*, a markup language that reads
like ASCII and can be converted to HTML automatically!