Skip to content

Commit 422ffbc

Browse files
Merge pull request #11695 from dotty-staging/add-safe-throws
Fixes and improvements to erasure
2 parents 8fcce8f + 0af3f59 commit 422ffbc

Some content is hidden

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

44 files changed

+643
-98
lines changed

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ object Feature:
1919
private def deprecated(str: String): TermName =
2020
QualifiedName(nme.deprecated, str.toTermName)
2121

22-
private val Xdependent = experimental("dependent")
23-
private val XnamedTypeArguments = experimental("namedTypeArguments")
24-
private val XgenericNumberLiterals = experimental("genericNumberLiterals")
25-
private val Xmacros = experimental("macros")
26-
private val symbolLiterals: TermName = deprecated("symbolLiterals")
22+
private val namedTypeArguments = experimental("namedTypeArguments")
23+
private val genericNumberLiterals = experimental("genericNumberLiterals")
24+
private val scala2macros = experimental("macros")
25+
26+
val dependent = experimental("dependent")
27+
val erasedDefinitions = experimental("erasedDefinitions")
28+
val symbolLiterals: TermName = deprecated("symbolLiterals")
2729

2830
/** Is `feature` enabled by by a command-line setting? The enabling setting is
2931
*
@@ -62,15 +64,13 @@ object Feature:
6264

6365
def dynamicsEnabled(using Context): Boolean = enabled(nme.dynamics)
6466

65-
def dependentEnabled(using Context) = enabled(Xdependent)
66-
67-
def namedTypeArgsEnabled(using Context) = enabled(XnamedTypeArguments)
67+
def dependentEnabled(using Context) = enabled(dependent)
6868

69-
def genericNumberLiteralsEnabled(using Context) = enabled(XgenericNumberLiterals)
69+
def namedTypeArgsEnabled(using Context) = enabled(namedTypeArguments)
7070

71-
def symbolLiteralsEnabled(using Context) = enabled(symbolLiterals)
71+
def genericNumberLiteralsEnabled(using Context) = enabled(genericNumberLiterals)
7272

73-
def scala2ExperimentalMacroEnabled(using Context) = enabled(Xmacros)
73+
def scala2ExperimentalMacroEnabled(using Context) = enabled(scala2macros)
7474

7575
def sourceVersionSetting(using Context): SourceVersion =
7676
SourceVersion.valueOf(ctx.settings.source.value)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings {
227227
// Extremely experimental language features
228228
val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting("-Yno-kind-polymorphism", "Disable kind polymorphism.")
229229
val YexplicitNulls: Setting[Boolean] = BooleanSetting("-Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.")
230-
val YerasedTerms: Setting[Boolean] = BooleanSetting("-Yerased-terms", "Allows the use of erased terms.")
231230
val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects")
232231
val YrequireTargetName: Setting[Boolean] = BooleanSetting("-Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation")
232+
val YerasedTerms: Setting[Boolean] = BooleanSetting("-Yerased-terms", "(disabled, use -language:experimental.erasedDefinitions instead)")
233233

234234
/** Area-specific debug output */
235235
val YexplainLowlevel: Setting[Boolean] = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.")

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ object Flags {
360360
/** An export forwarder */
361361
val (Exported @ _, _, _) = newFlags(41, "exported")
362362

363-
/** Labeled with `erased` modifier (erased value) */
364-
val (_, Erased @ _, _) = newFlags(42, "erased")
363+
/** Labeled with `erased` modifier (erased value or class) */
364+
val (Erased @ _, _, _) = newFlags(42, "erased")
365365

366366
/** An opaque type alias or a class containing one */
367367
val (Opaque @ _, _, _) = newFlags(43, "opaque")
@@ -439,13 +439,13 @@ object Flags {
439439

440440
/** Flags representing source modifiers */
441441
private val CommonSourceModifierFlags: FlagSet =
442-
commonFlags(Private, Protected, Final, Case, Implicit, Given, Override, JavaStatic, Transparent)
442+
commonFlags(Private, Protected, Final, Case, Implicit, Given, Override, JavaStatic, Transparent, Erased)
443443

444444
val TypeSourceModifierFlags: FlagSet =
445445
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque | Open
446446

447447
val TermSourceModifierFlags: FlagSet =
448-
CommonSourceModifierFlags.toTermFlags | Inline | AbsOverride | Lazy | Erased
448+
CommonSourceModifierFlags.toTermFlags | Inline | AbsOverride | Lazy
449449

450450
/** Flags representing modifiers that can appear in trees */
451451
val ModifierFlags: FlagSet =
@@ -515,12 +515,12 @@ object Flags {
515515
val RetainedModuleValAndClassFlags: FlagSet =
516516
AccessFlags | Package | Case |
517517
Synthetic | JavaDefined | JavaStatic | Artifact |
518-
Lifted | MixedIn | Specialized | ConstructorProxy | Invisible
518+
Lifted | MixedIn | Specialized | ConstructorProxy | Invisible | Erased
519519

520520
/** Flags that can apply to a module val */
521521
val RetainedModuleValFlags: FlagSet = RetainedModuleValAndClassFlags |
522522
Override | Final | Method | Implicit | Given | Lazy |
523-
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Erased | Transparent
523+
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Transparent
524524

525525
/** Flags that can apply to a module class */
526526
val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags | Enum

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ object StdNames {
466466
val equalsNumNum : N = "equalsNumNum"
467467
val equalsNumObject : N = "equalsNumObject"
468468
val equals_ : N = "equals"
469+
val erased: N = "erased"
469470
val error: N = "error"
470471
val eval: N = "eval"
471472
val eqlAny: N = "eqlAny"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,10 +729,10 @@ class TreePickler(pickler: TastyPickler) {
729729
if flags.is(Transparent) then writeModTag(TRANSPARENT)
730730
if flags.is(Infix) then writeModTag(INFIX)
731731
if flags.is(Invisible) then writeModTag(INVISIBLE)
732+
if (flags.is(Erased)) writeModTag(ERASED)
732733
if (isTerm) {
733734
if (flags.is(Implicit)) writeModTag(IMPLICIT)
734735
if (flags.is(Given)) writeModTag(GIVEN)
735-
if (flags.is(Erased)) writeModTag(ERASED)
736736
if (flags.is(Lazy, butNot = Module)) writeModTag(LAZY)
737737
if (flags.is(AbsOverride)) { writeModTag(ABSTRACT); writeModTag(OVERRIDE) }
738738
if (flags.is(Mutable)) writeModTag(MUTABLE)

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import util.Chars
2828
import scala.annotation.{tailrec, switch}
2929
import rewrites.Rewrites.{patch, overlapsPatch}
3030
import reporting._
31-
import config.Feature.{sourceVersion, migrateTo3, dependentEnabled, symbolLiteralsEnabled}
31+
import config.Feature
32+
import config.Feature.{sourceVersion, migrateTo3}
3233
import config.SourceVersion._
3334
import config.SourceVersion
3435

@@ -179,6 +180,7 @@ object Parsers {
179180

180181
def isIdent = in.isIdent
181182
def isIdent(name: Name) = in.isIdent(name)
183+
def isErased = isIdent(nme.erased) && in.erasedEnabled
182184
def isSimpleLiteral =
183185
simpleLiteralTokens.contains(in.token)
184186
|| isIdent(nme.raw.MINUS) && numericLitTokens.contains(in.lookahead.token)
@@ -446,19 +448,18 @@ object Parsers {
446448
* Parameters appear in reverse order.
447449
*/
448450
var placeholderParams: List[ValDef] = Nil
449-
var languageImportContext: Context = ctx
450451

451452
def checkNoEscapingPlaceholders[T](op: => T): T =
452453
val savedPlaceholderParams = placeholderParams
453-
val savedLanguageImportContext = languageImportContext
454+
val savedLanguageImportContext = in.languageImportContext
454455
placeholderParams = Nil
455456
try op
456457
finally
457458
placeholderParams match
458459
case vd :: _ => syntaxError(UnboundPlaceholderParameter(), vd.span)
459460
case _ =>
460461
placeholderParams = savedPlaceholderParams
461-
languageImportContext = savedLanguageImportContext
462+
in.languageImportContext = savedLanguageImportContext
462463

463464
def isWildcard(t: Tree): Boolean = t match {
464465
case Ident(name1) => placeholderParams.nonEmpty && name1 == placeholderParams.head.name
@@ -1141,7 +1142,7 @@ object Parsers {
11411142
Quote(t)
11421143
}
11431144
else
1144-
if !symbolLiteralsEnabled(using languageImportContext) then
1145+
if !in.featureEnabled(Feature.symbolLiterals) then
11451146
report.errorOrMigrationWarning(
11461147
em"""symbol literal '${in.name} is no longer supported,
11471148
|use a string literal "${in.name}" or an application Symbol("${in.name}") instead,
@@ -1374,7 +1375,7 @@ object Parsers {
13741375
functionRest(Nil)
13751376
}
13761377
else {
1377-
imods = modifiers(funTypeArgMods)
1378+
if isErased then imods = addModifier(imods)
13781379
val paramStart = in.offset
13791380
val ts = funArgType() match {
13801381
case Ident(name) if name != tpnme.WILDCARD && in.token == COLON =>
@@ -1572,7 +1573,7 @@ object Parsers {
15721573
typeIdent()
15731574
else
15741575
def singletonArgs(t: Tree): Tree =
1575-
if in.token == LPAREN && dependentEnabled(using languageImportContext)
1576+
if in.token == LPAREN && in.featureEnabled(Feature.dependent)
15761577
then singletonArgs(AppliedTypeTree(t, inParens(commaSeparated(singleton))))
15771578
else t
15781579
singletonArgs(simpleType1())
@@ -1861,7 +1862,7 @@ object Parsers {
18611862

18621863
def expr(location: Location): Tree = {
18631864
val start = in.offset
1864-
def isSpecialClosureStart = in.lookahead.token == ERASED
1865+
def isSpecialClosureStart = in.lookahead.isIdent(nme.erased) && in.erasedEnabled
18651866
if in.token == IMPLICIT then
18661867
closure(start, location, modifiers(BitSet(IMPLICIT)))
18671868
else if in.token == LPAREN && isSpecialClosureStart then
@@ -2093,7 +2094,7 @@ object Parsers {
20932094
Nil
20942095
else
20952096
var mods1 = mods
2096-
if in.token == ERASED then mods1 = addModifier(mods1)
2097+
if isErased then mods1 = addModifier(mods1)
20972098
try
20982099
commaSeparated(() => binding(mods1))
20992100
finally
@@ -2684,14 +2685,14 @@ object Parsers {
26842685
case FINAL => Mod.Final()
26852686
case IMPLICIT => Mod.Implicit()
26862687
case GIVEN => Mod.Given()
2687-
case ERASED => Mod.Erased()
26882688
case LAZY => Mod.Lazy()
26892689
case OVERRIDE => Mod.Override()
26902690
case PRIVATE => Mod.Private()
26912691
case PROTECTED => Mod.Protected()
26922692
case SEALED => Mod.Sealed()
26932693
case IDENTIFIER =>
26942694
name match {
2695+
case nme.erased if in.erasedEnabled => Mod.Erased()
26952696
case nme.inline => Mod.Inline()
26962697
case nme.opaque => Mod.Opaque()
26972698
case nme.open => Mod.Open()
@@ -2775,8 +2776,6 @@ object Parsers {
27752776
normalize(loop(start))
27762777
}
27772778

2778-
val funTypeArgMods: BitSet = BitSet(ERASED)
2779-
27802779
/** Wrap annotation or constructor in New(...).<init> */
27812780
def wrapNew(tpt: Tree): Select = Select(New(tpt), nme.CONSTRUCTOR)
27822781

@@ -2899,10 +2898,13 @@ object Parsers {
28992898
def addParamMod(mod: () => Mod) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
29002899

29012900
def paramMods() =
2902-
if in.token == IMPLICIT then addParamMod(() => Mod.Implicit())
2901+
if in.token == IMPLICIT then
2902+
addParamMod(() => Mod.Implicit())
29032903
else
2904-
if isIdent(nme.using) then addParamMod(() => Mod.Given())
2905-
if in.token == ERASED then addParamMod(() => Mod.Erased())
2904+
if isIdent(nme.using) then
2905+
addParamMod(() => Mod.Given())
2906+
if isErased then
2907+
addParamMod(() => Mod.Erased())
29062908

29072909
def param(): ValDef = {
29082910
val start = in.offset
@@ -2959,7 +2961,7 @@ object Parsers {
29592961
if in.token == RPAREN && !prefix && !impliedMods.is(Given) then Nil
29602962
else
29612963
val clause =
2962-
if prefix && !isIdent(nme.using) then param() :: Nil
2964+
if prefix && !isIdent(nme.using) && !isIdent(nme.erased) then param() :: Nil
29632965
else
29642966
paramMods()
29652967
if givenOnly && !impliedMods.is(Given) then
@@ -3032,7 +3034,7 @@ object Parsers {
30323034
def mkImport(outermost: Boolean = false): ImportConstr = (tree, selectors) =>
30333035
val imp = Import(tree, selectors)
30343036
if isLanguageImport(tree) then
3035-
languageImportContext = languageImportContext.importContext(imp, NoSymbol)
3037+
in.languageImportContext = in.languageImportContext.importContext(imp, NoSymbol)
30363038
for
30373039
case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors
30383040
if allSourceVersionNames.contains(imported)

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import scala.annotation.{switch, tailrec}
1717
import scala.collection.mutable
1818
import scala.collection.immutable.{SortedMap, BitSet}
1919
import rewrites.Rewrites.patch
20+
import config.Feature
2021
import config.Feature.migrateTo3
2122
import config.SourceVersion._
2223
import reporting.Message
@@ -185,6 +186,13 @@ object Scanners {
185186
error(s"illegal combination of -rewrite targets: ${enabled(0).name} and ${enabled(1).name}")
186187
}
187188

189+
private var myLanguageImportContext: Context = ctx
190+
def languageImportContext = myLanguageImportContext
191+
final def languageImportContext_=(c: Context) = myLanguageImportContext = c
192+
193+
def featureEnabled(name: TermName) = Feature.enabled(name)(using languageImportContext)
194+
def erasedEnabled = featureEnabled(Feature.erasedDefinitions) || ctx.settings.YerasedTerms.value
195+
188196
/** All doc comments kept by their end position in a `Map`.
189197
*
190198
* Note: the map is necessary since the comments are looked up after an
@@ -215,8 +223,7 @@ object Scanners {
215223
private val commentBuf = CharBuffer()
216224

217225
private def handleMigration(keyword: Token): Token =
218-
if keyword == ERASED && !ctx.settings.YerasedTerms.value then IDENTIFIER
219-
else if scala3keywords.contains(keyword) && migrateTo3 then treatAsIdent()
226+
if scala3keywords.contains(keyword) && migrateTo3 then treatAsIdent()
220227
else keyword
221228

222229
private def treatAsIdent(): Token =
@@ -907,7 +914,9 @@ object Scanners {
907914
reset()
908915
next
909916

910-
class LookaheadScanner() extends Scanner(source, offset)
917+
class LookaheadScanner() extends Scanner(source, offset) {
918+
override def languageImportContext = Scanner.this.languageImportContext
919+
}
911920

912921
/** Skip matching pairs of `(...)` or `[...]` parentheses.
913922
* @pre The current token is `(` or `[`
@@ -1009,14 +1018,17 @@ object Scanners {
10091018
}
10101019

10111020
def isSoftModifier: Boolean =
1012-
token == IDENTIFIER && softModifierNames.contains(name)
1021+
token == IDENTIFIER
1022+
&& (softModifierNames.contains(name) || name == nme.erased && erasedEnabled)
10131023

10141024
def isSoftModifierInModifierPosition: Boolean =
10151025
isSoftModifier && inModifierPosition()
10161026

10171027
def isSoftModifierInParamModifierPosition: Boolean =
10181028
isSoftModifier && lookahead.token != COLON
10191029

1030+
def isErased: Boolean = isIdent(nme.erased) && erasedEnabled
1031+
10201032
def canStartStatTokens =
10211033
if migrateTo3 then canStartStatTokens2 else canStartStatTokens3
10221034

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ abstract class TokensCommon {
9595
//final val THEN = 60; enter(THEN, "then")
9696
//final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
9797
//final val ENUM = 62; enter(ENUM, "enum")
98-
//final val ERASED = 63; enter(ERASED, "erased")
9998

10099
/** special symbols */
101100
final val COMMA = 70; enter(COMMA, "','")
@@ -181,10 +180,9 @@ object Tokens extends TokensCommon {
181180
final val THEN = 60; enter(THEN, "then")
182181
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
183182
final val ENUM = 62; enter(ENUM, "enum")
184-
final val ERASED = 63; enter(ERASED, "erased")
185-
final val GIVEN = 64; enter(GIVEN, "given")
186-
final val EXPORT = 65; enter(EXPORT, "export")
187-
final val MACRO = 67; enter(MACRO, "macro") // TODO: remove
183+
final val GIVEN = 63; enter(GIVEN, "given")
184+
final val EXPORT = 64; enter(EXPORT, "export")
185+
final val MACRO = 65; enter(MACRO, "macro") // TODO: remove
188186

189187
/** special symbols */
190188
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -240,8 +238,7 @@ object Tokens extends TokensCommon {
240238

241239
final val defIntroTokens: TokenSet = templateIntroTokens | dclIntroTokens
242240

243-
final val localModifierTokens: TokenSet = BitSet(
244-
ABSTRACT, FINAL, SEALED, IMPLICIT, LAZY, ERASED)
241+
final val localModifierTokens: TokenSet = BitSet(ABSTRACT, FINAL, SEALED, IMPLICIT, LAZY)
245242

246243
final val accessModifierTokens: TokenSet = BitSet(
247244
PRIVATE, PROTECTED)
@@ -251,7 +248,7 @@ object Tokens extends TokensCommon {
251248

252249
final val modifierTokensOrCase: TokenSet = modifierTokens | BitSet(CASE)
253250

254-
final val modifierFollowers = modifierTokens | defIntroTokens
251+
final val modifierFollowers = modifierTokensOrCase | defIntroTokens
255252

256253
/** Is token only legal as start of statement (eof also included)? */
257254
final val mustStartStatTokens: TokenSet = defIntroTokens | modifierTokens | BitSet(IMPORT, EXPORT, PACKAGE)
@@ -283,7 +280,7 @@ object Tokens extends TokensCommon {
283280
*/
284281
final val startParamTokens: BitSet = modifierTokens | BitSet(VAL, VAR, AT)
285282

286-
final val scala3keywords = BitSet(ENUM, ERASED, GIVEN)
283+
final val scala3keywords = BitSet(ENUM, GIVEN)
287284

288285
final val endMarkerTokens = identifierTokens | BitSet(IF, WHILE, FOR, MATCH, TRY, NEW, THROW, GIVEN, VAL, THIS)
289286

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
925925
else PrintableFlags(isType)
926926
if (homogenizedView && mods.flags.isTypeFlags) flagMask &~= GivenOrImplicit // drop implicit/given from classes
927927
val rawFlags = if (sym.exists) sym.flags else mods.flags
928-
if (rawFlags.is(Param)) flagMask = flagMask &~ Given
928+
if (rawFlags.is(Param)) flagMask = flagMask &~ Given &~ Erased
929929
val flags = rawFlags & flagMask
930930
var flagsText = toTextFlags(sym, flags)
931931
val annotations =

0 commit comments

Comments
 (0)