change tryGet() API misuse to Defect#41
change tryGet() API misuse to Defect#41etan-status wants to merge 1 commit intoarnetheduck:masterfrom
tryGet() API misuse to Defect#41Conversation
Assuming a `Result[T, E]` with `E: Exception`, `tryGet` has the nasty
side effect of triggering `{.raises: [E, ResultError[void]].}`. This is
because it tries to play nice when `tryGet()` is called on a `Result`
that has not yet been initialized.
That is not in line with how Nim typically operates. Accessing items
that are not initialized may yield to SIGSEGV in many situations.
```nim
proc f() =
var x: ref CatchableError
raise x
f()
```
`tryGet()` semantics are well-defined for an initialized `Result`.
- If a value has been set, it is returned.
- If an error has been set, it is raised.
Calling `tryGet()` on un-initialized data is not a typical usecase
and could instead become a `ResultDefect`. This way, it is not required
anymore to `except + discard` the `ResultError[void]` for hypothetical
API misuse, or to alternatively pollute the callstack with `{.raises.}`.
The alternatiev would be to `raise E(msg: ...)` instead, but that one
may trigger unexpected behaviour as it hides the API misuse error.
`LPError` is the top level error type of libp2p, it makes more sense to raise a multi address specific subtype to avoid requiring callers to catch errors too broadly. As `MaError` inherits from `LPError`, existing error handlers will still work fine. Requires arnetheduck/nim-results#41
|
Been thinking about this one - there are two ways to reason about it:
Originally, the latter story was chosen simply because nobody really cared about specific exception types and "correct" raises lists while the case of the default-initialized Result was deemed highly likely to occur due to how weak Nim is at detecting uninitialized variables / returns (somewhat a consequence of default-to-0 init). Since then, usage has gone in the direction of more explicit raises lists while the language slowly but surely is getting better at detecting lack of init. There are ways in which the impact of this PR could be diminished:
The interesting thing perhaps is that these methods of improving the safety of |
Assuming a
Result[T, E]withE: Exception,tryGethas the nasty side effect of triggering{.raises: [E, ResultError[void]].}. This is because it tries to play nice whentryGet()is called on aResultthat has not yet been initialized.That is not in line with how Nim typically operates. Accessing items that are not initialized may yield to SIGSEGV in many situations.
tryGet()semantics are well-defined for an initializedResult.Calling
tryGet()on un-initialized data is not a typical usecase and could instead become aResultDefect. This way, it is not required anymore toexcept + discardtheResultError[void]for hypothetical API misuse, or to alternatively pollute the callstack with{.raises.}.The alternatiev would be to
raise E(msg: ...)instead, but that one may trigger unexpected behaviour as it hides the API misuse error.