Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: prevent either block nesting to avoid type/try-catch mismatches #149

Closed
lbialy opened this issue Jun 4, 2024 · 1 comment
Closed

Comments

@lbialy
Copy link
Contributor

lbialy commented Jun 4, 2024

Either blocks, based on boundaries, provide implicit evidence for safe jumps. One problematic case is when .ok() combinator is called on a fork (or inside of exception capturing scope that can swallow a Break), another is when nested boundaries provide evidences for mismatched cases:

val effectMatchingOuterEither: Either[Throwable, Unit] = Left(Exception("oh no"))
val effectMatchingInnerEither: Either[String, Int] = Right(3)

val outer: Either[Throwable, Unit] = either {
  val inner: Either[String, Int] = either {
    effectMatchingOuterEither.ok()
    effectMatchingInnerEither.ok()
  }

  ()
}

Notice that first Either value evaluated with .ok() matches outer either block while being evaluated in the inner block. This might very well be considered a feature - types allow us to decide where to jump - but in my short but stressful experience with this kind of combinators - when this is used with type inference, results can be surprising. In my case the inner block was the body of Tapir handler while outer either block was in main function. The result was, unsurprisingly, a thread killed with Break. I would get a compilation error if nested either blocks were not allowed because without the outer block I'd be informed that it's impossible to use .ok() as either block in tapir handler is inferred to be Either[Unit, String]. I know this is a rather heavy-handed change and there are possible use cases for nested either blocks (tagged jumps for example) but this is confusing enough imho to warrant such a change. I can easily imagine such a change to occur during refactoring of code where inner either block stops matching one of the eithers with .ok() in it's scope and outer either providing evidence where it's no longer handled correctly.

#148

@lbialy
Copy link
Contributor Author

lbialy commented Jun 19, 2024

Solved by #148

@lbialy lbialy closed this as completed Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant