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

result type inference for defer, to help with a very useful debugging / contracts idiom #8793

Open
timotheecour opened this issue Aug 28, 2018 · 2 comments

Comments

@timotheecour
Copy link
Member

timotheecour commented Aug 28, 2018

the following is a very useful idiom for debugging, where adding defer: echo("result:", result) at top of body of a function allows printing its result, regardless of whether the function can return in many places:

  • use case1: debugging
proc foo(a:Arg): auto=
  defer: echo("result:", result)
  # restOfCode which may return in multiple places
  • use case1: contracts
proc foo(a:Arg): auto=
  defer: doAssert result.isSomeProperty
  # restOfCode which may return in multiple places

it's yet another advantage of defer over try/finally as all it does is add a single line of code instead of having to wrap lots of code into a try/finally (and then reverting back when we're done debugging).
However it has 1 limitation: it requires either an explicit type (see case3) or an explicit dummy initialization before defer (see case4); otherwise it gives Error: type mismatch: got <untyped>

Could that limitation be lifted? since the defer unwraps to try/finally, it would seem like it could, and be smarter about type inference in this case

when defined(case2):
  proc foo(a:int):auto=
    # Error: type mismatch: got <untyped>
    defer: echo("result:", result)
    if a==0:
      return 42
    if a==1:
      result=123
    elif a==2:
      return 101

  echo foo(1)

when defined(case3):
  # explicit return type: ok
  proc foo(a:int):int=
    defer: echo("result:", result)
    if a==0:
      return 42
    if a==1:
      result=123
    elif a==2:
      return 101

  let a = foo(1)

when defined(case4):
  # initialization of result before defer: ok
  proc foo(a:int):auto=
    if false: result = 0
    defer: echo("result:", result)
    if a==0:
      return 42
    if a==1:
      result=123
    elif a==2:
      return 101

  let a = foo(1)

links

@mratsim
Copy link
Collaborator

mratsim commented Aug 28, 2018

Nice trick, though I'm surprised return rewrites implicitly to result.

You might be relying on implementation details of return that is leaking and that may change.

@metagn
Copy link
Collaborator

metagn commented Aug 28, 2018

@mratsim not leaked

@timotheecour timotheecour changed the title result type inference for defer, to help with a very useful debugging idiom result type inference for defer, to help with a very useful debugging / assertion idiom Aug 28, 2018
@timotheecour timotheecour changed the title result type inference for defer, to help with a very useful debugging / assertion idiom result type inference for defer, to help with a very useful debugging / contracts idiom Aug 28, 2018
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

3 participants