From 7bc7c9ba5e04b9a17ed7d548f3ea8caf7bd8c4a7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 29 May 2015 14:14:28 +0200 Subject: Fix compilation failure by refining adaptation of constants Constants that are adapted to a different supertype need to do this explicitly (not just by changing the type). Otherwise tree checkers will compute the original type and fail. This caused a test failure in pos/harmonize. The mystery is why this was not caught in the checkin tests. --- src/dotty/tools/dotc/typer/Typer.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/dotty/tools/dotc/typer/Typer.scala') diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index ea19dd1c9..acf4f3845 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1337,10 +1337,22 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } + /** Adapt an expression of constant type to a different constant type `tpe`. */ + def adaptConstant(tree: Tree, tpe: ConstantType): Tree = { + def lit = Literal(tpe.value).withPos(tree.pos) + tree match { + case Literal(c) => lit + case tree @ Block(stats, expr) => tpd.cpy.Block(tree)(stats, adaptConstant(expr, tpe)) + case tree => + if (isIdempotentExpr(tree)) lit // See discussion in phase Literalize why we demand isIdempotentExpr + else Block(tree :: Nil, lit) + } + } + def adaptToSubType(wtp: Type): Tree = { // try converting a constant to the target type val folded = ConstFold(tree, pt) - if (folded ne tree) return folded + if (folded ne tree) return adaptConstant(folded, folded.tpe.asInstanceOf[ConstantType]) // drop type if prototype is Unit if (pt isRef defn.UnitClass) return tpd.Block(tree :: Nil, Literal(Constant(()))) -- cgit v1.2.3