Skip to content

Commit f26808e

Browse files
authored
Merge pull request #8700 from dotty-staging/change-options
Fix #8571: A new source version and migration scheme
2 parents bd1fff2 + 1236660 commit f26808e

File tree

184 files changed

+611
-443
lines changed

Some content is hidden

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

184 files changed

+611
-443
lines changed
Submodule scalap updated 1 file
Submodule scopt updated 1 file

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import typer.PrepareInlineable.InlineAccessors
1313
import typer.Nullables
1414
import transform.SymUtils._
1515
import core.Decorators.{given _}
16+
import config.SourceVersion
1617

1718
class CompilationUnit protected (val source: SourceFile) {
1819

@@ -24,6 +25,9 @@ class CompilationUnit protected (val source: SourceFile) {
2425

2526
def isJava: Boolean = source.file.name.endsWith(".java")
2627

28+
/** The source version for this unit, as determined by a language import */
29+
var sourceVersion: Option[SourceVersion] = None
30+
2731
/** Pickled TASTY binaries, indexed by class. */
2832
var pickled: Map[ClassSymbol, Array[Byte]] = Map()
2933

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import java.nio.file.{Files, Paths}
55
import dotty.tools.FatalError
66
import config.CompilerCommand
77
import core.Comments.{ContextDoc, ContextDocstrings}
8-
import core.Contexts.{Context, ContextBase}
8+
import core.Contexts.{Context, ContextBase, inContext, ctx}
99
import core.{MacroClassLoader, Mode, TypeError}
10+
import core.StdNames.nme
1011
import dotty.tools.dotc.ast.Positioned
1112
import dotty.tools.io.File
1213
import reporting._
1314
import core.Decorators._
15+
import config.Feature
1416

1517
import scala.util.control.NonFatal
1618
import fromtasty.{TASTYCompiler, TastyFileUtil}
@@ -70,11 +72,14 @@ class Driver {
7072
MacroClassLoader.init(ictx)
7173
Positioned.updateDebugPos(ictx)
7274

73-
if (!ictx.settings.YdropComments.value(ictx) || ictx.mode.is(Mode.ReadComments))
74-
ictx.setProperty(ContextDoc, new ContextDocstrings)
75-
76-
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ictx)
77-
fromTastySetup(fileNames, ictx)
75+
inContext(ictx) {
76+
if !ctx.settings.YdropComments.value || ctx.mode.is(Mode.ReadComments) then
77+
ictx.setProperty(ContextDoc, new ContextDocstrings)
78+
if Feature.enabledBySetting(nme.Scala2Compat) && false then // TODO: enable
79+
ctx.warning("-language:Scala2Compat will go away; use -source 3.0-migration instead")
80+
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
81+
fromTastySetup(fileNames, ctx)
82+
}
7883
}
7984

8085
/** Setup extra classpath and figure out class names for tasty file inputs */

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Decorators.{given _}, transform.SymUtils._
99
import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName}
1010
import typer.{FrontEnd, Namer}
1111
import util.{Property, SourceFile, SourcePosition}
12+
import config.Feature.{sourceVersion, migrateTo3, enabled}
13+
import config.SourceVersion._
1214
import collection.mutable.ListBuffer
1315
import reporting.messages._
1416
import reporting.trace
@@ -210,7 +212,7 @@ object desugar {
210212
val epbuf = ListBuffer[ValDef]()
211213
def desugarContextBounds(rhs: Tree): Tree = rhs match {
212214
case ContextBounds(tbounds, cxbounds) =>
213-
val iflag = if ctx.settings.strict.value then Given else Implicit
215+
val iflag = if sourceVersion.isAtLeast(`3.1`) then Given else Implicit
214216
epbuf ++= makeImplicitParameters(cxbounds, iflag, forPrimaryConstructor = isPrimaryConstructor)
215217
tbounds
216218
case LambdaTypeTree(tparams, body) =>
@@ -386,8 +388,8 @@ object desugar {
386388
case _ => false
387389
}
388390
def isScala(tree: Tree): Boolean = tree match {
389-
case Ident(nme.scala_) => true
390-
case Select(Ident(nme.ROOTPKG), nme.scala_) => true
391+
case Ident(nme.scala) => true
392+
case Select(Ident(nme.ROOTPKG), nme.scala) => true
391393
case _ => false
392394
}
393395

@@ -540,7 +542,7 @@ object desugar {
540542
ensureApplied(nu)
541543
}
542544

543-
val copiedAccessFlags = if (ctx.scala2CompatSetting) EmptyFlags else AccessFlags
545+
val copiedAccessFlags = if migrateTo3 then EmptyFlags else AccessFlags
544546

545547
// Methods to add to a case class C[..](p1: T1, ..., pN: Tn)(moreParams)
546548
// def _1: T1 = this.p1
@@ -1639,7 +1641,7 @@ object desugar {
16391641
}
16401642
else {
16411643
assert(ctx.mode.isExpr || ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive), ctx.mode)
1642-
if (!ctx.featureEnabled(nme.postfixOps)) {
1644+
if (!enabled(nme.postfixOps)) {
16431645
ctx.error(
16441646
s"""postfix operator `${op.name}` needs to be enabled
16451647
|by making the implicit value scala.language.postfixOps visible.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
154154
enum GenCheckMode {
155155
case Ignore // neither filter nor check since filtering was done before
156156
case Check // check that pattern is irrefutable
157-
case FilterNow //filter out non-matching elements since we are not in -strict
157+
case FilterNow // filter out non-matching elements since we are not yet in 3.1
158158
case FilterAlways // filter out non-matching elements since pattern is prefixed by `case`
159159
}
160160

@@ -447,7 +447,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
447447
TypedSplice(tpd.ref(tp))
448448

449449
def rootDot(name: Name)(implicit src: SourceFile): Select = Select(Ident(nme.ROOTPKG), name)
450-
def scalaDot(name: Name)(implicit src: SourceFile): Select = Select(rootDot(nme.scala_), name)
450+
def scalaDot(name: Name)(implicit src: SourceFile): Select = Select(rootDot(nme.scala), name)
451451
def scalaAnnotationDot(name: Name)(using SourceFile): Select = Select(scalaDot(nme.annotation), name)
452452
def scalaUnit(implicit src: SourceFile): Select = scalaDot(tpnme.Unit)
453453
def scalaAny(implicit src: SourceFile): Select = scalaDot(tpnme.Any)
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package dotty.tools
2+
package dotc
3+
package config
4+
5+
import core._
6+
import Contexts._, Symbols._, Names._
7+
import StdNames.nme
8+
import Decorators.{given _}
9+
import util.SourcePosition
10+
import SourceVersion._
11+
import reporting.Message
12+
13+
object Feature:
14+
15+
/** Is `feature` enabled by by a command-line setting? The enabling setting is
16+
*
17+
* -language:<prefix>feature
18+
*
19+
* where <prefix> is the fully qualified name of `owner`, followed by a ".",
20+
* but subtracting the prefix `scala.language.` at the front.
21+
*/
22+
def enabledBySetting(feature: TermName, owner: Symbol = NoSymbol)(using Context): Boolean =
23+
def toPrefix(sym: Symbol): String =
24+
if !sym.exists || sym == defn.LanguageModule.moduleClass then ""
25+
else toPrefix(sym.owner) + sym.name + "."
26+
val prefix = if owner.exists then toPrefix(owner) else ""
27+
ctx.base.settings.language.value.contains(prefix + feature)
28+
29+
/** Is `feature` enabled by by an import? This is the case if the feature
30+
* is imported by a named import
31+
*
32+
* import owner.feature
33+
*
34+
* and there is no visible nested import that excludes the feature, as in
35+
*
36+
* import owner.{ feature => _ }
37+
*/
38+
def enabledByImport(feature: TermName, owner: Symbol = NoSymbol)(using Context): Boolean =
39+
ctx.atPhase(ctx.typerPhase) {
40+
ctx.importInfo != null
41+
&& ctx.importInfo.featureImported(feature.toTermName,
42+
if owner.exists then owner else defn.LanguageModule.moduleClass)
43+
}
44+
45+
/** Is `feature` enabled by either a command line setting or an import?
46+
* @param feature The name of the feature
47+
* @param owner The prefix symbol (nested in `scala.language`) where the
48+
* feature is defined.
49+
*/
50+
def enabled(feature: TermName, owner: Symbol = NoSymbol)(using Context): Boolean =
51+
enabledBySetting(feature, owner) || enabledByImport(feature, owner)
52+
53+
/** Is auto-tupling enabled? */
54+
def autoTuplingEnabled(using Context): Boolean =
55+
!enabled(nme.noAutoTupling)
56+
57+
def dynamicsEnabled(using Context): Boolean =
58+
enabled(nme.dynamics)
59+
60+
def sourceVersionSetting(using Context): SourceVersion =
61+
SourceVersion.valueOf(ctx.settings.source.value)
62+
63+
def sourceVersion(using Context): SourceVersion =
64+
if ctx.compilationUnit == null then sourceVersionSetting
65+
else ctx.compilationUnit.sourceVersion.getOrElse(sourceVersionSetting)
66+
67+
def migrateTo3(using Context): Boolean =
68+
sourceVersion == `3.0-migration` || enabledBySetting(nme.Scala2Compat)
69+
70+
/** If current source migrates to `version`, issue given warning message
71+
* and return `true`, otherwise return `false`.
72+
*/
73+
def warnOnMigration(msg: Message, pos: SourcePosition,
74+
version: SourceVersion = defaultSourceVersion)(using Context): Boolean =
75+
if sourceVersion.isMigrating && sourceVersion.stable == version
76+
|| version == `3.0` && migrateTo3
77+
then
78+
ctx.migrationWarning(msg, pos)
79+
true
80+
else
81+
false
82+
83+
end Feature

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ScalaSettings extends Settings.SettingGroup {
3434
val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.") withAbbreviation "--feature"
3535
val help: Setting[Boolean] = BooleanSetting("-help", "Print a synopsis of standard options.") withAbbreviation "--help"
3636
val color: Setting[String] = ChoiceSetting("-color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/) withAbbreviation "--color"
37+
val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", List("3.0", "3.1", "3.0-migration", "3.1-migration"), "3.0").withAbbreviation("--source")
3738
val target: Setting[String] = ChoiceSetting("-target", "target", "Target platform for object files. All JVM 1.5 targets are deprecated.",
3839
List("jvm-1.5", "jvm-1.5-fjbg", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "jvm-1.8", "msil"), "jvm-1.8") withAbbreviation "--target"
3940
val scalajs: Setting[Boolean] = BooleanSetting("-scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).") withAbbreviation "--scalajs"
@@ -43,9 +44,8 @@ class ScalaSettings extends Settings.SettingGroup {
4344
val verbose: Setting[Boolean] = BooleanSetting("-verbose", "Output messages about what the compiler is doing.") withAbbreviation "--verbose"
4445
val version: Setting[Boolean] = BooleanSetting("-version", "Print product version and exit.") withAbbreviation "--version"
4546
val pageWidth: Setting[Int] = IntSetting("-pagewidth", "Set page width", 80) withAbbreviation "--page-width"
46-
val strict: Setting[Boolean] = BooleanSetting("-strict", "Use strict type rules, which means some formerly legal code does not typecheck anymore.") withAbbreviation "--strict"
4747
val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.") withAbbreviation "--language"
48-
val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2Compat rewrites sources to migrate to new syntax.") withAbbreviation "--rewrite"
48+
val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.") withAbbreviation "--rewrite"
4949
val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.") withAbbreviation "--no-warnings"
5050
val fromTasty: Setting[Boolean] = BooleanSetting("-from-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.") withAbbreviation "--from-tasty"
5151

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ object Settings {
135135
case (ListTag, _) =>
136136
if (argRest.isEmpty) missingArg
137137
else update((argRest split ",").toList, args)
138-
case (StringTag, _) if choices.nonEmpty =>
139-
if (argRest.isEmpty) missingArg
140-
else if (!choices.contains(argRest))
138+
case (StringTag, _) if choices.nonEmpty && argRest.nonEmpty =>
139+
if (!choices.contains(argRest))
141140
fail(s"$arg is not a valid choice for $name", args)
142141
else update(argRest, args)
142+
case (StringTag, arg2 :: args2) =>
143+
if (arg2 startsWith "-") missingArg
144+
else update(arg2, args2)
143145
case (OutputTag, arg :: args) =>
144146
val path = Directory(arg)
145147
val isJar = path.extension == "jar"
@@ -149,9 +151,6 @@ object Settings {
149151
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
150152
update(output, args)
151153
}
152-
case (StringTag, arg2 :: args2) =>
153-
if (arg2 startsWith "-") missingArg
154-
else update(arg2, args2)
155154
case (IntTag, arg2 :: args2) =>
156155
try {
157156
val x = arg2.toInt
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dotty.tools
2+
package dotc
3+
package config
4+
5+
import core.Contexts.{Context, ctx}
6+
import core.Names.TermName
7+
import core.StdNames.nme
8+
import core.Decorators.{given _}
9+
import util.Property
10+
11+
enum SourceVersion:
12+
case `3.0-migration`, `3.0`, `3.1-migration`, `3.1`
13+
14+
val isMigrating: Boolean = toString.endsWith("-migration")
15+
16+
def stable: SourceVersion =
17+
if isMigrating then SourceVersion.values(ordinal + 1) else this
18+
19+
def isAtLeast(v: SourceVersion) = stable.ordinal >= v.ordinal
20+
21+
object SourceVersion extends Property.Key[SourceVersion]:
22+
def defaultSourceVersion = `3.0`
23+
24+
val allSourceVersionNames = values.toList.map(_.toString.toTermName)
25+
end SourceVersion

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import Contexts._, Types._, Symbols._, Names._, Flags._
66
import Denotations.SingleDenotation
77
import Decorators._
88
import collection.mutable
9+
import config.SourceVersion.`3.1`
10+
import config.Feature.sourceVersion
911

1012
/** Realizability status */
1113
object CheckRealizable {
@@ -197,8 +199,8 @@ class CheckRealizable(implicit ctx: Context) {
197199
realizability(fld.info).mapError(r => new HasProblemField(fld, r))
198200
}
199201
}
200-
if (ctx.settings.strict.value)
201-
// check fields only under strict mode for now.
202+
if sourceVersion.isAtLeast(`3.1`) then
203+
// check fields only from version 3.1.
202204
// Reason: An embedded field could well be nullable, which means it
203205
// should not be part of a path and need not be checked; but we cannot recognize
204206
// this situation until we have a typesystem that tracks nullability.

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class Definitions {
116116
val cls = denot.asClass.classSymbol
117117
val decls = newScope
118118
val arity = name.functionArity
119-
val paramNamePrefix = tpnme.scala_ ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
119+
val paramNamePrefix = tpnme.scala ++ str.NAME_JOIN ++ name ++ str.EXPAND_SEPARATOR
120120
val argParamRefs = List.tabulate(arity) { i =>
121121
enterTypeParam(cls, paramNamePrefix ++ "T" ++ (i + 1).toString, Contravariant, decls).typeRef
122122
}
@@ -199,7 +199,7 @@ class Definitions {
199199
@tu lazy val OpsPackageVal: TermSymbol = ctx.newCompletePackageSymbol(RootClass, nme.OPS_PACKAGE).entered
200200
@tu lazy val OpsPackageClass: ClassSymbol = OpsPackageVal.moduleClass.asClass
201201

202-
@tu lazy val ScalaPackageVal: TermSymbol = ctx.requiredPackage(nme.scala_)
202+
@tu lazy val ScalaPackageVal: TermSymbol = ctx.requiredPackage(nme.scala)
203203
@tu lazy val ScalaMathPackageVal: TermSymbol = ctx.requiredPackage("scala.math")
204204
@tu lazy val ScalaPackageClass: ClassSymbol = {
205205
val cls = ScalaPackageVal.moduleClass.asClass
@@ -1370,7 +1370,7 @@ class Definitions {
13701370

13711371
// /** The `Class[?]` of a primitive value type name */
13721372
// def valueTypeNameToJavaType(name: TypeName)(implicit ctx: Context): Option[Class[?]] =
1373-
// valueTypeNamesToJavaType.get(if (name.firstPart eq nme.scala_) name.lastPart.toTypeName else name)
1373+
// valueTypeNamesToJavaType.get(if (name.firstPart eq nme.scala) name.lastPart.toTypeName else name)
13741374

13751375
type PrimitiveClassEnc = Int
13761376

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Decorators._
1717
import printing.Texts._
1818
import printing.Printer
1919
import io.AbstractFile
20+
import config.Feature.migrateTo3
2021
import config.Config
2122
import util.common._
2223
import typer.ProtoTypes.NoViewsAllowed
@@ -489,7 +490,7 @@ object Denotations {
489490
// things, starting with the return type of this method.
490491
if (preferSym(sym2, sym1)) info2
491492
else if (preferSym(sym1, sym2)) info1
492-
else if (pre.widen.classSymbol.is(Scala2x) || ctx.scala2CompatMode)
493+
else if (pre.widen.classSymbol.is(Scala2x) || migrateTo3)
493494
info1 // follow Scala2 linearization -
494495
// compare with way merge is performed in SymDenotation#computeMembersNamed
495496
else throw new MergeError(ex.sym1, ex.sym2, ex.tp1, ex.tp2, pre)
@@ -1355,7 +1356,7 @@ object Denotations {
13551356
def isPackageFromCoreLibMissing: Boolean =
13561357
owner.symbol == defn.RootClass &&
13571358
(
1358-
selector == nme.scala_ || // if the scala package is missing, the stdlib must be missing
1359+
selector == nme.scala || // if the scala package is missing, the stdlib must be missing
13591360
selector == nme.scalaShadowing // if the scalaShadowing package is missing, the dotty library must be missing
13601361
)
13611362
if (owner.exists) {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Symbols._
77
import Types._
88
import Flags._
99
import dotty.tools.dotc.reporting.trace
10+
import config.Feature.migrateTo3
1011
import config.Printers._
1112

1213
trait PatternTypeConstrainer { self: TypeComparer =>
@@ -199,7 +200,9 @@ trait PatternTypeConstrainer { self: TypeComparer =>
199200
}
200201
}
201202

202-
val widePt = if (ctx.scala2CompatMode || refinementIsInvariant(patternTp)) scrutineeTp else widenVariantParams(scrutineeTp)
203+
val widePt =
204+
if migrateTo3 || refinementIsInvariant(patternTp) then scrutineeTp
205+
else widenVariantParams(scrutineeTp)
203206
val narrowTp = SkolemType(patternTp)
204207
trace(i"constraining simple pattern type $narrowTp <:< $widePt", gadts, res => s"$res\ngadt = ${ctx.gadt.debugBoundsDescription}") {
205208
isSubType(narrowTp, widePt)

0 commit comments

Comments
 (0)