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
#23063)

… type mirroring proc params
  • Loading branch information
beef331 committed Dec 14, 2023
1 parent 7e4060c commit 91efa49
Show file tree
Hide file tree
Showing 4 changed files with 32 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, son = 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
13 changes: 12 additions & 1 deletion compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,17 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
result = userConvMatch(c, m, base(f), a, arg)
if result != nil: m.baseTypeMatch = true

proc staticAwareTypeRel(m: var TCandidate, f: PType, arg: var PNode): TTypeRelation =
if f.kind == tyStatic and f.base.kind == tyProc:
# The ast of the type does not point to the symbol.
# Without this we will never resolve a `static proc` with overloads
let copiedNode = copyNode(arg)
copiedNode.typ = exactReplica(copiedNode.typ)
copiedNode.typ.n = arg
arg = copiedNode
typeRel(m, f, arg.typ)


proc paramTypesMatch*(m: var TCandidate, f, a: PType,
arg, argOrig: PNode): PNode =
if arg == nil or arg.kind notin nkSymChoices:
Expand Down Expand Up @@ -2365,7 +2376,7 @@ 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 = staticAwareTypeRel(z, f, arg[i])
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 91efa49

Please sign in to comment.