Skip to content

Commit

Permalink
fix(sem): crash with procedure with error used as argument (#1443)
Browse files Browse the repository at this point in the history
## Summary

Fix a compiler crash when passing the name of a procedure with an error
as an argument to another routine.

## Details

Overloadable and overloaded procedure symbols forewent the `nkError`
wrapping done by `semSym`, thus not preventing instantiation or later
inspection by `sempass2`, crashing the compiler with an `IndexDefect`
on attempting to access the symbol's AST.

Non-overloaded procedure symbols can be passed to `semSym` directly,
which takes care of the wrapping. To handle overloaded symbols,
`sigmatch.paramTypesMatch` passes the picked symbol to `semExpr` first,
which subsequently calls `semSym`, also marking the symbols as used.

The problem with using `semExpr` in `paramTypesMatch` is that the
returned `nkError` currently dismisses the overload, resulting in an
unnecessary "type mismatch" compiler error (with `nimsuggest`, `check`,
etc.).

Fixes #1384.
Fixes #1442.
  • Loading branch information
zerbina authored Sep 3, 2024
1 parent c587666 commit 73b9136
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
4 changes: 4 additions & 0 deletions compiler/sem/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3561,6 +3561,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = symChoice(c, n, s, scClosed)
if result.kind == nkSym:
markIndirect(c, result.sym)
# the symbol was alrady marked as used, don't mark it as such again
# (via ``semSym``)
if result.sym.ast.isError:
result = c.config.newError(result, PAstDiag(kind: adWrappedSymError))
of skEnumField:
if overloadableEnums in c.features:
result = enumFieldSymChoice(c, n, s)
Expand Down
4 changes: 2 additions & 2 deletions compiler/sem/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2602,9 +2602,9 @@ proc paramTypesMatch*(

else:
# only one valid interpretation found, executing argument match
markUsed(candidate.c, arg.info, arg[bestArg].sym)
let realArg = candidate.c.semExpr(c, arg[bestArg], {})
result = paramTypesMatchAux(
candidate, formal, arg[bestArg].typ, arg[bestArg])
candidate, formal, realArg.typ, realArg)

when false:
if candidate.calleeSym != nil and
Expand Down
15 changes: 15 additions & 0 deletions tests/error_propagation/tgeneric_proc_sym_as_argument.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
discard """
description: '''
Ensure that generic procedure symbols are wrapped in an error, when used
in an argument context
'''
action: reject
matrix: "--errorMax:100"
"""

proc call(p: proc(x: int)) = discard

proc withError[T](x: T) =
missing

call(withError) # <- this crashed the compiler
18 changes: 18 additions & 0 deletions tests/error_propagation/toverloaded_proc_sym_as_argument.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
discard """
description: '''
Ensure that overloaded procedure symbols are wrapped in an error, when
used in an argument context
'''
action: reject
matrix: "--errorMax:100"
"""

proc call(p: proc()) = discard

proc withError() =
missing

proc withError(a: int) = # <- this overload is not picked below
discard

call(withError) # <- this crashed the compiler
15 changes: 15 additions & 0 deletions tests/error_propagation/tproc_sym_as_argument.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
discard """
description: '''
Ensure that procedure symbols are wrapped in an error, when used in an
argument context
'''
action: reject
matrix: "--errorMax:100"
"""

proc call(p: proc()) = discard

proc withError() =
missing

call(withError) # <- this crashed the compiler

0 comments on commit 73b9136

Please sign in to comment.