Skip to content

Commit 3d4cdd7

Browse files
OlivierBlanvillainDarkDimius
authored andcommitted
Clean up Simplify
1 parent ecaa6e9 commit 3d4cdd7

File tree

4 files changed

+81
-92
lines changed

4 files changed

+81
-92
lines changed

compiler/src/dotty/tools/dotc/config/CompilerCommand.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
package dotty.tools.dotc
32
package config
43

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ object SymDenotations {
467467
name.toTermName == nme.COMPANION_CLASS_METHOD ||
468468
name.toTermName == nme.COMPANION_MODULE_METHOD
469469

470-
/** Is this a syntetic method that represents conversions between representations of a value class
470+
/** Is this a synthetic method that represents conversions between representations of a value class
471471
* These methods are generated in ExtensionMethods
472472
* and used in ElimErasedValueType.
473473
*/

compiler/src/dotty/tools/dotc/transform/linker/Simplify.scala

Lines changed: 79 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -40,75 +40,6 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
4040
this
4141
}
4242

43-
private def desugarIdent(i: Ident)(implicit ctx: Context): Option[Select] = {
44-
i.tpe match {
45-
case TermRef(prefix: TermRef, name) =>
46-
Some(ref(prefix).select(i.symbol))
47-
case TermRef(prefix: ThisType, name) =>
48-
Some(This(prefix.cls).select(i.symbol))
49-
case _ => None
50-
}
51-
}
52-
53-
private def dropCasts(t: Tree)(implicit ctx: Context): Tree = t match {
54-
// case TypeApply(aio@Select(rec, nm), _) if aio.symbol == defn.Any_asInstanceOf => dropCasts(rec)
55-
case Typed(t, tpe) => t
56-
case _ => t
57-
}
58-
59-
private def readingOnlyVals(t: Tree)(implicit ctx: Context): Boolean = dropCasts(t) match {
60-
case Typed(exp, _) => readingOnlyVals(exp)
61-
case TypeApply(fun @ Select(rec, _), List(tp)) =>
62-
if ((fun.symbol eq defn.Any_asInstanceOf) && rec.tpe.derivesFrom(tp.tpe.classSymbol))
63-
readingOnlyVals(rec)
64-
else false
65-
case Apply(Select(rec, _), Nil) =>
66-
def isGetterOfAImmutableField = t.symbol.isGetter && !t.symbol.is(Flags.Mutable)
67-
def isCaseClassWithVar = t.symbol.info.decls.exists(_.is(Flags.Mutable))
68-
def isAccessingProductField = t.symbol.exists &&
69-
t.symbol.owner.derivesFrom(defn.ProductClass) &&
70-
t.symbol.owner.is(Flags.CaseClass) &&
71-
t.symbol.name.isSelectorName &&
72-
!isCaseClassWithVar // Conservative Covers case class A(var x: Int)
73-
def isImmutableCaseAccessor = t.symbol.is(Flags.CaseAccessor) && !t.symbol.is(Flags.Mutable)
74-
if (isGetterOfAImmutableField || isAccessingProductField || isImmutableCaseAccessor)
75-
readingOnlyVals(rec)
76-
else false
77-
case Select(rec, _) if t.symbol.is(Flags.Method) =>
78-
if (t.symbol.isGetter && !t.symbol.is(Flags.Mutable)) readingOnlyVals(rec) // getter of a immutable field
79-
else if (t.symbol.owner.derivesFrom(defn.ProductClass) && t.symbol.owner.is(Flags.CaseClass) && t.symbol.name.isSelectorName) {
80-
def isImmutableField = {
81-
val fieldId = t.symbol.name.toString.drop(1).toInt - 1
82-
!t.symbol.owner.caseAccessors(ctx)(fieldId).is(Flags.Mutable)
83-
}
84-
if (isImmutableField) readingOnlyVals(rec) // accessing a field of a product
85-
else false
86-
} else if (t.symbol.is(Flags.CaseAccessor) && !t.symbol.is(Flags.Mutable))
87-
readingOnlyVals(rec)
88-
else false
89-
case Select(qual, _) if !t.symbol.is(Flags.Mutable) =>
90-
readingOnlyVals(qual)
91-
case t: Ident if !t.symbol.is(Flags.Mutable) && !t.symbol.is(Flags.Method) && !t.symbol.info.dealias.isInstanceOf[ExprType] =>
92-
desugarIdent(t) match {
93-
case Some(t) => readingOnlyVals(t)
94-
case None => true
95-
}
96-
case t: This => true
97-
// null => false, or the following fails devalify:
98-
// trait I {
99-
// def foo: Any = null
100-
// }
101-
// object Main {
102-
// def main = {
103-
// val s: I = null
104-
// s.foo
105-
// }
106-
// }
107-
case Literal(Constant(null)) => false
108-
case t: Literal => true
109-
case _ => false
110-
}
111-
11243
type Visitor = Tree => Unit
11344
type ErasureCompatibility = Int
11445
val BeforeErasure: ErasureCompatibility = 1
@@ -134,14 +65,8 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
13465

