Skip to content

Commit a5c26cd

Browse files
authored
Make separation checking controlled by language import (#23560)
It's import language.experimental.separationChecking
2 parents e05e3a3 + aa13ddf commit a5c26cd

File tree

9 files changed

+26
-10
lines changed

9 files changed

+26
-10
lines changed

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ class CheckCaptures extends Recheck, SymTransformer:
259259
/** The set of symbols that were rechecked via a completer */
260260
private val completed = new mutable.HashSet[Symbol]
261261

262-
var needAnotherRun = false
262+
/** Set on recheckClassDef since there we see all language imports */
263+
private var sepChecksEnabled = false
264+
265+
private var needAnotherRun = false
263266

264267
def resetIteration()(using Context): Unit =
265268
needAnotherRun = false
@@ -511,7 +514,7 @@ class CheckCaptures extends Recheck, SymTransformer:
511514
// The path-use.scala neg test contains an example.
512515
val underlying = CaptureSet.ofTypeDeeply(c1.widen)
513516
capt.println(i"Widen reach $c to $underlying in ${env.owner}")
514-
if ccConfig.useSepChecks then
517+
if sepChecksEnabled then
515518
recur(underlying.filter(!_.isTerminalCapability), env, null)
516519
// we don't want to disallow underlying Fresh instances, since these are typically locally created
517520
// fresh capabilities. We don't need to also follow the hidden set since separation
@@ -1144,6 +1147,7 @@ class CheckCaptures extends Recheck, SymTransformer:
11441147
* is already done in the TypeApply.
11451148
*/
11461149
override def recheckClassDef(tree: TypeDef, impl: Template, cls: ClassSymbol)(using Context): Type =
1150+
if Feature.enabled(Feature.separationChecking) then sepChecksEnabled = true
11471151
val localSet = capturedVars(cls)
11481152
for parent <- impl.parents do // (1)
11491153
checkSubset(capturedVars(parent.tpe.classSymbol), localSet, parent.srcPos,
@@ -2014,7 +2018,7 @@ class CheckCaptures extends Recheck, SymTransformer:
20142018
end checker
20152019

20162020
checker.traverse(unit)(using ctx.withOwner(defn.RootClass))
2017-
if ccConfig.useSepChecks then SepCheck(this).traverse(unit)
2021+
if sepChecksEnabled then SepCheck(this).traverse(unit)
20182022
if !ctx.reporter.errorsReported then
20192023
// We dont report errors here if previous errors were reported, because other
20202024
// errors often result in bad applied types, but flagging these bad types gives

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ object Feature:
3232
val saferExceptions = experimental("saferExceptions")
3333
val pureFunctions = experimental("pureFunctions")
3434
val captureChecking = experimental("captureChecking")
35+
val separationChecking = experimental("separationChecking")
3536
val into = experimental("into")
3637
val modularity = experimental("modularity")
3738
val quotedPatternsWithPolymorphicFunctions = experimental("quotedPatternsWithPolymorphicFunctions")
@@ -40,7 +41,7 @@ object Feature:
4041
def experimentalAutoEnableFeatures(using Context): List[TermName] =
4142
defn.languageExperimentalFeatures
4243
.map(sym => experimental(sym.name))
43-
.filterNot(_ == captureChecking) // TODO is this correct?
44+
.filterNot(sym => sym == captureChecking || sym == separationChecking) // TODO is this correct?
4445

4546
val values = List(
4647
(nme.help, "Display all available features"),
@@ -60,6 +61,7 @@ object Feature:
6061
(saferExceptions, "Enable safer exceptions"),
6162
(pureFunctions, "Enable pure functions for capture checking"),
6263
(captureChecking, "Enable experimental capture checking"),
64+
(separationChecking, "Enable experimental separation checking (requires captureChecking)"),
6365
(into, "Allow into modifier on parameter types"),
6466
(modularity, "Enable experimental modularity features"),
6567
(packageObjectValues, "Enable experimental package objects as values"),

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,7 @@ object Checking {
926926
val name = Feature.experimental(sel.name)
927927
name == Feature.scala2macros
928928
|| name == Feature.captureChecking
929+
|| name == Feature.separationChecking
929930
trees.filter {
930931
case Import(qual, selectors) =>
931932
languageImport(qual) match

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class CompilationTests {
3737
compileFilesInDir("tests/pos-special/sourcepath/outer", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
3838
compileFile("tests/pos-special/sourcepath/outer/nested/Test4.scala", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")),
3939
compileFilesInDir("tests/pos-scala2", defaultOptions.and("-source", "3.0-migration")),
40-
compileFilesInDir("tests/pos-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking", "-source", "3.8")),
40+
compileFilesInDir("tests/pos-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking", "-language:experimental.separationChecking")),
4141
compileFile("tests/pos-special/utf8encoded.scala", defaultOptions.and("-encoding", "UTF8")),
4242
compileFile("tests/pos-special/utf16encoded.scala", defaultOptions.and("-encoding", "UTF16")),
4343
compileDir("tests/pos-special/i18589", defaultOptions.and("-Wsafe-init").without("-Ycheck:all")),
@@ -149,7 +149,7 @@ class CompilationTests {
149149
aggregateTests(
150150
compileFilesInDir("tests/neg", defaultOptions, FileFilter.exclude(TestSources.negScala2LibraryTastyExcludelisted)),
151151
compileFilesInDir("tests/neg-deep-subtype", allowDeepSubtypes),
152-
compileFilesInDir("tests/neg-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking", "-source", "3.8")),
152+
compileFilesInDir("tests/neg-custom-args/captures", defaultOptions.and("-language:experimental.captureChecking", "-language:experimental.separationChecking")),
153153
compileFile("tests/neg-custom-args/sourcepath/outer/nested/Test1.scala", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath")),
154154
compileDir("tests/neg-custom-args/sourcepath2/hi", defaultOptions.and("-sourcepath", "tests/neg-custom-args/sourcepath2", "-Xfatal-warnings")),
155155
compileList("duplicate source", List(
@@ -172,7 +172,7 @@ class CompilationTests {
172172
aggregateTests(
173173
compileFilesInDir("tests/run", defaultOptions.and("-Wsafe-init")),
174174
compileFilesInDir("tests/run-deep-subtype", allowDeepSubtypes),
175-
compileFilesInDir("tests/run-custom-args/captures", allowDeepSubtypes.and("-language:experimental.captureChecking", "-source", "3.8")),
175+
compileFilesInDir("tests/run-custom-args/captures", allowDeepSubtypes.and("-language:experimental.captureChecking", "-language:experimental.separationChecking")),
176176
// Run tests for legacy lazy vals.
177177
compileFilesInDir("tests/run", defaultOptions.and("-Wsafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.runLazyValsAllowlist)),
178178
).checkRuns()

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ object language:
8484
@compileTimeOnly("`captureChecking` can only be used at compile time in import statements")
8585
object captureChecking
8686

87+
/** Experimental support for separation checking; requires captureChecking also to be enabled.
88+
*
89+
* @see [[https://dotty.epfl.ch/docs/reference/experimental/cc]]
90+
*/
91+
@compileTimeOnly("`separationChecking` can only be used at compile time in import statements")
92+
object separationChecking
93+
8794
/** Experimental support for automatic conversions of arguments, without requiring
8895
* a language import `import scala.language.implicitConversions`.
8996
*

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,7 @@ object Build {
16041604
settings(scala2LibraryBootstrappedSettings).
16051605
settings(
16061606
moduleName := "scala2-library-cc",
1607-
scalacOptions ++= Seq("-source", "3.8"), // for separation checking
1607+
scalacOptions += "-language:experimental.separationChecking" // for separation checking
16081608
)
16091609

16101610
lazy val scala2LibraryBootstrappedSettings = Seq(

project/MiMaFilters.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ object MiMaFilters {
1616

1717
ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.stdLibPatches.language.2.13"),
1818
ProblemFilters.exclude[MissingClassProblem]("scala.runtime.stdLibPatches.language$2$u002E13$"),
19+
ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.stdLibPatches.language#experimental.separationChecking"),
20+
ProblemFilters.exclude[MissingClassProblem]("scala.runtime.stdLibPatches.language$experimental$separationChecking$"),
1921

2022
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.Conversion.underlying"),
2123
ProblemFilters.exclude[MissingClassProblem]("scala.Conversion$"),

tests/neg-custom-args/captures/capture-vars-subtyping.scala renamed to tests/neg/capture-vars-subtyping.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import language.experimental.captureChecking
2-
import language.`3.7` // no separation checking, TODO enable
2+
// no separation checking, TODO enable and move to neg-customargs
33
import caps.*
44

55
def test[C^] =

tests/neg-custom-args/captures/cc-fresh-levels.scala renamed to tests/neg/cc-fresh-levels.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//> using options -source 3.7
21
import language.experimental.captureChecking
2+
// no separation checking
33
import caps.*
44
class IO
55
class Ref[X](init: X):

0 commit comments

Comments
 (0)