parent
5bcf8bcb59
commit
16b594b532
3 changed files with 34 additions and 3 deletions
|
|
@ -247,26 +247,39 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||||
if i > 1:
|
if i > 1:
|
||||||
resetIdTable(cl.symMap)
|
resetIdTable(cl.symMap)
|
||||||
resetIdTable(cl.localCache)
|
resetIdTable(cl.localCache)
|
||||||
|
|
||||||
|
# take a note of the original type. If't a free type parameter
|
||||||
|
# we'll need to keep it unbount for the `fitNode` operation below...
|
||||||
|
var typeToFit = result[i]
|
||||||
|
|
||||||
let needsStaticSkipping = result[i].kind == tyFromExpr
|
let needsStaticSkipping = result[i].kind == tyFromExpr
|
||||||
result[i] = replaceTypeVarsT(cl, result[i])
|
result[i] = replaceTypeVarsT(cl, result[i])
|
||||||
if needsStaticSkipping:
|
if needsStaticSkipping:
|
||||||
result[i] = result[i].skipTypes({tyStatic})
|
result[i] = result[i].skipTypes({tyStatic})
|
||||||
|
|
||||||
|
# ...otherwise, we use the instantiated type in `fitNode`
|
||||||
|
if typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone:
|
||||||
|
typeToFit = result[i]
|
||||||
|
|
||||||
internalAssert c.config, originalParams[i].kind == nkSym
|
internalAssert c.config, originalParams[i].kind == nkSym
|
||||||
let oldParam = originalParams[i].sym
|
let oldParam = originalParams[i].sym
|
||||||
let param = copySym(oldParam)
|
let param = copySym(oldParam)
|
||||||
param.owner = prc
|
param.owner = prc
|
||||||
param.typ = result[i]
|
param.typ = result[i]
|
||||||
|
|
||||||
|
# The default value is instantiated and fitted against the final
|
||||||
|
# concrete param type. We avoid calling `replaceTypeVarsN` on the
|
||||||
|
# call head symbol, because this leads to infinite recursion.
|
||||||
if oldParam.ast != nil:
|
if oldParam.ast != nil:
|
||||||
var def = oldParam.ast.copyTree
|
var def = oldParam.ast.copyTree
|
||||||
if def.kind == nkCall:
|
if def.kind == nkCall:
|
||||||
for i in 1 ..< def.len:
|
for i in 1 ..< def.len:
|
||||||
def[i] = replaceTypeVarsN(cl, def[i])
|
def[i] = replaceTypeVarsN(cl, def[i])
|
||||||
def = semExprWithType(c, def)
|
def = semExprWithType(c, def)
|
||||||
param.ast = fitNode(c, param.typ, def, def.info)
|
param.ast = fitNode(c, typeToFit, def, def.info)
|
||||||
param.typ = param.ast.typ
|
param.typ = result[i]
|
||||||
|
|
||||||
result.n[i] = newSymNode(param)
|
result.n[i] = newSymNode(param)
|
||||||
result[i] = param.typ
|
|
||||||
propagateToOwner(result, result[i])
|
propagateToOwner(result, result[i])
|
||||||
addDecl(c, param)
|
addDecl(c, param)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1045,6 +1045,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
|
|
||||||
if typ == nil:
|
if typ == nil:
|
||||||
typ = def.typ
|
typ = def.typ
|
||||||
|
if typ.kind == tyTypeDesc:
|
||||||
|
# default typedesc values are mapped to the unbound typedesc type:
|
||||||
|
typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# if def.typ != nil and def.typ.kind != tyNone:
|
# if def.typ != nil and def.typ.kind != tyNone:
|
||||||
# example code that triggers it:
|
# example code that triggers it:
|
||||||
|
|
|
||||||
|
|
@ -34,3 +34,17 @@ when true:
|
||||||
type Point[T] = tuple[x, y: T]
|
type Point[T] = tuple[x, y: T]
|
||||||
proc origin(T: typedesc): Point[T] = discard
|
proc origin(T: typedesc): Point[T] = discard
|
||||||
discard origin(int)
|
discard origin(int)
|
||||||
|
|
||||||
|
# https://github.com/nim-lang/Nim/issues/7516
|
||||||
|
import typetraits
|
||||||
|
|
||||||
|
proc hasDefault1(T: type = int): auto = return T.name
|
||||||
|
doAssert hasDefault1(int) == "int"
|
||||||
|
doAssert hasDefault1(string) == "string"
|
||||||
|
doAssert hasDefault1() == "int"
|
||||||
|
|
||||||
|
proc hasDefault2(T = string): auto = return T.name
|
||||||
|
doAssert hasDefault2(int) == "int"
|
||||||
|
doAssert hasDefault2(string) == "string"
|
||||||
|
doAssert hasDefault2() == "string"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue