Skip to content

Commit

Permalink
Overloads passed to static proc parameters now convert to the desired…
Browse files Browse the repository at this point in the history
… type mirroring proc params
  • Loading branch information
beef331 committed Dec 13, 2023
1 parent db60323 commit 277428b
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 8 deletions.
14 changes: 10 additions & 4 deletions compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
# try transforming the argument into a static one before feeding it into
# typeRel
if formal.kind == tyStatic and arg.kind != tyStatic:
let evaluated = c.semTryConstExpr(c, n[i])
let evaluated = c.semTryConstExpr(c, n[i], n[i].typ)
if evaluated != nil:
arg = newTypeS(tyStatic, c, sons = @[evaluated.typ])
arg.n = evaluated
Expand All @@ -746,18 +746,24 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
onUse(info, s)
result = newSymNode(newInst, info)

proc setGenericParams(c: PContext, n: PNode) =
proc setGenericParams(c: PContext, n, expectedParams: PNode) =
## sems generic params in subscript expression
for i in 1..<n.len:
let e = semExprWithType(c, n[i])
let
constraint =
if expectedParams != nil and i <= expectedParams.len:
expectedParams[i - 1].typ
else:
nil
e = semExprWithType(c, n[i], expectedType = constraint)
if e.typ == nil:
n[i].typ = errorType(c)
else:
n[i].typ = e.typ.skipTypes({tyTypeDesc})

proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
setGenericParams(c, n)
setGenericParams(c, n, s.ast[genericParamsPos])
var s = s
var a = n[0]
if a.kind == nkSym:
Expand Down
4 changes: 2 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
elif n[0].kind == nkBracketExpr:
let s = bracketedMacro(n[0])
if s != nil:
setGenericParams(c, n[0])
setGenericParams(c, n[0], s.ast[genericParamsPos])
return semDirectOp(c, n, flags, expectedType)
elif isSymChoice(n[0]) and nfDotField notin n.flags:
# overloaded generic procs e.g. newSeq[int] can end up here
Expand Down Expand Up @@ -3172,7 +3172,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
isSymChoice(n[0][0]):
# indirectOp can deal with explicit instantiations; the fixes
# the 'newSeq[T](x)' bug
setGenericParams(c, n[0])
setGenericParams(c, n[0], nil)
result = semDirectOp(c, n, flags, expectedType)
elif nfDotField in n.flags:
result = semDirectOp(c, n, flags, expectedType)
Expand Down
9 changes: 8 additions & 1 deletion compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2384,7 +2384,14 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
# XXX this is still all wrong: (T, T) should be 2 generic matches
# and (int, int) 2 exact matches, etc. Essentially you cannot call
# typeRel here and expect things to work!
let r = typeRel(z, f, arg[i].typ)
let r = block:
if f.kind == tyStatic and f.base.kind == tyProc:
# Right now the ast of the type does not point to the symbol, so this will never resolve `static proc` with overloads
let copiedNode = copyNode(arg[i])
copiedNode.typ = exactReplica(copiedNode.typ)
copiedNode.typ.n = arg[i]
arg[i] = copiedNode
typeRel(z, f, arg[i].typ)
incMatches(z, r, 2)
if r != isNone:
z.state = csMatch
Expand Down
9 changes: 8 additions & 1 deletion tests/statictypes/tstaticprocparams.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
proc consumer[T: static proc(i: int): int{.nimcall.}](i: int): int = T(i)
proc consumer(T: static proc(i: int): int{.nimcall.}, i: int): int = T(i)

proc addIt(i: int): int = i + i
proc add(i: int): int = i + i # Checks if we can use overloads
proc squareIt(i: int): int = i * i

assert consumer[addIt](10) == 20
assert consumer[add](10) == 20
assert consumer[squareIt](30) == 900
assert consumer[proc(i: int): int{.nimcall.} = i * i + i](10) == 110


assert consumer(addIt, 10) == 20
assert consumer(add, 10) == 20
assert consumer(squareIt, 30) == 900
assert consumer(proc(i: int): int{.nimcall.} = i * i + i, 10) == 110

0 comments on commit 277428b

Please sign in to comment.