Skip to content

Commit 2a34add

Browse files
committed
Make magic imply capyure checking
Comes with two bug fixes: (1) Maybe arguments should not be boxed. (2) Capture sets of module vals need to be interpolated
1 parent 83e6f25 commit 2a34add

7 files changed

Lines changed: 22 additions & 19 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ class CheckCaptures extends Recheck, SymTransformer:
408408
* has been rechecked.
409409
*/
410410
private def interpolateIfInferred(tpt: Tree, sym: Symbol)(using Context): Unit =
411-
if tpt.isInstanceOf[InferredTypeTree] then
411+
if tpt.isInstanceOf[InferredTypeTree] || sym.is(ModuleVal) then
412412
interpolate(tpt.nuType, sym)
413413
.showing(i"solved vars for $sym in ${tpt.nuType}", capt)
414414
anchorCaps(sym).traverse(tpt.nuType)

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,11 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
311311
CapturingType(OrType(parent1, tp2, tp.isSoft), refs1, tp1.isBoxed)
312312
case tp @ OrType(tp1, tp2 @ CapturingType(parent2, refs2)) =>
313313
CapturingType(OrType(tp1, parent2, tp.isSoft), refs2, tp2.isBoxed)
314-
case tp @ AppliedType(tycon, args)
315-
if !defn.isFunctionClass(tp.dealias.typeSymbol) && (tp.dealias eq tp) =>
316-
tp.derivedAppliedType(tycon, args.mapConserve(_.boxDeeply))
314+
case tp @ AppliedType(tycon, args) if tp.dealias eq tp =>
315+
val sym = tycon.typeSymbol
316+
if !defn.isFunctionClass(sym) && sym != defn.MagicMaybeClass
317+
then tp.derivedAppliedType(tycon, args.mapConserve(_.boxDeeply))
318+
else tp
317319
case tp: RealTypeBounds =>
318320
tp.derivedTypeBounds(tp.lo, tp.hi.boxDeeply)
319321
case tp: LazyRef =>

compiler/src/dotty/tools/dotc/config/Feature.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,26 +327,27 @@ object Feature:
327327
* @return true iff the import was handled
328328
*/
329329
def handleGlobalLanguageImport(prefix: TermName, imported: Name)(using Context): Boolean =
330+
def enableCC() =
331+
ctx.compilationUnit.needsCaptureChecking = true
332+
if ctx.run != null then ctx.run.nn.ccEnabledSomewhere = true
330333
QualifiedName(prefix, imported.asTermName) match
331334
case `pureFunctions` =>
332335
ctx.compilationUnit.knowsPureFuns = true
333336
if ctx.run != null then ctx.run.nn.pureFunsImportEncountered = true
334337
true
335338
case `captureChecking` =>
336-
ctx.compilationUnit.needsCaptureChecking = true
337-
if ctx.run != null then ctx.run.nn.ccEnabledSomewhere = true
339+
enableCC()
338340
true
339341
case `separationChecking` =>
340-
ctx.compilationUnit.needsCaptureChecking = true
342+
enableCC()
341343
ctx.compilationUnit.needsSeparationChecking = true
342-
if ctx.run != null then ctx.run.nn.ccEnabledSomewhere = true
343344
true
344345
case `safe` =>
345-
ctx.compilationUnit.needsCaptureChecking = true
346+
enableCC()
346347
ctx.compilationUnit.safeMode = true
347-
if ctx.run != null then ctx.run.nn.ccEnabledSomewhere = true
348348
true
349349
case `magic` =>
350+
enableCC()
350351
ctx.compilationUnit.magic = true
351352
ctx.compilationUnit.sourceVersion = Some(SourceVersion.future)
352353
true

library/src/scala/Tuple.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import compiletime.*
66
import compiletime.ops.int.*
77

88
/** Tuple of arbitrary arity. */
9-
sealed trait Tuple extends Product {
9+
sealed trait Tuple extends Product, caps.Pure {
1010
import Tuple.*
1111

1212
/** Creates a copy of this tuple as an Array. */

tests/neg-custom-args/captures/local-mutables-2.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- Error: tests/neg-custom-args/captures/local-mutables-2.scala:7:9 ----------------------------------------------------
22
7 |def foo() = // error: separation failure
33
| ^
4-
|Separation failure in method foo's inferred result type (() ->{any.rd} Int, (x: Int) => Unit)^{}.
4+
|Separation failure in method foo's inferred result type (() ->{any.rd} Int, (x: Int) => Unit).
55
|One part, () ->{any.rd} Int, hides capabilities {any².rd}.
66
|Another part, (x: Int) => Unit, captures capabilities {any³, any, any²}.
77
|The two sets overlap at {`any` of value r}.
@@ -12,7 +12,7 @@
1212
-- Error: tests/neg-custom-args/captures/local-mutables-2.scala:11:10 --------------------------------------------------
1313
11 |def foo2() = // error: separation failure
1414
| ^
15-
| Separation failure in method foo2's inferred result type (() ->{any.rd} Int, (x: Int) => Unit)^{}.
15+
| Separation failure in method foo2's inferred result type (() ->{any.rd} Int, (x: Int) => Unit).
1616
| One part, (x: Int) => Unit, hides capabilities {any}.
1717
| Another part, () ->{any.rd} Int, captures capabilities {any.rd}.
1818
| The two sets overlap at {`any` of variable r}.

tests/run/fully-abstract-nat-maybe.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//> using options -Yexplicit-nulls
2+
package test
23
import language.experimental.magic
34
import scala.magic.*
45
import scala.reflect.ClassTag
@@ -74,7 +75,7 @@ object Test {
7475

7576
}
7677

77-
abstract class Numbers {
78+
abstract class Numbers extends caps.Pure {
7879

7980
// === Nat ==========================================
8081
// Represents:
@@ -212,7 +213,7 @@ object IntImplementation extends Numbers {
212213
def pred: Nat = succ - 1
213214
}
214215

215-
private def intClassTag(cond: Int => Boolean): ClassTag[Int] = new ClassTag[Int] {
216+
private def intClassTag(cond: Int -> Boolean): ClassTag[Int] = new ClassTag[Int] {
216217
def runtimeClass: Class[?] = classOf[Int]
217218
override def unapply(x: Any): Option[Int] = x match {
218219
case i: Int if cond(i) => Some(i)

tests/run/i13968-maybe.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ object Bar {
55
}
66

77
object Bar23 {
8-
def unapply(x: Any): Option[
8+
def unapply(x: Any): (
99
Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *:
1010
Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *: Int *:
1111
Int *: Int *: Int *: EmptyTuple
12-
] = Some(
12+
)? = (
1313
1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *:
1414
11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *:
15-
21 *: 22 *: 23 *: Tuple()
16-
)
15+
21 *: 22 *: 23 *: Tuple())
1716
}
1817

1918
@main def Test() =

0 commit comments

Comments
 (0)