Skip to content

Commit 1c03333

Browse files
authored
Merge pull request #5506 from dotty-staging/fix-constfold
Fix #5486: Constant-fold types in TypeAssigner
2 parents d56af69 + 47ebafe commit 1c03333

File tree

8 files changed

+39
-25
lines changed

8 files changed

+39
-25
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Decorators._, DenotTransformers._
1313
import collection.mutable
1414
import util.{Property, SourceFile, NoSource}
1515
import NameKinds.{TempResultName, OuterSelectName}
16+
import typer.ConstFold
1617

1718
import scala.annotation.tailrec
1819
import scala.io.Codec
@@ -525,10 +526,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
525526
tree match {
526527
case tree: Select if qualifier.tpe eq tree.qualifier.tpe =>
527528
tree1.withTypeUnchecked(tree.tpe)
528-
case _ => tree.tpe match {
529-
case tpe: NamedType => tree1.withType(tpe.derivedSelect(qualifier.tpe.widenIfUnstable))
530-
case _ => tree1.withTypeUnchecked(tree.tpe)
531-
}
529+
case _ =>
530+
val tree2 = tree.tpe match {
531+
case tpe: NamedType => tree1.withType(tpe.derivedSelect(qualifier.tpe.widenIfUnstable))
532+
case _ => tree1.withTypeUnchecked(tree.tpe)
533+
}
534+
ConstFold(tree2)
532535
}
533536
}
534537

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Flags._
1616
import Constants._
1717
import Annotations._
1818
import NameKinds._
19+
import typer.ConstFold
1920
import typer.Checking.checkNonCyclic
2021
import util.Positions._
2122
import ast.{TreeTypeMap, Trees, tpd, untpd}
@@ -1004,7 +1005,7 @@ class TreeUnpickler(reader: TastyReader,
10041005
val localCtx =
10051006
if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx
10061007
val qual = readTerm()(localCtx)
1007-
untpd.Select(qual, name).withType(tpf(qual.tpe.widenIfUnstable))
1008+
ConstFold(untpd.Select(qual, name).withType(tpf(qual.tpe.widenIfUnstable)))
10081009
}
10091010

10101011
def readQualId(): (untpd.Ident, TypeRef) = {

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -588,15 +588,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
588588
// add type to term nodes; replace type nodes with their types unless -Yprint-pos is also set.
589589
def tp = tree.typeOpt match {
590590
case tp: TermRef if tree.isInstanceOf[RefTree] && !tp.denot.isOverloaded => tp.underlying
591-
case tp: ConstantType if homogenizedView =>
592-
// constant folded types are forgotten in Tasty, are reconstituted subsequently in FirstTransform.
593-
// Therefore we have to gloss over this when comparing before/after pickling by widening to
594-
// underlying type `T`, or, if expression is a unary primitive operation, to `=> T`.
595-
tree match {
596-
case Select(qual, _) if qual.typeOpt.widen.typeSymbol.isPrimitiveValueClass =>
597-
ExprType(tp.widen)
598-
case _ => tp.widen
599-
}
600591
case tp => tp
601592
}
602593
if (!suppressTypes)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
769769
new ApplyToTyped(tree, fun1, funRef, proto.typedArgs, pt)
770770
else
771771
new ApplyToUntyped(tree, fun1, funRef, proto, pt)(argCtx(tree))
772-
convertNewGenericArray(ConstFold(app.result))
772+
convertNewGenericArray(app.result)
773773
case _ =>
774774
handleUnexpectedFunType(tree, fun1)
775775
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object ConstFold {
1717
import tpd._
1818

1919
/** If tree is a constant operation, replace with result. */
20-
def apply(tree: Tree)(implicit ctx: Context): Tree = finish(tree) {
20+
def apply[T <: Tree](tree: T)(implicit ctx: Context): T = finish(tree) {
2121
tree match {
2222
case Apply(Select(xt, op), yt :: Nil) =>
2323
xt.tpe.widenTermRefExpr match {
@@ -40,18 +40,18 @@ object ConstFold {
4040
/** If tree is a constant value that can be converted to type `pt`, perform
4141
* the conversion.
4242
*/
43-
def apply(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
43+
def apply[T <: Tree](tree: T, pt: Type)(implicit ctx: Context): T =
4444
finish(apply(tree)) {
4545
tree.tpe.widenTermRefExpr match {
4646
case ConstantType(x) => x convertTo pt
4747
case _ => null
4848
}
4949
}
5050

51-
private def finish(tree: Tree)(compX: => Constant)(implicit ctx: Context): Tree =
51+
private def finish[T <: Tree](tree: T)(compX: => Constant)(implicit ctx: Context): T =
5252
try {
5353
val x = compX
54-
if (x ne null) tree withType ConstantType(x)
54+
if (x ne null) tree.withType(ConstantType(x)).asInstanceOf[T]
5555
else tree
5656
} catch {
5757
case _: ArithmeticException => tree // the code will crash at runtime,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ trait TypeAssigner {
291291

292292
case _ => accessibleSelectionType(tree, qual)
293293
}
294-
tree.withType(tp)
294+
ConstFold(tree.withType(tp))
295295
}
296296

297297
def assignType(tree: untpd.New, tpt: Tree)(implicit ctx: Context): New =
@@ -372,7 +372,7 @@ trait TypeAssigner {
372372
case t =>
373373
errorType(err.takesNoParamsStr(fn, ""), tree.pos)
374374
}
375-
tree.withType(ownType)
375+
ConstFold(tree.withType(ownType))
376376
}
377377

378378
def assignType(tree: untpd.TypeApply, fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {

tests/pos/constfold.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
object A {
2-
val x = 2;
3-
val y = x.asInstanceOf[Byte];
4-
val z = 1.0 / 2;
5-
val s = "z is " + z;
2+
val x = 2
3+
val y = x.asInstanceOf[Byte]
4+
val z = 1.0 / 2
5+
val s = "z is " + z
6+
7+
val a = 1 + 1
8+
val b = -(1:1)
9+
val c = -(1:1 & Any)
610
}
711

812
object Test extends App {

tests/pos/inline-constfold.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object Test {
2+
inline def not(x: Boolean) <: Boolean = {
3+
!x
4+
}
5+
6+
final val a = not(true)
7+
val b: false = a
8+
9+
inline def add(x: Int, y: Int) <: Int = {
10+
x + y
11+
}
12+
13+
final val c = add(3, 4)
14+
val d: 7 = c
15+
}

0 commit comments

Comments
 (0)