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

Leaking scoped capability when the expected type of a block is boxed #16114

Closed
Linyxus opened this issue Sep 27, 2022 · 1 comment · Fixed by #16136
Closed

Leaking scoped capability when the expected type of a block is boxed #16114

Linyxus opened this issue Sep 27, 2022 · 1 comment · Fixed by #16136
Labels
area:typer cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug
Milestone

Comments

@Linyxus
Copy link
Contributor

Linyxus commented Sep 27, 2022

Compiler version

main branch

Minimized code

trait Cap { def use(): Int; def close(): Unit }
def mkCap(): {*} Cap = ???
type Id[T] = Unit => T

def expect[T](x: T): x.type = x

def withCap[T](op: ({*} Cap) => T): T = {
  val cap: {*} Cap = mkCap()
  val result = op(cap)
  cap.close()
  result
}

def main(): Unit = {
  def badOp(io: {*} Cap): {} Unit -> Unit = {
    val op: {} Unit -> Unit = (x: Unit) =>
      expect[{*} Cap] {
        io.use()
        io
      }
    op
  }

  val leaked: {} Unit -> Unit = withCap(badOp)
  leaked(())  // use the leaked capability
}

Output

The code compiles.

Expectation

The code should not compile. More specifically, we should issue an error when typechecking the val op: ... = ... line, since the function uses the io capability inside its body so it is impure.

The cause of this issue: when type checking the block in the expect[{*} Cap] { ... } expression, the expected type is □ {*} Cap which is boxed, so we will create a temporary boxed Env for it and prevent the captured variable inside the block from charging the outer environment. However, at runtime the block does access the capability io when executing its statements.

Ideally, we should only create a boxed environment when typechecking the expression of the block, but not its statements.

@Linyxus Linyxus added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label cc-experiment Intended to be merged with cc-experiment branch on origin and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 27, 2022
@odersky
Copy link
Contributor

odersky commented Sep 27, 2022

Yes, that's a good point. We should create boxed environments only for values and references.

Linyxus added a commit that referenced this issue Oct 19, 2022
…6136)

Fixes #16114.

According to the
[comment](#16114 (comment))
in the issue, only create boxed environment when the rechecked tree is a
reference or a function value.

This PR also fixes a testcase, as explained in this
[commit](25daaa8).
@Kordyjan Kordyjan added this to the 3.2.2 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:typer cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants