Skip to content

Commit 2a0479b

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 ca9750b commit 2a0479b

File tree

7 files changed

+26
-32
lines changed

7 files changed

+26
-32
lines changed

Diff for: compiler/src/dotty/tools/dotc/config/Feature.scala

+2-3
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)

Diff for: compiler/src/dotty/tools/dotc/transform/PostTyper.scala

+3-11
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
416416
)
417417
}
418418
case tree: ValDef =>
419-
annotateExperimental(tree.symbol)
419+
annotateExperimentalCompanion(tree.symbol)
420420
registerIfHasMacroAnnotations(tree)
421421
checkErasedDef(tree)
422422
Checking.checkPolyFunctionType(tree.tpt)
@@ -425,7 +425,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
425425
checkStableSelection(tree.rhs)
426426
processValOrDefDef(super.transform(tree1))
427427
case tree: DefDef =>
428-
annotateExperimental(tree.symbol)
429428
registerIfHasMacroAnnotations(tree)
430429
checkErasedDef(tree)
431430
Checking.checkPolyFunctionType(tree.tpt)
@@ -437,7 +436,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
437436
val sym = tree.symbol
438437
if (sym.isClass)
439438
VarianceChecker.check(tree)
440-
annotateExperimental(sym)
439+
annotateExperimentalCompanion(sym)
441440
checkMacroAnnotation(sym)
442441
if sym.isOneOf(GivenOrImplicit) then
443442
sym.keepAnnotationsCarrying(thisPhase, Set(defn.CompanionClassMetaAnnot), orNoneOf = defn.MetaAnnots)
@@ -583,16 +582,9 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
583582
else if tpe.derivesFrom(defn.NullClass) then
584583
report.error("`erased` definition cannot be implemented with en expression of type Null", tree.srcPos)
585584

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

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

Diff for: compiler/src/dotty/tools/dotc/typer/Checking.scala

+15-12
Original file line numberDiff line numberDiff line change
@@ -841,20 +841,23 @@ object Checking {
841841
}
842842

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

Diff for: tests/neg-macros/i18677-a.check

+2-2
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

Diff for: tests/neg-macros/i18677-b.check

+2-2
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
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

Diff for: tests/neg/experimental-message-experimental-flag.check

+1-1
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)