diff --git a/src/dotty/tools/dotc/transform/ElimByName.scala b/src/dotty/tools/dotc/transform/ElimByName.scala index e656c8438958..1d0307398fc3 100644 --- a/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/src/dotty/tools/dotc/transform/ElimByName.scala @@ -76,16 +76,29 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform cpy.Apply(tree)(tree.fun, args1) } - private def becomesFunction(symd: SymDenotation)(implicit ctx: Context) = + /** If denotation had an ExprType before, it now gets a function type */ + private def exprBecomesFunction(symd: SymDenotation)(implicit ctx: Context) = (symd is Param) || (symd is (ParamAccessor, butNot = Method)) - override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = { - val origDenot = originalDenotation(tree) - if (becomesFunction(origDenot) && (origDenot.info.isInstanceOf[ExprType])) + /** Map `tree` to `tree.apply()` is `ftree` was of ExprType and becomes now a function */ + private def applyIfFunction(tree: Tree, ftree: Tree)(implicit ctx: Context) = { + val origDenot = originalDenotation(ftree) + if (exprBecomesFunction(origDenot) && (origDenot.info.isInstanceOf[ExprType])) tree.select(defn.Function0_apply).appliedToNone else tree } + override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = + applyIfFunction(tree, tree) + + override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { + case TypeApply(Select(_, nme.asInstanceOf_), arg :: Nil) => + // tree might be of form e.asInstanceOf[x.type] where x becomes a function. + // See pos/t296.scala + applyIfFunction(tree, arg) + case _ => tree + } + def elimByNameParams(tp: Type)(implicit ctx: Context): Type = tp match { case tp: PolyType => tp.derivedPolyType(tp.paramNames, tp.paramBounds, elimByNameParams(tp.resultType)) @@ -102,6 +115,6 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform } def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = - if (becomesFunction(sym)) transformParamInfo(tp) + if (exprBecomesFunction(sym)) transformParamInfo(tp) else elimByNameParams(tp) } diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index e99a3a91ce35..379a59c0bdd2 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -238,7 +238,7 @@ object Erasure extends TypeTestsCasts{ override def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = { assert(tree.hasType) - val erased = erasedType(tree)(ctx.withPhase(ctx.erasurePhase)) + val erased = erasedType(tree) ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}") tree.withType(erased) } diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 79d86de06789..ccf67b55b9ae 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -209,10 +209,11 @@ trait TypeAssigner { def assignType(tree: untpd.Literal)(implicit ctx: Context) = tree.withType { - tree.const.tag match { + val value = tree.const + value.tag match { case UnitTag => defn.UnitType case NullTag => defn.NullType - case _ => ConstantType(tree.const) + case _ => if (ctx.erasedTypes) value.tpe else ConstantType(value) } } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index aa8cc05524d7..2816224f16d9 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -114,7 +114,7 @@ class tests extends CompilerTest { @Test def dotc_typer = compileDir(dotcDir + "tools/dotc/typer", twice) @Test def dotc_util = compileDir(dotcDir + "tools/dotc/util", twice) @Test def tools_io = compileDir(dotcDir + "tools/io", twice) - @Test def tools = compileDir(dotcDir + "tools", twice)(allowDeepSubtypes) + @Test def tools = compileDir(dotcDir + "tools", "-deep" :: twice)(allowDeepSubtypes) @Test def testNonCyclic = compileArgs(Array( dotcDir + "tools/dotc/CompilationUnit.scala", diff --git a/test/test/CompilerTest.scala b/test/test/CompilerTest.scala index f5b13845434c..c9c7c602bdea 100644 --- a/test/test/CompilerTest.scala +++ b/test/test/CompilerTest.scala @@ -24,8 +24,12 @@ class CompilerTest extends DottyTest { compileDir(Directory(path), args, xerrors) def compileDir(dir: Directory, args: List[String], xerrors: Int)(implicit defaultOptions: List[String]): Unit = { - val fileNames = dir.deepFiles.toArray.map(_.toString).filter(_ endsWith ".scala") - compileArgs(fileNames ++ args, xerrors) + val (files, normArgs) = args match { + case "-deep" :: args1 => (dir.deepFiles, args1) + case _ => (dir.files, args) + } + val fileNames = files.toArray.map(_.toString).filter(_ endsWith ".scala") + compileArgs(fileNames ++ normArgs, xerrors) } def compileFiles(path: String, args: List[String] = Nil)(implicit defaultOptions: List[String]): Unit = { diff --git a/tests/neg/t7093-generics-encoding.scala b/tests/neg/t7093-generics-encoding.scala new file mode 100644 index 000000000000..cea106668f08 --- /dev/null +++ b/tests/neg/t7093-generics-encoding.scala @@ -0,0 +1,34 @@ +// Encoding with type fields of the +// variance test in pos. This time, the +// test does not pass because of the encoding +// This points to a difference between type members +// and parameters which we should investigate further. +object Test2 { + + trait A { + type X + protected[this] def f(x: X): X = x + } + + trait B extends A { + type X <: B + def kaboom = f(new B {}) + } + +// protected[this] disables variance checking +// of the signature of `f`. +// +// C's parent list unifies A[B] with A[C] +// +// The protected[this] loophole is widely used +// in the collections, every newBuilder method +// would fail variance checking otherwise. + class C extends B with A { + type X <: C + override protected[this] def f(c: C) = c + } + +// java.lang.ClassCastException: B$$anon$1 cannot be cast to C +// at C.f(:15) + new C().kaboom +} diff --git a/tests/neg/t7093.scala b/tests/neg/t7093.scala new file mode 100644 index 000000000000..0cf0c658d663 --- /dev/null +++ b/tests/neg/t7093.scala @@ -0,0 +1,13 @@ + +object Test2 { + + trait A { + type X + protected[this] def f(x: X): X = x + } + + trait B extends A { + type X <: B + def kaboom = f(new B {}) + } +} diff --git a/tests/pending/pos/test.scala b/tests/pending/pos/test.scala new file mode 100644 index 000000000000..8139ed3d914f --- /dev/null +++ b/tests/pending/pos/test.scala @@ -0,0 +1,12 @@ +object Test { + + object returns { + + def foo(x: Int): Int = { + return 3 + } + } + +} + + diff --git a/tests/pos/test.scala b/tests/pos/test.scala new file mode 100644 index 000000000000..454686c3d7a7 --- /dev/null +++ b/tests/pos/test.scala @@ -0,0 +1,5 @@ +object Test { + + def foo(x: Int): Int = return 3 + +} diff --git a/tests/pos/trees.scala b/tests/pos/trees.scala new file mode 100644 index 000000000000..27785d248029 --- /dev/null +++ b/tests/pos/trees.scala @@ -0,0 +1,5 @@ +class Tree[T] + +class Empty[T] extends Tree[Nothing] +class Node[T](elem: T, l: Tree[T], r: Tree[T]) +