Skip to content

Commit bdc5b6f

Browse files
committed
Move "is this a value?" check from Typer to Erasure
Doing the check in Typer leads to cyclic errors, and I can't figure out a nice way to do this in any other phase since it requires knowledge about the expected type.
1 parent 98cd179 commit bdc5b6f

File tree

7 files changed

+26
-42
lines changed

7 files changed

+26
-42
lines changed

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ object Erasure {
328328
case _ => tree.symbol.isEffectivelyErased
329329
}
330330

331+
/** Check that Java statics and packages can only be used in selections.
332+
*/
333+
private def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = {
334+
if (!proto.isInstanceOf[SelectionProto] && !proto.isInstanceOf[ApplyingProto]) {
335+
val sym = tree.tpe.termSymbol
336+
// The check is avoided inside Java compilation units because it always fails
337+
// on the singleton type Module.type.
338+
if ((sym is Flags.Package) || (sym.isAllOf(Flags.JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(reporting.diagnostic.messages.JavaSymbolIsNotAValue(sym), tree.sourcePos)
339+
}
340+
tree
341+
}
342+
331343
private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = {
332344
if (!ctx.mode.is(Mode.Type)) {
333345
if (isErased(tree))
@@ -390,7 +402,7 @@ object Erasure {
390402
super.typedLiteral(tree)
391403

392404
override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = {
393-
checkNotErased(super.typedIdent(tree, pt))
405+
checkValue(checkNotErased(super.typedIdent(tree, pt)), pt)
394406
}
395407

396408
/** Type check select nodes, applying the following rewritings exhaustively
@@ -484,7 +496,7 @@ object Erasure {
484496
}
485497
}
486498

487-
checkNotErased(recur(qual1))
499+
checkValue(checkNotErased(recur(qual1)), pt)
488500
}
489501

490502
override def typedThis(tree: untpd.This)(implicit ctx: Context): Tree =

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ class TreeChecker extends Phase with SymTransformer {
263263

264264
override def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = {
265265
val tpdTree = super.typed(tree, pt)
266-
checkIdentNotJavaClass(tpdTree)
266+
if (ctx.erasedTypes)
267+
// Can't be checked in earlier phases since `checkValue` is only run in
268+
// Erasure (because running it in Typer would force too much)
269+
checkIdentNotJavaClass(tpdTree)
267270
tpdTree
268271
}
269272

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

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -594,18 +594,6 @@ trait Checking {
594594
def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit =
595595
Checking.checkNonCyclicInherited(joint, parents, decls, posd)
596596

597-
/** Check that Java statics and packages can only be used in selections.
598-
*/
599-
def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = {
600-
if (!proto.isInstanceOf[SelectionProto] && !proto.isInstanceOf[ApplyingProto]) {
601-
val sym = tree.tpe.termSymbol
602-
// The check is avoided inside Java compilation units because it always fails
603-
// on the singleton type Module.type.
604-
if ((sym is Package) || (sym.isAllOf(JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(JavaSymbolIsNotAValue(sym), tree.sourcePos)
605-
}
606-
tree
607-
}
608-
609597
/** Check that type `tp` is stable. */
610598
def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit =
611599
if (!tp.isStable) ctx.error(ex"$tp is not stable", pos)
@@ -1171,7 +1159,6 @@ trait NoChecking extends ReChecking {
11711159
import tpd._
11721160
override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = info
11731161
override def checkNonCyclicInherited(joint: Type, parents: List[Type], decls: Scope, posd: Positioned)(implicit ctx: Context): Unit = ()
1174-
override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree
11751162
override def checkStable(tp: Type, pos: SourcePosition)(implicit ctx: Context): Unit = ()
11761163
override def checkClassType(tp: Type, pos: SourcePosition, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp
11771164
override def checkImplicitConversionDefOK(sym: Symbol)(implicit ctx: Context): Unit = ()

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,6 @@ class Typer extends Namer
429429
}
430430

431431
checkStableIdentPattern(tree1, pt)
432-
checkValue(tree1, pt)
433432
}
434433

435434
/** Check that a stable identifier pattern is indeed stable (SLS 8.1.5)
@@ -453,7 +452,7 @@ class Typer extends Namer
453452
}
454453
case qual =>
455454
if (tree.name.isTypeName) checkStable(qual.tpe, qual.sourcePos)
456-
val select = checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt)
455+
val select = assignType(cpy.Select(tree)(qual, tree.name), qual)
457456
if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt))
458457
else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select
459458
else typedDynamicSelect(tree, Nil, pt)

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import dotty.tools.dotc.core.Contexts.Context
77
import dotty.tools.dotc.core.Types.WildcardType
88
import dotty.tools.dotc.parsing.Tokens
99
import dotty.tools.dotc.reporting.diagnostic.messages._
10-
import dotty.tools.dotc.transform.{CheckStatic, PostTyper, TailRec}
10+
import dotty.tools.dotc.transform.{CheckStatic, Erasure, PostTyper, TailRec}
1111
import dotty.tools.dotc.typer.{FrontEnd, RefChecks}
1212
import org.junit.Assert._
1313
import org.junit.Test
@@ -1475,22 +1475,6 @@ class ErrorMessagesTests extends ErrorMessagesTest {
14751475
assertEquals("class Object", parentSym.show)
14761476
}
14771477

1478-
@Test def javaSymbolIsNotAValue =
1479-
checkMessagesAfter(CheckStatic.name) {
1480-
"""
1481-
|package p
1482-
|object O {
1483-
| val v = p
1484-
|}
1485-
""".stripMargin
1486-
}.expect { (itcx, messages) =>
1487-
implicit val ctx: Context = itcx
1488-
1489-
assertMessageCount(1, messages)
1490-
val JavaSymbolIsNotAValue(symbol) = messages.head
1491-
assertEquals(symbol.show, "package p")
1492-
}
1493-
14941478
@Test def i3187 =
14951479
checkMessagesAfter(GenBCode.name) {
14961480
"""

tests/fuzzy/parser-stability-15.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package x0
2+
class x0 {
3+
def x1 =
4+
x2 match
5+
]
6+
case x3[] => x0

tests/neg/parser-stability-15.scala

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)