Skip to content

Commit b888f66

Browse files
committed
Purity checking should take constant expressions into account.
A constant expression with pure arguments is pure. Previously, this was not taken into account, which meant that literalize did not work for constant expressions contiaining primitive operations or String adds.
1 parent af98163 commit b888f66

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,18 +326,26 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
326326
// see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm`
327327
free.symbol.hasStableFlag && isIdempotentExpr(free)
328328
*/
329-
case Apply(fn, Nil) =>
329+
case Apply(fn, args) =>
330+
def isKnownPureOp(sym: Symbol) =
331+
sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass
330332
// Note: After uncurry, field accesses are represented as Apply(getter, Nil),
331333
// so an Apply can also be pure.
332-
if (fn.symbol is Stable) exprPurity(fn) else Impure
334+
if (args.isEmpty && fn.symbol.is(Stable)) exprPurity(fn)
335+
else if (tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol))
336+
// A constant expression with pure arguments is pure.
337+
minOf(exprPurity(fn), args.map(exprPurity))
338+
else Impure
333339
case Typed(expr, _) =>
334340
exprPurity(expr)
335341
case Block(stats, expr) =>
336-
(exprPurity(expr) /: stats.map(statPurity))(_ min _)
342+
minOf(exprPurity(expr), stats.map(statPurity))
337343
case _ =>
338344
Impure
339345
}
340346

347+
private def minOf(l0: PurityLevel, ls: List[PurityLevel]) = (l0 /: ls)(_ min _)
348+
341349
def isPureExpr(tree: tpd.Tree)(implicit ctx: Context) = exprPurity(tree) == Pure
342350
def isIdempotentExpr(tree: tpd.Tree)(implicit ctx: Context) = exprPurity(tree) >= Idempotent
343351

0 commit comments

Comments
 (0)