Skip to content

[WIP] Check if opts succeed in CI #2545

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

Closed
wants to merge 80 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e5478f7
Simplify: initial wip
DarkDimius Aug 29, 2016
6402faa
Simplify: more WIP
DarkDimius Aug 29, 2016
0386c89
Simplify: implement constant folding.
DarkDimius Jun 27, 2016
e48d70f
Simplify: do not generate blocks with empty stats.
DarkDimius Jun 27, 2016
b438f93
Simplify: devalify now also performs constant propagation
DarkDimius Jun 27, 2016
b934d28
Simplify: fix bug in bubbleUpNothing. Definitions should not be skipped.
DarkDimius Jun 27, 2016
dd817b6
Simplify: improve constant folding & leave breadcrumbs for contributors
DarkDimius Jun 28, 2016
4ad34ee
After-rebase fixes
DarkDimius Aug 29, 2016
1349bda
Simplify: fix owner corruption when inlining LabelDefs.
DarkDimius Aug 30, 2016
5c98aac
Start getting rid from Scala2 compiling artefacts.
DarkDimius Aug 30, 2016
c96ee1e
Don't alias lazy vals
DarkDimius Aug 30, 2016
f26b62e
Don't create empty DefDefs if they should do nothing.
DarkDimius Aug 30, 2016
b84861a
Simplify: Fix bug with elimination of side-effects.
DarkDimius Aug 30, 2016
356bdc8
Simplify: Don't partials-evaluate case-defs.
DarkDimius Aug 30, 2016
639e739
Simplify: make object inlining robust against Nothing.
DarkDimius Aug 30, 2016
bc38d7f
Simplify: Fix several infinite cycles.
DarkDimius Aug 30, 2016
9ad8364
Simplify: Don't drop lazy val reads.
DarkDimius Aug 31, 2016
4eaed86
Simplify: jump jump: optimise label-defs that are themselves forwarders
DarkDimius Aug 31, 2016
b572508
Simplify: start joining ifs if branches are similar.
DarkDimius Aug 31, 2016
c757460
Simplify: String+ isn't symmetric
DarkDimius Aug 31, 2016
bb9dc47
Simplify: fix a bug inside isSimilar
DarkDimius Aug 31, 2016
6e7b918
Simplify: don't remove by-name calls
DarkDimius Aug 31, 2016
330272d
Simplify: don't remove infinite cycles :-)
DarkDimius Aug 31, 2016
701c994
Got tired of fixing Pattern*Factorization.
DarkDimius Aug 31, 2016
5b8ce74
simplify: Reading vals through successful casts should be allowed
DarkDimius Sep 2, 2016
205d139
simplify: Playing with optimising if expressions.
DarkDimius Sep 2, 2016
23dfcbf
simplify: fixes to inlineLocalObjects.
DarkDimius Sep 2, 2016
52aa8e7
Simplify: add vilify transformation
DarkDimius Sep 2, 2016
b2b94f9
Simplify: add dropGoodCasts that drops good casts in stat position.
DarkDimius Sep 2, 2016
dbac9ac
Simplify: fix the fix of handling by-name arguments.
DarkDimius Sep 2, 2016
165de21
Simplify: dropNoEffects now flattens blocks.
DarkDimius Sep 2, 2016
af32e43
Simplify: inline case-defs that have literal in rhs.
DarkDimius Sep 2, 2016
d1acbda
Simplify: Somes\options can be null :-(
DarkDimius Sep 2, 2016
8268b18
Make optimisation optional.
DarkDimius Sep 6, 2016
32ace53
Simplify:inlineLocalObjects: don't inline mutable fields.
DarkDimius Sep 6, 2016
37066ec
Simplify: DropGoodCasts: Don't accumulate cast on garbage.
DarkDimius Sep 6, 2016
10a2f37
Simplify: devalify: correctly rebase New when prefix changes.
DarkDimius Sep 6, 2016
d2be8f9
Simplify:inlineLocalObjects: make more robust against complex labels.
DarkDimius Sep 6, 2016
6ef5859
Simplify: NullCheck: as proposed by @jvican
DarkDimius Sep 6, 2016
75e2856
Simplify: fix and enable removeUnnecessaryNullChecks.
DarkDimius Sep 6, 2016
b903556
Add missing NamedType import
jvican Sep 7, 2016
bc152a8
Simplify: devalify: don't kick in on by-name params
jvican Sep 7, 2016
58d90d3
Simplify: fix infinite recursion in followCases
DarkDimius Sep 20, 2016
d504664
Simplify: remove duplicate null tests.
DarkDimius Sep 20, 2016
bb577ea
Simplify: this can be dropped inside a block.
DarkDimius Sep 20, 2016
417792e
Finish rebase over dotty upstream
DarkDimius Mar 1, 2017
a5a789d
Document Simplify optimizations
OlivierBlanvillain Mar 2, 2017
85542f5
Fix Erasure of uniqueRefDenotations with different underlying type.
DarkDimius Apr 11, 2017
d44ffd8
Rewrite labelDefs phase
DarkDimius Apr 26, 2017
8cede17
Soften Ycheck scoping rules for local jumps after LabelDefs
DarkDimius Apr 27, 2017
25f9a8c
Fix compilation after rebase
OlivierBlanvillain Apr 28, 2017
5e4e966
Restore tests moved to disabled
OlivierBlanvillain Apr 28, 2017
8822ddb
Remove PatternConstantsFactorization & PatternTypeFactorization for now
OlivierBlanvillain Apr 28, 2017
01e3c4e
Run all tests with -optimise
OlivierBlanvillain Apr 28, 2017
bb9fcad
Formating / refactoring
OlivierBlanvillain Apr 28, 2017
d2f23b9
Remove usage of -optimise in ClassfileParser
OlivierBlanvillain Apr 28, 2017
81954d1
Fix a few bugs in Simplify
OlivierBlanvillain Apr 28, 2017
c9bb952
Expose tpd problem, temporary .toString hack
OlivierBlanvillain Apr 28, 2017
67fe148
Work in progress
OlivierBlanvillain May 11, 2017
f810797
Add missing `.ensureApplied` in `constantFold`
OlivierBlanvillain May 11, 2017
301ab23
bubbleUpNothing: do we want it? It breaks the last 4 failing tests
OlivierBlanvillain May 11, 2017
2705b70
Kinda fix toString hack: testPicking w/o -optimise + tpd swtich
OlivierBlanvillain May 11, 2017
e0c07c6
Reimplement TypeErasure#erasedLub with the documented algorithm
OlivierBlanvillain May 22, 2017
7fa7b22
Clean up Simplify
OlivierBlanvillain May 22, 2017
d62071c
Partially fix pickling tests failing with smarter tpd
OlivierBlanvillain May 22, 2017
e61b70d
Add byte code SimplifyTests
OlivierBlanvillain May 22, 2017
950b6ab
Refactor the temporary tpd fix
OlivierBlanvillain May 22, 2017
0431c5a
Import Flags._
OlivierBlanvillain May 22, 2017
22e9022
Add null check and evalOnce to inlineCaseIntrinsics
OlivierBlanvillain May 22, 2017
120a391
Don't run problematic optimisations AfterErasure
OlivierBlanvillain May 22, 2017
c0e0f9c
Move to pending t7126.scala (could also be run without -optimise)
OlivierBlanvillain May 22, 2017
8d490ae
Isolate the two failing tests in run-not-optimised
OlivierBlanvillain May 22, 2017
44aff1b
Fix ShallowFolder
OlivierBlanvillain May 23, 2017
7a03550
Do not inline val across class boundaries
OlivierBlanvillain May 23, 2017
935858c
Minor reformatting
OlivierBlanvillain May 23, 2017
baf43ab
Add time travelling copies
odersky May 26, 2017
80612fd
Use tpd.cpy in Simplify.
DarkDimius May 26, 2017
3c536d6
tpd: handle closures with less copying + use sameTypes
DarkDimius May 26, 2017
71f06ef
Simpler class hiararchy in SimplifyTests to please JUnit
OlivierBlanvillain May 29, 2017
befa11f
Restore t7126
OlivierBlanvillain May 29, 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 @@ -75,6 +76,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 @@ -87,9 +89,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 @@ -400,6 +400,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 @@ -431,6 +441,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 @@ -491,6 +508,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 @@ -522,6 +544,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