Skip to content

Commit dbdd1b3

Browse files
committed
Improve error messages for @experimental on case classes
1 parent c950006 commit dbdd1b3

File tree

3 files changed

+16
-6
lines changed

3 files changed

+16
-6
lines changed

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,16 @@ object Feature:
105105

106106
def checkExperimentalDef(sym: Symbol, srcPos: SrcPos)(using Context) =
107107
if !isExperimentalEnabled then
108-
report.error(i"$sym is marked @experimental and therefore may only be used with a nightly or snapshot version of the compiler", srcPos)
108+
val symMsg =
109+
if sym.hasAnnotation(defn.ExperimentalAnnot) then
110+
i"$sym is marked @experimental"
111+
else if sym.owner.hasAnnotation(defn.ExperimentalAnnot) then
112+
i"${sym.owner} is marked @experimental"
113+
else if sym.owner.companionClass.hasAnnotation(defn.ExperimentalAnnot) then
114+
i"${sym.owner.companionClass} is marked @experimental"
115+
else
116+
i"$sym inherits @experimental"
117+
report.error(s"$symMsg and therefore may only be used with a nightly or snapshot version of the compiler", srcPos)
109118

110119
/** Check that experimental compiler options are only set for snapshot or nightly compiler versions. */
111120
def checkExperimentalSettings(using Context): Unit =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ object SymUtils:
265265
self.eq(defn.ExperimentalAnnot)
266266
|| self.hasAnnotation(defn.ExperimentalAnnot)
267267
|| (self.maybeOwner.isClass && self.owner.hasAnnotation(defn.ExperimentalAnnot))
268+
|| (self.maybeOwner.is(Module) && self.owner.companionClass.isExperimental)
268269

269270
/** The declared self type of this class, as seen from `site`, stripping
270271
* all refinements for opaque types.

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -978,15 +978,15 @@ object RefChecks {
978978
then
979979
Feature.checkExperimentalDef(sym, pos)
980980

981-
private def checkExperimentalTypes(tpe: Type, pos: SrcPos)(using Context): Unit =
981+
private def checkExperimentalSignature(sym: Symbol, pos: SrcPos)(using Context): Unit =
982982
val checker = new TypeTraverser:
983983
def traverse(tp: Type): Unit =
984984
if tp.typeSymbol.isExperimental then
985985
Feature.checkExperimentalDef(tp.typeSymbol, pos)
986986
else
987987
traverseChildren(tp)
988-
if !pos.span.isSynthetic then // avoid double errors
989-
checker.traverse(tpe)
988+
if !sym.owner.isExperimental && !pos.span.isSynthetic then // avoid double errors
989+
checker.traverse(sym.info)
990990

991991
private def checkExperimentalAnnots(sym: Symbol)(using Context): Unit =
992992
for annot <- sym.annotations if annot.symbol.isExperimental && annot.tree.span.exists do
@@ -1230,7 +1230,7 @@ class RefChecks extends MiniPhase { thisPhase =>
12301230
checkNoPrivateOverrides(tree)
12311231
checkDeprecatedOvers(tree)
12321232
checkExperimentalAnnots(tree.symbol)
1233-
checkExperimentalTypes(tree.symbol.info, tree)
1233+
checkExperimentalSignature(tree.symbol, tree)
12341234
val sym = tree.symbol
12351235
if (sym.exists && sym.owner.isTerm) {
12361236
tree.rhs match {
@@ -1252,7 +1252,7 @@ class RefChecks extends MiniPhase { thisPhase =>
12521252
checkNoPrivateOverrides(tree)
12531253
checkDeprecatedOvers(tree)
12541254
checkExperimentalAnnots(tree.symbol)
1255-
checkExperimentalTypes(tree.symbol.info, tree)
1255+
checkExperimentalSignature(tree.symbol, tree)
12561256
checkImplicitNotFoundAnnotation.defDef(tree.symbol.denot)
12571257
tree
12581258
}

0 commit comments

Comments
 (0)