fixes #25784; Object default field initialized with an object constructor (#25785)

fixes #25784

This pull request addresses the handling of forward object types during
type determination in the Nim compiler and adds new test cases to ensure
correct default value initialization for objects with forward
references. The main focus is to allow forward object types to remain
unresolved during the initial type analysis, deferring their resolution
to a later compilation phase. This helps support object constructors
with default values involving forward types.

**Compiler improvements:**

* Updated `semObjConstr` in `compiler/semobjconstr.nim` to allow forward
object types (`tyForward`) to remain unresolved during determine-type
analysis. This avoids premature errors and ensures that such types are
resolved later, supporting delayed field-default resolution.

**Testing enhancements:**

* Added new test cases in `tests/objects/mobject_default_value.nim` to
verify that objects with default fields referencing forward types are
correctly initialized, and that their default values are properly set.

---------

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
ringabout
2026-05-06 03:05:17 +08:00
committed by GitHub
parent b73908a361
commit e9a0c9634e
3 changed files with 40 additions and 1 deletions

View File

@@ -486,6 +486,11 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
# we have to watch out, there are also 'owned proc' types that can be used
# multiple times as long as they don't have closures.
result.typ.incl tfHasOwned
if t.kind == tyForward and efDetermineType in flags:
# a forward object type does not error during determine-type analysis;
# it now stays unresolved long enough for the existing delayed field-default pass to resolve it after the type section finishes.
result.typ = t
return result
if t.kind != tyObject:
return localErrorNode(c, result, if t.kind != tyGenericBody:
"object constructor needs an object type".dup(addTypeNodeDeclaredLoc(c.config, t))

View File

@@ -370,6 +370,7 @@ proc semFieldDefault(c: PContext; owner, expectedType: PType; field: PNode): PTy
propagateToOwner(owner, result)
proc semDelayedFieldDefault(c: PContext; owner, expectedType: PType; field: PNode) =
resetSemFlag(field[^1])
fitDefaultNode(c, field[^1], expectedType)
propagateToOwner(owner, field[^1].typ.skipIntLit(c.idgen))

View File

@@ -833,4 +833,37 @@ proc overloaded[T: object](x: T) =
var v: typeof(val)
overloaded(v)
overloaded(Thing())
overloaded(Thing())
block:
type
Foo = object
x = Bar()
Bar = object
x: int
var f = Foo()
doassert f.x.x == 0
block:
type
Foo = object
x = Bar(x: 55)
Bar = object
x: int
var f = Foo()
doassert f.x.x == 55
block:
type
Bar = object
x: int
Foo = object
x = Bar()
var f = Foo()
doassert f.x.x == 0