Skip to content

Commit 54fab4d

Browse files
committed
Band-aidy fix for ClassCastException on malformed programs
To typecheck ```scala class Foo extends someTree ``` we need to detect correctly if `someTree` should be typechecked as a term or a type; `Int => 1` should be typechecked as a type, even though it looks like a term according to `isTerm`. Really, we shouldn't use isType at all, because the user might write a type in place of a term or viceversa. I think we only want to know this is a constructor call or a type; and maybe we should just let the parser tell us which, since it knows.
1 parent 1947222 commit 54fab4d

File tree

5 files changed

+30
-1
lines changed

5 files changed

+30
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,13 @@ class Typer extends Namer
15931593
val seenParents = mutable.Set[Symbol]()
15941594

15951595
def typedParent(tree: untpd.Tree): Tree = {
1596-
var result = if (tree.isType) typedType(tree)(superCtx) else typedExpr(tree)(superCtx)
1596+
@tailrec
1597+
def isTreeType(t: untpd.Tree): Boolean = t match {
1598+
case _: untpd.Function => true
1599+
case untpd.Parens(t1) => isTreeType(t1)
1600+
case _ => tree.isType
1601+
}
1602+
var result = if (isTreeType(tree)) typedType(tree)(superCtx) else typedExpr(tree)(superCtx)
15971603
val psym = result.tpe.dealias.typeSymbol
15981604
if (seenParents.contains(psym) && !cls.isRefinementClass) {
15991605
if (!ctx.isAfterTyper) ctx.error(i"$psym is extended twice", tree.sourcePos)

tests/neg/parser-stability-25.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class A extends (Int => i1) // error
2+
class B extends (Int => this) // error
3+
trait C {
4+
val bar: Int => this // error
5+
}
6+
7+
// Test that function types ending in SIP-23 singleton types are understood correctly.
8+
9+
class D extends (Int => 1) {
10+
def apply(x: Int) = 2 // error
11+
}
12+
13+
class Wrap(x: Int)
14+
class E extends (Wrap)( // error
15+
// error

tests/neg/parser-stability-26.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Test that function types ending in SIP-23 singleton types are understood correctly.
2+
class E extends (Int => 1) // error

tests/neg/parser-stability-27.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class F extends (Int => 1)( // error
2+
// error

tests/pos/singleton-fun-types.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
trait C extends (Int => 1)
2+
class D extends (Int => 1) {
3+
def apply(x: Int) = 1
4+
}

0 commit comments

Comments
 (0)