@@ -367,13 +367,19 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
367
367
}
368
368
369
369
/** 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
+ *
371
374
* Pure if expression has no side effects
372
375
* Idempotent if running the expression a second time has no side effects
373
- * Impure otherwise
374
376
*
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
377
383
* takes a different code path than all to follow; but they are idempotent
378
384
* because running the expression a second time gives the cached result.
379
385
*/
@@ -382,12 +388,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
382
388
| This (_)
383
389
| Super (_, _)
384
390
| Literal (_) =>
385
- SimplyPure
391
+ PurePath
386
392
case Ident (_) =>
387
393
refPurity(tree)
388
394
case Select (qual, _) =>
389
395
if (tree.symbol.is(Erased )) Pure
390
- else refPurity(tree). min( exprPurity(qual) )
396
+ else refPurity(tree) ` min` exprPurity(qual)
391
397
case New (_) | Closure (_, _, _) =>
392
398
Pure
393
399
case TypeApply (fn, _) =>
@@ -415,37 +421,38 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
415
421
Impure
416
422
}
417
423
418
- private def minOf (l0 : PurityLevel , ls : List [PurityLevel ]) = (l0 /: ls)(_ min _)
424
+ private def minOf (l0 : PurityLevel , ls : List [PurityLevel ]) = (l0 /: ls)(_ ` min` _)
419
425
420
- def isSimplyPure (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) == SimplyPure
426
+ def isPurePath (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) == PurePath
421
427
def isPureExpr (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= Pure
422
428
def isIdempotentExpr (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= Idempotent
429
+ def isIdempotentPath (tree : Tree )(implicit ctx : Context ): Boolean = exprPurity(tree) >= IdempotentPath
423
430
424
431
def isPureBinding (tree : Tree )(implicit ctx : Context ): Boolean = statPurity(tree) >= Pure
425
432
426
433
/** The purity level of this reference.
427
434
* @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
431
438
* @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
432
439
* flags set.
433
440
*/
434
441
def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel = {
435
442
val sym = tree.symbol
436
443
if (! tree.hasType) Impure
437
- else if (! tree.tpe.widen.isParameterless || sym.isEffectivelyErased) SimplyPure
444
+ else if (! tree.tpe.widen.isParameterless || sym.isEffectivelyErased) PurePath
438
445
else if (! sym.isStableMember) Impure
439
446
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
443
450
}
444
451
445
452
def isPureRef (tree : Tree )(implicit ctx : Context ): Boolean =
446
- refPurity(tree) == SimplyPure
453
+ refPurity(tree) == PurePath
447
454
def isIdempotentRef (tree : Tree )(implicit ctx : Context ): Boolean =
448
- refPurity(tree) >= Idempotent
455
+ refPurity(tree) >= IdempotentPath
449
456
450
457
/** (1) If `tree` is a constant expression, its value as a Literal,
451
458
* or `tree` itself otherwise.
@@ -840,12 +847,15 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
840
847
841
848
object TreeInfo {
842
849
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)
845
852
}
846
853
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 )
849
856
val Idempotent : PurityLevel = new PurityLevel (1 )
850
857
val Impure : PurityLevel = new PurityLevel (0 )
858
+
859
+ val PurePath : PurityLevel = new PurityLevel (7 )
860
+ val IdempotentPath : PurityLevel = new PurityLevel (5 )
851
861
}
0 commit comments