File tree Expand file tree Collapse file tree 4 files changed +55
-20
lines changed
compiler/src/dotty/tools/dotc/cc
tests/neg-custom-args/captures Expand file tree Collapse file tree 4 files changed +55
-20
lines changed Original file line number Diff line number Diff line change @@ -142,32 +142,19 @@ object CheckCaptures:
142142
143143 private val seen = new EqHashSet [TypeRef ]
144144
145- /** Check that there is at least one method containing carrier and defined
146- * in the scope of tparam. E.g. this is OK:
147- * def f[T] = { ... var x: T ... }
148- * So is this:
149- * class C[T] { def f() = { class D { var x: T }}}
150- * But this is not OK:
151- * class C[T] { object o { var x: T }}
152- */
153- extension (tparam : Symbol ) def isParametricIn (carrier : Symbol ): Boolean =
154- carrier.exists && {
155- val encl = carrier.owner.enclosingMethodOrClass
156- if encl.isClass then tparam.isParametricIn(encl)
157- else
158- def recur (encl : Symbol ): Boolean =
159- if tparam.owner == encl then true
160- else if encl.isStatic || ! encl.exists then false
161- else recur(encl.owner.enclosingMethodOrClass)
162- recur(encl)
163- }
164-
165145 def traverse (t : Type ) =
166146 t.dealiasKeepAnnots match
167147 case t : TypeRef =>
168148 if ! seen.contains(t) then
169149 seen += t
170150 traverseChildren(t)
151+
152+ // Check the lower bound of path dependent types.
153+ // See issue #19330.
154+ val isMember = t.prefix ne NoPrefix
155+ t.info match
156+ case TypeBounds (lo, _) if isMember => traverse(lo)
157+ case _ =>
171158 case AnnotatedType (_, ann) if ann.symbol == defn.UncheckedCapturesAnnot =>
172159 ()
173160 case t =>
Original file line number Diff line number Diff line change 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!
Original file line number Diff line number Diff line change 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
Original file line number Diff line number Diff line change 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!
You can’t perform that action at this time.
0 commit comments