mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 02:12:11 +00:00
allow untyped arguments to fail to compile in overload mismatch error (#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.
(cherry picked from commit 34719cad9d)
This commit is contained in:
@@ -329,16 +329,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)
|
||||
|
||||
|
||||
37
tests/errmsgs/tuntypedoverload.nim
Normal file
37
tests/errmsgs/tuntypedoverload.nim
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user