Skip to content

Commit ab2664f

Browse files
authored
Merge pull request #11852 from dotty-staging/fix-11774
Fix #11774: only enable experimental features for snapshot and nightly
2 parents bf98ec5 + 9f62255 commit ab2664f

File tree

66 files changed

+138
-67
lines changed

Some content is hidden

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

66 files changed

+138
-67
lines changed

community-build/src/scala/dotty/communitybuild/projects.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ lazy val compilerVersion: String =
1010
val file = communitybuildDir.resolve("scala3-bootstrapped.version")
1111
new String(Files.readAllBytes(file), UTF_8)
1212

13+
lazy val compilerSupportExperimental: Boolean =
14+
compilerVersion.contains("SNAPSHOT") || compilerVersion.contains("NIGHTLY")
15+
1316
lazy val sbtPluginFilePath: String =
1417
// Workaround for https://github.com/sbt/sbt/issues/4395
1518
new File(sys.props("user.home") + "/.sbt/1.0/plugins").mkdirs()

community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class CommunityBuildTestB extends CommunityBuildTest:
116116
@Test def disciplineSpecs2 = projects.disciplineSpecs2.run()
117117
@Test def munit = projects.munit.run()
118118
@Test def perspective = projects.perspective.run()
119-
@Test def scodec = projects.scodec.run()
119+
@Test def scodec = if (compilerSupportExperimental) projects.scodec.run()
120120
@Test def scodecBits = projects.scodecBits.run()
121121
@Test def simulacrumScalafixAnnotations = projects.simulacrumScalafixAnnotations.run()
122122
end CommunityBuildTestB

compiler/src/dotty/tools/dotc/Driver.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class Driver {
7777
val ictx = rootCtx.fresh
7878
val summary = command.distill(args, ictx.settings)(ictx.settingsState)(using ictx)
7979
ictx.setSettings(summary.sstate)
80+
Feature.checkExperimentalFlags(using ictx)
8081
MacroClassLoader.init(ictx)
8182
Positioned.init(using ictx)
8283

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
279279

280280
def isLanguageImport(path: Tree): Boolean = languageImport(path).isDefined
281281

282+
def isExperimentalImport(path: Tree): Boolean =
283+
languageImport(path) match
284+
case Some(nme.experimental) => true
285+
case _ => false
286+
282287
/** The underlying pattern ignoring any bindings */
283288
def unbind(x: Tree): Tree = unsplice(x) match {
284289
case Bind(_, y) => unbind(y)

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,19 @@ object Feature:
2828
val symbolLiterals = deprecated("symbolLiterals")
2929
val fewerBraces = experimental("fewerBraces")
3030

31-
/** Is `feature` enabled by by a command-line setting? The enabling setting is
31+
val experimentalWarningMessage = "Experimental features may only be used with nightly or snapshot version of compiler."
32+
33+
/** Experimental features are only enabled for snapshot and nightly compiler versions
34+
*/
35+
def experimentalEnabled(using Context): Boolean =
36+
Properties.experimental && !ctx.settings.YnoExperimental.value
37+
38+
def isExperimental(feature: TermName): Boolean =
39+
feature != scala2macros && feature.match
40+
case QualifiedName(nme.experimental, _) => true
41+
case _ => false
42+
43+
/** Is `feature` enabled by by a command-line setting? The enabling setting is
3244
*
3345
* -language:<prefix>feature
3446
*
@@ -56,9 +68,12 @@ object Feature:
5668
* @param feature The name of the feature
5769
* @param owner The prefix symbol (nested in `scala.language`) where the
5870
* feature is defined.
71+
*
72+
* Note: Experimental features are only enabled for snapshot and nightly version of compiler.
5973
*/
6074
def enabled(feature: TermName)(using Context): Boolean =
61-
enabledBySetting(feature) || enabledByImport(feature)
75+
(experimentalEnabled || !isExperimental(feature))
76+
&& (enabledBySetting(feature) || enabledByImport(feature))
6277

6378
/** Is auto-tupling enabled? */
6479
def autoTuplingEnabled(using Context): Boolean = !enabled(nme.noAutoTupling)
@@ -71,6 +86,8 @@ object Feature:
7186

7287
def genericNumberLiteralsEnabled(using Context) = enabled(genericNumberLiterals)
7388

89+
def erasedEnabled(using Context) = enabled(Feature.erasedDefinitions)
90+
7491
def scala2ExperimentalMacroEnabled(using Context) = enabled(scala2macros)
7592

7693
def sourceVersionSetting(using Context): SourceVersion =
@@ -97,4 +114,16 @@ object Feature:
97114
else
98115
false
99116

117+
/** Check that experimental compiler options are only set for snapshot or nightly compiler versions. */
118+
def checkExperimentalFlags(using Context): Unit =
119+
if !experimentalEnabled then
120+
val features = ctx.settings.language.value.filter { feature =>
121+
feature.contains(nme.experimental.toString) && !feature.contains("macros")
122+
}
123+
if features.nonEmpty then
124+
report.error(
125+
experimentalWarningMessage +
126+
"\nThe experimental language features are enabled via -language:" + features.mkString(",")
127+
)
128+
100129
end Feature

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import java.nio.charset.StandardCharsets
1111
/** Loads `library.properties` from the jar. */
1212
object Properties extends PropertiesTrait {
1313
protected def propCategory: String = "compiler"
14-
protected def pickJarBasedOn: Class[Option[?]] = classOf[Option[?]]
14+
protected def pickJarBasedOn: Class[PropertiesTrait] = classOf[PropertiesTrait]
1515

1616
/** Scala manifest attributes.
1717
*/

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings {
215215
val YretainTrees: Setting[Boolean] = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree")
216216
val YshowTreeIds: Setting[Boolean] = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.")
217217
val YfromTastyIgnoreList: Setting[List[String]] = MultiStringSetting("-Yfrom-tasty-ignore-list", "file", "List of `tasty` files in jar files that will not be loaded when using -from-tasty")
218+
val YnoExperimental: Setting[Boolean] = BooleanSetting("-Yno-experimental", "Disable experimental language features")
218219

219220
val YprofileEnabled: Setting[Boolean] = BooleanSetting("-Yprofile-enabled", "Enable profiling.")
220221
val YprofileDestination: Setting[String] = StringSetting("-Yprofile-destination", "file", "Where to send profiling output - specify a file, default is to the console.", "")

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ object StdNames {
520520
val longHash: N = "longHash"
521521
val macroThis : N = "_this"
522522
val macroContext : N = "c"
523+
val macros: N = "macros"
523524
val main: N = "main"
524525
val manifest: N = "manifest"
525526
val ManifestFactory: N = "ManifestFactory"

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import config.Feature
3232
import config.Feature.{sourceVersion, migrateTo3}
3333
import config.SourceVersion._
3434
import config.SourceVersion
35+
import config.Properties
3536

3637
object Parsers {
3738

@@ -3079,6 +3080,11 @@ object Parsers {
30793080
val imp = Import(tree, selectors)
30803081
if isLanguageImport(tree) then
30813082
in.languageImportContext = in.languageImportContext.importContext(imp, NoSymbol)
3083+
if isExperimentalImport(tree)
3084+
&& !Feature.experimentalEnabled
3085+
&& selectors.exists(_.name != nme.macros)
3086+
then
3087+
report.error(Feature.experimentalWarningMessage, imp.srcPos)
30823088
for
30833089
case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors
30843090
if allSourceVersionNames.contains(imported)

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ class BootstrappedOnlyCompilationTests {
118118
aggregateTests(
119119
compileFilesInDir("tests/run-macros", defaultOptions.and("-Xcheck-macros")),
120120
compileFilesInDir("tests/run-custom-args/Yretain-trees", defaultOptions and "-Yretain-trees"),
121-
compileFilesInDir("tests/run-custom-args/run-macros-erased", defaultOptions.and("-language:experimental.erasedDefinitions").and("-Xcheck-macros")),
122121
)
123122
}.checkRuns()
124123

@@ -199,6 +198,24 @@ class BootstrappedOnlyCompilationTests {
199198
compileFilesInDir("tests/plugins/neg").checkExpectedErrors()
200199
compileDir("tests/plugins/custom/analyzer", withCompilerOptions.and("-Yretain-trees")).checkCompile()
201200
}
201+
202+
// tests for experimental featuress ------------------------------------------
203+
204+
@Test def experimental: Unit =
205+
implicit val testGroup: TestGroup = TestGroup("experimental")
206+
val enableExperimental = defaultOptions.without("-Yno-experimental")
207+
val enableErased = enableExperimental.and("-language:experimental.erasedDefinitions")
208+
compileFilesInDir("tests/neg-custom-args/no-experimental", defaultOptions.and("-Yno-experimental")).checkExpectedErrors()
209+
if config.Properties.experimental then
210+
compileFilesInDir("tests/run-custom-args/experimental", enableExperimental).checkRuns()
211+
compileFilesInDir("tests/neg-custom-args/experimental", enableExperimental).checkExpectedErrors()
212+
compileFilesInDir("tests/pos-custom-args/experimental", enableExperimental).checkCompile()
213+
compileFilesInDir("tests/run-staging-experimental", withStagingOptions.without("-Yno-experimental")).checkRuns()
214+
compileFilesInDir("tests/neg-custom-args/erased", enableErased).checkExpectedErrors()
215+
compileFilesInDir("tests/pos-custom-args/erased", enableErased).checkCompile()
216+
compileFilesInDir("tests/run-custom-args/run-macros-erased", enableErased.and("-Xcheck-macros")).checkRuns()
217+
compileFilesInDir("tests/run-custom-args/erased", enableErased)
218+
202219
}
203220

204221
object BootstrappedOnlyCompilationTests extends ParallelTesting {

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class CompilationTests {
3939
compileFilesInDir("tests/pos-special/isInstanceOf", allowDeepSubtypes.and("-Xfatal-warnings")),
4040
compileFilesInDir("tests/new", defaultOptions),
4141
compileFilesInDir("tests/pos-scala2", scala2CompatMode),
42-
compileFilesInDir("tests/pos-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
4342
compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init")),
4443
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
4544
compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")),
@@ -125,7 +124,6 @@ class CompilationTests {
125124
compileFilesInDir("tests/neg-no-kind-polymorphism", defaultOptions and "-Yno-kind-polymorphism"),
126125
compileFilesInDir("tests/neg-custom-args/deprecation", defaultOptions.and("-Xfatal-warnings", "-deprecation")),
127126
compileFilesInDir("tests/neg-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")),
128-
compileFilesInDir("tests/neg-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
129127
compileFilesInDir("tests/neg-custom-args/allow-double-bindings", allowDoubleBindings),
130128
compileFilesInDir("tests/neg-custom-args/allow-deep-subtypes", allowDeepSubtypes),
131129
compileFilesInDir("tests/neg-custom-args/explicit-nulls", defaultOptions.and("-Yexplicit-nulls")),
@@ -164,9 +162,7 @@ class CompilationTests {
164162
compileDir("tests/neg-custom-args/adhoc-extension", defaultOptions.and("-source", "future", "-feature", "-Xfatal-warnings")),
165163
compileFile("tests/neg/i7575.scala", defaultOptions.withoutLanguageFeatures.and("-language:_")),
166164
compileFile("tests/neg-custom-args/kind-projector.scala", defaultOptions.and("-Ykind-projector")),
167-
compileFile("tests/neg-custom-args/typeclass-derivation2.scala", defaultOptions.and("-language:experimental.erasedDefinitions")),
168165
compileFile("tests/neg-custom-args/i5498-postfixOps.scala", defaultOptions withoutLanguageFeature "postfixOps"),
169-
compileFile("tests/neg-custom-args/deptypes.scala", defaultOptions.and("-language:experimental.dependent")),
170166
compileFile("tests/neg-custom-args/matchable.scala", defaultOptions.and("-Xfatal-warnings", "-source", "future")),
171167
compileFile("tests/neg-custom-args/i7314.scala", defaultOptions.and("-Xfatal-warnings", "-source", "future")),
172168
compileFile("tests/neg-custom-args/feature-shadowing.scala", defaultOptions.and("-Xfatal-warnings", "-feature")),
@@ -188,7 +184,6 @@ class CompilationTests {
188184
compileFile("tests/run-custom-args/fors.scala", defaultOptions.and("-source", "future")),
189185
compileFile("tests/run-custom-args/no-useless-forwarders.scala", defaultOptions and "-Xmixin-force-forwarders:false"),
190186
compileFile("tests/run-custom-args/defaults-serizaliable-no-forwarders.scala", defaultOptions and "-Xmixin-force-forwarders:false"),
191-
compileFilesInDir("tests/run-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
192187
compileFilesInDir("tests/run-deep-subtype", allowDeepSubtypes),
193188
compileFilesInDir("tests/run", defaultOptions.and("-Ysafe-init"))
194189
).checkRuns()
@@ -247,7 +242,6 @@ class CompilationTests {
247242
val lib =
248243
compileList("lib", librarySources,
249244
defaultOptions.and("-Ycheck-reentrant",
250-
"-language:experimental.erasedDefinitions", // support declaration of scala.compiletime.erasedValue
251245
// "-source", "future", // TODO: re-enable once we allow : @unchecked in pattern definitions. Right now, lots of narrowing pattern definitions fail.
252246
))(libGroup)
253247

compiler/test/dotty/tools/vulpix/TestConfiguration.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ object TestConfiguration {
99
val noCheckOptions = Array(
1010
"-pagewidth", "120",
1111
"-color:never",
12+
"-Yno-experimental",
1213
"-Xtarget", defaultTarget
1314
)
1415

project/Build.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ object Build {
246246

247247
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test,
248248

249+
// TODO: enable after bootstrap
250+
// scalacOptions += "-Yno-experimental",
251+
249252
// If someone puts a source file at the root (e.g., for manual testing),
250253
// don't pick it up as part of any project.
251254
sourcesInBase := false,
@@ -445,6 +448,9 @@ object Build {
445448
// Add git-hash used to package the distribution to the manifest to know it in runtime and report it in REPL
446449
packageOptions += ManifestAttributes(("Git-Hash", VersionUtil.gitHash)),
447450

451+
// TODO: enable after bootstrap
452+
// scalacOptions += "-Yno-experimental",
453+
448454
javaOptions ++= {
449455
val managedSrcDir = {
450456
// Populate the directory

tests/neg-custom-args/typeclass-derivation2.scala renamed to tests/neg-custom-args/erased/typeclass-derivation2.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import language.experimental.erasedDefinitions
2+
13
import scala.collection.mutable
24
import scala.annotation.tailrec
35

tests/neg-macros/BigFloat/BigFloat_1.scala renamed to tests/neg-custom-args/experimental/BigFloat/BigFloat_1.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,3 @@ object BigFloat extends App {
4848
'{BigInt(${Expr(x.toString)})}
4949
}
5050
}
51-

tests/neg-custom-args/deptypes.scala renamed to tests/neg-custom-args/experimental/deptypes.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import language.experimental.dependent
12

23
type Vec[T] = (n: Int) =>> Array[T] // error: not yet implemented
34

tests/neg/erased-inheritance.scala renamed to tests/neg-custom-args/experimental/erased-inheritance.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,3 @@ erased trait D
88

99
val x = new A{} // ok, x is erased
1010
val y = new C with D{} // error
11-
12-

tests/neg/language-import.scala renamed to tests/neg-custom-args/experimental/language-import.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,3 @@ object d:
2020
import language.experimental.genericNumberLiterals // ok
2121
import scala.language.noAutoTupling // ok
2222
import _root_.scala.language.strictEquality // ok
23-
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
class Test0 {
2+
import language.experimental.namedTypeArguments // error
3+
object Foo {
4+
inline def f[S, T](x: S): T = ???
5+
def g(x: Int) = f[T = Any](x) // error
6+
}
7+
}
8+
9+
class Test1 {
10+
import language.experimental.erasedDefinitions // error
11+
import scala.compiletime.erasedValue
12+
type UnivEq[A]
13+
object UnivEq:
14+
erased def force[A]: UnivEq[A] = erasedValue // error // error // error
15+
extension [A](erased proof: UnivEq[A]) // error
16+
inline def univEq(a: A, b: A): Boolean =
17+
a == b
18+
}
19+
20+
class Test2 {
21+
import scala.language.experimental.genericNumberLiterals // error
22+
val x: BigInt = 13232202002020202020202 // error
23+
val y: BigInt = -0xaabb12345ACF12345AC // error
24+
}
25+
26+
class Test3 {
27+
import scala.language.experimental.namedTypeArguments // error
28+
object Foo {
29+
inline def f[S, T](x: S): T = ???
30+
def g(x: Int) = f[T = Any](x) // error
31+
}
32+
}
33+
34+
class Test4 {
35+
import scala.language.experimental.erasedDefinitions // error
36+
import scala.compiletime.erasedValue
37+
type UnivEq[A]
38+
object UnivEq:
39+
erased def force[A]: UnivEq[A] = erasedValue // error // error // error
40+
extension [A](erased proof: UnivEq[A]) // error
41+
inline def univEq(a: A, b: A): Boolean =
42+
a == b
43+
}
44+
45+
class Test5 {
46+
import scala.language.experimental.genericNumberLiterals // error
47+
val x: BigInt = 13232202002020202020202 // error
48+
val y: BigInt = -0xaabb12345ACF12345AC // error
49+
}
50+
51+
class Test6 {
52+
import scala.language.experimental
53+
}
54+
55+
class Test7 {
56+
import scala.language.experimental
57+
import experimental.genericNumberLiterals // error: no aliases can be used to refer to a language import
58+
val x: BigInt = 13232202002020202020202 // error
59+
}

tests/neg-with-compiler/GenericNumLits/EvenFromDigitsImpl_1.scala

Lines changed: 0 additions & 19 deletions
This file was deleted.

tests/neg-with-compiler/GenericNumLits/Even_1.scala

Lines changed: 0 additions & 24 deletions
This file was deleted.

tests/neg-with-compiler/GenericNumLits/Test_2.scala

Lines changed: 0 additions & 6 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
import language.experimental.erasedDefinitions
22
erased class A
3-

0 commit comments

Comments
 (0)