-
Notifications
You must be signed in to change notification settings - Fork 12
Description
A requiresInit type requires that all fields are explicitly initialized:
type RI {.requiresInit.} = object
v*: int
var v = RI(v: 5) # valid
var v2 = RI() # invalidUntil recently, this worked partially by accident due bugs: nim-lang/Nim#25116 and nim-lang/Nim#25117.
When deserializing such a type, the framewould could, at runtime, make sure that all public fields are deserialized and generate a constructor call accordingly, but this only works for one "level" of creation.
Another problem is that there is no way to call readValue(r: .., value: var RI) because there is no way to construct value for this call - if a generic deserializer for readValue prepares a default instance for value to be "filled in" during deserialization, this implementation will not work for requiresInit types.
If v is private, we are further restricted and cannot touch v at all, except in an override in the module that declared the type.
To support requiresInit, we would thus have to add a way to overload the "style" of readValue called for a type and consistently use that when nesting calls, something like:
template callReadValue(r, target: auto) =
r.readValue(target)
template callReadValue(r, target: RI) =
target = RI(...)
this would allow an "overrider" of readValue to also choose the calling style used throughout for arbitrary types. This is more work for the override but requiresInit are rare.
Alternatively, readValue should in generic contexts always be called as value = readValue(T), introducing potential inefficiency.
Other options to be explored.