Skip to content

Commit 97927ac

Browse files
committed
Add cap when creating an object of a Capability class
Was cap.rd before, which was a left-over of the old model.
1 parent a04c098 commit 97927ac

File tree

6 files changed

+41
-37
lines changed

6 files changed

+41
-37
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -950,10 +950,9 @@ object Capabilities:
950950
i" when instantiating argument of unapply with type $info"
951951
case LocalInstance(restpe) =>
952952
i" when instantiating expected result type $restpe of function literal"
953-
case NewMutable(tp) =>
954-
i" when constructing mutable $tp"
955953
case NewCapability(tp) =>
956-
i" when constructing Capability instance $tp"
954+
val kind = if tp.derivesFromMutable then "mutable" else "Capability instance"
955+
i" when constructing $kind $tp"
957956
case LambdaExpected(respt) =>
958957
i" when instantiating expected result type $respt of lambda"
959958
case LambdaActual(restp: Type) =>

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -863,16 +863,13 @@ class CheckCaptures extends Recheck, SymTransformer:
863863
*
864864
* Second half: union of initial capture set and all capture sets of arguments
865865
* to tracked parameters. The initial capture set `initCs` is augmented with
866-
* - FreshCap(...) if `core` extends Mutable
867-
* - FreshCap(...).rd if `core` extends Capability
866+
* a fresh cap if `core` extends Capability.
868867
*/
869868
def addParamArgRefinements(core: Type, initCs: CaptureSet): (Type, CaptureSet) =
870869
var refined: Type = core
871870
var allCaptures: CaptureSet =
872-
if core.derivesFromMutable then
873-
initCs ++ FreshCap(Origin.NewMutable(core)).singletonCaptureSet
874-
else if core.derivesFromCapability then
875-
initCs ++ FreshCap(Origin.NewCapability(core)).readOnly.singletonCaptureSet
871+
if core.derivesFromCapability
872+
then initCs ++ FreshCap(Origin.NewCapability(core)).singletonCaptureSet
876873
else initCs
877874
for (getterName, argType) <- mt.paramNames.lazyZip(argTypes) do
878875
val getter = cls.info.member(getterName).suchThat(_.isRefiningParamAccessor).symbol
@@ -897,6 +894,21 @@ class CheckCaptures extends Recheck, SymTransformer:
897894
val (refined, cs) = addParamArgRefinements(core, initCs)
898895
refined.capturing(cs)
899896

897+
/*
898+
def impliedFresh: CaptureSet =
899+
cls.info.fields.foldLeft(CaptureSet.empty: CaptureSet): (cs, field) =>
900+
if !cs.isAlwaysEmpty || field.symbol.is(ParamAccessor) then
901+
cs
902+
else
903+
val fieldFreshCaps = field.info.spanCaptureSet.elems.filter(_.isTerminalCapability)
904+
if fieldFreshCaps.isEmpty then cs
905+
else
906+
val classFresh = FreshCap(ctx.owner, NoPrefix, )
907+
if fieldFreshCaps.forall(_.isReadOnly)
908+
then cs + classFresh.readOnly
909+
else cs + classFresh
910+
*/
911+
900912
augmentConstructorType(resType, capturedVars(cls))
901913
.showing(i"constr type $mt with $argTypes%, % in $constr = $result", capt)
902914
end refineConstructorInstance

