Skip to content

Fix #1442: add new phase, SelectStatic #1445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class Compiler {
new Flatten, // Lift all inner classes to package scope
new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group
List(new ExpandPrivate, // Widen private definitions accessed from nested classes
new SelectStatic, // get rid of selects that would be compiled into GetStatic
new CollectEntryPoints, // Find classes with main methods
new CollectSuperCalls, // Find classes that are called with super
new MoveStatics, // Move static methods to companion classes
Expand Down
60 changes: 60 additions & 0 deletions src/dotty/tools/dotc/transform/SelectStatic.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package dotty.tools.dotc
package transform

import dotty.tools.dotc.ast.Trees._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core._
import dotty.tools.dotc.transform.TreeTransforms._

/** Removes selects that would be compiled into GetStatic
* otherwise backend needs to be aware that some qualifiers need to be dropped.
* Similar transformation seems to be performed by flatten in nsc
* @author Dmytro Petrashko
*/
class SelectStatic extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
import ast.tpd._

override def phaseName: String = "selectStatic"
private val isPackage = FlagConjunction(PackageCreationFlags.bits)

override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
val sym = tree.symbol
val r1 =
if (!sym.is(isPackage) && !sym.maybeOwner.is(isPackage) &&
(
((sym is Flags.Module) && sym.maybeOwner.isStaticOwner) ||
(sym is Flags.JavaStatic) ||
(sym.maybeOwner is Flags.ImplClass) ||
sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot)
)
)
if (!tree.qualifier.symbol.is(JavaModule) && !tree.qualifier.isType)
Block(List(tree.qualifier), ref(sym))
else tree
else tree

normalize(r1)
}

private def normalize(t: Tree)(implicit ctx: Context) = t match {
case Select(Block(stats, qual), nm) =>
Block(stats, cpy.Select(t)(qual, nm))
case Apply(Block(stats, qual), nm) =>
Block(stats, Apply(qual, nm))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason not to copy Apply and TypeApplyas you do with Select?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying does not copy the tree here, as it always has a different structure.
cpy.Select can preserve the symbol though, in case method is overloaded. This is not needed for Apply\TypeApply as by the time they are applied overloads are already resolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I asked because I ran into the overloading issues some time ago. Great!

case TypeApply(Block(stats, qual), nm) =>
Block(stats, TypeApply(qual, nm))
case _ => t
}

override def transformApply(tree: tpd.Apply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
normalize(tree)
}

override def transformTypeApply(tree: tpd.TypeApply)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
normalize(tree)
}
}
24 changes: 24 additions & 0 deletions tests/pos/i1442.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
object Test1442 {
final def sumMinimized[B](num: Numeric[B]): Int = {
var cse: scala.math.Numeric.type = null.asInstanceOf[scala.math.Numeric.type]
({cse = scala.math.Numeric; num eq cse.IntIsIntegral} ||
(num eq cse.DoubleAsIfIntegral))
2
}

final def sum[B](implicit num: Numeric[B]): B = {
// arithmetic series formula can be used for regular addition
var cse: scala.math.Numeric.type = null.asInstanceOf[scala.math.Numeric.type]
if ({cse = scala.math.Numeric; num eq cse.IntIsIntegral}||
(num eq cse.BigIntIsIntegral)||
(num eq cse.ShortIsIntegral)||
(num eq cse.ByteIsIntegral)||
(num eq cse.CharIsIntegral)||
(num eq cse.LongIsIntegral)||
(num eq cse.FloatAsIfIntegral)||
(num eq cse.BigDecimalIsFractional)||
(num eq cse.DoubleAsIfIntegral)) {
null.asInstanceOf[B]
} else null.asInstanceOf[B]
}
}
2 changes: 1 addition & 1 deletion tests/run/t4859.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Outer
Inner
Inner.i
About to reference Inner.i
Outer
Inner.i
About to reference O.N
About to reference O.N
Expand Down