@@ -449,7 +449,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
449
449
def isIdempotentRef (tree : Tree )(implicit ctx : Context ): Boolean =
450
450
refPurity(tree) >= Idempotent
451
451
452
- /** If `tree` is a constant expression, its value as a Literal,
452
+ /** (1) If `tree` is a constant expression, its value as a Literal,
453
453
* or `tree` itself otherwise.
454
454
*
455
455
* Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
@@ -485,11 +485,27 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
485
485
* Ident
486
486
* Select
487
487
* TypeApply
488
+ *
489
+ * (2) A primitive unary operator expression `pre.op` where `op` is one of `+`, `-`, `~`, `!`
490
+ * that has a constant type `ConstantType(v)` but that is not a constant expression
491
+ * (i.e. `pre` has side-effects) is translated to
492
+ *
493
+ * { pre; v }
494
+ *
495
+ * This avoids the situation where we have a Select node that does not have a symbol.
488
496
*/
489
497
def constToLiteral (tree : Tree )(implicit ctx : Context ): Tree = {
490
498
val tree1 = ConstFold (tree)
491
499
tree1.tpe.widenTermRefExpr match {
492
- case ConstantType (value) if isIdempotentExpr(tree1) => Literal (value)
500
+ case ConstantType (value) =>
501
+ if (isIdempotentExpr(tree1)) Literal (value)
502
+ else tree1 match {
503
+ case Select (qual, _) if tree1.tpe.isInstanceOf [ConstantType ] =>
504
+ // it's a primitive unary operator; Simplify `pre.op` to `{ pre; v }` where `v` is the value of `pre.op`
505
+ Block (qual :: Nil , Literal (value))
506
+ case _ =>
507
+ tree1
508
+ }
493
509
case _ => tree1
494
510
}
495
511
}
0 commit comments