@@ -449,7 +449,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
449449 def isIdempotentRef (tree : Tree )(implicit ctx : Context ): Boolean =
450450 refPurity(tree) >= Idempotent
451451
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,
453453 * or `tree` itself otherwise.
454454 *
455455 * 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] =>
485485 * Ident
486486 * Select
487487 * 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.
488496 */
489497 def constToLiteral (tree : Tree )(implicit ctx : Context ): Tree = {
490498 val tree1 = ConstFold (tree)
491499 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+ }
493509 case _ => tree1
494510 }
495511 }
0 commit comments