@@ -240,6 +240,35 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
240
240
case y => y
241
241
}
242
242
243
+ /** The largest subset of {NoInits, PureInterface} that a
244
+ * trait or class enclosing this statement can have as flags.
245
+ */
246
+ def defKind (tree : Tree )(implicit ctx : Context ): FlagSet = unsplice(tree) match {
247
+ case EmptyTree | _ : Import => NoInitsInterface
248
+ case tree : TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface
249
+ case tree : DefDef =>
250
+ if (tree.unforcedRhs == EmptyTree &&
251
+ tree.vparamss.forall(_.forall(_.rhs.isEmpty))) NoInitsInterface
252
+ else NoInits
253
+ case tree : ValDef => if (tree.unforcedRhs == EmptyTree ) NoInitsInterface else EmptyFlags
254
+ case _ => EmptyFlags
255
+ }
256
+
257
+ /** The largest subset of {NoInits, PureInterface} that a
258
+ * trait or class with these parents can have as flags.
259
+ */
260
+ def parentsKind (parents : List [Tree ])(implicit ctx : Context ): FlagSet = parents match {
261
+ case Nil => NoInitsInterface
262
+ case Apply (_, _ :: _) :: _ => EmptyFlags
263
+ case _ :: parents1 => parentsKind(parents1)
264
+ }
265
+
266
+ /** The largest subset of {NoInits, PureInterface} that a
267
+ * trait or class with this body can have as flags.
268
+ */
269
+ def bodyKind (body : List [Tree ])(implicit ctx : Context ): FlagSet =
270
+ (NoInitsInterface /: body)((fs, stat) => fs & defKind(stat))
271
+
243
272
/** Checks whether predicate `p` is true for all result parts of this expression,
244
273
* where we zoom into Ifs, Matches, and Blocks.
245
274
*/
@@ -358,6 +387,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
358
387
refPurity(tree)
359
388
case Select (qual, _) =>
360
389
refPurity(tree).min(exprPurity(qual))
390
+ case New (_) =>
391
+ SimplyPure
361
392
case TypeApply (fn, _) =>
362
393
exprPurity(fn)
363
394
/*
@@ -369,13 +400,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
369
400
case Apply (fn, args) =>
370
401
def isKnownPureOp (sym : Symbol ) =
371
402
sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass
372
- // Note: After uncurry, field accesses are represented as Apply(getter, Nil),
373
- // so an Apply can also be pure.
374
- if (args.isEmpty && fn.symbol.is(Stable )) exprPurity(fn)
375
- else if (tree.tpe.isInstanceOf [ConstantType ] && isKnownPureOp(tree.symbol))
376
- // A constant expression with pure arguments is pure.
403
+ if (tree.tpe.isInstanceOf [ConstantType ] && isKnownPureOp(tree.symbol)
404
+ // A constant expression with pure arguments is pure.
405
+ || fn.symbol.isStable)
377
406
minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
378
- else Impure
407
+ else
408
+ Impure
379
409
case Typed (expr, _) =>
380
410
exprPurity(expr)
381
411
case Block (stats, expr) =>
@@ -402,11 +432,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
402
432
* @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
403
433
* flags set.
404
434
*/
405
- def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel =
406
- if (! tree.tpe.widen.isParameterless || tree.symbol.is(Erased )) SimplyPure
407
- else if (! tree.symbol.isStable) Impure
408
- else if (tree.symbol.is(Lazy )) Idempotent // TODO add Module flag, sinxce Module vals or not Lazy from the start.
435
+ def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel = {
436
+ val sym = tree.symbol
437
+ if (! tree.hasType) Impure
438
+ else if (! tree.tpe.widen.isParameterless || sym.is(Erased )) SimplyPure
439
+ else if (! sym.isStable) Impure
440
+ else if (sym.is(Module ))
441
+ if (sym.moduleClass.isNoInitsClass) Pure else Idempotent
442
+ else if (sym.is(Lazy )) Idempotent
409
443
else SimplyPure
444
+ }
410
445
411
446
def isPureRef (tree : Tree )(implicit ctx : Context ) =
412
447
refPurity(tree) == SimplyPure
@@ -623,17 +658,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
623
658
accum(Nil , root)
624
659
}
625
660
626
- /** The largest subset of {NoInits, PureInterface} that a
627
- * trait enclosing this statement can have as flags.
628
- */
629
- def defKind (tree : Tree ): FlagSet = unsplice(tree) match {
630
- case EmptyTree | _ : Import => NoInitsInterface
631
- case tree : TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface
632
- case tree : DefDef => if (tree.unforcedRhs == EmptyTree ) NoInitsInterface else NoInits
633
- case tree : ValDef => if (tree.unforcedRhs == EmptyTree ) NoInitsInterface else EmptyFlags
634
- case _ => EmptyFlags
635
- }
636
-
637
661
/** The top level classes in this tree, including only those module classes that
638
662
* are not a linked class of some other class in the result.
639
663
*/
0 commit comments