Skip to content

Commit e676508

Browse files
committed
Disallow covariant caps in the lower bound of type members
1 parent 5850d2d commit e676508

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ object CheckCaptures:
168168
if !seen.contains(t) then
169169
seen += t
170170
traverseChildren(t)
171+
172+
// Check the lower bound of path dependent types.
173+
// See issue #19330.
174+
val isTypeParam = t.prefix eq NoPrefix
175+
t.info match
176+
case TypeBounds(lo, hi) if !isTypeParam => traverse(lo)
177+
case _ =>
171178
case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot =>
172179
()
173180
case t =>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import language.experimental.captureChecking
2+
3+
trait Logger
4+
def usingLogger[T](op: Logger^ => T): T = ???
5+
6+
def foo[T >: () => Logger^](): T =
7+
val leaked = usingLogger[T]: l => // ok
8+
val t: () => Logger^ = () => l
9+
t: T
10+
leaked
11+
12+
def test(): Unit =
13+
val bad: () => Logger^ = foo[() => Logger^] // error
14+
val leaked: Logger^ = bad() // leaked scoped capability!
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import language.experimental.captureChecking
2+
3+
trait Logger
4+
def usingLogger[T](op: Logger^ => T): T = ???
5+
6+
trait Foo:
7+
type T >: () => Logger^
8+
9+
def foo: this.T =
10+
val leaked = usingLogger[T]: l => // error
11+
val t: () => Logger^ = () => l
12+
t: T
13+
leaked
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import language.experimental.captureChecking
2+
3+
trait Logger
4+
def usingLogger[T](op: Logger^ => T): T = ???
5+
6+
trait Foo:
7+
type T >: () => Logger^
8+
9+
class Bar extends Foo:
10+
type T = () => Logger^
11+
12+
def foo(x: Foo): x.T =
13+
val leaked = usingLogger[x.T]: l => // error
14+
val t: () => Logger^ = () => l
15+
t: x.T
16+
leaked
17+
18+
def test(): Unit =
19+
val bar = new Bar
20+
val bad: bar.T = foo(bar)
21+
val leaked: Logger^ = bad() // leaked scoped capability!

0 commit comments

Comments
 (0)