Skip to content

Deserialization of requiresInit types #104

@arnetheduck

Description

@arnetheduck

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() # invalid

Until 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions