File tree 2 files changed +50
-10
lines changed
compiler/src/dotty/tools/dotc/cc
tests/neg-custom-args/captures
2 files changed +50
-10
lines changed Original file line number Diff line number Diff line change @@ -72,16 +72,23 @@ object CheckCaptures:
72
72
*/
73
73
final class SubstParamsMap (from : BindingType , to : List [Type ])(using Context )
74
74
extends ApproximatingTypeMap , IdempotentCaptRefMap :
75
- def apply (tp : Type ): Type = tp match
76
- case tp : ParamRef =>
77
- if tp.binder == from then to(tp.paramNum) else tp
78
- case tp : NamedType =>
79
- if tp.prefix `eq` NoPrefix then tp
80
- else tp.derivedSelect(apply(tp.prefix))
81
- case _ : ThisType =>
82
- tp
83
- case _ =>
84
- mapOver(tp)
75
+ /** This SubstParamsMap is exact if `to` only contains `CaptureRef`s. */
76
+ private val isExactSubstitution : Boolean = to.forall(_.isInstanceOf [CaptureRef ])
77
+
78
+ /** As long as this substitution is exact, there is no need to create `Range`s when mapping invariant positions. */
79
+ override protected def needsRangeIfInvariant (refs : CaptureSet ): Boolean = ! isExactSubstitution
80
+
81
+ def apply (tp : Type ): Type =
82
+ tp match
83
+ case tp : ParamRef =>
84
+ if tp.binder == from then to(tp.paramNum) else tp
85
+ case tp : NamedType =>
86
+ if tp.prefix `eq` NoPrefix then tp
87
+ else tp.derivedSelect(apply(tp.prefix))
88
+ case _ : ThisType =>
89
+ tp
90
+ case _ =>
91
+ mapOver(tp)
85
92
86
93
/** Check that a @retains annotation only mentions references that can be tracked.
87
94
* This check is performed at Typer.
Original file line number Diff line number Diff line change
1
+ import language .experimental .captureChecking
2
+ import caps .*
3
+
4
+ trait Ref [T ] { def set (x : T ): T }
5
+ def test () = {
6
+
7
+ def swap [T ](x : Ref [T ]^ )(y : Ref [T ]^ {x}): Unit = ???
8
+ def foo [T ](x : Ref [T ]^ ): Unit =
9
+ swap(x)(x)
10
+
11
+ def bar [T ](x : () => Ref [T ]^ )(y : Ref [T ]^ {x}): Unit =
12
+ swap(x())(y) // error
13
+
14
+ def baz [T ](x : Ref [T ]^ )(y : Ref [T ]^ {x}): Unit =
15
+ swap(x)(y)
16
+ }
17
+
18
+ trait IO
19
+ type Op = () -> Unit
20
+ def test2 (c : IO ^ , f : Op ^ {c}) = {
21
+ def run (io : IO ^ )(op : Op ^ {io}): Unit = op()
22
+ run(c)(f)
23
+
24
+ def bad (getIO : () => IO ^ , g : Op ^ {getIO}): Unit =
25
+ run(getIO())(g) // error
26
+ }
27
+
28
+ def test3 () = {
29
+ def run (io : IO ^ )(op : Op ^ {io}): Unit = ???
30
+ val myIO : IO ^ = ???
31
+ val myOp : Op ^ {myIO} = ???
32
+ run(myIO)(myOp)
33
+ }
You can’t perform that action at this time.
0 commit comments