Skip to content

Commit 010633b

Browse files
committed
Complete the language import functionality
Complete the functionality of allowing language imports for pureFunctions and captureChecking: - make parser work with them - make printer to recognize them
1 parent 8d729ad commit 010633b

File tree

12 files changed

+84
-15
lines changed

12 files changed

+84
-15
lines changed

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
145145
case Floating
146146
}
147147

148-
/** {x1, ..., xN} T (only relevant under -Ycc) */
148+
/** {x1, ..., xN} T (only relevant under captureChecking) */
149149
case class CapturingTypeTree(refs: List[Tree], parent: Tree)(implicit @constructorOnly src: SourceFile) extends TypTree
150150

151151
/** Short-lived usage in typer, does not need copy/transform/fold infrastructure */

compiler/src/dotty/tools/dotc/core/Mode.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ object Mode {
7878
/** Use Scala2 scheme for overloading and implicit resolution */
7979
val OldOverloadingResolution: Mode = newMode(15, "OldOverloadingResolution")
8080

81-
/** Treat CapturingTypes as plain AnnotatedTypes even in phase =Ycc.
81+
/** Treat CapturingTypes as plain AnnotatedTypes even in phase CheckCaptures.
8282
* Reuses the value of OldOverloadingResolution to save Mode bits.
8383
* This is OK since OldOverloadingResolution only affects implicit search, which
8484
* is done during phases Typer and Inlinig, and IgnoreCaptures only has an

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,7 @@ object NameOps {
209209
if str == mustHave then found = true
210210
idx + str.length
211211
else idx
212-
val start = if Feature.pureFunsEnabled then skip(0, "Impure") else 0
213-
skip(skip(start, "Erased"), "Context") == suffixStart
212+
skip(skip(skip(0, "Impure"), "Erased"), "Context") == suffixStart
214213
&& found
215214
}
216215

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ object Parsers {
196196

197197
def isIdent = in.isIdent
198198
def isIdent(name: Name) = in.isIdent(name)
199-
def isPureArrow(name: Name): Boolean = Feature.pureFunsEnabled && isIdent(name)
199+
def isPureArrow(name: Name): Boolean = in.pureFunsEnabled && isIdent(name)
200200
def isPureArrow: Boolean = isPureArrow(nme.PUREARROW) || isPureArrow(nme.PURECTXARROW)
201201
def isErased = isIdent(nme.erased) && in.erasedEnabled
202202
def isSimpleLiteral =
@@ -972,7 +972,7 @@ object Parsers {
972972
* capture set `{ref1, ..., refN}` followed by a token that can start a type?
973973
*/
974974
def followingIsCaptureSet(): Boolean =
975-
Feature.ccEnabled && {
975+
in.featureEnabled(Feature.captureChecking) && {
976976
val lookahead = in.LookaheadScanner()
977977
def followingIsTypeStart() =
978978
lookahead.nextToken()
@@ -1485,7 +1485,7 @@ object Parsers {
14851485
if !imods.flags.isEmpty || params.isEmpty then
14861486
syntaxError(em"illegal parameter list for type lambda", start)
14871487
token = ARROW
1488-
else if Feature.pureFunsEnabled then
1488+
else if in.pureFunsEnabled then
14891489
// `=>` means impure function under pureFunctions or captureChecking
14901490
// language imports, whereas `->` is then a regular function.
14911491
imods |= Impure
@@ -1891,7 +1891,7 @@ object Parsers {
18911891
if in.token == ARROW || isPureArrow(nme.PUREARROW) then
18921892
val isImpure = in.token == ARROW
18931893
val tp = atSpan(in.skipToken()) { ByNameTypeTree(core()) }
1894-
if isImpure && Feature.pureFunsEnabled then ImpureByNameTypeTree(tp) else tp
1894+
if isImpure && in.pureFunsEnabled then ImpureByNameTypeTree(tp) else tp
18951895
else if in.token == LBRACE && followingIsCaptureSet() then
18961896
val start = in.offset
18971897
val cs = captureSet()

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ object Scanners {
230230
postfixOpsEnabledCtx = myLanguageImportContext
231231
postfixOpsEnabledCache
232232

233+
private var pureFunsEnabledCache = false
234+
private var pureFunsEnabledCtx: Context = NoContext
235+
236+
def pureFunsEnabled =
237+
if pureFunsEnabledCtx ne myLanguageImportContext then
238+
pureFunsEnabledCache = featureEnabled(Feature.pureFunctions) || featureEnabled(Feature.captureChecking)
239+
pureFunsEnabledCtx = myLanguageImportContext
240+
pureFunsEnabledCache
241+
233242
/** All doc comments kept by their end position in a `Map`.
234243
*
235244
* Note: the map is necessary since the comments are looked up after an

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
5858
try op finally myCtx = savedCtx
5959
}
6060

61+
inline def inContextBracket(inline op: Text): Text =
62+
val savedCtx = myCtx
63+
try op finally myCtx = savedCtx
64+
6165
def withoutPos(op: => Text): Text = {
6266
val savedPrintPos = printPos
6367
printPos = false
@@ -308,7 +312,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
308312
blockText(block.stats :+ block.expr)
309313

310314
protected def blockText[T >: Untyped](trees: List[Tree[T]]): Text =
311-
("{" ~ toText(trees, "\n") ~ "}").close
315+
inContextBracket {
316+
("{" ~ toText(trees, "\n") ~ "}").close
317+
}
312318

313319
protected def typeApplyText[T >: Untyped](tree: TypeApply[T]): Text = {
314320
val funText = toTextLocal(tree.fun)
@@ -598,7 +604,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
598604
typeDefText(tparamsTxt, optText(rhs)(" = " ~ _))
599605
}
600606
recur(rhs, "", true)
601-
case Import(expr, selectors) =>
607+
case tree @ Import(expr, selectors) =>
608+
myCtx = myCtx.importContext(tree, tree.symbol)
602609
keywordText("import ") ~ importText(expr, selectors)
603610
case Export(expr, selectors) =>
604611
keywordText("export ") ~ importText(expr, selectors)
@@ -965,7 +972,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
965972
}
966973
else impl.body
967974

968-
val bodyText = " {" ~~ selfText ~ toTextGlobal(primaryConstrs ::: body, "\n") ~ "}"
975+
val bodyText = inContextBracket(
976+
" {" ~~ selfText ~ toTextGlobal(primaryConstrs ::: body, "\n") ~ "}")
969977

970978
prefix ~
971979
keywordText(" extends").provided(!ofNew && impl.parents.nonEmpty) ~~ parentsText ~
@@ -988,7 +996,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
988996
protected def packageDefText(tree: PackageDef): Text = {
989997
val statsText = tree.stats match {
990998
case (pdef: PackageDef) :: Nil => toText(pdef)
991-
case _ => toTextGlobal(tree.stats, "\n")
999+
case _ => inContextBracket(toTextGlobal(tree.stats, "\n"))
9921000
}
9931001
val bodyText =
9941002
if (currentPrecedence == TopLevelPrec) "\n" ~ statsText else " {" ~ statsText ~ "}"

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ i2797a
7878
# allows to simplify a type that was already computed
7979
i13842.scala
8080

81+
# Position change under captureChecking
82+
boxmap-paper.scala
83+
8184
# GADT cast applied to singleton type difference
8285
i4176-gadt.scala
8386

library/src/scala/runtime/stdLibPatches/language.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ object language:
6464
*
6565
* @see [[https://dotty.epfl.ch/docs/reference/experimental/purefuns]]
6666
*/
67+
@compileTimeOnly("`pureFunctions` can only be used at compile time in import statements")
6768
object pureFunctions
6869

6970
/** Experimental support for capture checking; implies support for pureFunctions
7071
*
7172
* @see [[https://dotty.epfl.ch/docs/reference/experimental/cc]]
7273
*/
74+
@compileTimeOnly("`captureChecking` can only be used at compile time in import statements")
7375
object captureChecking
7476
end experimental
7577

tests/neg/cc-only-defs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ trait Test {
55

66
val z: *.type // error
77

8-
val b: ImpureFunction1[Int, Int] // error
8+
val b: ImpureFunction1[Int, Int] // now OK
99

1010
val a: {z} String // error
1111
} // error
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import annotation.retainsUniversal
1+
import annotation.retains
22

33
val foo: Int => Int = x => x
4-
val bar: (Int -> Int) @retainsUniversal = foo
4+
val bar: (Int -> Int) @retains(caps.*) = foo
55
val baz: {*} Int -> Int = bar
66

77

0 commit comments

Comments
 (0)