@@ -240,6 +240,35 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
240240 case y => y
241241 }
242242
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+
243272 /** Checks whether predicate `p` is true for all result parts of this expression,
244273 * where we zoom into Ifs, Matches, and Blocks.
245274 */
@@ -298,11 +327,15 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
298327
299328 /** Is `tree` an implicit function or closure, possibly nested in a block? */
300329 def isImplicitClosure (tree : Tree )(implicit ctx : Context ): Boolean = unsplice(tree) match {
330+ case tree : FunctionWithMods => tree.mods.is(Implicit )
301331 case Function ((param : untpd.ValDef ) :: _, _) => param.mods.is(Implicit )
302332 case Closure (_, meth, _) => true
303333 case Block (Nil , expr) => isImplicitClosure(expr)
304- case Block (DefDef (nme.ANON_FUN , _, (param :: _) :: _, _, _) :: Nil , _ : Closure ) =>
305- param.mods.is(Implicit )
334+ case Block (DefDef (nme.ANON_FUN , _, params :: _, _, _) :: Nil , cl : Closure ) =>
335+ params match {
336+ case param :: _ => param.mods.is(Implicit )
337+ case Nil => cl.tpt.eq(untpd.ImplicitEmptyTree ) || defn.isImplicitFunctionType(cl.tpt.typeOpt)
338+ }
306339 case _ => false
307340 }
308341
@@ -354,6 +387,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
354387 refPurity(tree)
355388 case Select (qual, _) =>
356389 refPurity(tree).min(exprPurity(qual))
390+ case New (_) =>
391+ SimplyPure
357392 case TypeApply (fn, _) =>
358393 exprPurity(fn)
359394/*
@@ -365,13 +400,12 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
365400 case Apply (fn, args) =>
366401 def isKnownPureOp (sym : Symbol ) =
367402 sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass
368- // Note: After uncurry, field accesses are represented as Apply(getter, Nil),
369- // so an Apply can also be pure.
370- if (args.isEmpty && fn.symbol.is(Stable )) exprPurity(fn)
371- else if (tree.tpe.isInstanceOf [ConstantType ] && isKnownPureOp(tree.symbol))
372- // 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)
373406 minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
374- else Impure
407+ else
408+ Impure
375409 case Typed (expr, _) =>
376410 exprPurity(expr)
377411 case Block (stats, expr) =>
@@ -398,11 +432,16 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
398432 * @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
399433 * flags set.
400434 */
401- def refPurity (tree : Tree )(implicit ctx : Context ): PurityLevel =
402- if (! tree.tpe.widen.isParameterless || tree.symbol.is(Erased )) SimplyPure
403- else if (! tree.symbol.isStable) Impure
404- 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
405443 else SimplyPure
444+ }
406445
407446 def isPureRef (tree : Tree )(implicit ctx : Context ) =
408447 refPurity(tree) == SimplyPure
@@ -547,6 +586,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
547586 /** An extractor for def of a closure contained the block of the closure. */
548587 object closureDef {
549588 def unapply (tree : Tree ): Option [DefDef ] = tree match {
589+ case Block (Nil , expr) => unapply(expr)
550590 case Block ((meth @ DefDef (nme.ANON_FUN , _, _, _, _)) :: Nil , closure : Closure ) =>
551591 Some (meth)
552592 case _ => None
@@ -618,17 +658,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
618658 accum(Nil , root)
619659 }
620660
621- /** The largest subset of {NoInits, PureInterface} that a
622- * trait enclosing this statement can have as flags.
623- */
624- def defKind (tree : Tree ): FlagSet = unsplice(tree) match {
625- case EmptyTree | _ : Import => NoInitsInterface
626- case tree : TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface
627- case tree : DefDef => if (tree.unforcedRhs == EmptyTree ) NoInitsInterface else NoInits
628- case tree : ValDef => if (tree.unforcedRhs == EmptyTree ) NoInitsInterface else EmptyFlags
629- case _ => EmptyFlags
630- }
631-
632661 /** The top level classes in this tree, including only those module classes that
633662 * are not a linked class of some other class in the result.
634663 */
0 commit comments