Skip to content

[backport] fixes #4086, #9355 for v2.2.x (#25799)#25804

Closed
puffball1567 wants to merge 2 commits into
nim-lang:version-2-2from
puffball1567:backport-25799-v2-2
Closed

[backport] fixes #4086, #9355 for v2.2.x (#25799)#25804
puffball1567 wants to merge 2 commits into
nim-lang:version-2-2from
puffball1567:backport-25799-v2-2

Conversation

@puffball1567
Copy link
Copy Markdown
Contributor

@puffball1567 puffball1567 commented May 10, 2026

Backport of #25799 to v2.2.x

Backport of #25799 ("fixes #4086, #9355; allow generic param defaults to reference other type params") to the v2.2.x maintenance branch.

Prerequisite: #25799 should be merged to devel first.

How this differs from a plain cherry-pick

Direct cherry-pick of #25799 onto version-2-2 doesn't work as-is because:

  • containsForwardType* helpers (= the hasForwardTypeParam machinery from fixes #16754 #25519) don't exist in v2.2.x — inlined locally
  • Several compiler-internal API differences (e.g. result.flags.incl X vs devel's result.incl X, absence of LazySym wrapper for addPureEnum, c.skipTypes.add n vs c.forwardTypeUpdates.add (...))

The patch adapts to v2.2.x by inlining the missing helpers and matching the older API. Touched file set is the same as #25799:

  • compiler/semtypes.nim
  • compiler/semstmts.nim
  • compiler/sigmatch.nim
  • tests/generics/tgeneric_param_default_deps.nim

Verification

Local on Linux x86_64, Nim 2.2.11 (bin/nim built fresh from this branch via csources_v3 + koch boot):

  • nim check compiler/nim.nim — [SuccessX]
  • target test tests/generics/tgeneric_param_default_deps.nim — PASS
  • testament regression on the same 19 cats as fixes #4086; allow type-side generic param defaults to reference other type params #25799 (generic generics objects typerel types metatype statictypes concepts proc overload template macros tuples collections distinct varstmt let varres assign init) — no FAILURE summary in any cat. (One valgrind-tagged test in objects aborted locally because valgrind is not installed; CI should cover that path.)

ref: #25799 (devel)
Related issues: #4086, #9355

…eference other type params

Generic type parameter defaults that reference other type parameters
currently fail in Nim, even though C++ / TypeScript / Rust / Scala all
support the pattern. This change enables four related sub-cases:

1. type-side reference: `type Foo[T; U = seq[T]]`
   (also `U = ref T`, `U = array[3, T]`, alias, distinct, cascade)
2. type-side direct: `type Foo[T; U = T]`
3. type-side 0-arg invocation: `var f: Foo` for `type Foo[T = int]`
4. proc-side: `func foo[T](U = T): U` and `func foo[T](U: type = T): U`

Implementation
--------------
compiler/semtypes.nim
  - semGeneric: accumulate already-resolved generic params into a
    layered type map and substitute them in subsequent default values
    before they are added to the invocation. Handles cascade defaults
    like `[T; U = seq[T]; V = seq[U]]` left-to-right. Gated on
    `hasAnyDefault` so generic types with no defaults pay no overhead.
  - semProcTypeNode: treat a bare generic-param default (`U = T`) as
    an unbound typedesc parameter, equivalent to `U: type = T`, so the
    existing typedesc-param machinery handles it.
  - tryGenericBodyDefaultInvocation: helper that synthesizes a
    `Foo[default1, default2, ...]` invocation when every generic param
    has a default, and dispatches to semGeneric.

compiler/semstmts.nim
  - semVarOrLet / semConst: after type resolution, if the resulting
    type is a tyGenericBody whose every param has a default, expand
    it via tryGenericBodyDefaultInvocation. Restricted to var/let/
    const so type-level computations like `arity(SomeGeneric)` in
    template/typetraits contexts keep treating bare generic-body
    references as intended.

compiler/sigmatch.nim
  - matches default-completion: when the default value is a bare
    reference to an earlier generic type param (recognised by the
    default's static type being `tyGenericParam`), substitute T
    against the explicit-instantiation bindings via prepareTypesInBody
    and wrap the result as `tyTypeDesc` so the implicit
    `tfImplicitTypeParam` binding path treats it like a literal type
    default. Defaults whose type is anything else — value expressions
    like `arr.high`, proc-call expressions like `newTensor[T](0)` whose
    result type is `tyGenericInvocation`/`tyGenericInst`, etc. — are
    left untouched, so the existing default-handling machinery (and
    later sem stages) continue to handle them as before. Verified by
    locally building tests/test_indep_import.nim from arraymancer
    against ~/.nimble pkgs2.

Tests
-----
tests/generics/tgeneric_param_default_deps.nim covers all four
sub-cases and the cascade / alias / distinct variants. Local
regression on tests/{generic,generics,objects,typerel,types,
metatype,statictypes,concepts,proc,overload,template,macros,tuples,
collections,distinct,varstmt,let,varres,assign,init}: 663 reSuccess
across 19 categories. The single non-success entry,
tests/types/tforwardcycletimeout reTimeout, reproduces on clean
upstream/devel and is unrelated.

closes nim-lang#4086
closes nim-lang#9355
…g#9355

Adds three review-requested tests to tgeneric_param_default_deps.nim
covering generic param defaults in combination with:

  1. union constraint:    type Foo[T; U: seq[T]|Deque[T] = seq[T]]
  2. typeclass constraint: type Foo[T: SomeInteger = int]
  3. concept constraint:   type Foo[T: HasLen = string]

These exercise the default-completion machinery added in 18f250e
across constraint kinds adjacent to higher-kinded-type accidental
behavior (RFCs#5). All three pass under both --mm:orc (default) and
--mm:refc.

Local regression on tests/concepts: 45/46 reSuccess, 0 reFail
(1 reDisabled is unrelated). Local regression on tests/generics:
116/116 reSuccess, 0 reFail.
@Araq
Copy link
Copy Markdown
Member

Araq commented May 12, 2026

Sorry for this late reply but this is exactly the kind of backport we should avoid. Can cause unforeseen regressions on the now-finally stable again 2.2.x line.

@puffball1567
Copy link
Copy Markdown
Contributor Author

Thanks for your reply. I'll respect the project's backport policy and close this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants