@@ -4,13 +4,12 @@ package transform.localopt
44import core .Constants .Constant
55import core .Contexts .Context
66import core .Flags ._
7- import core .NameOps ._
87import core .Symbols ._
98import core .Types ._
109import ast .Trees ._
1110import scala .collection .mutable
1211import config .Printers .simplify
13- import Simplify .{ desugarIdent , isEffectivelyMutable }
12+ import Simplify ._
1413import transform .SymUtils ._
1514
1615/** Inline vals and remove vals that are aliases to other vals
@@ -164,66 +163,38 @@ class Devalify extends Optimisation {
164163 case _ => t
165164 }
166165
167- def readingOnlyVals (t : Tree )(implicit ctx : Context ): Boolean = {
168- def isGetterOfAImmutableField = t.symbol.isGetter && ! t.symbol.is(Mutable )
169- def isCaseClassWithVar = t.symbol.info.decls.exists(_.is(Mutable ))
170- def isAccessingProductField = t.symbol.exists &&
171- t.symbol.owner.derivesFrom(defn.ProductClass ) &&
172- t.symbol.owner.is(CaseClass ) &&
173- t.symbol.name.isSelectorName &&
174- ! isCaseClassWithVar // Conservatively covers case class A(var x: Int)
175- def isImmutableCaseAccessor = t.symbol.is(CaseAccessor ) && ! t.symbol.is(Mutable )
176-
177- dropCasts(t) match {
178- case Typed (exp, _) => readingOnlyVals(exp)
179-
180- case TypeApply (fun @ Select (rec, _), List (tp)) =>
181- if ((fun.symbol eq defn.Any_asInstanceOf ) && rec.tpe.derivesFrom(tp.tpe.classSymbol))
182- readingOnlyVals(rec)
183- else false
184-
185- case Apply (Select (rec, _), Nil ) =>
186- if (isGetterOfAImmutableField || isAccessingProductField || isImmutableCaseAccessor)
187- readingOnlyVals(rec)
188- else false
189-
190- case Select (rec, _) if t.symbol.is(Method ) =>
191- if (isGetterOfAImmutableField)
192- readingOnlyVals(rec) // Getter of an immutable field
193- else if (isAccessingProductField) {
194- def isImmutableField = {
195- val fieldId = t.symbol.name.toString.drop(1 ).toInt - 1
196- ! t.symbol.owner.caseAccessors(ctx)(fieldId).is(Mutable )
197- }
198- if (isImmutableField) readingOnlyVals(rec) // Accessing a field of a product
199- else false
200- } else if (isImmutableCaseAccessor)
201- readingOnlyVals(rec)
202- else false
203-
204- case t @ Select (qual, _) if ! isEffectivelyMutable(t) =>
205- readingOnlyVals(qual)
206-
207- case t : Ident if ! t.symbol.is(Mutable | Method ) && ! t.symbol.info.dealias.isInstanceOf [ExprType ] =>
208- desugarIdent(t) match {
209- case Some (t) => readingOnlyVals(t)
210- case None => true
211- }
212-
213- case t : This => true
214- // null => false, or the following fails devalify:
215- // trait I {
216- // def foo: Any = null
217- // }
218- // object Main {
219- // def main = {
220- // val s: I = null
221- // s.foo
222- // }
223- // }
224- case Literal (Constant (null )) => false
225- case t : Literal => true
226- case _ => false
227- }
166+ def readingOnlyVals (t : Tree )(implicit ctx : Context ): Boolean = dropCasts(t) match {
167+ case Typed (exp, _) => readingOnlyVals(exp)
168+
169+ case TypeApply (fun @ Select (rec, _), List (tp)) =>
170+ val isAsInstanceOf = fun.symbol == defn.Any_asInstanceOf && rec.tpe.derivesFrom(tp.tpe.classSymbol)
171+ isAsInstanceOf && readingOnlyVals(rec)
172+
173+ case t @ Apply (Select (rec, _), Nil ) =>
174+ isImmutableAccessor(t) && readingOnlyVals(rec)
175+
176+ case t @ Select (rec, _) if t.symbol.is(Method ) =>
177+ isImmutableAccessor(t) && readingOnlyVals(rec)
178+
179+ case t @ Select (qual, _) if ! isEffectivelyMutable(t) =>
180+ readingOnlyVals(qual)
181+
182+ case t : Ident if ! t.symbol.is(Mutable | Method ) && ! t.symbol.info.dealias.isInstanceOf [ExprType ] =>
183+ desugarIdent(t).forall(readingOnlyVals)
184+
185+ case t : This => true
186+ // null => false, or the following fails devalify:
187+ // trait I {
188+ // def foo: Any = null
189+ // }
190+ // object Main {
191+ // def main = {
192+ // val s: I = null
193+ // s.foo
194+ // }
195+ // }
196+ case Literal (Constant (null )) => false
197+ case t : Literal => true
198+ case _ => false
228199 }
229200}
0 commit comments