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

Invoking non-resuming effect in effect handler skips finalizers #360

Open
JanBeh opened this issue Sep 17, 2023 · 2 comments
Open

Invoking non-resuming effect in effect handler skips finalizers #360

JanBeh opened this issue Sep 17, 2023 · 2 comments

Comments

@JanBeh
Copy link

JanBeh commented Sep 17, 2023

In the given program

effect ctl myeffect() : ()

fun main() : <console> ()
    with ctl myeffect()
        ()
    with ctl myeffect()
        myeffect()
    with finally
        println("cleanup")
    myeffect()

the line println("cleanup") apparently isn't executed. I assume this is a bug, but I'm not entirely sure.

Tested with koka version 2.4.2.

If this is intended, is there some documentation on this?

@TimWhiting
Copy link
Collaborator

TimWhiting commented Sep 22, 2023

This is the relevant code from hnd.kk


pub fun finally( fin : () -> e (), action : () -> e a ) : e a 
  finally-prompt(fin, action());

fun finally-prompt(fin : () -> e (), res : a ) : e a 
  if !yielding() then 
    fin()
    res
  elif yielding-non-final() then 
    yield-cont(fn(cont,x){ finally-prompt(unsafe-decreasing(fin),cont(x)) })
  else 
    val yld = yield-capture()
    fin()
    if yielding() return yield-extend( fn(_x) unsafe-reyield(yld) )
    unsafe-reyield(yld)

It looks like in the else branch where it deals with the non-resumptive handler clauses, it invokes the finalize function fin() after it captures where it actually needs to yield to. However, in your case there is no handler above that actually resumes, so yield-capture never resumes.

So it looks like there might need to be some handler/prompt to delimit the main function, so that when capturing the yield, it actually captures something.

Rather than creating a separate effect to do so, you can just use finally which will install a delimiting prompt. This works for me:

effect ctl myeffect() : ()

fun main() : <console> ()
  with finally
    ()
  with ctl myeffect()
    resume(())
  with override ctl myeffect()
    myeffect()
  with finally
    println("cleanup")
  myeffect()

@JanBeh
Copy link
Author

JanBeh commented Sep 22, 2023

I still don't understand if the exhibited behavior is intentional or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants