diff options
-rw-r--r-- | compiler/semtypes.nim | 25 | ||||
-rw-r--r-- | tests/template/tdefaultparam.nim | 41 |
2 files changed, 59 insertions, 7 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 9af71ba8f..113946fef 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1372,14 +1372,25 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, "either use ';' (semicolon) or explicitly write each default value") message(c.config, a.info, warnImplicitDefaultValue, msg) block determineType: - if kind == skTemplate and hasUnresolvedArgs(c, def): - # template default value depends on other parameter - # don't do any typechecking - def.typ = makeTypeFromExpr(c, def.copyTree) - break determineType + var canBeVoid = false + if kind == skTemplate: + if typ != nil and typ.kind == tyUntyped: + # don't do any typechecking or assign a type for + # `untyped` parameter default value + break determineType + elif hasUnresolvedArgs(c, def): + # template default value depends on other parameter + # don't do any typechecking + def.typ = makeTypeFromExpr(c, def.copyTree) + break determineType + elif typ != nil and typ.kind == tyTyped: + canBeVoid = true let isGeneric = isCurrentlyGeneric() inc c.inGenericContext, ord(isGeneric) - def = semExprWithType(c, def, {efDetermineType, efAllowSymChoice}, typ) + if canBeVoid: + def = semExpr(c, def, {efDetermineType, efAllowSymChoice}, typ) + else: + def = semExprWithType(c, def, {efDetermineType, efAllowSymChoice}, typ) dec c.inGenericContext, ord(isGeneric) if def.referencesAnotherParam(getCurrOwner(c)): def.flags.incl nfDefaultRefsParam @@ -1399,7 +1410,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c)) typ.flags.incl tfCheckedForDestructor - elif def.typ.kind != tyFromExpr: + elif def.typ != nil and def.typ.kind != tyFromExpr: # def.typ can be void # if def.typ != nil and def.typ.kind != tyNone: # example code that triggers it: # proc sort[T](cmp: proc(a, b: T): int = cmp) diff --git a/tests/template/tdefaultparam.nim b/tests/template/tdefaultparam.nim index ecbb0e145..7ea0b2b25 100644 --- a/tests/template/tdefaultparam.nim +++ b/tests/template/tdefaultparam.nim @@ -13,3 +13,44 @@ block: # issue #23506 a = $($x, $y) foo(1) doAssert a == "(\"1\", \"1\")" + +block: # untyped params with default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: untyped = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: untyped = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" + template test3(body: untyped = willNotCompile) = + discard + test3() + +block: # typed params with `void` default value + macro foo(x: typed): untyped = + result = x + template test(body: untyped, alt: typed = (;), maxTries = 3): untyped {.foo.} = + body + alt + var s = "a" + test: + s.add "b" + do: + s.add "c" + doAssert s == "abc" + template test2(body: untyped, alt: typed = s.add("e"), maxTries = 3): untyped = + body + alt + test2: + s.add "d" + doAssert s == "abcde" |