Skip to content

Local optimisations #2513

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 88 commits into from
May 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
098036a
Simplify: initial structure and first optimizations
DarkDimius Aug 29, 2016
968f478
Simplify: add inlineOptions fixes to inlineCaseIntrinsics
DarkDimius Aug 29, 2016
e592460
Simplify: implement constant folding.
DarkDimius Jun 27, 2016
fa75463
Simplify: do not generate blocks with empty stats.
DarkDimius Jun 27, 2016
fc9c60d
Simplify: devalify now also performs constant propagation
DarkDimius Jun 27, 2016
ff0a888
Simplify: fix bug in bubbleUpNothing. Definitions should not be skipped.
DarkDimius Jun 27, 2016
0e6de0a
Simplify: improve constant folding & leave breadcrumbs for contributors
DarkDimius Jun 28, 2016
e024e86
Add PatternFactorization
DarkDimius Aug 29, 2016
b44e796
Simplify: fix owner corruption when inlining LabelDefs.
DarkDimius Aug 30, 2016
a1c1f7f
Simplify: Start getting rid from Scala2 options and tupples in patterns
DarkDimius Aug 30, 2016
5974a80
Simplify: Don't alias lazy vals
DarkDimius Aug 30, 2016
626488a
Simplify: Don't create empty DefDefs if they should do nothing.
DarkDimius Aug 30, 2016
f66ac7f
Simplify: Fix bug with elimination of side-effects.
DarkDimius Aug 30, 2016
9cdc557
Simplify: Don't partials-evaluate case-defs.
DarkDimius Aug 30, 2016
f521d86
Simplify: make object inlining robust against Nothing.
DarkDimius Aug 30, 2016
e111da9
Simplify: Fix several infinite cycles.
DarkDimius Aug 30, 2016
c3f518a
Simplify: Don't drop lazy val reads.
DarkDimius Aug 31, 2016
315728d
Simplify: jump jump: optimise label-defs that are themselves forwarders
DarkDimius Aug 31, 2016
a9930f4
Simplify: start joining ifs if branches are similar.
DarkDimius Aug 31, 2016
e4d36ea
Simplify: String+ isn't symmetric
DarkDimius Aug 31, 2016
cc1b78f
Simplify: fix a bug inside isSimilar
DarkDimius Aug 31, 2016
05c2afd
Simplify: don't remove by-name calls
DarkDimius Aug 31, 2016
9d288e1
Simplify: don't remove infinite cycles :-)
DarkDimius Aug 31, 2016
5e70a0b
Got tired of fixing Pattern*Factorization.
DarkDimius Aug 31, 2016
d16ad9a
simplify: Reading vals through successful casts should be allowed
DarkDimius Sep 2, 2016
b236b04
simplify: Playing with optimising if expressions.
DarkDimius Sep 2, 2016
dc75bd4
simplify: fixes to inlineLocalObjects.
DarkDimius Sep 2, 2016
aa854ec
Simplify: add vilify transformation
DarkDimius Sep 2, 2016
ae35fb7
Simplify: add dropGoodCasts that drops good casts in stat position.
DarkDimius Sep 2, 2016
646f11a
Simplify: fix the fix of handling by-name arguments.
DarkDimius Sep 2, 2016
a1ad54c
Simplify: dropNoEffects now flattens blocks.
DarkDimius Sep 2, 2016
c6f0e8d
Simplify: inline case-defs that have literal in rhs.
DarkDimius Sep 2, 2016
05a5382
Simplify: Somes\options can be null :-(
DarkDimius Sep 2, 2016
e93dd61
Make optimisation optional.
DarkDimius Sep 6, 2016
ae9a562
Simplify:inlineLocalObjects: don't inline mutable fields.
DarkDimius Sep 6, 2016
14bc530
Simplify: DropGoodCasts: Don't accumulate cast on garbage.
DarkDimius Sep 6, 2016
a8c9e94
Simplify: devalify: correctly rebase New when prefix changes.
DarkDimius Sep 6, 2016
6536d8f
Simplify:inlineLocalObjects: make more robust against complex labels.
DarkDimius Sep 6, 2016
2b3d0d2
Simplify: NullCheck: as proposed by @jvican
DarkDimius Sep 6, 2016
8fb9554
Simplify: fix and enable removeUnnecessaryNullChecks.
DarkDimius Sep 6, 2016
9314e91
Add missing NamedType import
jvican Sep 7, 2016
02be44b
Simplify: devalify: don't kick in on by-name params
jvican Sep 7, 2016
1b6074c
Simplify: fix infinite recursion in followCases
DarkDimius Sep 20, 2016
d25a221
Simplify: remove duplicate null tests.
DarkDimius Sep 20, 2016
f79f06f
Simplify: this can be dropped inside a block.
DarkDimius Sep 20, 2016
6cc53c7
Finish rebase over dotty upstream
DarkDimius Mar 1, 2017
232761c
Document Simplify optimizations
OlivierBlanvillain Mar 2, 2017
76af6c5
Fix Erasure of uniqueRefDenotations with different underlying type.
DarkDimius Apr 11, 2017
aaca2b1
Rewrite labelDefs phase
DarkDimius Apr 26, 2017
b7596ef
Soften Ycheck scoping rules for local jumps after LabelDefs
DarkDimius Apr 27, 2017
a5b688d
Fix compilation after rebase
OlivierBlanvillain Apr 28, 2017
4ea9a84
Restore tests moved to disabled
OlivierBlanvillain Apr 28, 2017
8f470f0
Remove PatternConstantsFactorization & PatternTypeFactorization for now
OlivierBlanvillain Apr 28, 2017
b4af143
Run all tests with -optimise
OlivierBlanvillain Apr 28, 2017
f775345
Formating / refactoring
OlivierBlanvillain Apr 28, 2017
c42a944
Remove usage of -optimise in ClassfileParser
OlivierBlanvillain Apr 28, 2017
ef2d967
Fix a few bugs in Simplify
OlivierBlanvillain Apr 28, 2017
d255b32
Expose tpd problem, temporary .toString hack
OlivierBlanvillain Apr 28, 2017
4763a36
Work in progress
OlivierBlanvillain May 11, 2017
2f22230
Add missing `.ensureApplied` in `constantFold`
OlivierBlanvillain May 11, 2017
cad5515
bubbleUpNothing: do we want it? It breaks the last 4 failing tests
OlivierBlanvillain May 11, 2017
520e347
Kinda fix toString hack: testPicking w/o -optimise + tpd swtich
OlivierBlanvillain May 11, 2017
ecaa6e9
Reimplement TypeErasure#erasedLub with the documented algorithm
OlivierBlanvillain May 22, 2017
3d4cdd7
Clean up Simplify
OlivierBlanvillain May 22, 2017
a2bead9
Partially fix pickling tests failing with smarter tpd
OlivierBlanvillain May 22, 2017
dec2766
Add byte code SimplifyTests
OlivierBlanvillain May 22, 2017
a2465b1
Refactor the temporary tpd fix
OlivierBlanvillain May 22, 2017
bb0e5b2
Import Flags._
OlivierBlanvillain May 22, 2017
92ffff7
Add null check and evalOnce to inlineCaseIntrinsics
OlivierBlanvillain May 22, 2017
0e8cbae
Don't run problematic optimisations AfterErasure
OlivierBlanvillain May 22, 2017
c516fb3
Move to pending t7126.scala (could also be run without -optimise)
OlivierBlanvillain May 22, 2017
123a02d
Isolate the two failing tests in run-not-optimised
OlivierBlanvillain May 22, 2017
e92c40f
Fix ShallowFolder
OlivierBlanvillain May 23, 2017
8a51d32
Do not inline val across class boundaries
OlivierBlanvillain May 23, 2017
f564340
Minor reformatting
OlivierBlanvillain May 23, 2017
3cc3121
Add time travelling copies
odersky May 26, 2017
8a66a25
Simplify: do not drop complex prefixes to case-class apply & unapply.
DarkDimius May 29, 2017
65265e6
Simplify: fix build
DarkDimius May 29, 2017
7740db5
tpd: handle closures with less copying + use sameTypes
DarkDimius May 26, 2017
4d54f3d
Allow redefining tree-copier per phase.
DarkDimius May 29, 2017
ea7a578
Simplify: use a better tree copier.
DarkDimius May 29, 2017
d09dbd6
Fix SimplifyTests
OlivierBlanvillain May 29, 2017
8220305
Simplify: drop more stuff in dropNoEffects.
DarkDimius May 29, 2017
9c68552
Simplify: run devalify before erasure.
DarkDimius May 29, 2017
ce50cfe
Refactoring and comments
OlivierBlanvillain May 29, 2017
de4dd2c
Fix t4859
OlivierBlanvillain May 30, 2017
fba0d51
Devalify: also visitType for New nodes
OlivierBlanvillain May 30, 2017
b7149c9
Simpler class hiararchy in SimplifyTests to please JUnit
OlivierBlanvillain May 30, 2017
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
104 changes: 14 additions & 90 deletions compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,11 @@ import StdNames.nme
* Unreachable jumps will be eliminated by local dead code analysis.
* After JVM is smart enough to remove next-line jumps
*
* Note that Label DefDefs can be only nested in Block, otherwise no one would
* be able to call them Other DefDefs are eliminated
* Note that his phase Ychecking this phase required softening scoping rules
* as it intentionally allowed to break scoping rules inside methods for labels.
* This is modified by setting `labelsReordered` flag in Phases.
*
* @author Dmitry Petrashko
*/
class LabelDefs extends MiniPhaseTransform {
def phaseName: String = "labelDef"
Expand All @@ -90,76 +93,24 @@ class LabelDefs extends MiniPhaseTransform {
else {
collectLabelDefs.clear
val newRhs = collectLabelDefs.transform(tree.rhs)
val labelCalls = collectLabelDefs.labelCalls
var entryPoints = collectLabelDefs.parentLabelCalls
var labelDefs = collectLabelDefs.labelDefs
var callCounts = collectLabelDefs.callCounts

// make sure that for every label there's a single location it should return and single entry point
// if theres already a location that it returns to that's a failure
val disallowed = new mutable.HashMap[Symbol, Tree]()
queue.sizeHint(labelCalls.size + entryPoints.size)

def putLabelDefsNearCallees = new TreeMap() {

override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
tree match {
case t: Apply if (entryPoints.contains(t)) =>
entryPoints = entryPoints - t
labelLevel = labelLevel + 1
val r = Block(moveLabels(t), t)
labelLevel = labelLevel - 1
if (labelLevel == 0) beingAppended.clear()
r
case _ => if (entryPoints.nonEmpty && labelDefs.nonEmpty) super.transform(tree) else tree
}
case t: Apply if labelDefs.contains(t.symbol) =>
val labelDef = labelDefs(t.symbol)
labelDefs -= t.symbol

}
}
val labelDef2 = transform(labelDef)
Block(labelDef2:: Nil, t)

def moveLabels(entryPoint: Apply): List[Tree] = {
val entrySym = entryPoint.symbol
if ((entrySym is Flags.Label) && labelDefs.contains(entrySym)) {
val visitedNow = new mutable.HashMap[Symbol, Tree]()
val treesToAppend = new ArrayBuffer[Tree]() // order matters. parents should go first
treesToAppend += labelDefs(entrySym)
queue.clear()

var visited = 0
queue += entryPoint
while (visited < queue.size) {
val owningLabelDefSym = queue(visited).symbol
for (call <- labelCalls(owningLabelDefSym)) {
val callSym = call.symbol
if (!beingAppended.contains(callSym)) {
if (disallowed.contains(callSym)) {
val oldCall = disallowed(callSym)
ctx.error(s"Multiple return locations for Label $oldCall and $call", callSym.pos)
} else {
if ((!visitedNow.contains(callSym)) && labelDefs.contains(callSym)) {
val defTree = labelDefs(callSym)
visitedNow.put(callSym, defTree)
val callCount = callCounts(callSym)
if (callCount > 1) {
if (!treesToAppend.contains(defTree)) {
treesToAppend += defTree
queue += call

}
} else if (entryPoint.symbol ne callSym) entryPoints += call
}
}
}
}

visited += 1
case _ => if (labelDefs.nonEmpty) super.transform(tree) else tree
}
beingAppended ++= treesToAppend.map(_.symbol)
treesToAppend.toList.map(putLabelDefsNearCallees.transform)
} else Nil
}
}


val res = cpy.DefDef(tree)(rhs = putLabelDefsNearCallees.transform(newRhs))

res
Expand All @@ -168,22 +119,11 @@ class LabelDefs extends MiniPhaseTransform {

object collectLabelDefs extends TreeMap() {

// label calls from this DefDef
var parentLabelCalls: mutable.Set[Tree] = new mutable.HashSet[Tree]()
var callCounts: mutable.Map[Symbol, Int] = new mutable.HashMap[Symbol, Int]().withDefaultValue(0)

def shouldMoveLabel = true

// labelSymbol -> Defining tree
val labelDefs = new mutable.HashMap[Symbol, Tree]()
// owner -> all calls by this owner
val labelCalls = new mutable.HashMap[Symbol, mutable.Set[Tree]]()
var owner: Symbol = null

def clear = {
parentLabelCalls.clear()
labelDefs.clear()
labelCalls.clear()
}

override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
Expand All @@ -196,30 +136,14 @@ class LabelDefs extends MiniPhaseTransform {
}
case t: DefDef =>
assert(t.symbol is Flags.Label)

val st = parentLabelCalls
parentLabelCalls = new mutable.HashSet[Tree]()
val symt = owner
owner = t.symbol

val r = super.transform(tree)

owner = symt
labelCalls(r.symbol) = parentLabelCalls
parentLabelCalls = st

if (shouldMoveLabel) {
labelDefs(r.symbol) = r
EmptyTree
} else r
labelDefs(r.symbol) = r
EmptyTree
case t: Apply if t.symbol is Flags.Label =>
val sym = t.symbol
parentLabelCalls = parentLabelCalls + t
if (owner != sym) callCounts(sym) = callCounts(sym) + 1
super.transform(tree)
case _ =>
super.transform(tree)

}
}
}
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import core.DenotTransformers.DenotTransformer
import core.Denotations.SingleDenotation

import dotty.tools.backend.jvm.{LabelDefs, GenBCode, CollectSuperCalls}
import dotty.tools.dotc.transform.linker.Simplify

/** The central class of the dotc compiler. The job of a compiler is to create
* runs, which process given `phases` in a given `rootContext`.
Expand Down Expand Up @@ -74,6 +75,7 @@ class Compiler {
new ElimByName, // Expand by-name parameter references
new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings
new ResolveSuper, // Implement super accessors and add forwarders to trait methods
new Simplify, // Perform local optimizations, simplified versions of what linker does.
new PrimitiveForwarders, // Add forwarders to trait methods that have a mismatch between generic and primitives
new ArrayConstructors), // Intercept creation of (non-generic) arrays and intrinsify.
List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
Expand All @@ -86,9 +88,10 @@ class Compiler {
new NonLocalReturns, // Expand non-local returns
new CapturedVars, // Represent vars captured by closures as heap objects
new Constructors, // Collect initialization code in primary constructors
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
// Note: constructors changes decls in transformTemplate, no InfoTransformers should be added after it
new FunctionalInterfaces, // Rewrites closures to implement @specialized types of Functions.
new GetClass), // Rewrites getClass calls on primitive types.
new GetClass, // Rewrites getClass calls on primitive types.
new Simplify), // Perform local optimizations, simplified versions of what linker does.
List(new LambdaLift, // Lifts out nested functions to class scope, storing free variables in environments
// Note: in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,9 @@ object Trees {
}

abstract class TreeAccumulator[X] {
// Ties the knot of the traversal: call `foldOver(x, tree))` to dive in the `tree` node.
def apply(x: X, tree: Tree)(implicit ctx: Context): X

def apply(x: X, trees: Traversable[Tree])(implicit ctx: Context): X = (x /: trees)(apply)
def foldOver(x: X, tree: Tree)(implicit ctx: Context): X = {
def localCtx =
Expand Down Expand Up @@ -1301,7 +1303,7 @@ object Trees {
class ShallowFolder[X](f: (X, Tree) => X) extends TreeAccumulator[X] {
def apply(x: X, tree: Tree)(implicit ctx: Context): X = {
val x1 = f(x, tree)
if (x1.asInstanceOf[AnyRef] ne x1.asInstanceOf[AnyRef]) x1
if (x1.asInstanceOf[AnyRef] ne x.asInstanceOf[AnyRef]) x1
else foldOver(x1, tree)
}
}
Expand Down
59 changes: 47 additions & 12 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
override val cpy: TypedTreeCopier = // Type ascription needed to pick up any new members in TreeCopier (currently there are none)
new TypedTreeCopier

val cpyBetweenPhases = new TimeTravellingTreeCopier

class TypedTreeCopier extends TreeCopier {
def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[Type] =
copied.withTypeUnchecked(tree.tpe)
Expand All @@ -472,16 +474,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply =
ta.assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
// Note: Reassigning the original type if `fun` and `args` have the same types as before
// does not work here: The computed type depends on the widened function type, not
// the function type itself. A treetransform may keep the function type the
// same but its widened type might change.
override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = {
val tree1 = untpd.cpy.Apply(tree)(fun, args)
tree match {
case tree: Apply
if (fun.tpe eq tree.fun.tpe) && sameTypes(args, tree.args) =>
tree1.withTypeUnchecked(tree.tpe)
case _ => ta.assignType(tree1, fun, args)
}
}

override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args)
// Same remark as for Apply
override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
val tree1 = untpd.cpy.TypeApply(tree)(fun, args)
tree match {
case tree: TypeApply
if (fun.tpe eq tree.fun.tpe) && sameTypes(args, tree.args) =>
tree1.withTypeUnchecked(tree.tpe)
case _ => ta.assignType(tree1, fun, args)
}
}

override def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal =
ta.assignType(untpd.cpy.Literal(tree)(const))
Expand Down Expand Up @@ -514,10 +525,15 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}

override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure =
ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt)
// Same remark as for Apply

override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = {
val tree1 = untpd.cpy.Closure(tree)(env, meth, tpt)
tree match {
case tree: Closure if sameTypes(env, tree.env) && (meth.tpe eq tree.meth.tpe) && (tpt.tpe eq tree.tpt.tpe) =>
tree1.withTypeUnchecked(tree.tpe)
case _ => ta.assignType(tree1, meth, tpt)
}
}
override def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = {
val tree1 = untpd.cpy.Match(tree)(selector, cases)
tree match {
Expand Down Expand Up @@ -574,6 +590,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Try(tree: Tree)(expr, cases, finalizer)
}

class TimeTravellingTreeCopier extends TypedTreeCopier {
override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply =
ta.assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
// Note: Reassigning the original type if `fun` and `args` have the same types as before
// does not work here: The computed type depends on the widened function type, not
// the function type itself. A treetransform may keep the function type the
// same but its widened type might change.

override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args)
// Same remark as for Apply

override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure =
ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt)

override def Closure(tree: Closure)(env: List[Tree] = tree.env, meth: Tree = tree.meth, tpt: Tree = tree.tpt)(implicit ctx: Context): Closure =
Closure(tree: Tree)(env, meth, tpt)
}

override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError

implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/config/CompilerCommand.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package dotty.tools.dotc
package config

Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ object Printers {
val pickling: Printer = noPrinter
val inlining: Printer = noPrinter
val exhaustivity: Printer = noPrinter
val simplify: Printer = noPrinter
}
26 changes: 26 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,16 @@ class Definitions {
def Boolean_&& = Boolean_andR.symbol
lazy val Boolean_orR = BooleanClass.requiredMethodRef(nme.ZOR)
def Boolean_|| = Boolean_orR.symbol
lazy val Boolean_eqeqR = BooleanClass.info.member(nme.EQ).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case _ => false
})
def Boolean_== = Boolean_eqeqR.symbol
lazy val Boolean_neqeqR = BooleanClass.info.member(nme.NE).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case _ => false
})
def Boolean_!= = Boolean_neqeqR.symbol

lazy val ByteType: TypeRef = valueTypeRef("scala.Byte", BoxedByteType, java.lang.Byte.TYPE, ByteEnc)
def ByteClass(implicit ctx: Context) = ByteType.symbol.asClass
Expand Down Expand Up @@ -430,6 +440,13 @@ class Definitions {
lazy val Long_LSR_Int = LongType.member(nme.LSR).requiredSymbol(
x => (x is Method) && (x.info.firstParamTypes.head isRef defn.IntClass)
)
lazy val Long_plusR = LongClass.requiredMethodRef(nme.PLUS, List(LongType))
def Long_+ = Long_plusR.symbol
lazy val Long_mulR = LongClass.requiredMethodRef(nme.MUL, List(LongType))
def Long_* = Long_mulR.symbol
lazy val Long_divR = LongClass.requiredMethodRef(nme.DIV, List(LongType))
def Long_/ = Long_divR.symbol

lazy val FloatType: TypeRef = valueTypeRef("scala.Float", BoxedFloatType, java.lang.Float.TYPE, FloatEnc)
def FloatClass(implicit ctx: Context) = FloatType.symbol.asClass
lazy val DoubleType: TypeRef = valueTypeRef("scala.Double", BoxedDoubleType, java.lang.Double.TYPE, DoubleEnc)
Expand Down Expand Up @@ -490,6 +507,11 @@ class Definitions {
lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number")
lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable")
lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException")
lazy val ArithmeticExceptionClass = ctx.requiredClass("java.lang.ArithmeticException")
lazy val ArithmeticExceptionClass_stringConstructor = ArithmeticExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef StringClass)
case _ => false
}).symbol.asTerm
lazy val JavaSerializableClass = ctx.requiredClass("java.io.Serializable")
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")

Expand Down Expand Up @@ -521,6 +543,10 @@ class Definitions {
def DynamicClass(implicit ctx: Context) = DynamicType.symbol.asClass
lazy val OptionType: TypeRef = ctx.requiredClassRef("scala.Option")
def OptionClass(implicit ctx: Context) = OptionType.symbol.asClass
lazy val SomeType: TypeRef = ctx.requiredClassRef("scala.Some")
def SomeClass(implicit ctx: Context) = SomeType.symbol.asClass
lazy val NoneModuleRef: TermRef = ctx.requiredModuleRef("scala.None")
def NoneClass(implicit ctx: Context) = NoneModuleRef.symbol.moduleClass.asClass
lazy val EnumType: TypeRef = ctx.requiredClassRef("scala.Enum")
def EnumClass(implicit ctx: Context) = EnumType.symbol.asClass
lazy val EnumValuesType: TypeRef = ctx.requiredClassRef("scala.runtime.EnumValues")
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ object NameKinds {
val PatMatCaseName = new UniqueNameKind("case")
val PatMatMatchFailName = new UniqueNameKind("matchFail")
val PatMatSelectorName = new UniqueNameKind("selector")
val LocalOptFact = new UniqueNameKind("fact")
val LocalOptSelector = new UniqueNameKind("selector")
val LocalOptFallback = new UniqueNameKind("fallback")

/** The kind of names of default argument getters */
val DefaultGetterName = new NumberedNameKind(DEFAULTGETTER, "DefaultGetter") {
Expand Down Expand Up @@ -384,4 +387,4 @@ object NameKinds {
def qualifiedNameKindOfTag : collection.Map[Int, QualifiedNameKind] = qualifiedNameKinds
def numberedNameKindOfTag : collection.Map[Int, NumberedNameKind] = numberedNameKinds
def uniqueNameKindOfSeparator: collection.Map[String, UniqueNameKind] = uniqueNameKinds
}
}
8 changes: 7 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Scopes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ object Scopes {
/** Is the scope empty? */
def isEmpty: Boolean = lastEntry eq null

def foreach[U](p: Symbol => U)(implicit ctx: Context): Unit = toList foreach p
/** Applies a function f to all Symbols of this Scope. */
def foreach[U](f: Symbol => U)(implicit ctx: Context): Unit = toList.foreach(f)

/** Selects all Symbols of this Scope which satisfy a predicate. */
def filter(p: Symbol => Boolean)(implicit ctx: Context): List[Symbol] = {
ensureComplete()
var syms: List[Symbol] = Nil
Expand All @@ -105,6 +107,10 @@ object Scopes {
syms
}

/** Tests whether a predicate holds for at least one Symbol of this Scope. */
def exists(p: Symbol => Boolean)(implicit ctx: Context): Boolean = filter(p).isEmpty

/** Finds the first Symbol of this Scope satisfying a predicate, if any. */
def find(p: Symbol => Boolean)(implicit ctx: Context): Symbol = filter(p) match {
case sym :: _ => sym
case _ => NoSymbol
Expand Down
Loading