Skip to content

Commit ce75a8c

Browse files
Fix a few bugs in Simplify
1 parent 16cc57e commit ce75a8c

File tree

1 file changed

+53
-28
lines changed

1 file changed

+53
-28
lines changed

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

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
8787
case None => true
8888
}
8989
case t: This => true
90+
// null => false, or the following fails devalify:
91+
// trait I {
92+
// def foo: Any = null
93+
// }
94+
// object Main {
95+
// def main = {
96+
// val s: I = null
97+
// s.foo
98+
// }
99+
// }
100+
case Literal(Constant(null)) => false
90101
case t: Literal => true
91102
case _ => false
92103
}
@@ -114,21 +125,21 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
114125
*/
115126
type Optimization = (Context) => (String, ErasureCompatibility, Visitor, Transformer)
116127

117-
private lazy val _optimizations: Seq[Optimization] = Seq(
118-
inlineCaseIntrinsics
119-
,removeUnnecessaryNullChecks
120-
,inlineOptions
121-
,inlineLabelsCalledOnce
122-
,valify
123-
,devalify
124-
,jumpjump
125-
,dropGoodCasts
126-
,dropNoEffects
127-
,inlineLocalObjects // followCases needs to be fixed, see ./tests/pos/rbtree.scala
128-
/*, varify*/ // varify could stop other transformations from being applied. postponed.
129-
//, bubbleUpNothing
130-
,constantFold
131-
)
128+
private lazy val _optimizations: Seq[Optimization] =
129+
inlineCaseIntrinsics ::
130+
removeUnnecessaryNullChecks ::
131+
inlineOptions ::
132+
inlineLabelsCalledOnce ::
133+
valify ::
134+
devalify ::
135+
jumpjump ::
136+
dropGoodCasts ::
137+
dropNoEffects ::
138+
// inlineLocalObjects :: // followCases needs to be fixed, see ./tests/pos/rbtree.scala
139+
// varify :: // varify could stop other transformations from being applied. postponed.
140+
// bubbleUpNothing ::
141+
constantFold ::
142+
Nil
132143