tests/neg-custom-args/captures/boundary.check

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
4 | boundary[AnyRef^]:
33
5 | l1 ?=> // error // error
44
| ^
5-
|Found: scala.util.boundary.Label[Object^'s1]^{cap.rd}
6-
|Required: scala.util.boundary.Label[Object^]^²
5+
|Found: scala.util.boundary.Label[Object^'s1]^
6+
|Required: scala.util.boundary.Label[Object^²]^³
77
|
8-
|Note that capability cap² cannot be included in outer capture set 's1.
8+
|Note that capability cap cannot be included in outer capture set 's1.
99
|
10-
|where: ^ refers to the universal root capability
11-
| ^² refers to a fresh root capability classified as Control in the type of value local
12-
| cap is a fresh root capability classified as Control created in value local when constructing Capability instance scala.util.boundary.Label[Object^'s1]
13-
| cap² is the universal root capability
10+
|where: ^ refers to a fresh root capability classified as Control created in value local when constructing Capability instance scala.util.boundary.Label[Object^'s1]
11+
| ^² refers to the universal root capability
12+
| ^³ refers to a fresh root capability classified as Control in the type of value local
13+
| cap is the universal root capability
1414
6 | boundary[Unit]: l2 ?=>
1515
7 | boundary.break(l2)(using l1) // error
1616
8 | ???

tests/neg-custom-args/captures/extending-cap-classes.check

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/extending-cap-classes.scala:7:15 -------------------------
22
7 | val x2: C1 = new C2 // error
33
| ^^^^^^
4-
|Found: C2^{cap.rd}
4+
|Found: C2^
55
|Required: C1
66
|
7-
|Note that capability cap.rd is not included in capture set {}.
7+
|Note that capability cap is not included in capture set {}.
88
|
9-
|where: cap is a fresh root capability classified as SharedCapability created in value x2 when constructing Capability instance C2
9+
|where: ^ refers to a fresh root capability classified as SharedCapability created in value x2 when constructing Capability instance C2
10+
| cap is a fresh root capability classified as SharedCapability created in value x2 when constructing Capability instance C2
1011
|
1112
| longer explanation available when compiling with `-explain`
1213
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/extending-cap-classes.scala:8:15 -------------------------
1314
8 | val x3: C1 = new C3 // error
1415
| ^^^^^^
15-
|Found: C3^{cap.rd}
16+
|Found: C3^
1617
|Required: C1
1718
|
18-
|Note that capability cap.rd is not included in capture set {}.
19+
|Note that capability cap is not included in capture set {}.
1920
|
20-
|where: cap is a fresh root capability classified as SharedCapability created in value x3 when constructing Capability instance C3
21+
|where: ^ refers to a fresh root capability classified as SharedCapability created in value x3 when constructing Capability instance C3
22+
| cap is a fresh root capability classified as SharedCapability created in value x3 when constructing Capability instance C3
2123
|
2224
| longer explanation available when compiling with `-explain`
2325
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/extending-cap-classes.scala:13:15 ------------------------
Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i21614.scala:12:33 ---------------------------------------
2-
12 | files.map((f: F) => new Logger(f)) // error // error, Q: can we make this pass (see #19076)?
2+
12 | files.map((f: F) => new Logger(f)) // error, Q: can we make this pass (see #19076)?
33
| ^
44
|Found: (f : F)
55
|Required: File^
@@ -11,25 +11,16 @@
1111
| cap² is a fresh root capability classified as SharedCapability created in anonymous function of type (f²: F): Logger when checking argument to parameter f of constructor Logger
1212
|
1313
| longer explanation available when compiling with `-explain`
14-
-- Error: tests/neg-custom-args/captures/i21614.scala:12:8 -------------------------------------------------------------
15-
12 | files.map((f: F) => new Logger(f)) // error // error, Q: can we make this pass (see #19076)?
16-
| ^^^^^^^^^
17-
|Type variable U of method map cannot be instantiated to Logger{val f: File^'s1}^{cap.rd} since
18-
|that type captures the root capability `cap`.
19-
|This is often caused by a local capability in an argument of method map
20-
|leaking as part of its result.
21-
|
22-
|where: cap is a root capability associated with the result type of (f²: F^{files*}): Logger{val f: File^'s1}^'s2
2314
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i21614.scala:15:12 ---------------------------------------
2415
15 | files.map(new Logger(_)) // error, Q: can we improve the error message?
2516
| ^^^^^^^^^^^^^
26-
|Found: (_$1: File^'s3) ->{C} Logger{val f: File^{_$1}}^{cap.rd, _$1}
27-
|Required: File^{C} => Logger{val f: File^'s4}^'s5
17+
|Found: (_$1: File^'s1) ->{C} Logger{val f: File^{_$1}}^{cap, _$1}
18+
|Required: File^{C} => Logger{val f: File^'s2}^'s3
2819
|
2920
|Note that capability C is not classified as trait SharedCapability, therefore it
30-
|cannot be included in capture set 's3 of parameter _$1 of SharedCapability elements.
21+
|cannot be included in capture set 's1 of parameter _$1 of SharedCapability elements.
3122
|
3223
|where: => refers to a fresh root capability created in method mkLoggers2 when checking argument to parameter f of method map
33-
| cap is a root capability associated with the result type of (_$1: File^'s3): Logger{val f: File^{_$1}}^{cap.rd, _$1}
24+
| cap is a root capability associated with the result type of (_$1: File^'s1): Logger{val f: File^{_$1}}^{cap, _$1}
3425
|
3526
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/i21614.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ trait File extends SharedCapability
99
class Logger(f: File^) extends SharedCapability // <- will work if we remove the extends clause
1010

1111
def mkLoggers1[F <: File^](files: List[F]): List[Logger^] =
12-
files.map((f: F) => new Logger(f)) // error // error, Q: can we make this pass (see #19076)?
12+
files.map((f: F) => new Logger(f)) // error, Q: can we make this pass (see #19076)?
1313

1414
def mkLoggers2[C^](files: List[File^{C}]): List[Logger^] =
1515
files.map(new Logger(_)) // error, Q: can we improve the error message?

0 commit comments

Comments
 (0)