Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Clarification: Why do try blocks need a result type? #83

Closed
mirkosertic opened this issue Jul 4, 2019 · 4 comments
Closed

Clarification: Why do try blocks need a result type? #83

mirkosertic opened this issue Jul 4, 2019 · 4 comments

Comments

@mirkosertic
Copy link
Contributor

Given the following textual representation:

(module
  (func (export "dosomething") (result i32)
    (try $globalTry
      (return (i32.const 10))
      (catch
        (rethrow)
      )
     )
  )
)

yields the following validation error:

Error: validate failed:
test.wast:5:7: error: type mismatch in implicit return, expected [i32] but got []
      (catch
      ^

The following code with an additional result type on the try block passes validation:

(module
  (func (export "dosomething") (result i32)
    (try $globalTry (result i32)
      (return (i32.const 10))
      (catch
        (rethrow)
      )
     )
  )
)

I really don't get why the result type on try is needed, as the block either returns directly of rethrows an exception. I'd like to request a clarification on this.

@rossberg
Copy link
Member

rossberg commented Jul 4, 2019

That's exactly the same as with other block instructions. Your example is no different from:

(func (result i32)
    (block (result i32)  ;; result type necessary
      (return (i32.const 10))
    )
)

The block type specifies the type of the stack afterwards. Furthermore, at the end of the function, the stack must conceptually contain the function results. So the block type needs to match that. That's enforced regardless of whether there is a return or not or what the control flow is, because we do not want to require validation to perform control flow analysis.

@mirkosertic
Copy link
Contributor Author

Thank you for your quick response!

Here is an example without result type, validating perfectly:

(module
  (func (export "dosomething") (result i32)
	(local $local_1_REFERENCE i32)
        (local $local_2_INT i32)
        (block $L_10
            (loop $L_10_inner
                (block $IF_10
                    (if $IF_10_inner (i32.ge_s (get_local $local_2_INT) (i32.const 10))
                        (then
                            (return (get_local $local_1_REFERENCE))
                            ))
                    (br $L_10_inner))
                )
            )
       (return (i32.const 10))
  )
)

Here we have block, loop and if statements without any result type, but it works, Conceptually there is no difference to the try/catch example from above, so why are here no result types required?

@rossberg
Copy link
Member

rossberg commented Jul 4, 2019

That example is different because the block isn't the last instruction in the function body, the return is. If you move the return out of the try block in your original example it validates as well.

@mirkosertic
Copy link
Contributor Author

That was the hint: block is the last instruction of the function body. I missed that, Thank you for clarification!

ioannad pushed a commit to ioannad/exception-handling that referenced this issue Jun 6, 2020
* Add definition of free index sets
* Simplify datacount side condition
* Explain convention about multiple occurrences of meta variables
ioannad pushed a commit to ioannad/exception-handling that referenced this issue Jun 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants