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

Scoped capabilities can leak through path-dependent types #19330

Closed
Linyxus opened this issue Dec 23, 2023 · 0 comments · Fixed by #19624
Closed

Scoped capabilities can leak through path-dependent types #19330

Linyxus opened this issue Dec 23, 2023 · 0 comments · Fixed by #19624
Assignees
Labels
area:experimental:cc Capture checking related cc-experiment Intended to be merged with cc-experiment branch on origin itype:bug
Milestone

Comments

@Linyxus
Copy link
Contributor

Linyxus commented Dec 23, 2023

Compiler version

main

Minimized code

import language.experimental.captureChecking

trait Logger
def usingLogger[T](op: Logger^ => T): T = ???

trait Foo:
  type T >: () => Logger^

class Bar extends Foo:
  type T = () => Logger^

def foo(x: Foo): x.T =
  val leaked = usingLogger[x.T]: l =>
    val t: () => Logger^ = () => l
    t: x.T
  leaked

def test(): Unit =
  val bar = new Bar
  val bad: bar.T = foo(bar)
  val leaked: Logger^ = bad()  // leaked scoped capability!

Output

It compiles.

Expectation

It should not compile.

Essentially, the above example is equivalent to the following code but the following uses type parameters instead of path-dependent types:

def foo[X >: () => Logger^](): X =
  val leaked = usingLogger[X]: l =>
    val t: () => Logger^ = () => l
    t: X
  leaked
val bad = foo[() => Logger^]()  // error

But this code is rejected as wanted, as we perform the no-root-capability check for the type application foo[() => Logger^].
Given that path-dependent types is, in some sense, equivalent to type parameters, a similar check should be performed for foo(bar) in the unsound code example.
But that one is currently missing.

Alternatively, instead of checking the type members on the callsite, we could do that check when instantiating a type member. In this case, that would be when defining the class Bar.

@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 Dec 23, 2023
@Linyxus Linyxus self-assigned this Dec 23, 2023
@Gedochao Gedochao added the area:experimental:cc Capture checking related label Jan 18, 2024
Linyxus added a commit that referenced this issue Feb 15, 2024
Fixes #19330.

Since when instantiating a type member we do not disallow covariant
`cap`s in the instance, a check is added at the application site to
check for covariant `cap`s in the lower bound of type members to
maintain soundness. This check is elided for type parameters since their
instances are always checked at the instantiation site.
@Kordyjan Kordyjan added this to the 3.4.2 milestone Mar 28, 2024
@Kordyjan Kordyjan modified the milestones: 3.4.2, 3.5.0 May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:experimental:cc Capture checking related 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.

3 participants