Skip to content

Commit 1ebae87

Browse files
committed
Refactor the way we mark experimental top-level definition
Move similar logic from PostTyper into `checkAndAdaptExperimentalImports`. Also make the message of `@experimental` more precise for experimental language settings.
1 parent b92e62d commit 1ebae87

File tree

7 files changed

+26
-32
lines changed

7 files changed

+26
-32
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,8 @@ object Feature:
170170
ctx.settings.experimental.value ||
171171
experimentalAutoEnableFeatures.exists(enabled)
172172

173-
def isExperimentalEnabledBySetting(using Context): Boolean =
174-
ctx.settings.experimental.value ||
175-
experimentalAutoEnableFeatures.exists(enabledBySetting)
173+
def experimentalEnabledByLanguageSetting(using Context): Option[TermName] =
174+
experimentalAutoEnableFeatures.find(enabledBySetting)
176175

177176
def isExperimentalEnabledByImport(using Context): Boolean =
178177
experimentalAutoEnableFeatures.exists(enabledByImport)

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
417417
)
418418
}
419419
case tree: ValDef =>
420-
annotateExperimental(tree.symbol)
420+
annotateExperimentalCompanion(tree.symbol)
421421
registerIfHasMacroAnnotations(tree)
422422
checkErasedDef(tree)
423423
Checking.checkPolyFunctionType(tree.tpt)
@@ -426,7 +426,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
426426
checkStableSelection(tree.rhs)
427427
processValOrDefDef(super.transform(tree1))
428428
case tree: DefDef =>
429-
annotateExperimental(tree.symbol)
430429
registerIfHasMacroAnnotations(tree)
431430
checkErasedDef(tree)
432431
Checking.checkPolyFunctionType(tree.tpt)
@@ -438,7 +437,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
438437
val sym = tree.symbol
439438
if (sym.isClass)
440439
VarianceChecker.check(tree)
441-
annotateExperimental(sym)
440+
annotateExperimentalCompanion(sym)
442441
checkMacroAnnotation(sym)
443442
if sym.isOneOf(GivenOrImplicit) then
444443
sym.keepAnnotationsCarrying(thisPhase, Set(defn.CompanionClassMetaAnnot), orNoneOf = defn.MetaAnnots)
@@ -584,16 +583,9 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
584583
else if tpe.derivesFrom(defn.NullClass) then
585584
report.error("`erased` definition cannot be implemented with en expression of type Null", tree.srcPos)
586585

587-
private def annotateExperimental(sym: Symbol)(using Context): Unit =
588-
def isTopLevelDefinitionInSource(sym: Symbol) =
589-
!sym.is(Package) && !sym.name.isPackageObjectName &&
590-
(sym.owner.is(Package) || (sym.owner.isPackageObject && !sym.isConstructor))
586+
private def annotateExperimentalCompanion(sym: Symbol)(using Context): Unit =
591587
if sym.is(Module) then
592588
ExperimentalAnnotation.copy(sym.companionClass).foreach(sym.addAnnotation)
593-
if !sym.hasAnnotation(defn.ExperimentalAnnot)
594-
&& Feature.isExperimentalEnabledBySetting && isTopLevelDefinitionInSource(sym)
595-
then
596-
sym.addAnnotation(ExperimentalAnnotation("Added by -experimental or -language:experimental.*", sym.span))
597589

598590
// It needs to run at the phase of the postTyper --- otherwise, the test of the symbols will use
599591
// the transformed denotation with added `Serializable` and `AbstractFunction1`.

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

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -836,20 +836,23 @@ object Checking {
836836
}
837837

838838
if ctx.owner.is(Package) || ctx.owner.name.startsWith(str.REPL_SESSION_LINE) then
839+
def markTopLevelDefsAsExperimental(why: String): Unit =
840+
for tree <- nonExperimentalStats(trees) do
841+
tree match
842+
case tree: MemberDef =>
843+
val sym = tree.symbol
844+
if !sym.isExperimental then
845+
sym.addAnnotation(ExperimentalAnnotation(s"Added by $why", sym.span))
846+
case tree =>
847+
// There is no definition to attach the @experimental annotation
848+
report.error(s"Implementation restriction: top-level `val _ = ...` is not supported with $why.", tree.srcPos)
839849
unitExperimentalLanguageImports match
840-
case imp :: _ =>
841-
// mark all top-level definitions as @experimental
842-
for tree <- nonExperimentalStats(trees) do
843-
tree match
844-
case tree: MemberDef =>
845-
// TODO move this out of checking (into posttyper?)
846-
val sym = tree.symbol
847-
if !sym.isExperimental then
848-
sym.addAnnotation(ExperimentalAnnotation(i"Added by top level $imp", sym.span))
849-
case tree =>
850-
// There is no definition to attach the @experimental annotation
851-
report.error("Implementation restriction: top-level `val _ = ...` is not supported with experimental language imports.", tree.srcPos)
850+
case imp :: _ => markTopLevelDefsAsExperimental(i"top level $imp")
852851
case _ =>
852+
Feature.experimentalEnabledByLanguageSetting match
853+
case Some(sel) => markTopLevelDefsAsExperimental(i"-language:experimental.$sel")
854+
case _ if ctx.settings.experimental.value => markTopLevelDefsAsExperimental(i"-experimental")
855+
case _ =>
853856
else
854857
for imp <- unitExperimentalLanguageImports do
855858
Feature.checkExperimentalFeature("feature local import", imp.srcPos)

tests/neg-macros/i18677-a.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
|The tree does not conform to the compiler's tree invariants.
88
|
99
|Macro was:
10-
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental("Added by -experimental or -language:experimental.*") @extendFoo class AFoo()
10+
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental("Added by -experimental") @extendFoo class AFoo()
1111
|
1212
|The macro returned:
13-
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental("Added by -experimental or -language:experimental.*") @extendFoo class AFoo() extends Foo
13+
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental("Added by -experimental") @extendFoo class AFoo() extends Foo
1414
|
1515
|Error:
1616
|assertion failed: Parents of class symbol differs from the parents in the tree for class AFoo

tests/neg-macros/i18677-b.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
|The tree does not conform to the compiler's tree invariants.
88
|
99
|Macro was:
10-
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental("Added by -experimental or -language:experimental.*") @extendFoo class AFoo()
10+
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental("Added by -experimental") @extendFoo class AFoo()
1111
|
1212
|The macro returned:
13-
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental("Added by -experimental or -language:experimental.*") @extendFoo class AFoo() extends Foo
13+
|@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental("Added by -experimental") @extendFoo class AFoo() extends Foo
1414
|
1515
|Error:
1616
|assertion failed: Parents of class symbol differs from the parents in the tree for class AFoo
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-- Error: tests/neg/experimental-import-with-top-level-val-underscore.scala:4:4 ----------------------------------------
22
4 |val _ = // error
33
| ^
4-
| Implementation restriction: top-level `val _ = ...` is not supported with experimental language imports.
4+
|Implementation restriction: top-level `val _ = ...` is not supported with top level import language.experimental.erasedDefinitions.
55
5 | println("Hello, world!")
66
6 | 42

tests/neg/experimental-message-experimental-flag.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
-- Error: tests/neg/experimental-message-experimental-flag/Test_2.scala:3:10 -------------------------------------------
33
3 |def g() = f() // error
44
| ^
5-
| method f is marked @experimental: Added by -experimental or -language:experimental.*
5+
| method f is marked @experimental: Added by -experimental
66
|
77
| Experimental definition may only be used under experimental mode:
88
| 1. in a definition marked as @experimental, or

0 commit comments

Comments
 (0)