Overloads passed to static proc parameters now convert to the desired… (#23063)

… type mirroring proc params
This commit is contained in:
Jason Beetham
2023-12-14 09:05:14 -07:00
committed by GitHub
parent 7e4060cb4a
commit 91efa49550
4 changed files with 32 additions and 8 deletions

View File

@@ -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
@@ -746,10 +746,16 @@ 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:
@@ -757,7 +763,7 @@ proc setGenericParams(c: PContext, n: PNode) =
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:

View File

@@ -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
@@ -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)

View File

@@ -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:
@@ -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

View File

@@ -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