@@ -311,9 +311,9 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
311311 import tpd ._
312312
313313 /** The purity level of this statement.
314- * @return pure if statement has no side effects
315- * idempotent if running the statement a second time has no side effects
316- * impure otherwise
314+ * @return Pure if statement has no side effects
315+ * Idempotent if running the statement a second time has no side effects
316+ * Impure otherwise
317317 */
318318 private def statPurity (tree : Tree )(implicit ctx : Context ): PurityLevel = unsplice(tree) match {
319319 case EmptyTree
@@ -322,17 +322,18 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
322322 | DefDef (_, _, _, _, _) =>
323323 Pure
324324 case vdef @ ValDef (_, _, _) =>
325- if (vdef.symbol.flags is Mutable ) Impure else exprPurity(vdef.rhs)
325+ if (vdef.symbol.flags is Mutable ) Impure else exprPurity(vdef.rhs) `min` Pure
326326 case _ =>
327327 Impure
328328 // TODO: It seem like this should be exprPurity(tree)
329329 // But if we do that the repl/vars test break. Need to figure out why that's the case.
330330 }
331331
332332 /** The purity level of this expression.
333- * @return pure if expression has no side effects
334- * idempotent if running the expression a second time has no side effects
335- * impure otherwise
333+ * @return SimplyPure if expression has no side effects and cannot contain local definitions
334+ * Pure if expression has no side effects
335+ * Idempotent if running the expression a second time has no side effects
336+ * Impure otherwise
336337 *
337338 * Note that purity and idempotency are different. References to modules and lazy
338339 * vals are impure (side-effecting) both because side-effecting code may be executed and because the first reference
@@ -345,7 +346,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
345346 | Super (_, _)
346347 | Literal (_)
347348 | Closure (_, _, _) =>
348- Pure
349+ SimplyPure
349350 case Ident (_) =>
350351 refPurity(tree)
351352 case Select (qual, _) =>
@@ -366,7 +367,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
366367 if (args.isEmpty && fn.symbol.is(Stable )) exprPurity(fn)
367368 else if (tree.tpe.isInstanceOf [ConstantType ] && isKnownPureOp(tree.symbol))
368369 // A constant expression with pure arguments is pure.
369- minOf(exprPurity(fn), args.map(exprPurity))
370+ minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
370371 else Impure
371372 case Typed (expr, _) =>
372373 exprPurity(expr)
@@ -382,25 +383,26 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
382383
383384 private def minOf (l0 : PurityLevel , ls : List [PurityLevel ]) = (l0 /: ls)(_ min _)
384385
385- def isPureExpr (tree : Tree )(implicit ctx : Context ) = exprPurity(tree) == Pure
386+ def isSimplyPure (tree : Tree )(implicit ctx : Context ) = exprPurity(tree) == SimplyPure
387+ def isPureExpr (tree : Tree )(implicit ctx : Context ) = exprPurity(tree) >= Pure
386388 def isIdempotentExpr (tree : Tree )(implicit ctx : Context ) = exprPurity(tree) >= Idempotent
387389
388390 /** The purity level of this reference.
389391 * @return
390- * pure if reference is (nonlazy and stable) or to a parameterized function
391- * idempotent if reference is lazy and stable
392- * impure otherwise
392+ * SimplyPure if reference is (nonlazy and stable) or to a parameterized function
393+ * Idempotent if reference is lazy and stable
394+ * Impure otherwise
393395 * @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
394396 * flags set.
395397 */
396398 private def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel =
397- if (! tree.tpe.widen.isParameterless) Pure
399+ if (! tree.tpe.widen.isParameterless) SimplyPure
398400 else if (! tree.symbol.isStable) Impure
399401 else if (tree.symbol.is(Lazy )) Idempotent // TODO add Module flag, sinxce Module vals or not Lazy from the start.
400- else Pure
402+ else SimplyPure
401403
402404 def isPureRef (tree : Tree )(implicit ctx : Context ) =
403- refPurity(tree) == Pure
405+ refPurity(tree) == SimplyPure
404406 def isIdempotentRef (tree : Tree )(implicit ctx : Context ) =
405407 refPurity(tree) >= Idempotent
406408
@@ -554,6 +556,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
554556 val acc = new TreeAccumulator [List [Symbol ]] {
555557 def apply (syms : List [Symbol ], tree : Tree )(implicit ctx : Context ) = tree match {
556558 case Bind (_, body) => apply(tree.symbol :: syms, body)
559+ case Annotated (tree, id @ Ident (tpnme.BOUNDTYPE_ANNOT )) => apply(id.symbol :: syms, tree)
557560 case _ => foldOver(syms, tree)
558561 }
559562 }
@@ -724,6 +727,7 @@ object TreeInfo {
724727 def min (that : PurityLevel ) = new PurityLevel (x min that.x)
725728 }
726729
730+ val SimplyPure = new PurityLevel (3 )
727731 val Pure = new PurityLevel (2 )
728732 val Idempotent = new PurityLevel (1 )
729733 val Impure = new PurityLevel (0 )
0 commit comments