Skip to content

Commit a6749fa

Browse files
committed
CC-UPDATE: Changes to compiler codebase so that it passes capture checking
1 parent a4fd953 commit a6749fa

File tree

83 files changed

+313
-223
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+313
-223
lines changed

tests/pos-with-compiler-cc/dotc/Run.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import java.nio.charset.StandardCharsets
3131
import scala.collection.mutable
3232
import scala.util.control.NonFatal
3333
import scala.io.Codec
34+
import caps.unsafe.unsafeUnbox
3435

3536
/** A compiler run. Exports various methods to compile source files */
3637
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {
@@ -270,7 +271,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
270271
Rewrites.writeBack()
271272
suppressions.runFinished(hasErrors = ctx.reporter.hasErrors)
272273
while (finalizeActions.nonEmpty) {
273-
val action = finalizeActions.remove(0)
274+
val action = finalizeActions.remove(0).unsafeUnbox
274275
action()
275276
}
276277
compiling = false

tests/pos-with-compiler-cc/dotc/ast/Desugar.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ object desugar {
683683
else (Nil, Nil)
684684
}
685685

686-
var parents1 = parents
686+
var parents1: List[untpd.Tree] = parents // !cc! need explicit type to make capture checking pass
687687
if (isEnumCase && parents.isEmpty)
688688
parents1 = enumClassTypeRef :: Nil
689689
if (isNonEnumCase)
@@ -1789,7 +1789,10 @@ object desugar {
17891789
val elems = segments flatMap {
17901790
case ts: Thicket => ts.trees.tail
17911791
case t => Nil
1792-
} map {
1792+
} map { (t: Tree) => t match
1793+
// !cc! explicitly typed parameter (t: Tree) is needed since otherwise
1794+
// we get an error similar to #16268. (The explicit type constrains the type of `segments`
1795+
// which is otherwise List[{*} tree])
17931796
case Block(Nil, EmptyTree) => Literal(Constant(())) // for s"... ${} ..."
17941797
case Block(Nil, expr) => expr // important for interpolated string as patterns, see i1773.scala
17951798
case t => t

tests/pos-with-compiler-cc/dotc/ast/Positioned.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import annotation.internal.sharable
1515

1616
/** A base class for things that have positions (currently: modifiers and trees)
1717
*/
18-
abstract class Positioned(implicit @constructorOnly src: SourceFile) extends SrcPos, Product, Cloneable {
18+
abstract class Positioned(implicit @constructorOnly src: SourceFile) extends SrcPos, Product, Cloneable, caps.Pure {
1919
import Positioned.{ids, nextId, debugId}
2020

2121
private var mySpan: Span = _

tests/pos-with-compiler-cc/dotc/ast/TreeTypeMap.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Types._, Contexts._, Flags._
77
import Symbols._, Annotations._, Trees._, Symbols._, Constants.Constant
88
import Decorators._
99
import dotty.tools.dotc.transform.SymUtils._
10+
import language.experimental.pureFunctions
1011

1112
/** A map that applies three functions and a substitution together to a tree and
1213
* makes sure they are coordinated so that the result is well-typed. The functions are
@@ -32,8 +33,8 @@ import dotty.tools.dotc.transform.SymUtils._
3233
* set, we would get a data race assertion error.
3334
*/
3435
class TreeTypeMap(
35-
val typeMap: Type => Type = IdentityTypeMap,
36-
val treeMap: tpd.Tree => tpd.Tree = identity _,
36+
val typeMap: Type -> Type = IdentityTypeMap,
37+
val treeMap: tpd.Tree -> tpd.Tree = identity[tpd.Tree](_), // !cc! need explicit instantiation of default argument
3738
val oldOwners: List[Symbol] = Nil,
3839
val newOwners: List[Symbol] = Nil,
3940
val substFrom: List[Symbol] = Nil,
@@ -42,8 +43,8 @@ class TreeTypeMap(
4243
import tpd._
4344

4445
def copy(
45-
typeMap: Type => Type,
46-
treeMap: tpd.Tree => tpd.Tree,
46+
typeMap: Type -> Type,
47+
treeMap: tpd.Tree -> tpd.Tree,
4748
oldOwners: List[Symbol],
4849
newOwners: List[Symbol],
4950
substFrom: List[Symbol],

tests/pos-with-compiler-cc/dotc/ast/Trees.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import annotation.unchecked.uncheckedVariance
1717
import annotation.constructorOnly
1818
import compiletime.uninitialized
1919
import Decorators._
20+
import annotation.retains
21+
import language.experimental.pureFunctions
2022

2123
object Trees {
2224

@@ -431,7 +433,7 @@ object Trees {
431433
def isBackquoted: Boolean = hasAttachment(Backquoted)
432434
}
433435

434-
class SearchFailureIdent[+T <: Untyped] private[ast] (name: Name, expl: => String)(implicit @constructorOnly src: SourceFile)
436+
class SearchFailureIdent[+T <: Untyped] private[ast] (name: Name, expl: -> String)(implicit @constructorOnly src: SourceFile)
435437
extends Ident[T](name) {
436438
def explanation = expl
437439
override def toString: String = s"SearchFailureIdent($explanation)"
@@ -1518,7 +1520,7 @@ object Trees {
15181520
}
15191521
}
15201522

1521-
abstract class TreeAccumulator[X] { self =>
1523+
abstract class TreeAccumulator[X] { self: TreeAccumulator[X] @retains(caps.*) =>
15221524
// Ties the knot of the traversal: call `foldOver(x, tree))` to dive in the `tree` node.
15231525
def apply(x: X, tree: Tree)(using Context): X
15241526

tests/pos-with-compiler-cc/dotc/ast/tpd.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import typer.ConstFold
1818

1919
import scala.annotation.tailrec
2020
import scala.collection.mutable.ListBuffer
21+
import language.experimental.pureFunctions
2122

2223
/** Some creators for typed trees */
2324
object tpd extends Trees.Instance[Type] with TypedTreeInfo {
@@ -1454,7 +1455,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
14541455
* @return The symbols imported.
14551456
*/
14561457
def importedSymbols(imp: Import,
1457-
selectorPredicate: untpd.ImportSelector => Boolean = util.common.alwaysTrue)
1458+
selectorPredicate: untpd.ImportSelector -> Boolean = util.common.alwaysTrue)
14581459
(using Context): List[Symbol] =
14591460
imp.selectors.find(selectorPredicate) match
14601461
case Some(sel) => importedSymbols(imp.expr, sel.name)

tests/pos-with-compiler-cc/dotc/ast/untpd.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import util.Spans.Span
1111
import annotation.constructorOnly
1212
import annotation.internal.sharable
1313
import Decorators._
14+
import annotation.retains
15+
import language.experimental.pureFunctions
1416

1517
object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
1618

@@ -150,7 +152,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
150152
case class CapturingTypeTree(refs: List[Tree], parent: Tree)(implicit @constructorOnly src: SourceFile) extends TypTree
151153

152154
/** Short-lived usage in typer, does not need copy/transform/fold infrastructure */
153-
case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @constructorOnly src: SourceFile) extends Tree
155+
case class DependentTypeTree(tp: List[Symbol] -> Type)(implicit @constructorOnly src: SourceFile) extends Tree
154156

155157
@sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(NoSource) with WithoutTypeOrPos[Untyped] {
156158
override def isEmpty: Boolean = true
@@ -370,7 +372,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
370372
// ------ Creation methods for untyped only -----------------
371373

372374
def Ident(name: Name)(implicit src: SourceFile): Ident = new Ident(name)
373-
def SearchFailureIdent(name: Name, explanation: => String)(implicit src: SourceFile): SearchFailureIdent = new SearchFailureIdent(name, explanation)
375+
def SearchFailureIdent(name: Name, explanation: -> String)(implicit src: SourceFile): SearchFailureIdent = new SearchFailureIdent(name, explanation)
374376
def Select(qualifier: Tree, name: Name)(implicit src: SourceFile): Select = new Select(qualifier, name)
375377
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature)(implicit src: SourceFile): Select = new SelectWithSig(qualifier, name, sig)
376378
def This(qual: Ident)(implicit src: SourceFile): This = new This(qual)
@@ -737,7 +739,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
737739
}
738740
}
739741

740-
abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] { self =>
742+
abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] {
743+
self: UntypedTreeAccumulator[X] @retains(caps.*) =>
741744
override def foldMoreCases(x: X, tree: Tree)(using Context): X = tree match {
742745
case ModuleDef(name, impl) =>
743746
this(x, impl)

tests/pos-with-compiler-cc/dotc/cc/CaptureSet.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import util.{SimpleIdentitySet, Property}
1616
import util.common.alwaysTrue
1717
import scala.collection.mutable
1818
import config.Config.ccAllowUnsoundMaps
19+
import language.experimental.pureFunctions
1920

2021
/** A class for capture sets. Capture sets can be constants or variables.
2122
* Capture sets support inclusion constraints <:< where <:< is subcapturing.
@@ -37,7 +38,7 @@ import config.Config.ccAllowUnsoundMaps
3738
* if the mapped function is either a bijection or if it is idempotent
3839
* on capture references (c.f. doc comment on `map` below).
3940
*/
40-
sealed abstract class CaptureSet extends Showable:
41+
sealed abstract class CaptureSet extends Showable, caps.Pure:
4142
import CaptureSet.*
4243

4344
/** The elements of this capture set. For capture variables,
@@ -222,7 +223,7 @@ sealed abstract class CaptureSet extends Showable:
222223
/** The largest subset (via <:<) of this capture set that only contains elements
223224
* for which `p` is true.
224225
*/
225-
def filter(p: CaptureRef => Boolean)(using Context): CaptureSet =
226+
def filter(p: CaptureRef -> Boolean)(using Context): CaptureSet =
226227
if this.isConst then
227228
val elems1 = elems.filter(p)
228229
if elems1 == elems then this
@@ -372,8 +373,10 @@ object CaptureSet:
372373
def isConst = isSolved
373374
def isAlwaysEmpty = false
374375

375-
/** A handler to be invoked if the root reference `*` is added to this set */
376-
var rootAddedHandler: () => Context ?=> Unit = () => ()
376+
/** A handler to be invoked if the root reference `*` is added to this set
377+
* The handler is pure in the sense that it will only output diagnostics.
378+
*/
379+
var rootAddedHandler: () -> Context ?-> Unit = () => ()
377380

378381
var description: String = ""
379382

@@ -421,7 +424,7 @@ object CaptureSet:
421424
else
422425
CompareResult.fail(this)
423426

424-
override def disallowRootCapability(handler: () => Context ?=> Unit)(using Context): this.type =
427+
override def disallowRootCapability(handler: () -> Context ?-> Unit)(using Context): this.type =
425428
rootAddedHandler = handler
426429
super.disallowRootCapability(handler)
427430

@@ -613,7 +616,7 @@ object CaptureSet:
613616

614617
/** A variable with elements given at any time as { x <- source.elems | p(x) } */
615618
class Filtered private[CaptureSet]
616-
(val source: Var, p: CaptureRef => Boolean)(using @constructorOnly ctx: Context)
619+
(val source: Var, p: CaptureRef -> Boolean)(using @constructorOnly ctx: Context)
617620
extends DerivedVar(source.elems.filter(p)):
618621

619622
override def addNewElems(newElems: Refs, origin: CaptureSet)(using Context, VarState): CompareResult =

tests/pos-with-compiler-cc/dotc/cc/CheckCaptures.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import CaptureSet.{withCaptureSetsExplained, IdempotentCaptRefMap}
2121
import StdNames.nme
2222
import NameKinds.DefaultGetterName
2323
import reporting.trace
24+
import language.experimental.pureFunctions
2425

2526
/** The capture checker */
2627
object CheckCaptures:
@@ -738,20 +739,21 @@ class CheckCaptures extends Recheck, SymTransformer:
738739
* the innermost capturing type. The outer capture annotations can be
739740
* reconstructed with the returned function.
740741
*/
741-
def destructCapturingType(tp: Type, reconstruct: Type => Type = x => x): ((Type, CaptureSet, Boolean), Type => Type) =
742+
def destructCapturingType(tp: Type, reconstruct: Type -> Type = (x: Type) => x) // !cc! need monomorphic default argument
743+
: (Type, CaptureSet, Boolean, Type -> Type) =
742744
tp.dealias match
743745
case tp @ CapturingType(parent, cs) =>
744746
if parent.dealias.isCapturingType then
745747
destructCapturingType(parent, res => reconstruct(tp.derivedCapturingType(res, cs)))
746748
else
747-
((parent, cs, tp.isBoxed), reconstruct)
749+
(parent, cs, tp.isBoxed, reconstruct)
748750
case actual =>
749-
((actual, CaptureSet(), false), reconstruct)
751+
(actual, CaptureSet(), false, reconstruct)
750752

751753
def adapt(actual: Type, expected: Type, covariant: Boolean): Type = trace(adaptInfo(actual, expected, covariant), recheckr, show = true) {
752754
if expected.isInstanceOf[WildcardType] then actual
753755
else
754-
val ((parent, cs, actualIsBoxed), recon) = destructCapturingType(actual)
756+
val (parent, cs, actualIsBoxed, recon: (Type -> Type)) = destructCapturingType(actual)
755757

756758
val needsAdaptation = actualIsBoxed != expected.isBoxedCapturing
757759
val insertBox = needsAdaptation && covariant != actualIsBoxed

tests/pos-with-compiler-cc/dotc/classpath/DirectoryClassPath.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import PlainFile.toPlainFile
1717
import scala.jdk.CollectionConverters._
1818
import scala.collection.immutable.ArraySeq
1919
import scala.util.control.NonFatal
20+
import language.experimental.pureFunctions
2021

2122
/**
2223
* A trait allowing to look for classpath entries in directories. It provides common logic for
@@ -32,7 +33,7 @@ trait DirectoryLookup[FileEntryType <: ClassRepresentation] extends EfficientCla
3233

3334
protected def emptyFiles: Array[F] // avoids reifying ClassTag[F]
3435
protected def getSubDir(dirName: String): Option[F]
35-
protected def listChildren(dir: F, filter: Option[F => Boolean] = None): Array[F]
36+
protected def listChildren(dir: F, filter: Option[F -> Boolean] = (None: Option[F -> Boolean])): Array[F] // !cc! need explicit typing of default argument
3637
protected def getName(f: F): String
3738
protected def toAbstractFile(f: F): AbstractFile
3839
protected def isPackage(f: F): Boolean
@@ -90,7 +91,7 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends Directo
9091
if (packageDir.exists && packageDir.isDirectory) Some(packageDir)
9192
else None
9293
}
93-
protected def listChildren(dir: JFile, filter: Option[JFile => Boolean]): Array[JFile] = {
94+
protected def listChildren(dir: JFile, filter: Option[JFile -> Boolean]): Array[JFile] = {
9495
val listing = filter match {
9596
case Some(f) => dir.listFiles(mkFileFilter(f))
9697
case None => dir.listFiles()

tests/pos-with-compiler-cc/dotc/classpath/FileUtils.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import scala.language.unsafeNulls
99
import java.io.{File => JFile, FileFilter}
1010
import java.net.URL
1111
import dotty.tools.io.AbstractFile
12+
import language.experimental.pureFunctions
1213

1314
/**
1415
* Common methods related to Java files and abstract files used in the context of classpath
@@ -78,7 +79,7 @@ object FileUtils {
7879
def mayBeValidPackage(dirName: String): Boolean =
7980
(dirName != "META-INF") && (dirName != "") && (dirName.charAt(0) != '.')
8081

81-
def mkFileFilter(f: JFile => Boolean): FileFilter = new FileFilter {
82+
def mkFileFilter(f: JFile -> Boolean): FileFilter = new FileFilter {
8283
def accept(pathname: JFile): Boolean = f(pathname)
8384
}
8485
}

tests/pos-with-compiler-cc/dotc/classpath/VirtualDirectoryClassPath.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import FileUtils._
88
import java.net.URL
99

1010
import dotty.tools.io.ClassPath
11+
import language.experimental.pureFunctions
1112

1213
case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths {
1314
type F = AbstractFile
@@ -28,7 +29,7 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi
2829
protected def emptyFiles: Array[AbstractFile] = Array.empty
2930
protected def getSubDir(packageDirName: String): Option[AbstractFile] =
3031
Option(lookupPath(dir)(packageDirName.split(java.io.File.separator).toIndexedSeq, directory = true))
31-
protected def listChildren(dir: AbstractFile, filter: Option[AbstractFile => Boolean] = None): Array[F] = filter match {
32+
protected def listChildren(dir: AbstractFile, filter: Option[AbstractFile -> Boolean]): Array[F] = filter match {
3233
case Some(f) => dir.iterator.filter(f).toArray
3334
case _ => dir.toArray
3435
}

tests/pos-with-compiler-cc/dotc/config/Feature.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import util.{SrcPos, NoSourcePosition}
1010
import SourceVersion._
1111
import reporting.Message
1212
import NameKinds.QualifiedName
13+
import language.experimental.pureFunctions
1314

1415
object Feature:
1516

@@ -128,7 +129,7 @@ object Feature:
128129
else
129130
false
130131

131-
def checkExperimentalFeature(which: String, srcPos: SrcPos, note: => String = "")(using Context) =
132+
def checkExperimentalFeature(which: String, srcPos: SrcPos, note: -> String = "")(using Context) =
132133
if !isExperimentalEnabled then
133134
report.error(em"Experimental $which may only be used with a nightly or snapshot version of the compiler$note", srcPos)
134135

0 commit comments

Comments
 (0)