mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
Overloads passed to static proc parameters now convert to the desired… (#23063)
… type mirroring proc params
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user