toitlang / toit

Program your microcontrollers in a fast and robust high-level language.
https://toitlang.org/
GNU Lesser General Public License v2.1
1.23k stars 81 forks source link

A finally body should not be allowed to return #376

Open floitsch opened 2 years ago

floitsch commented 2 years ago

A finally block should not be allowed to eat exceptions. That means that it shouldn't be allowed to return, break, or continue.

lask commented 2 years ago

Note that we do exploit this in the kernel in https://github.com/toitware/toit

lask commented 2 years ago

I just did a quick survey to see how extensively this feature is used, and it is a lot less than I recall. In https://github.com/toitlang/toit we exploit this to implement catch: https://github.com/toitlang/toit/blob/d8749a7156684522d4167db74c2b6c94767d0f9f/lib/core/exceptions.toit#L131 and we use it in a couple of other places: https://github.com/toitlang/toit/blob/d8749a7156684522d4167db74c2b6c94767d0f9f/lib/expect.toit#L97 https://github.com/toitlang/toit/blob/d8749a7156684522d4167db74c2b6c94767d0f9f/lib/rpc/broker.toit#L105

In https://github.com/toitware/toit we only use it in a test: https://github.com/toitware/toit/blob/b4402bc0336f6a7e4e7c0764698b209a4e21ff9f/tools/wilson/tests/pubsub_test.toit#L65

dumblob commented 1 year ago

I can not access the linked repositories to see how the VM (and especially the kernel!) is actually implemented.

Any insights?

floitsch commented 1 year ago

@dumblob for the VM and its implementation have a look here: https://github.com/toitlang/toit

The toitware reference just links to a test that changes an exception in a finally to a return. That code is now deprecated. All the interesting code has been moved to the toitlang repository.

Here is the code:

test_pubsub_close_listen_ sub/pubsub.TemporarySubscription started/monitor.Latch closed/monitor.Latch -> int:
  received := 0
  started.set null
  try:
    sub.listen: | msg/pubsub.Message |
      received++
  finally: | is_exception exception |
    expect is_exception
    expect_equals pubsub.ERR_SUBSCRIPTION_CLOSED exception.value
    closed.set null
    return received