Skip to content

Commit

Permalink
fix(sem): crash on unmatched immediate routines (#929)
Browse files Browse the repository at this point in the history
## Summary

Unmatched `immediate` `macro`s and `template`s within a generic context
no longer result in a compiler error.

## Details

Immediate macros and templates are not dispatched via `sigmatch` and
instead `semgnrc` directly calls `evaltempl.evalTemplate`, in turn
`evalTemplateArgs` is called which can produce an error if an incorrect
number of arguments are provided. `evalTemplateArgs` is also used by
`semMacroExpr`, so similar issues would also exist for macros.

Now the error from `evalTemplateArgs` is immediately returned by
`evalTemplate` and treated as a mismatch in `semgnrc.semGenericStmt`.
Doing so prevents a compiler crash, attempt to access the sons of an
error
node. A test has been added as part of this change, which was
originally
from: zevv/npeg#68 (comment)
  • Loading branch information
saem committed Oct 3, 2023
1 parent 9f2e2a8 commit 1821094
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
2 changes: 2 additions & 0 deletions compiler/sem/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
instID: instID[],
idgen: idgen
)
if args.kind == nkError:
return args # xxx: not the best way to do it, but this signals a mismatch
let body = tmpl.ast[bodyPos]
if isAtom(body):
result = newNodeI(nkPar, body.info)
Expand Down
7 changes: 6 additions & 1 deletion compiler/sem/semgnrc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ proc semGenericStmt(c: PContext, n: PNode,
of skMacro:
if macroToExpand(s) and sc.safeLen <= 1:
result = semMacroExpr(c, n, s, {efNoSemCheck})
result =
if result.kind == nkError: n # an error means a "mismatch"
else: semGenericStmt(c, result, flags, ctx)
result = semGenericStmt(c, result, flags, ctx)
if result.isError: return
else:
Expand All @@ -287,7 +290,9 @@ proc semGenericStmt(c: PContext, n: PNode,
of skTemplate:
if macroToExpand(s) and sc.safeLen <= 1:
result = semTemplateExpr(c, n, s, {efNoSemCheck})
result = semGenericStmt(c, result, flags, ctx)
result =
if result.kind == nkError: n # an error means a "mismatch"
else: semGenericStmt(c, result, flags, ctx)
if result.isError: return
else:
n[0] = sc
Expand Down
16 changes: 16 additions & 0 deletions tests/lang_callable/overload/timmediate_meta_routine_mismatch.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
discard """
action: reject
description: "Ensure immediate macros/templates mismatches are reported"
"""

template unique(x, y: untyped) =
## A template (macro would work too) that is not overloaded.
# it's important that an argument is actually used within the template, in
# order to force traveral of the actual arguments (it's lazy and driven by
# the body).
y

proc test[T]() =
unique("test")

test()

0 comments on commit 1821094

Please sign in to comment.