Lwt 3.2.0 released – we plan to change Lwt.bind

Having had time to discuss and think about the Lwt.bind change, I think it’s indeed better to postpone or completely abandon it. The reasoning is:

  • A lot of code would potentially have to be reviewed, and it’s difficult to do automatically.
  • The semantic problem, I think, is quite minor, when taken in context. The details are immediately below.

So, it doesn’t seem like the tradeoff is worth it. We may have a fresh “front-facing” Lwt API at some point, and then we will have the opportunity to get the semantics fully right without risking any big breakage.


The original issue is: Lwt.bind p f raises an exception if p is already resolved and f raises. This is inconsistent with the rest of Lwt, including Lwt.bind when p is not resolved: in all other cases, if f raises, the Lwt API puts the exception into rejecting a promise rather than raising it further up the stack.

Why this is probably not important: in an Lwt program, the exception leaked by Lwt.bind p f is ultimately going to almost always have the same “fate” as an exception used to reject Lwt.bind p f. Examples:

  • If the Lwt.bind p f is called within any other Lwt callback, which is very common when chaining Lwt computations, the Lwt API that is calling the callback will capture the exception and reject ultimately the same promise as Lwt.bind p f “should” reject.
  • If Lwt.bind p f is being called as part of resolving a promise that Lwt_main.run depends on, converting Lwt.bind to reject instead of raising will just cause Lwt_main.run to raise the exception from the rejeted promise right afterwards.
  • Leaking an exception to Lwt.async has the same effect as rejecting the promise returned to it, which is a call to !Lwt.async_exception_hook.

…and so on.

The above is not a proof. There are probably corner cases where the behavior is actually different in some material fashion. So, these semantics are still bad. However, the corner cases seem to be rare (nobody has ever reported an instance, we found the issue by reading the Lwt code), and so fixing this is not worth making people lose trust in already-written code.


Thanks to @talex5 and others for resisting this change, and to everyone else as well, for all feedback and testing :slight_smile:

11 Likes