13566
private lazy val _optimizations: Seq[Optimization] =
13667
inlineCaseIntrinsics ::
137-
removeUnnecessaryNullChecks :: // Doesn't seams to work AfterErasure
68+
removeUnnecessaryNullChecks ::
13869
inlineOptions ::
139-
// Tests that fail when enabled AfterErasure, to be investigated?
140-
// ../tests/run/Course-2002-04.scala failed
141-
// ../tests/run/t2005.scala failed
142-
// ../tests/run/optimizer-array-load.scala failed
143-
// ../tests/pos/virtpatmat_exist1.scala failed
144-
// ../tests/pos/t1133.scala failed
14570
inlineLabelsCalledOnce ::
14671
valify ::
14772
devalify ::
@@ -151,11 +76,6 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
15176
// inlineLocalObjects :: // followCases needs to be fixed, see ./tests/pos/rbtree.scala
15277
// varify :: // varify could stop other transformations from being applied. postponed.
15378
// bubbleUpNothing ::
154-
// Still need to import the tailRec thing
155-
// t2429.scala
156-
// constraining-lub.scala
157-
// t8933c.scala
158-
// t348plus.scala
15979
constantFold ::
16080
Nil
16181

@@ -170,7 +90,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
17090
while (rhs1 ne rhs0) {
17191
rhs1 = rhs0
17292
val initialized = _optimizations.map(x => x(ctx.withOwner(tree.symbol)))
173-
var (names, erasureSupport, visitors, transformers) = unzip4(initialized)
93+
var (names, erasureSupport , visitors, transformers) = unzip4(initialized)
17494
// TODO: fuse for performance
17595
while (names.nonEmpty) {
17696
val nextVisitor = visitors.head
@@ -202,6 +122,75 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
202122
} else tree
203123
}
204124

