From 49d63b1528c04cf6598be9ced971a3df46fec73f Mon Sep 17 00:00:00 2001 From: zerbina <100542850+zerbina@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:05:27 +0000 Subject: [PATCH] fix(sem): crash with procedure with error used as argument 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.). --- compiler/sem/semexprs.nim | 1 + compiler/sem/sigmatch.nim | 4 ++-- .../tgeneric_proc_sym_as_argument.nim | 15 +++++++++++++++ .../toverloaded_proc_sym_as_argument.nim | 18 ++++++++++++++++++ .../tproc_sym_as_argument.nim | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 tests/error_propagation/tgeneric_proc_sym_as_argument.nim create mode 100644 tests/error_propagation/toverloaded_proc_sym_as_argument.nim create mode 100644 tests/error_propagation/tproc_sym_as_argument.nim diff --git a/compiler/sem/semexprs.nim b/compiler/sem/semexprs.nim index f86df14858c..13c8b139b55 100644 --- a/compiler/sem/semexprs.nim +++ b/compiler/sem/semexprs.nim @@ -3561,6 +3561,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = symChoice(c, n, s, scClosed) if result.kind == nkSym: markIndirect(c, result.sym) + result = semSym(c, n, result.sym, flags) of skEnumField: if overloadableEnums in c.features: result = enumFieldSymChoice(c, n, s) diff --git a/compiler/sem/sigmatch.nim b/compiler/sem/sigmatch.nim index 73cb0c5bcaf..b155ed49551 100644 --- a/compiler/sem/sigmatch.nim +++ b/compiler/sem/sigmatch.nim @@ -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 diff --git a/tests/error_propagation/tgeneric_proc_sym_as_argument.nim b/tests/error_propagation/tgeneric_proc_sym_as_argument.nim new file mode 100644 index 00000000000..88b600dfc60 --- /dev/null +++ b/tests/error_propagation/tgeneric_proc_sym_as_argument.nim @@ -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 diff --git a/tests/error_propagation/toverloaded_proc_sym_as_argument.nim b/tests/error_propagation/toverloaded_proc_sym_as_argument.nim new file mode 100644 index 00000000000..cbd2811b6d2 --- /dev/null +++ b/tests/error_propagation/toverloaded_proc_sym_as_argument.nim @@ -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 diff --git a/tests/error_propagation/tproc_sym_as_argument.nim b/tests/error_propagation/tproc_sym_as_argument.nim new file mode 100644 index 00000000000..2bc1e0f79f6 --- /dev/null +++ b/tests/error_propagation/tproc_sym_as_argument.nim @@ -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