Skip to content

Commit 67446d2

Browse files
committed
Solve all capture sets in types of vals and defs by default
1 parent fc06af6 commit 67446d2

18 files changed

+99
-112
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object ccConfig:
4949

5050
/** Not used currently. Handy for trying out new features */
5151
def newScheme(using Context): Boolean =
52-
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.8`)
52+
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.7`)
5353

5454
end ccConfig
5555

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -317,14 +317,16 @@ class CheckCaptures extends Recheck, SymTransformer:
317317
/** Instantiate capture set variables appearing contra-variantly to their
318318
* upper approximation.
319319
*/
320-
private def interpolator(startingVariance: Int = 1)(using Context) = new TypeTraverser:
320+
private def interpolator(sym: Symbol, startingVariance: Int = 1)(using Context) = new TypeTraverser:
321321
variance = startingVariance
322322
override def traverse(t: Type) = t match
323323
case t @ CapturingType(parent, refs) =>
324324
refs match
325325
case refs: CaptureSet.Var if !refs.isConst =>
326-
if variance < 0 then refs.solve()
327-
else if ccConfig.newScheme then refs.markSolved(provisional = true)
326+
if variance < 0 then
327+
refs.solve()
328+
else if ccConfig.newScheme && !sym.isAnonymousFunction then
329+
refs.markSolved(provisional = !sym.isMutableVar)
328330
case _ =>
329331
traverse(parent)
330332
case t @ defn.RefinedFunctionOf(rinfo) =>
@@ -356,7 +358,7 @@ class CheckCaptures extends Recheck, SymTransformer:
356358
*/
357359
private def interpolateVarsIn(tpt: Tree, sym: Symbol)(using Context): Unit =
358360
if tpt.isInstanceOf[InferredTypeTree] then
359-
interpolator().traverse(tpt.nuType)
361+
interpolator(sym).traverse(tpt.nuType)
360362
.showing(i"solved vars for $sym in ${tpt.nuType}", capt)
361363
anchorCaps(sym).traverse(tpt.nuType)
362364
for msg <- ccState.approxWarnings do
@@ -378,8 +380,9 @@ class CheckCaptures extends Recheck, SymTransformer:
378380
if d.isEmpty then provenance else ""
379381
em"$prefix included in the allowed capture set ${res.blocking}$descr$toAdd"
380382
target match
381-
case target: CaptureSet.Var if res.blocking.isProvisionallySolved =>
382-
report.warning(msg.prepend(i"Another capture checking run needs to be scheduled because:"), pos)
383+
case target: CaptureSet.Var
384+
if res.blocking.isProvisionallySolved =>
385+
report.error(msg.prepend(i"Another capture checking run needs to be scheduled because\n"), pos)
383386
needAnotherRun = true
384387
added match
385388
case added: CaptureRef => target.elems += added
@@ -745,7 +748,7 @@ class CheckCaptures extends Recheck, SymTransformer:
745748
protected override def recheckArg(arg: Tree, formal: Type)(using Context): Type =
746749
val freshenedFormal = root.capToFresh(formal)
747750
val argType = recheck(arg, freshenedFormal)
748-
.showing(i"recheck arg $arg vs $freshenedFormal", capt)
751+
.showing(i"recheck arg $arg vs $freshenedFormal = $result", capt)
749752
if formal.hasAnnotation(defn.UseAnnot) || formal.hasAnnotation(defn.ConsumeAnnot) then
750753
// The @use and/or @consume annotation is added to `formal` by `prepareFunction`
751754
capt.println(i"charging deep capture set of $arg: ${argType} = ${argType.deepCaptureSet}")
@@ -1016,7 +1019,7 @@ class CheckCaptures extends Recheck, SymTransformer:
10161019

10171020
val saved = curEnv
10181021
val localSet = capturedVars(sym)
1019-
if !localSet.isAlwaysEmpty then
1022+
if localSet ne CaptureSet.empty then
10201023
curEnv = Env(sym, EnvKind.Regular, localSet, curEnv, nestedClosure(tree.rhs))
10211024

