From 591168002ae1caacad2b5a86c68f76e6e91dac1a Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Tue, 9 Sep 2025 22:48:19 +0800 Subject: [PATCH 1/3] fixes #25116; default(T) breaks requiresInit requirements --- compiler/semmagic.nim | 12 ++++++++---- tests/errmsgs/t25116.nim | 9 +++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 tests/errmsgs/t25116.nim diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 0ad6117813a68..e5799c5c1f68f 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -580,12 +580,16 @@ proc semPrivateAccess(c: PContext, n: PNode): PNode = c.currentScope.allowPrivateAccess.add t.sym result = newNodeIT(nkEmpty, n.info, getSysType(c.graph, n.info, tyVoid)) -proc checkDefault(c: PContext, n: PNode): PNode = +proc checkDefault(c: PContext, n: PNode; isDefault: bool): PNode = result = n c.config.internalAssert result[1].typ.kind == tyTypeDesc let constructed = result[1].typ.base if constructed.requiresInit: - message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) + # TODO: sorts out `nimPreviewRangeDefault` with `ranges` in the future + if isDefault: + localError(c.config, n.info, "The '$1' type doesn't have a valid default value" % typeToString(constructed)) + else: + message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = @@ -675,13 +679,13 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, if seqType.kind == tySequence and seqType.base.requiresInit: message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base)) of mDefault: - result = checkDefault(c, n) + result = checkDefault(c, n, true) let typ = result[^1].typ.skipTypes({tyTypeDesc}) let defaultExpr = defaultNodeField(c, result[^1], typ, false) if defaultExpr != nil: result = defaultExpr of mZeroDefault: - result = checkDefault(c, n) + result = checkDefault(c, n, false) of mIsolate: if not checkIsolate(n[1]): localError(c.config, n.info, "expression cannot be isolated: " & $n[1]) diff --git a/tests/errmsgs/t25116.nim b/tests/errmsgs/t25116.nim new file mode 100644 index 0000000000000..611a1bda4c376 --- /dev/null +++ b/tests/errmsgs/t25116.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "The 'RI' type doesn't have a valid default value" +""" + + +type RI {.requiresInit.} = object + v: int + +var v = default(RI) # should be flagged as invalid \ No newline at end of file From 8e7afb6bd64788c9b31120e46dc5e1eb16bb7149 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:45:23 +0800 Subject: [PATCH 2/3] make the low bound the default value of ranges + ignoring `views` and `notnil` --- compiler/sem.nim | 5 +---- compiler/semmagic.nim | 10 +++++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 3392db7a9da02..c70cf412b598a 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -710,10 +710,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P else: result = nil of tyRange: - if c.graph.config.isDefined("nimPreviewRangeDefault"): - result = firstRange(c.config, aTypSkip) - else: - result = nil + result = firstRange(c.config, aTypSkip) else: result = nil diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index e5799c5c1f68f..667abb9aaf15c 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -584,9 +584,11 @@ proc checkDefault(c: PContext, n: PNode; isDefault: bool): PNode = result = n c.config.internalAssert result[1].typ.kind == tyTypeDesc let constructed = result[1].typ.base - if constructed.requiresInit: + # allows simple range types because they now have a valid default value + if constructed.requiresInit and constructed.skipTypes({tyGenericInst}).kind != tyRange: # TODO: sorts out `nimPreviewRangeDefault` with `ranges` in the future - if isDefault: + # TODO: be lenient with views and notnil types for now + if isDefault and c.config.features * {views, notnil} != {}: localError(c.config, n.info, "The '$1' type doesn't have a valid default value" % typeToString(constructed)) else: message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) @@ -676,7 +678,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, let seqType = result[1].typ.skipTypes({tyPtr, tyRef, # in case we had auto-dereferencing tyVar, tyGenericInst, tyOwned, tySink, tyAlias, tyUserTypeClassInst}) - if seqType.kind == tySequence and seqType.base.requiresInit: + if seqType.kind == tySequence and seqType.base.requiresInit and + seqType.base.skipTypes({tyGenericInst}).kind != tyRange: + # allows simple range types because they now have a valid default value message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base)) of mDefault: result = checkDefault(c, n, true) From b36dc53bf2c270590f7e8af995f419a57b858a05 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 17 Sep 2025 22:58:09 +0800 Subject: [PATCH 3/3] oops --- compiler/semmagic.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 667abb9aaf15c..af9ccde850938 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -588,7 +588,7 @@ proc checkDefault(c: PContext, n: PNode; isDefault: bool): PNode = if constructed.requiresInit and constructed.skipTypes({tyGenericInst}).kind != tyRange: # TODO: sorts out `nimPreviewRangeDefault` with `ranges` in the future # TODO: be lenient with views and notnil types for now - if isDefault and c.config.features * {views, notnil} != {}: + if isDefault and c.config.features * {views, notnil} == {}: localError(c.config, n.info, "The '$1' type doesn't have a valid default value" % typeToString(constructed)) else: message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))