133144
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
134145
val ctx0 = ctx
@@ -184,8 +195,13 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
184195
*/
185196
val inlineCaseIntrinsics: Optimization = { implicit ctx: Context =>
186197
val transformer: Transformer = () => localCtx => {
187-
case a: Apply if !a.tpe.isInstanceOf[MethodicType] && a.symbol.is(Flags.Synthetic) && a.symbol.owner.is(Flags.Module) &&
188-
(a.symbol.name == nme.apply) && a.symbol.owner.companionClass.is(Flags.CaseClass) =>
198+
case a: Apply if !a.tpe.isInstanceOf[MethodicType] &&
199+
a.symbol.is(Flags.Synthetic) &&
200+
a.symbol.owner.is(Flags.Module) &&
201+
(a.symbol.name == nme.apply) &&
202+
a.symbol.owner.companionClass.is(Flags.CaseClass) &&
203+
!a.tpe.derivesFrom(defn.EnumClass) &&
204+
isPureExpr(a.tree) =>
189205
def unrollArgs(t: Tree, l: List[List[Tree]]): List[List[Tree]] = t match {
190206
case Apply(t, args) => unrollArgs(t, args :: l)
191207
case _ => l
@@ -195,9 +211,15 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
195211
case head :: tail => rollInArgs(tail, fun.appliedToArgs(head))
196212
case _ => fun
197213
}
198-
rollInArgs(argss.tail, tpd.New(a.tpe.dealias, argss.head))
199-
case a: Apply if a.symbol.is(Flags.Synthetic) && a.symbol.owner.is(Flags.Module) &&
200-
(a.symbol.name == nme.unapply) && a.symbol.owner.companionClass.is(Flags.CaseClass) =>
214+
val constructor = a.symbol.owner.companionClass.primaryConstructor.asTerm
215+
rollInArgs(argss.tail, New(a.tpe.widenDealias, constructor, argss.head))
216+
217+
case a: Apply if a.symbol.is(Flags.Synthetic) &&
218+
a.symbol.owner.is(Flags.Module) &&
219+
(a.symbol.name == nme.unapply) &&
220+
a.symbol.owner.companionClass.is(Flags.CaseClass) &&
221+
!a.tpe.derivesFrom(defn.EnumClass) &&
222+
isPureExpr(a.tree) =>
201223
if (!a.symbol.owner.is(Flags.Scala2x)) {
202224
if (a.tpe.derivesFrom(defn.BooleanClass)) Literal(Constant(true))
203225
else a.args.head
@@ -210,14 +232,17 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
210232
val tplType = a.tpe.baseArgTypes(defn.OptionClass).head
211233

212234
if (fields.tail.nonEmpty) {
213-
val tplAlloc = tpd.New(tplType, fields)
214-
tpd.New(a.tpe.dealias.translateParameterized(defn.OptionClass, defn.SomeClass), tplAlloc :: Nil)
215-
} else { // scalac does not have tupple1
216-
tpd.New(a.tpe.dealias.translateParameterized(defn.OptionClass, defn.SomeClass), fields.head :: Nil)
235+
val tplAlloc = New(tplType, fields)
236+
New(a.tpe.translateParameterized(defn.OptionClass, defn.SomeClass), tplAlloc :: Nil)
237+
} else { // scalac does not have Tuple1
238+
New(a.tpe.translateParameterized(defn.OptionClass, defn.SomeClass), fields.head :: Nil)
217239
}
218240
}
219241
else a
220-
case a: Apply if (a.symbol.name == nme.unapplySeq) && a.symbol.owner.derivesFrom(SeqFactoryClass) && a.symbol.extendedOverriddenSymbols.isEmpty =>
242+
case a: Apply if (a.symbol.name == nme.unapplySeq) &&
243+
a.symbol.owner.derivesFrom(SeqFactoryClass) &&
244+
a.symbol.extendedOverriddenSymbols.isEmpty &&
245+
isPureExpr(a.tree) =>
221246
def reciever(t: Tree): Type = t match {
222247
case t: Apply => reciever(t.fun)
223248
case t: TypeApply => reciever(t.fun)
@@ -231,7 +256,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
231256

232257
val recv = reciever(a)
233258
if (recv.typeSymbol.is(Flags.Module))
234-
tpd.New(a.tpe.dealias.translateParameterized(defn.OptionClass, defn.SomeClass), a.args.head :: Nil)
259+
New(a.tpe.translateParameterized(defn.OptionClass, defn.SomeClass), a.args.head :: Nil)
235260
else a
236261
case t => t
237262
}
@@ -682,7 +707,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
682707
case t: Tree =>
683708
}
684709

685-
@inline def isNullLiteral(tree: Tree) = tree match {
710+
def isNullLiteral(tree: Tree) = tree match {
686711
case literal: Literal =>
687712
literal.const.tag == Constants.NullTag
688713
case _ => false
@@ -982,7 +1007,7 @@ class Simplify extends MiniPhaseTransform with IdentityDenotTransformer {
9821007
case t: ValDef if t.symbol.is(Flags.Mutable, Flags.Lazy) && !t.symbol.is(Flags.Method) && !t.symbol.owner.isClass =>
9831008
if (isPureExpr(t.rhs))
9841009
defined(t.symbol) = t
985-
case t: RefTree if !t.symbol.is(Flags.Method) && !t.symbol.owner.isClass =>
1010+
case t: RefTree if t.symbol.exists && !t.symbol.is(Flags.Method) && !t.symbol.owner.isClass =>
9861011
if (!firstWrite.contains(t.symbol)) firstRead(t.symbol) = t
9871012
case t @ Assign(l, expr) if !l.symbol.is(Flags.Method) && !l.symbol.owner.isClass =>
9881013
if (!firstRead.contains(l.symbol)) {

0 commit comments

Comments
 (0)