From 54fab4d0199d6eb950e3305b36b9c3ec0e8ed75f Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Tue, 8 May 2018 11:08:38 +0200 Subject: [PATCH 1/2] 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. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 8 +++++++- tests/neg/parser-stability-25.scala | 15 +++++++++++++++ tests/neg/parser-stability-26.scala | 2 ++ tests/neg/parser-stability-27.scala | 2 ++ tests/pos/singleton-fun-types.scala | 4 ++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/neg/parser-stability-25.scala create mode 100644 tests/neg/parser-stability-26.scala create mode 100644 tests/neg/parser-stability-27.scala create mode 100644 tests/pos/singleton-fun-types.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 03d33f330927..fab1ed966237 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1593,7 +1593,13 @@ class Typer extends Namer val seenParents = mutable.Set[Symbol]() def typedParent(tree: untpd.Tree): Tree = { - var result = if (tree.isType) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) + @tailrec + def isTreeType(t: untpd.Tree): Boolean = t match { + case _: untpd.Function => true + case untpd.Parens(t1) => isTreeType(t1) + case _ => tree.isType + } + var result = if (isTreeType(tree)) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) val psym = result.tpe.dealias.typeSymbol if (seenParents.contains(psym) && !cls.isRefinementClass) { if (!ctx.isAfterTyper) ctx.error(i"$psym is extended twice", tree.sourcePos) diff --git a/tests/neg/parser-stability-25.scala b/tests/neg/parser-stability-25.scala new file mode 100644 index 000000000000..23db4498af0e --- /dev/null +++ b/tests/neg/parser-stability-25.scala @@ -0,0 +1,15 @@ +class A extends (Int => i1) // error +class B extends (Int => this) // error +trait C { + val bar: Int => this // error +} + +// Test that function types ending in SIP-23 singleton types are understood correctly. + +class D extends (Int => 1) { + def apply(x: Int) = 2 // error +} + +class Wrap(x: Int) +class E extends (Wrap)( // error +// error \ No newline at end of file diff --git a/tests/neg/parser-stability-26.scala b/tests/neg/parser-stability-26.scala new file mode 100644 index 000000000000..dd2c00d5c5b9 --- /dev/null +++ b/tests/neg/parser-stability-26.scala @@ -0,0 +1,2 @@ +// Test that function types ending in SIP-23 singleton types are understood correctly. +class E extends (Int => 1) // error diff --git a/tests/neg/parser-stability-27.scala b/tests/neg/parser-stability-27.scala new file mode 100644 index 000000000000..ed841d95c08b --- /dev/null +++ b/tests/neg/parser-stability-27.scala @@ -0,0 +1,2 @@ +class F extends (Int => 1)( // error +// error \ No newline at end of file diff --git a/tests/pos/singleton-fun-types.scala b/tests/pos/singleton-fun-types.scala new file mode 100644 index 000000000000..dd2f8525c9c4 --- /dev/null +++ b/tests/pos/singleton-fun-types.scala @@ -0,0 +1,4 @@ +trait C extends (Int => 1) +class D extends (Int => 1) { + def apply(x: Int) = 1 +} From 2732c6b3d58b11a1ba563357df56524d56428961 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Tue, 15 Jan 2019 20:46:56 +0100 Subject: [PATCH 2/2] Address review comments and use alternative fix --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fab1ed966237..4fbeb406351d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1593,11 +1593,9 @@ class Typer extends Namer val seenParents = mutable.Set[Symbol]() def typedParent(tree: untpd.Tree): Tree = { - @tailrec def isTreeType(t: untpd.Tree): Boolean = t match { - case _: untpd.Function => true - case untpd.Parens(t1) => isTreeType(t1) - case _ => tree.isType + case _: untpd.Apply => false + case _ => true } var result = if (isTreeType(tree)) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) val psym = result.tpe.dealias.typeSymbol