diff options
author | metagn <metagngn@gmail.com> | 2024-10-03 21:38:42 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-03 20:38:42 +0200 |
commit | 4eed341ba53e69674d7e8e8a609efd1ea0a54b4b (patch) | |
tree | 8be1f170a39a4795f2dbb85d07843c2f32ac18be /compiler | |
parent | d98ef312f0cf8745d39c940b16d8d2dce1dfa70f (diff) | |
download | Nim-4eed341ba53e69674d7e8e8a609efd1ea0a54b4b.tar.gz |
don't typecheck `untyped` + allow void `typed` template param default values (#24219)
Previously, the compiler never differentiated between `untyped`/`typed` argument default values and other types, it considered any parameter with a type as typed and called `semExprWithType`, which both typechecked it and disallowed `void` expressions. Now, we perform no typechecking at all on `untyped` template param default values, and call `semExpr` instead for `typed` params, which allows expressions with `void` type.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semtypes.nim | 25 |
1 files changed, 18 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) |