Skip to content

Commit e45f8b3

Browse files
committed
More changes to dotc so that it can be capture checked
1 parent 9c0a65c commit e45f8b3

22 files changed

+90
-64
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@annotation.experimental class C(x: () => Unit) extends caps.Pure // error
2+
3+
@annotation.experimental class D(@annotation.constructorOnly x: () => Unit) extends caps.Pure // ok
4+

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/core/classfile/ClassfileParser.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import scala.annotation.switch
2323
import typer.Checking.checkNonCyclic
2424
import io.{AbstractFile, ZipArchive}
2525
import scala.util.control.NonFatal
26+
import language.experimental.pureFunctions
2627

2728
object ClassfileParser {
2829
/** Marker trait for unpicklers that can be embedded in classfiles. */
@@ -629,10 +630,10 @@ class ClassfileParser(
629630
case (name, tag: EnumTag) => untpd.NamedArg(name.name, tag.toTree).withSpan(NoSpan)
630631
}
631632

632-
protected var mySym: Symbol | (Context ?=> Symbol) =
633+
protected var mySym: Symbol | (Context ?-> Symbol) =
633634
(ctx: Context) ?=> annotType.classSymbol
634635

635-
protected var myTree: Tree | (Context ?=> Tree) =
636+
protected var myTree: Tree | (Context ?-> Tree) =
636637
(ctx: Context) ?=> untpd.resolveConstructor(annotType, args)
637638

638639
def untpdTree(using Context): untpd.Tree =

tests/pos-with-compiler-cc/dotc/core/tasty/TastyUnpickler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import TastyBuffer.NameRef
1111
import scala.collection.mutable
1212
import Names.{TermName, termName, EmptyTermName}
1313
import NameKinds._
14+
import language.experimental.pureFunctions
1415

1516
object TastyUnpickler {
1617

1718
abstract class SectionUnpickler[R](val name: String) {
1819
def unpickle(reader: TastyReader, nameAtRef: NameTable): R
1920
}
2021

21-
class NameTable extends (NameRef => TermName) {
22+
class NameTable extends (NameRef -> TermName) {
2223
private val names = new mutable.ArrayBuffer[TermName]
2324
def add(name: TermName): mutable.ArrayBuffer[TermName] = names += name
2425
def apply(ref: NameRef): TermName = names(ref.index)

tests/pos-with-compiler-cc/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import dotty.tools.tasty.TastyFormat._
4646

4747
import scala.annotation.constructorOnly
4848
import scala.annotation.internal.sharable
49+
import language.experimental.pureFunctions
4950

5051
/** Unpickler for typed trees
5152
* @param reader the reader from which to unpickle
@@ -663,9 +664,9 @@ class TreeUnpickler(reader: TastyReader,
663664
/** Read modifier list into triplet of flags, annotations and a privateWithin
664665
* boundary symbol.
665666
*/
666-
def readModifiers(end: Addr)(using Context): (FlagSet, List[Symbol => Annotation], Symbol) = {
667+
def readModifiers(end: Addr)(using Context): (FlagSet, List[Symbol -> Annotation], Symbol) = {
667668
var flags: FlagSet = EmptyFlags
668-
var annotFns: List[Symbol => Annotation] = Nil
669+
var annotFns: List[Symbol -> Annotation] = Nil
669670
var privateWithin: Symbol = NoSymbol
670671
while (currentAddr.index != end.index) {
671672
def addFlag(flag: FlagSet) = {
@@ -732,7 +733,7 @@ class TreeUnpickler(reader: TastyReader,
732733

733734
private def readWithin(using Context): Symbol = readType().typeSymbol
734735

735-
private def readAnnot(using Context): Symbol => Annotation =
736+
private def readAnnot(using Context): Symbol -> Annotation =
736737
readByte()
737738
val end = readEnd()
738739
val tp = readType()
@@ -1450,10 +1451,10 @@ class TreeUnpickler(reader: TastyReader,
14501451
setSpan(start, CaseDef(pat, guard, rhs))
14511452
}
14521453

1453-
def readLater[T <: AnyRef](end: Addr, op: TreeReader => Context ?=> T)(using Context): Trees.Lazy[T] =
1454+
def readLater[T <: AnyRef](end: Addr, op: TreeReader -> Context ?-> T)(using Context): Trees.Lazy[T] =
14541455
readLaterWithOwner(end, op)(ctx.owner)
14551456

1456-
def readLaterWithOwner[T <: AnyRef](end: Addr, op: TreeReader => Context ?=> T)(using Context): Symbol => Trees.Lazy[T] = {
1457+
def readLaterWithOwner[T <: AnyRef](end: Addr, op: TreeReader -> Context ?-> T)(using Context): Symbol -> Trees.Lazy[T] = {
14571458
val localReader = fork
14581459
goto(end)
14591460
val mode = ctx.mode

tests/pos-with-compiler-cc/dotc/parsing/Parsers.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import config.Feature
3333
import config.Feature.{sourceVersion, migrateTo3, globalOnlyImports}
3434
import config.SourceVersion._
3535
import config.SourceVersion
36+
import language.experimental.pureFunctions
3637

3738
object Parsers {
3839

@@ -143,10 +144,10 @@ object Parsers {
143144
syntaxError(msg, Span(offset, offset + length))
144145
lastErrorOffset = in.offset
145146

146-
def syntaxError(msg: => String, offset: Int): Unit =
147+
def syntaxError(msg: -> String, offset: Int): Unit =
147148
syntaxError(msg.toMessage, offset)
148149

149-
def syntaxError(msg: => String): Unit =
150+
def syntaxError(msg: -> String): Unit =
150151
syntaxError(msg, in.offset)
151152

152153
/** Unconditionally issue an error at given span, without
@@ -155,7 +156,7 @@ object Parsers {
155156
def syntaxError(msg: Message, span: Span): Unit =
156157
report.error(msg, source.atSpan(span))
157158

158-
def syntaxError(msg: => String, span: Span): Unit =
159+
def syntaxError(msg: -> String, span: Span): Unit =
159160
syntaxError(msg.toMessage, span)
160161

161162
def unimplementedExpr(using Context): Select =
@@ -288,7 +289,7 @@ object Parsers {
288289
syntaxError(msg, offset)
289290
skip()
290291

291-
def syntaxErrorOrIncomplete(msg: => String): Unit =
292+
def syntaxErrorOrIncomplete(msg: -> String): Unit =
292293
syntaxErrorOrIncomplete(msg.toMessage, in.offset)
293294

294295
def syntaxErrorOrIncomplete(msg: Message, span: Span): Unit =

tests/pos-with-compiler-cc/dotc/sbt/ExtractDependencies.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import xsbti.api.DependencyContext
2525
import xsbti.api.DependencyContext._
2626

2727
import scala.collection.{Set, mutable}
28-
28+
import language.experimental.pureFunctions
2929

3030
/** This phase sends information on classes' dependencies to sbt via callbacks.
3131
*
@@ -189,7 +189,7 @@ object ExtractDependencies {
189189
sym.fullName.stripModuleClassSuffix.toString
190190

191191
/** Report an internal error in incremental compilation. */
192-
def internalError(msg: => String, pos: SrcPos = NoSourcePosition)(using Context): Unit =
192+
def internalError(msg: -> String, pos: SrcPos = NoSourcePosition)(using Context): Unit =
193193
report.error(s"Internal error in the incremental compiler while compiling ${ctx.compilationUnit.source}: $msg", pos)
194194
}
195195

tests/pos-with-compiler-cc/dotc/semanticdb/internal/SemanticdbTypeMapper.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package dotty.tools.dotc.semanticdb.internal
2+
import language.experimental.pureFunctions
23

34
abstract class SemanticdbTypeMapper[BaseType, CustomType] {
45
def toCustom(base: BaseType): CustomType
56
def toBase(custom: CustomType): BaseType
67
}
78

89
object SemanticdbTypeMapper {
9-
def apply[BaseType, CustomType](baseToCustom: BaseType => CustomType)(
10-
customToBase: CustomType => BaseType
10+
def apply[BaseType, CustomType](baseToCustom: BaseType -> CustomType)(
11+
customToBase: CustomType -> BaseType
1112
): SemanticdbTypeMapper[BaseType, CustomType] =
1213
new SemanticdbTypeMapper[BaseType, CustomType] {
1314
def toCustom(base: BaseType): CustomType = baseToCustom(base)

tests/pos-with-compiler-cc/dotc/transform/TypeTestsCasts.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import core.Flags._
1515
import util.Spans._
1616
import reporting._
1717
import config.Printers.{ transforms => debug }
18+
import language.experimental.pureFunctions
1819

1920
/** This transform normalizes type tests and type casts,
2021
* also replacing type tests with singleton argument type with reference equality check
@@ -195,7 +196,7 @@ object TypeTestsCasts {
195196
def testCls = effectiveClass(testType.widen)
196197
def unboxedTestCls = effectiveClass(unboxedTestType.widen)
197198

198-
def unreachable(why: => String)(using Context): Boolean = {
199+
def unreachable(why: -> String)(using Context): Boolean = {
199200
if (flagUnrelated)
200201
if (inMatch) report.error(em"this case is unreachable since $why", expr.srcPos)
201202
else report.warning(em"this will always yield false since $why", expr.srcPos)

tests/pos-with-compiler-cc/dotc/transform/init/Semantic.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import Errors.*
1818

1919
import scala.collection.mutable
2020
import scala.annotation.tailrec
21+
import caps.unsafeBoxFunArg
2122

2223
object Semantic:
2324

@@ -1669,7 +1670,8 @@ object Semantic:
16691670
}
16701671

16711672
// initialize super classes after outers are set
1672-
tasks.foreach(task => task())
1673+
tasks.foreach(((task: () => Unit) => task()).unsafeBoxFunArg)
1674+
// !cc! .asInstanceOf needed to convert from `(() => Unit) -> Unit` to `(box () => Unit) -> Unit`.
16731675
end if
16741676

16751677
var fieldsChanged = true

tests/pos-with-compiler-cc/dotc/transform/sjs/ExplicitJSClasses.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,9 @@ object ExplicitJSClasses {
722722
val LocalJSClassValueName: UniqueNameKind = new UniqueNameKind("$jsclass")
723723

724724
private final class MyState {
725-
val nestedObject2superTypeConstructor = new MutableSymbolMap[Type]
726-
val localClass2jsclassVal = new MutableSymbolMap[TermSymbol]
727-
val notYetReferencedLocalClasses = new util.HashSet[Symbol]
725+
val nestedObject2superTypeConstructor: MutableSymbolMap[Type] = new MutableSymbolMap[Type]
726+
val localClass2jsclassVal: MutableSymbolMap[TermSymbol] = new MutableSymbolMap[TermSymbol]
727+
val notYetReferencedLocalClasses: util.HashSet[Symbol] = new util.HashSet[Symbol]
728+
// !cc! type ascriptions needed for 3 vals above, otherwise they get strange inferred types
728729
}
729730
}

tests/pos-with-compiler-cc/dotc/typer/Checking.scala

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import transform.TypeUtils.*
4242

4343
import collection.mutable
4444
import reporting._
45+
import language.experimental.pureFunctions
4546

4647
object Checking {
4748
import tpd._
@@ -471,7 +472,7 @@ object Checking {
471472
def checkWithDeferred(flag: FlagSet) =
472473
if (sym.isOneOf(flag))
473474
fail(AbstractMemberMayNotHaveModifier(sym, flag))
474-
def checkNoConflict(flag1: FlagSet, flag2: FlagSet, msg: => String) =
475+
def checkNoConflict(flag1: FlagSet, flag2: FlagSet, msg: -> String) =
475476
if (sym.isAllOf(flag1 | flag2)) fail(msg.toMessage)
476477
def checkCombination(flag1: FlagSet, flag2: FlagSet) =
477478
if sym.isAllOf(flag1 | flag2) then
@@ -599,7 +600,7 @@ object Checking {
599600
*/
600601
def checkNoPrivateLeaks(sym: Symbol)(using Context): Type = {
601602
class NotPrivate extends TypeMap {
602-
var errors: List[() => String] = Nil
603+
var errors: List[() -> String] = Nil
603604
private var inCaptureSet: Boolean = false
604605

605606
def accessBoundary(sym: Symbol): Symbol =
@@ -781,7 +782,7 @@ object Checking {
781782
languageImport(qual) match
782783
case Some(nme.experimental)
783784
if !ctx.owner.isInExperimentalScope && !selectors.forall(isAllowedImport) =>
784-
def check(stable: => String) =
785+
def check(stable: -> String) =
785786
Feature.checkExperimentalFeature("features", imp.srcPos,
786787
s"\n\nNote: the scope enclosing the import is not considered experimental because it contains the\nnon-experimental $stable")
787788
if ctx.owner.is(Package) then
@@ -1035,7 +1036,7 @@ trait Checking {
10351036

10361037
/** Issue a feature warning if feature is not enabled */
10371038
def checkFeature(name: TermName,
1038-
description: => String,
1039+
description: -> String,
10391040
featureUseSite: Symbol,
10401041
pos: SrcPos)(using Context): Unit =
10411042
if !Feature.enabled(name) then
@@ -1045,7 +1046,7 @@ trait Checking {
10451046
* are feasible, i.e. that their lower bound conforms to their upper bound. If a type
10461047
* argument is infeasible, issue and error and continue with upper bound.
10471048
*/
1048-
def checkFeasibleParent(tp: Type, pos: SrcPos, where: => String = "")(using Context): Type = {
1049+
def checkFeasibleParent(tp: Type, pos: SrcPos, where: -> String = "")(using Context): Type = {
10491050
def checkGoodBounds(tp: Type) = tp match {
10501051
case tp @ TypeBounds(lo, hi) if !(lo <:< hi) =>
10511052
report.error(ex"no type exists between low bound $lo and high bound $hi$where", pos)
@@ -1506,7 +1507,7 @@ trait ReChecking extends Checking {
15061507
override def checkCanThrow(tp: Type, span: Span)(using Context): Tree = EmptyTree
15071508
override def checkCatch(pat: Tree, guard: Tree)(using Context): Unit = ()
15081509
override def checkNoContextFunctionType(tree: Tree)(using Context): Unit = ()
1509-
override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SrcPos)(using Context): Unit = ()
1510+
override def checkFeature(name: TermName, description: -> String, featureUseSite: Symbol, pos: SrcPos)(using Context): Unit = ()
15101511
}
15111512

15121513
trait NoChecking extends ReChecking {
@@ -1517,7 +1518,7 @@ trait NoChecking extends ReChecking {
15171518
override def checkClassType(tp: Type, pos: SrcPos, traitReq: Boolean, stablePrefixReq: Boolean)(using Context): Type = tp
15181519
override def checkImplicitConversionDefOK(sym: Symbol)(using Context): Unit = ()
15191520
override def checkImplicitConversionUseOK(tree: Tree)(using Context): Unit = ()
1520-
override def checkFeasibleParent(tp: Type, pos: SrcPos, where: => String = "")(using Context): Type = tp
1521+
override def checkFeasibleParent(tp: Type, pos: SrcPos, where: -> String = "")(using Context): Type = tp
15211522
override def checkAnnotArgs(tree: Tree)(using Context): tree.type = tree
15221523
override def checkNoTargetNameConflict(stats: List[Tree])(using Context): Unit = ()
15231524
override def checkParentCall(call: Tree, caller: ClassSymbol)(using Context): Unit = ()

tests/pos-with-compiler-cc/dotc/typer/ErrorReporting.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import reporting._
1515
import collection.mutable
1616

1717
import scala.util.matching.Regex
18+
import language.experimental.pureFunctions
1819

1920
object ErrorReporting {
2021

@@ -26,7 +27,7 @@ object ErrorReporting {
2627
def errorTree(tree: untpd.Tree, msg: Message)(using Context): tpd.Tree =
2728
errorTree(tree, msg, tree.srcPos)
2829

29-
def errorTree(tree: untpd.Tree, msg: => String)(using Context): tpd.Tree =
30+
def errorTree(tree: untpd.Tree, msg: -> String)(using Context): tpd.Tree =
3031
errorTree(tree, msg.toMessage)
3132

3233
def errorTree(tree: untpd.Tree, msg: TypeError, pos: SrcPos)(using Context): tpd.Tree =
@@ -37,7 +38,7 @@ object ErrorReporting {
3738
ErrorType(msg)
3839
}
3940

40-
def errorType(msg: => String, pos: SrcPos)(using Context): ErrorType =
41+
def errorType(msg: -> String, pos: SrcPos)(using Context): ErrorType =
4142
errorType(msg.toMessage, pos)
4243

4344
def errorType(ex: TypeError, pos: SrcPos)(using Context): ErrorType = {
@@ -64,7 +65,7 @@ object ErrorReporting {
6465
case tp: AppliedType if tp.isMatchAlias => MatchTypeTrace.record(tp.tryNormalize)
6566
case tp: MatchType => MatchTypeTrace.record(tp.tryNormalize)
6667
case _ => foldOver(s, tp)
67-
tps.foldLeft("")(collectMatchTrace)
68+
tps.foldLeft("")(collectMatchTrace.apply) // !cc! .apply needed since otherwise box conversion gets confused
6869

6970
class Errors(using Context) {
7071

@@ -267,8 +268,8 @@ class ImplicitSearchError(
267268
pt: Type,
268269
where: String,
269270
paramSymWithMethodCallTree: Option[(Symbol, tpd.Tree)] = None,
270-
ignoredInstanceNormalImport: => Option[SearchSuccess],
271-
importSuggestionAddendum: => String
271+
ignoredInstanceNormalImport: -> Option[SearchSuccess],
272+
importSuggestionAddendum: -> String
272273
)(using ctx: Context) {
273274

274275
def missingArgMsg = arg.tpe match {

tests/pos-with-compiler-cc/dotc/typer/Implicits.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,7 @@ end Implicits
16511651
* recursive references and emit a complete implicit dictionary when the outermost search
16521652
* is complete.
16531653
*/
1654-
abstract class SearchHistory:
1654+
abstract class SearchHistory extends caps.Pure:
16551655
val root: SearchRoot
16561656
/** Does this search history contain any by name implicit arguments. */
16571657
val byname: Boolean
@@ -1896,7 +1896,8 @@ sealed class TermRefSet(using Context):
18961896
prefixes0 match
18971897
case prefix: Type => f(TermRef(prefix, sym.uncheckedNN))
18981898
case prefixes: List[Type] => prefixes.foreach(pre => f(TermRef(pre, sym.uncheckedNN)))
1899-
elems.forEach(handle)
1899+
elems.forEach(handle.asInstanceOf)
1900+
// !cc! cast is needed to circumvent problematic interaction of box and Java wildcards
19001901

19011902
// used only for debugging
19021903
def showAsList: List[TermRef] = {

tests/pos-with-compiler-cc/dotc/typer/ImportInfo.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Implicits.RenamedImplicitRef
1111
import StdNames.nme
1212
import printing.Texts.Text
1313
import NameKinds.QualifiedName
14+
import language.experimental.pureFunctions
1415

1516
object ImportInfo {
1617

@@ -49,10 +50,10 @@ object ImportInfo {
4950
* @param isRootImport true if this is one of the implicit imports of scala, java.lang,
5051
* scala.Predef in the start context, false otherwise.
5152
*/
52-
class ImportInfo(symf: Context ?=> Symbol,
53+
class ImportInfo(symf: Context ?-> Symbol,
5354
val selectors: List[untpd.ImportSelector],
5455
val qualifier: untpd.Tree,
55-
val isRootImport: Boolean = false) extends Showable {
56+
val isRootImport: Boolean = false) extends Showable, caps.Pure {
5657

5758
private def symNameOpt = qualifier match {
5859
case ref: untpd.RefTree => Some(ref.name.asTermName)

0 commit comments

Comments
 (0)