Skip to content

Conversation

@kobi2187
Copy link
Contributor

Would need proper checking/testing:

Fix compiler crash when types are used as values (issue #16507)
Replace internal error with clear error message when type symbols (skType)
reach code generation, which can occur when types are passed to concept
parameters or used incorrectly as values.
Previously, code like:
type K = concept x
true
proc foo(t: K) = echo "ok"
int.foo
would crash with: "Error: internal error: expr(skType); unknown symbol"
Now it provides a helpful error:
"cannot use type 'int' as a value; use 'typedesc[int]' if you need to
pass it as a parameter"
The issue occurs when semantic analysis doesn't properly catch type symbols
being used in value contexts, allowing skType symbols to reach the C code
generator where they're not expected. This typically happens with concept
parameters that should accept typedesc but instead accept the raw type.
The fix adds explicit handling for skType in the code generator's expression
handler, providing actionable feedback to users about how to fix the problem.
Changes:

  • compiler/ccgexprs.nim:3537-3541: Add skType case with helpful error message

Fix compiler crash on parenthesized generic proc names (issue #15797)
Replace fatal error with clear error message when generic parameters reach
ordinal bound functions (firstOrd/lastOrd) without proper instantiation.
Previously, code like:
echo (succ)(1)
would crash with: "Error: fatal error: invalid kind for firstOrd(tyGenericParam)"
Now it provides a helpful error:
"cannot use generic parameter 'T: Ordinal' without instantiation;
provide explicit type arguments"
The issue occurs when parenthesizing a generic procedure name prevents the
compiler from inferring type parameters from arguments. When succ is
parenthesized as (succ), the compiler treats it as a value expression
rather than a callable, and the generic parameter T reaches the firstOrd
function uninstantiated.
The fix adds explicit handling for tyGenericParam in both firstOrd() and
lastOrd() functions, providing actionable feedback instead of crashing.
Workaround: Use explicit type instantiation: (succ[int])(1)
Changes:

  • compiler/types.nim:841-847: Handle tyGenericParam in firstOrd
  • compiler/types.nim:944-950: Handle tyGenericParam in lastOrd

Fix internal compiler crash on untyped expressions in code generation (issue #23965)
Replace internal error with clear error message when untyped template parameters
reach code generation phase, commonly occurring in ambiguous table literals.
Previously, code like:
template foo(f) = f
discard {foo: ord(true)}
would crash with: "Error: internal error: getTypeDescAux(tyUntyped)"
Now it provides a helpful error:
"cannot generate code for untyped expression; check for ambiguous or
malformed constructs like templates in table literals"
The issue occurs when templates with untyped parameters are used in contexts
where the compiler cannot infer a concrete type, such as keys in table/set
constructors. The semantic analysis should ideally catch this earlier, but
this fix ensures a graceful degradation with actionable feedback instead of
an internal error.
The fix adds explicit handling for tyUntyped and tyTyped in the code generator,
returning a placeholder type (NimInt) to avoid cascading errors while providing
clear guidance to users about the problematic construct.
Changes:

  • compiler/ccgtypes.nim:1087-1092: Add tyUntyped/tyTyped case with error message

Fix internal compiler crash on malformed generic type instantiation (issue #24848)
Replace internal error with clear error message when encountering malformed
generic type constructs like R[R[int]].
Previously, code like:
type R[C] = ref object
discard R[R[int]]
would crash with: "Error: internal error: '=destroy' operator not found for type R"
Now it provides a helpful error:
"cannot use uninstantiated generic type 'R'; generic parameters required"
The issue occurs when double-bracketing creates a malformed type that reaches
destructor injection without proper instantiation. The construct R[[R[int]]]
is syntactically parsed but semantically invalid - it attempts to instantiate
R with a bracket expression [R[int]] rather than a proper type.
The fix detects when a type appears to be an uninstantiated generic (short
uppercase name without proper structure) before attempting to find destructors,
providing actionable feedback to users.
Changes:

  • compiler/injectdestructors.nim:248-255: Detect and report uninstantiated generics

Fix compiler crash on uninitialized variable in named arguments (issue #24963)
Replace internal error with clear, informative error message when variables
are referenced before initialization or out of scope, particularly in cases
involving named argument reordering.
Previously, code like:
foo(
b = (let x = 123; 456),
a = x)
would crash with: "Error: internal error: expr: var not init x_553648133"
Now it provides a helpful error:
"variable 'x' not initialized or out of scope; check for variable usage
before definition or scope issues with named arguments"
The issue occurs when named arguments are reordered and variables defined in
one argument expression are referenced in another. The variable 'x' is local
to the statement expression in parameter 'b' but is being referenced in
parameter 'a', causing a scope/initialization issue.
This fix improves the error message to help users understand what went wrong
and suggests checking for scope issues with named arguments.
Changes:

  • compiler/ccgexprs.nim:3505-3509: Replace internal error with descriptive message

Fix compiler crash when using magic procs as first-class functions (issue #24616)
Replace internal error with clear, actionable error message when attempting
to use compiler magic procedures (like operators +, -, *, etc.) as first-class
functions.
Previously, code like:
let op: proc(x: int, y: int): int = +
would crash with: "Error: internal error: proc has no result symbol"
Now it provides a helpful error:
"cannot use compiler magic '+' as a first-class function; consider wrapping it in a lambda"
The issue occurs because magic procedures are compiled directly to backend
operations and don't have normal proc structure with result symbols. They
cannot be passed around as function pointers.
The fix checks if a proc is a compiler magic (prc.magic != mNone) before
expecting a result symbol, and provides guidance to users on how to work
around the limitation (wrap in a lambda).
Changes:

  • compiler/cgen.nim:1309-1316: Check for magic procs and provide better error

Fix compiler crash on invalid empty generic instantiation (issue #25231)
Replace internal error with clear user-friendly error message when attempting
to use generic types without providing type parameters.
Previously, code like discard Test[] where Test is a generic type would
crash with: "Error: internal error: expr(nkBracketExpr, tyGenericBody)"
Now it provides a clear error: "cannot use generic type without instantiation"
The fix adds defensive checks at multiple levels:

  1. semtypes.nim:2224-2226: Check for empty bracket expressions in type context
  2. semexprs.nim:1708-1711: Handle tyGenericBody in expression subscript
  3. ccgexprs.nim:1330-1332: Final safety net in code generation
    This prevents the compiler from crashing and helps users understand what
    went wrong with their code.
    Changes:
  • compiler/semtypes.nim: Add check for empty generic instantiation
  • compiler/semexprs.nim: Handle tyGenericBody type kind
  • compiler/ccgexprs.nim: Provide error instead of internal crash

Fix internal compiler crash on void proc result assignment (issue #18556)
Replace internalAssert with proper error message when void procedures try
to assign to 'result'.
Previously, the compiler would crash with an internal error when nested
procedures without return types attempted to use the 'result' variable:
proc p():auto =
let a = "a"
result = proc () = # This nested void proc tries to use 'result'
let b = "b"
result = proc () = # This one too
echo a & b
The crash occurred because c.p.resultSym was nil for void procedures,
but the code asserted it should exist.
Following maintainer recommendation (Araq), the fix provides a clear error
message instead of crashing: "cannot use 'result' in a void procedure;
consider adding a return type"
This gives developers actionable feedback instead of an internal error.
Changes:

  • compiler/semexprs.nim:2042-2046: Replace assertion with helpful error message

Fix internal compiler crash on recursive type instantiation (issue #24826)
Replace internalAssert with proper tyStatic normalization for array indices.
Previously, the compiler would crash with an internal error when encountering
recursive generic types with array bounds that depend on type parameters:
type X[N: int] = object
x: array[N, int]
n: X[2 * N.high]
The crash occurred because after type instantiation, the array index type
was still tyStatic but the code asserted it should be a concrete type.
Now, similar to how tyRange handles this (line 766), we skip tyStatic types
for array indices instead of asserting. This allows the compiler to provide
proper error messages (e.g., overflow detection) instead of crashing.
Valid recursive types continue to work correctly.
Changes:

  • compiler/semtypinst.nim:754-756: Replace assertion with tyStatic normalization

Replace internal error with clear error message when type symbols (skType)
reach code generation, which can occur when types are passed to concept
parameters or used incorrectly as values.

Previously, code like:
  type K = concept x
    true
  proc foo(t: K) = echo "ok"
  int.foo

would crash with: "Error: internal error: expr(skType); unknown symbol"

Now it provides a helpful error:
  "cannot use type 'int' as a value; use 'typedesc[int]' if you need to
   pass it as a parameter"

The issue occurs when semantic analysis doesn't properly catch type symbols
being used in value contexts, allowing skType symbols to reach the C code
generator where they're not expected. This typically happens with concept
parameters that should accept typedesc but instead accept the raw type.

The fix adds explicit handling for skType in the code generator's expression
handler, providing actionable feedback to users about how to fix the problem.

Changes:
- compiler/ccgexprs.nim:3537-3541: Add skType case with helpful error message
…g#15797)

Replace fatal error with clear error message when generic parameters reach
ordinal bound functions (firstOrd/lastOrd) without proper instantiation.

Previously, code like:
  echo (succ)(1)

would crash with: "Error: fatal error: invalid kind for firstOrd(tyGenericParam)"

Now it provides a helpful error:
  "cannot use generic parameter 'T: Ordinal' without instantiation;
   provide explicit type arguments"

The issue occurs when parenthesizing a generic procedure name prevents the
compiler from inferring type parameters from arguments. When `succ` is
parenthesized as `(succ)`, the compiler treats it as a value expression
rather than a callable, and the generic parameter T reaches the firstOrd
function uninstantiated.

The fix adds explicit handling for tyGenericParam in both firstOrd() and
lastOrd() functions, providing actionable feedback instead of crashing.

Workaround: Use explicit type instantiation: (succ[int])(1)

Changes:
- compiler/types.nim:841-847: Handle tyGenericParam in firstOrd
- compiler/types.nim:944-950: Handle tyGenericParam in lastOrd
… (issue nim-lang#23965)

Replace internal error with clear error message when untyped template parameters
reach code generation phase, commonly occurring in ambiguous table literals.

Previously, code like:
  template foo(f) = f
  discard {foo: ord(true)}

would crash with: "Error: internal error: getTypeDescAux(tyUntyped)"

Now it provides a helpful error:
  "cannot generate code for untyped expression; check for ambiguous or
   malformed constructs like templates in table literals"

The issue occurs when templates with untyped parameters are used in contexts
where the compiler cannot infer a concrete type, such as keys in table/set
constructors. The semantic analysis should ideally catch this earlier, but
this fix ensures a graceful degradation with actionable feedback instead of
an internal error.

The fix adds explicit handling for tyUntyped and tyTyped in the code generator,
returning a placeholder type (NimInt) to avoid cascading errors while providing
clear guidance to users about the problematic construct.

Changes:
- compiler/ccgtypes.nim:1087-1092: Add tyUntyped/tyTyped case with error message
…issue nim-lang#24848)

Replace internal error with clear error message when encountering malformed
generic type constructs like R[[R[int]]]().

Previously, code like:
  type R[C] = ref object
  discard R[[R[int]]]()

would crash with: "Error: internal error: '=destroy' operator not found for type R"

Now it provides a helpful error:
  "cannot use uninstantiated generic type 'R'; generic parameters required"

The issue occurs when double-bracketing creates a malformed type that reaches
destructor injection without proper instantiation. The construct R[[R[int]]]
is syntactically parsed but semantically invalid - it attempts to instantiate
R with a bracket expression [R[int]] rather than a proper type.

The fix detects when a type appears to be an uninstantiated generic (short
uppercase name without proper structure) before attempting to find destructors,
providing actionable feedback to users.

Changes:
- compiler/injectdestructors.nim:248-255: Detect and report uninstantiated generics
…nim-lang#24963)

Replace internal error with clear, informative error message when variables
are referenced before initialization or out of scope, particularly in cases
involving named argument reordering.

Previously, code like:
  foo(
    b = (let x = 123; 456),
    a = x)

would crash with: "Error: internal error: expr: var not init x_553648133"

Now it provides a helpful error:
  "variable 'x' not initialized or out of scope; check for variable usage
   before definition or scope issues with named arguments"

The issue occurs when named arguments are reordered and variables defined in
one argument expression are referenced in another. The variable 'x' is local
to the statement expression in parameter 'b' but is being referenced in
parameter 'a', causing a scope/initialization issue.

This fix improves the error message to help users understand what went wrong
and suggests checking for scope issues with named arguments.

Changes:
- compiler/ccgexprs.nim:3505-3509: Replace internal error with descriptive message
…ssue nim-lang#24616)

Replace internal error with clear, actionable error message when attempting
to use compiler magic procedures (like operators +, -, *, etc.) as first-class
functions.

Previously, code like:
  let op: proc(x: int, y: int): int = `+`

would crash with: "Error: internal error: proc has no result symbol"

Now it provides a helpful error:
  "cannot use compiler magic '+' as a first-class function; consider wrapping it in a lambda"

The issue occurs because magic procedures are compiled directly to backend
operations and don't have normal proc structure with result symbols. They
cannot be passed around as function pointers.

The fix checks if a proc is a compiler magic (prc.magic != mNone) before
expecting a result symbol, and provides guidance to users on how to work
around the limitation (wrap in a lambda).

Changes:
- compiler/cgen.nim:1309-1316: Check for magic procs and provide better error
…lang#25231)

Replace internal error with clear user-friendly error message when attempting
to use generic types without providing type parameters.

Previously, code like `discard Test[]` where Test is a generic type would
crash with: "Error: internal error: expr(nkBracketExpr, tyGenericBody)"

Now it provides a clear error: "cannot use generic type without instantiation"

The fix adds defensive checks at multiple levels:
1. semtypes.nim:2224-2226: Check for empty bracket expressions in type context
2. semexprs.nim:1708-1711: Handle tyGenericBody in expression subscript
3. ccgexprs.nim:1330-1332: Final safety net in code generation

This prevents the compiler from crashing and helps users understand what
went wrong with their code.

Changes:
- compiler/semtypes.nim: Add check for empty generic instantiation
- compiler/semexprs.nim: Handle tyGenericBody type kind
- compiler/ccgexprs.nim: Provide error instead of internal crash
…-lang#18556)

Replace internalAssert with proper error message when void procedures try
to assign to 'result'.

Previously, the compiler would crash with an internal error when nested
procedures without return types attempted to use the 'result' variable:

  proc p():auto =
    let a = "a"
    result = proc () =    # This nested void proc tries to use 'result'
      let b = "b"
      result = proc () =  # This one too
        echo a & b

The crash occurred because c.p.resultSym was nil for void procedures,
but the code asserted it should exist.

Following maintainer recommendation (Araq), the fix provides a clear error
message instead of crashing: "cannot use 'result' in a void procedure;
consider adding a return type"

This gives developers actionable feedback instead of an internal error.

Changes:
- compiler/semexprs.nim:2042-2046: Replace assertion with helpful error message
…m-lang#24826)

Replace internalAssert with proper tyStatic normalization for array indices.

Previously, the compiler would crash with an internal error when encountering
recursive generic types with array bounds that depend on type parameters:

  type X[N: int] = object
    x: array[N, int]
    n: X[2 * N.high]

The crash occurred because after type instantiation, the array index type
was still tyStatic but the code asserted it should be a concrete type.

Now, similar to how tyRange handles this (line 766), we skip tyStatic types
for array indices instead of asserting. This allows the compiler to provide
proper error messages (e.g., overflow detection) instead of crashing.

Valid recursive types continue to work correctly.

Changes:
- compiler/semtypinst.nim:754-756: Replace assertion with tyStatic normalization
@Araq
Copy link
Member

Araq commented Jan 22, 2026

Congrats, quite a useful PR! Please address my comment.

@nocturn9x
Copy link

It's always a joy to see how active the Nim community is, despite it being more of a Niche language

Copy link
Contributor Author

@kobi2187 kobi2187 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified file as requested

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.

4 participants