@@ -367,13 +367,19 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
367367 }
368368
369369 /** The purity level of this expression.
370- * @return SimplyPure if expression has no side effects is a path
370+ * @return A possibly combination of
371+ *
372+ * Path if expression is at least idempotent and is a path
373+ *
371374 * Pure if expression has no side effects
372375 * Idempotent if running the expression a second time has no side effects
373- * Impure otherwise
374376 *
375- * Note that purity and idempotency are different. References to modules and lazy
376- * vals are impure (side-effecting) both because side-effecting code may be executed and because the first reference
377+ * Pure implies Idempotent.
378+ * Impure designates the empty combination.
379+ *
380+ * Note that purity and idempotency are treated differently.
381+ * References to modules and lazy vals are impure (side-effecting) both because
382+ * side-effecting code may be executed and because the first reference
377383 * takes a different code path than all to follow; but they are idempotent
378384 * because running the expression a second time gives the cached result.
379385 */
@@ -382,12 +388,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
382388 | This (_)
383389 | Super (_, _)
384390 | Literal (_) =>
385- SimplyPure
391+ PurePath
386392 case Ident (_) =>
387393 refPurity(tree)
388394 case Select (qual, _) =>
389395 if (tree.symbol.is(Erased )) Pure
390- else refPurity(tree). min( exprPurity(qual) )
396+ else refPurity(tree) ` min` exprPurity(qual)
391397 case New (_) | Closure (_, _, _) =>
392398 Pure
393399 case TypeApply (fn, _) =>
@@ -415,37 +421,38 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
415421 Impure
416422 }
417423
418- private def minOf (l0 : PurityLevel , ls : List [PurityLevel ]) = (l0 /: ls)(_ min _)
424+ private def minOf (l0 : PurityLevel , ls : List [PurityLevel ]) = (l0 /: ls)(_ ` min` _)
419425
420- def isSimplyPure (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) == SimplyPure
426+ def isPurePath (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) == PurePath
421427 def isPureExpr (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= Pure
422428 def isIdempotentExpr (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= Idempotent
429+ def isIdempotentPath (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= IdempotentPath
423430
424431 def isPureBinding (tree : Tree )(implicit ctx : Context ): Boolean = statPurity(tree) >= Pure
425432
426433 /** The purity level of this reference.
427434 * @return
428- * SimplyPure if reference is (nonlazy and stable) or to a parameterized function
429- * Idempotent if reference is lazy and stable
430- * Impure otherwise
435+ * PurePath if reference is (nonlazy and stable) or to a parameterized function
436+ * IdempotentPath if reference is lazy and stable
437+ * Impure otherwise
431438 * @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
432439 * flags set.
433440 */
434441 def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel = {
435442 val sym = tree.symbol
436443 if (! tree.hasType) Impure
437- else if (! tree.tpe.widen.isParameterless || sym.isEffectivelyErased) SimplyPure
444+ else if (! tree.tpe.widen.isParameterless || sym.isEffectivelyErased) PurePath
438445 else if (! sym.isStableMember) Impure
439446 else if (sym.is(Module ))
440- if (sym.moduleClass.isNoInitsClass) Pure else Idempotent
441- else if (sym.is(Lazy )) Idempotent
442- else SimplyPure
447+ if (sym.moduleClass.isNoInitsClass) PurePath else IdempotentPath
448+ else if (sym.is(Lazy )) IdempotentPath
449+ else PurePath
443450 }
444451
445452 def isPureRef (tree : Tree )(implicit ctx : Context ): Boolean =
446- refPurity(tree) == SimplyPure
453+ refPurity(tree) == PurePath
447454 def isIdempotentRef (tree : Tree )(implicit ctx : Context ): Boolean =
448- refPurity(tree) >= Idempotent
455+ refPurity(tree) >= IdempotentPath
449456
450457 /** (1) If `tree` is a constant expression, its value as a Literal,
451458 * or `tree` itself otherwise.
@@ -840,12 +847,15 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
840847
841848object TreeInfo {
842849 class PurityLevel (val x : Int ) extends AnyVal {
843- def >= (that : PurityLevel ): Boolean = x > = that.x
844- def min (that : PurityLevel ): PurityLevel = new PurityLevel (x min that.x)
850+ def >= (that : PurityLevel ): Boolean = (x & that.x) = = that.x
851+ def min (that : PurityLevel ): PurityLevel = new PurityLevel (x & that.x)
845852 }
846853
847- val SimplyPure : PurityLevel = new PurityLevel (3 )
848- val Pure : PurityLevel = new PurityLevel (2 )
854+ val Path : PurityLevel = new PurityLevel (4 )
855+ val Pure : PurityLevel = new PurityLevel (3 )
849856 val Idempotent : PurityLevel = new PurityLevel (1 )
850857 val Impure : PurityLevel = new PurityLevel (0 )
858+
859+ val PurePath : PurityLevel = new PurityLevel (7 )
860+ val IdempotentPath : PurityLevel = new PurityLevel (5 )
851861}
0 commit comments