125+
private def desugarIdent(i: Ident)(implicit ctx: Context): Option[Select] = {
126+
i.tpe match {
127+
case TermRef(prefix: TermRef, name) =>
128+
Some(ref(prefix).select(i.symbol))
129+
case TermRef(prefix: ThisType, name) =>
130+
Some(This(prefix.cls).select(i.symbol))
131+
case _ => None
132+
}
133+
}
134+
135+
private def dropCasts(t: Tree)(implicit ctx: Context): Tree = t match {
136+
// case TypeApply(aio@Select(rec, nm), _) if aio.symbol == defn.Any_asInstanceOf => dropCasts(rec)
137+
case Typed(t, tpe) => t
138+
case _ => t
139+
}
140+
141+
private def readingOnlyVals(t: Tree)(implicit ctx: Context): Boolean = dropCasts(t) match {
142+
case Typed(exp, _) => readingOnlyVals(exp)
143+
case TypeApply(fun @ Select(rec, _), List(tp)) =>
144+
if ((fun.symbol eq defn.Any_asInstanceOf) && rec.tpe.derivesFrom(tp.tpe.classSymbol))
145+
readingOnlyVals(rec)
146+
else false
147+
case Apply(Select(rec, _), Nil) =>
148+
def isGetterOfAImmutableField = t.symbol.isGetter && !t.symbol.is(Flags.Mutable)
149+
def isCaseClassWithVar = t.symbol.info.decls.exists(_.is(Flags.Mutable))
150+
def isAccessingProductField = t.symbol.exists &&
151+
t.symbol.owner.derivesFrom(defn.ProductClass) &&
152+
t.symbol.owner.is(Flags.CaseClass) &&
153+
t.symbol.name.isSelectorName &&
154+
!isCaseClassWithVar // Conservative Covers case class A(var x: Int)
155+
def isImmutableCaseAccessor = t.symbol.is(Flags.CaseAccessor) && !t.symbol.is(Flags.Mutable)
156+
if (isGetterOfAImmutableField || isAccessingProductField || isImmutableCaseAccessor)
157+
readingOnlyVals(rec)
158+
else false
159+
case Select(rec, _) if t.symbol.is(Flags.Method) =>
160+
if (t.symbol.isGetter && !t.symbol.is(Flags.Mutable)) readingOnlyVals(rec) // getter of a immutable field
161+
else if (t.symbol.owner.derivesFrom(defn.ProductClass) && t.symbol.owner.is(Flags.CaseClass) && t.symbol.name.isSelectorName) {
162+
def isImmutableField = {
163+
val fieldId = t.symbol.name.toString.drop(1).toInt - 1
164+
!t.symbol.owner.caseAccessors(ctx)(fieldId).is(Flags.Mutable)
165+
}
166+
if (isImmutableField) readingOnlyVals(rec) // accessing a field of a product
167+
else false
168+
} else if (t.symbol.is(Flags.CaseAccessor) && !t.symbol.is(Flags.Mutable))
169+
readingOnlyVals(rec)
170+
else false
171+
case Select(qual, _) if !t.symbol.is(Flags.Mutable) =>
172+
readingOnlyVals(qual)
173+
case t: Ident if !t.symbol.is(Flags.Mutable) && !t.symbol.is(Flags.Method) && !t.symbol.info.dealias.isInstanceOf[ExprType] =>
174+
desugarIdent(t) match {
175+
case Some(t) => readingOnlyVals(t)
176+
case None => true
177+
}
178+
case t: This => true
179+
// null => false, or the following fails devalify:
180+
// trait I {
181+
// def foo: Any = null
182+
// }
183+
// object Main {
184+
// def main = {
185+
// val s: I = null
186+
// s.foo
187+
// }
188+
// }
189+
case Literal(Constant(null)) => false
190+
case t: Literal => true
191+
case _ => false
192+
}
193+
205194
/** Inline case class specific methods using desugarings assumptions.
206195
*
207196
* - CC.apply(args) → new CC(args)
@@ -374,17 +363,17 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
374363
// case ift @ If(cond, thenp, elsep :Literal) if ift.tpe.derivesFrom(defn.BooleanClass) && !elsep.const.booleanValue =>
375364
// cond.select(defn.Boolean_&&).appliedTo(elsep)
376365
// // the other case ins't handled intentionally. See previous case for explanation
377-
case If(t@ Select(recv, _), thenp, elsep) if t.symbol eq defn.Boolean_! =>
366+
case If(t @ Select(recv, _), thenp, elsep) if t.symbol eq defn.Boolean_! =>
378367
If(recv, elsep, thenp)
379-
case If(t@ Apply(Select(recv, _), Nil), thenp, elsep) if t.symbol eq defn.Boolean_! =>
368+
case If(t @ Apply(Select(recv, _), Nil), thenp, elsep) if t.symbol eq defn.Boolean_! =>
380369
If(recv, elsep, thenp)
381370
// TODO: similar trick for comparisons.
382371
// TODO: handle comparison with min\max values
383372
case Apply(meth1 @ Select(Apply(meth2 @ Select(rec, _), Nil), _), Nil) if meth1.symbol == defn.Boolean_! && meth2.symbol == defn.Boolean_! =>
384373
rec
385374
case meth1 @ Select(meth2 @ Select(rec, _), _) if meth1.symbol == defn.Boolean_! && meth2.symbol == defn.Boolean_! && !ctx.erasedTypes =>
386375
rec
387-
case t@Apply(Select(lhs, _), List(rhs)) =>
376+
case t @ Apply(Select(lhs, _), List(rhs)) =>
388377
val sym = t.symbol
389378
(lhs, rhs) match {
390379
case (lhs, Literal(_)) if !lhs.isInstanceOf[Literal] && symmetricOperations.contains(sym) =>
@@ -441,6 +430,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
441430
case t if !isPureExpr(t) =>
442431
t
443432
case t =>
433+
// TODO: did not manage to trigger this in tests
444434
val s = ConstFold.apply(t)
445435
if ((s ne null) && s.tpe.isInstanceOf[ConstantType]) {
446436
val constant = s.tpe.asInstanceOf[ConstantType].value
@@ -798,7 +788,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
798788

799789
private def keepOnlySideEffects(t: Tree)(implicit ctx: Context): Tree = {
800790
t match {
801-
case t: Literal =>
791+
case l: Literal =>
802792
EmptyTree
803793
case t: This =>
804794
EmptyTree
@@ -889,8 +879,8 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
889879
case Block(Nil, expr) => expr
890880
case a: Block =>
891881
val newStats0 = a.stats.mapConserve(keepOnlySideEffects)
892-
val newStats1 = if (newStats0 eq a.stats) newStats0 else newStats0.flatMap{
893-
case x: Block=> x.stats ::: List(x.expr)
882+
val newStats1 = if (newStats0 eq a.stats) newStats0 else newStats0.flatMap {
883+
case x: Block => x.stats ::: List(x.expr)
894884
case EmptyTree => Nil
895885
case t => t :: Nil
896886
}
@@ -1037,7 +1027,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
10371027
if (nw ne old) nw
10381028
else tree
10391029
}
1040-
("inlineLabelsCalledOnce", BeforeErasure, visitor, transformer)
1030+
("inlineOptions", BeforeErasure, visitor, transformer)
10411031
}
10421032

10431033
/** Rewrite vars with exactly one assignment as vals. */

compiler/test/dotty/tools/DottyTypeStealer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ object DottyTypeStealer extends DottyTest {
1414
val gatheredSource = s" ${source}\n object A$dummyName {$vals}"
1515
var scontext : Context = null
1616
var tp: List[Type] = null
17-
checkCompile("frontend",gatheredSource) {
17+
checkCompile("frontend", gatheredSource) {
1818
(tree, context) =>
1919
implicit val ctx = context
2020
val findValDef: (List[ValDef], tpd.Tree) => List[ValDef] =

0 commit comments

Comments
 (0)