Skip to content

Commit

Permalink
allow untyped arguments to fail to compile in overload mismatch err…
Browse files Browse the repository at this point in the history
…or (#23984)

fixes #8697, fixes #9620, fixes #23265

When matching a `template` with an `untyped` argument fails because of a
mismatching typed argument, `presentFailedCandidates` tries to sem every
single argument to show their types, but trying to type the `untyped`
argument can fail if it's supposed to use an injected symbol, so we get
an unrelated error message like "undeclared identifier".

Instead we use `tryExpr` as the comment suggests, setting the type to
`untyped` if it fails to compile. We could also maybe check if an
`untyped` argument is expected in its place and not try to compile the
expression if it is but this would require a bit of reorganizing the
code here and IMO it's better to have the information of what type it
would be if it can be typed.
  • Loading branch information
metagn authored Aug 20, 2024
1 parent 8bd0422 commit 34719ca
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
23 changes: 17 additions & 6 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -338,16 +338,27 @@ template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = p
result.add renderTree(n[i][0])
result.add ": "
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
# XXX we really need to 'tryExpr' here!
arg = c.semOperand(c, n[i][1])
n[i].typ = arg.typ
n[i][1] = arg
arg = c.semTryExpr(c, n[i][1])
if arg == nil:
arg = n[i][1]
arg.typ = newTypeS(tyUntyped, c)
else:
if arg.typ == nil:
arg.typ = newTypeS(tyVoid, c)
n[i].typ = arg.typ
n[i][1] = arg
else:
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
nkOfBranch, nkElifBranch,
nkExceptBranch}:
arg = c.semOperand(c, n[i])
n[i] = arg
arg = c.semTryExpr(c, n[i])
if arg == nil:
arg = n[i]
arg.typ = newTypeS(tyUntyped, c)
else:
if arg.typ == nil:
arg.typ = newTypeS(tyVoid, c)
n[i] = arg
if arg.typ != nil and arg.typ.kind == tyError: return
result.add argTypeToString(arg, prefer)

Expand Down
37 changes: 37 additions & 0 deletions tests/errmsgs/tuntypedoverload.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
discard """
cmd: "nim check $file"
"""

block:
template foo(x: var int, y: untyped) = discard
var a: float
foo(a, undeclared) #[tt.Error
^ type mismatch: got <float, untyped>]# # `untyped` is arbitary
# previous error: undeclared identifier: 'undeclared'

block: # issue #8697
type
Fruit = enum
apple
banana
orange
macro hello(x, y: untyped) = discard
hello(apple, banana, orange) #[tt.Error
^ type mismatch: got <Fruit, Fruit, Fruit>]#

block: # issue #23265
template declareFoo(fooName: untyped, value: uint16) =
const `fooName Value` {.inject.} = value

declareFoo(FOO, 0xFFFF)
declareFoo(BAR, 0xFFFFF) #[tt.Error
^ type mismatch: got <untyped, int literal(1048575)>]#

block: # issue #9620
template forLoop(index: untyped, length: int{lvalue}, body: untyped) =
for `index`{.inject.} in 0 ..< length:
body
var x = newSeq[int](10)
forLoop(i, x.len): #[tt.Error
^ type mismatch: got <untyped, int, void>]#
x[i] = i

0 comments on commit 34719ca

Please sign in to comment.