10221025
// ctx with AssumedContains entries for each Contains parameter
@@ -1098,7 +1101,7 @@ class CheckCaptures extends Recheck, SymTransformer:
10981101
.toMap
10991102
def restoreEnvFor(sym: Symbol): Env =
11001103
val localSet = capturedVars(sym)
1101-
if localSet.isAlwaysEmpty then rootEnv
1104+
if localSet eq CaptureSet.empty then rootEnv
11021105
else envForOwner.get(sym) match
11031106
case Some(e) => e
11041107
case None => Env(sym, EnvKind.Regular, localSet, restoreEnvFor(sym.owner))
@@ -1125,7 +1128,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11251128
checkSubset(capturedVars(parent.tpe.classSymbol), localSet, parent.srcPos,
11261129
i"\nof the references allowed to be captured by $cls")
11271130
val saved = curEnv
1128-
if !localSet.isAlwaysEmpty then
1131+
if localSet ne CaptureSet.empty then
11291132
curEnv = Env(cls, EnvKind.Regular, localSet, curEnv)
11301133
try
11311134
val thisSet = cls.classInfo.selfType.captureSet.withDescription(i"of the self type of $cls")
@@ -1779,7 +1782,7 @@ class CheckCaptures extends Recheck, SymTransformer:
17791782
inContext(ctx.fresh.setOwner(root)):
17801783
checkSelfAgainstParents(root, root.baseClasses)
17811784
val selfType = root.asClass.classInfo.selfType
1782-
interpolator(startingVariance = -1).traverse(selfType)
1785+
interpolator(root, startingVariance = -1).traverse(selfType)
17831786
selfType match
17841787
case CapturingType(_, refs: CaptureSet.Var)
17851788
if !root.isEffectivelySealed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
-- Error: tests/neg-custom-args/captures/byname.scala:5:21 -------------------------------------------------------------
2+
5 | def g(x: Int) = if cap2 == cap2 then 1 else x // error
3+
| ^^^^
4+
| Another capture checking run needs to be scheduled because
5+
| reference (cap2 : Cap) is not included in the allowed capture set {} of method f
16
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/byname.scala:10:6 ----------------------------------------
27
10 | h(f2()) // error
38
| ^^^^

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class Cap extends caps.Capability
22

33
def test(cap1: Cap, cap2: Cap) =
44
def f() = if cap1 == cap1 then g else g
5-
def g(x: Int) = if cap2 == cap2 then 1 else x
5+
def g(x: Int) = if cap2 == cap2 then 1 else x // error
66
def g2(x: Int) = if cap1 == cap1 then 1 else x
77
def f2() = if cap1 == cap1 then g2 else g2
88
def h(ff: => Int ->{cap2} Int) = ff

tests/neg-custom-args/captures/gears-problem.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/gears-problem.scala:24:34 --------------------------------
99
24 | val fut2: Future[T]^{fs*} = r.get // error
1010
| ^^^^^
11-
| Found: Future[box T^?]^{collector.futures*}
11+
| Found: Future[box T^{}]^{collector.futures*}
1212
| Required: Future[T]^{fs*}
1313
|
1414
| longer explanation available when compiling with `-explain`

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i21313.scala:15:12 ---------------------------------------
66
15 | ac1.await(src2) // error
77
| ^^^^
8-
| Found: (src2 : Source[Int, scala.caps.CapSet^{ac2}]^?)
8+
| Found: (src2 : Source[Int, scala.caps.CapSet^{ac2}]^{})
99
| Required: Source[Int, scala.caps.CapSet^{ac1}]^
1010
|
1111
| longer explanation available when compiling with `-explain`

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ def test1(io: Object^): Unit =
66
val x = () =>
77
foo()
88
val y = Box(io)
9-
println(y.m)
10-
val _: () -> Unit = x // error
9+
println(y.m) // error: another run needs to be scheduled
10+
val _: () -> Unit = x // was error
1111

1212
def test2(io: Object^): Unit =
1313
def foo(): Unit = bar()
@@ -16,5 +16,5 @@ def test2(io: Object^): Unit =
1616
foo()
1717
val _: () -> Unit = x
1818
val y = Box(io)
19-
println(y.m) // error
19+
println(y.m) // error: another run needs to be scheduled
2020
val _: () -> Unit = x

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:35:29 -------------------------------------
99
35 | val ref1c: LazyList[Int] = ref1 // error
1010
| ^^^^
11-
| Found: (ref1 : lazylists.LazyCons[Int]{val xs: () ->{cap1} lazylists.LazyList[Int]^?}^{cap1})
12-
| Required: lazylists.LazyList[Int]
11+
| Found: (ref1 : lazylists.LazyCons[Int]{val xs: () ->{cap1} lazylists.LazyList[Int]^{}}^{cap1})
12+
| Required: lazylists.LazyList[Int]
1313
|
1414
| longer explanation available when compiling with `-explain`
1515
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:37:36 -------------------------------------

tests/neg-custom-args/captures/leaking-iterators.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/leaking-iterators.scala:56:16 ----------------------------
22
56 | usingLogFile: log => // error
33
| ^
4-
| Found: (log: java.io.FileOutputStream^) ->{xs} box cctest.Iterator[Int]^{log}
4+
| Found: (log: java.io.FileOutputStream^) ->? box cctest.Iterator[Int]^{log}
55
| Required: (log: java.io.FileOutputStream^) ->{fresh} box cctest.Iterator[Int]^?
66
|
77
| Note that reference log.type

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/levels.scala:22:11 ---------------------------------------
77
22 | r.setV(g) // error
88
| ^
9-
| Found: box (x: String) ->{cap3} String
10-
| Required: box (x: String) ->? String
11-
|
12-
| Note that reference (cap3 : CC^), defined in method scope
13-
| cannot be included in outer capture set ? of value r
9+
| Found: (x: String) ->{cap3} String
10+
| Required: (x: String) -> String
1411
|
1512
| longer explanation available when compiling with `-explain`

0 commit comments

Comments
 (0)