summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml6
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala5
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala1
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala622
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala12
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala35
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala24
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala77
-rw-r--r--src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala15
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala8
-rw-r--r--src/compiler/scala/tools/util/PathResolver.scala2
-rw-r--r--src/eclipse/partest/.classpath1
-rw-r--r--src/eclipse/repl/.classpath11
-rw-r--r--src/eclipse/repl/.project35
-rw-r--r--src/eclipse/scaladoc/.classpath4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/RangePositions.scala5
-rw-r--r--src/library/scala/AnyVal.scala2
-rw-r--r--src/library/scala/NotNull.scala2
-rw-r--r--src/library/scala/collection/immutable/RedBlackTree.scala69
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala51
-rw-r--r--src/library/scala/collection/parallel/TaskSupport.scala24
-rw-r--r--src/library/scala/collection/parallel/Tasks.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala13
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala74
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/reflect/scala/reflect/internal/tpe/GlbLubs.scala8
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala160
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala5
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala2
-rw-r--r--src/reflect/scala/reflect/io/AbstractFile.scala34
-rw-r--r--src/reflect/scala/reflect/io/Path.scala9
-rw-r--r--src/reflect/scala/reflect/io/ZipArchive.scala62
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala174
-rw-r--r--src/scalap/scala/tools/scalap/JavaWriter.scala9
-rw-r--r--test/files/jvm/constant-optimization/Foo_1.flags1
-rw-r--r--test/files/jvm/constant-optimization/Foo_1.scala9
-rw-r--r--test/files/jvm/constant-optimization/Test.scala27
-rw-r--r--test/files/neg/constructor-init-order.check9
-rw-r--r--test/files/neg/constructor-init-order.flags1
-rw-r--r--test/files/neg/constructor-init-order.scala23
-rw-r--r--test/files/neg/t0764.scala4
-rw-r--r--test/files/neg/t3977.check2
-rw-r--r--test/files/neg/t3977.scala6
-rwxr-xr-xtest/files/neg/t6446-additional.check9
-rwxr-xr-xtest/files/neg/t6446-missing.check7
-rw-r--r--test/files/neg/t6446-show-phases.check7
-rw-r--r--test/files/neg/t6601.check4
-rw-r--r--test/files/neg/t6601/AccessPrivateConstructor_2.scala3
-rw-r--r--test/files/neg/t6601/PrivateConstructor_1.scala1
-rw-r--r--test/files/neg/t7235.check4
-rw-r--r--test/files/neg/t7235.scala14
-rw-r--r--test/files/neg/t7238.check6
-rw-r--r--test/files/neg/t7238.scala7
-rw-r--r--test/files/pos/switch-small.flags1
-rw-r--r--test/files/pos/t3108.scala5
-rw-r--r--test/files/pos/t3417.scala11
-rw-r--r--test/files/pos/t7226.scala26
-rw-r--r--test/files/pos/t7228.scala75
-rw-r--r--test/files/pos/t7234.scala15
-rw-r--r--test/files/pos/t7234b.scala20
-rw-r--r--test/files/presentation/hyperlinks.check137
-rw-r--r--test/files/presentation/hyperlinks/src/SuperTypes.scala32
-rw-r--r--test/files/run/bitsets.check5
-rw-r--r--test/files/run/bitsets.scala22
-rw-r--r--test/files/run/blame_eye_triple_eee.check9
-rw-r--r--test/files/run/blame_eye_triple_eee.flags1
-rw-r--r--test/files/run/blame_eye_triple_eee.scala61
-rw-r--r--test/files/run/constant-optimization.check5
-rw-r--r--test/files/run/constant-optimization.flags1
-rw-r--r--test/files/run/constant-optimization.scala61
-rw-r--r--test/files/run/programmatic-main.check7
-rw-r--r--test/files/run/t5710-1.check1
-rw-r--r--test/files/run/t5710-1.scala15
-rw-r--r--test/files/run/t5710-2.check1
-rw-r--r--test/files/run/t5710-2.scala15
-rw-r--r--test/files/run/t6608.check1
-rw-r--r--test/files/run/t6608.scala16
-rw-r--r--test/files/run/t6646.check2
-rw-r--r--test/files/run/t6646.scala6
-rw-r--r--test/files/run/t7235.check4
-rw-r--r--test/files/run/t7235.scala14
-rw-r--r--test/pending/pos/no-widen-locals.flags1
-rw-r--r--test/pending/pos/no-widen-locals.scala (renamed from test/files/pos/no-widen-locals.scala)0
98 files changed, 1990 insertions, 396 deletions
diff --git a/build.xml b/build.xml
index 7e4948c938..8294f17d33 100644
--- a/build.xml
+++ b/build.xml
@@ -1388,6 +1388,7 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
+ <pathelement location="${build-quick.dir}/classes/continuations-library"/>
<pathelement location="${jline.jar}"/>
<path refid="asm.classpath"/>
<path refid="forkjoin.classpath"/>
@@ -1511,9 +1512,11 @@ PACKED QUICK BUILD (PACK)
<copy file="META-INF/MANIFEST.MF" toDir="${build-pack.dir}/META-INF"/>
<manifest file="${build-pack.dir}/META-INF/MANIFEST.MF" mode="update">
<attribute name="Bundle-Version" value="${version.number}"/>
+ <attribute name="Class-Path" value="scala-reflect.jar scala-library.jar"/>
</manifest>
<mkdir dir="${build-pack.dir}/lib"/>
<jar destfile="${build-pack.dir}/lib/scala-compiler.jar" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
+ <service type="javax.script.ScriptEngineFactory" provider="scala.tools.nsc.interpreter.IMain$Factory"/>
<fileset dir="${build-quick.dir}/classes/compiler"/>
<fileset dir="${build-quick.dir}/classes/scaladoc"/>
<fileset dir="${build-quick.dir}/classes/interactive"/>
@@ -1984,7 +1987,7 @@ SBT Compiler Interface
<target name="sbt.start" depends="init">
<!-- TODO - Put this in init? Allow this to be overriden simply -->
- <property name="sbt.latest.version" value="0.12.0"/>
+ <property name="sbt.latest.version" value="0.12.2"/>
<property name="sbt.src.dir" value="${build-sbt.dir}/${sbt.latest.version}/src"/>
@@ -2032,6 +2035,7 @@ SBT Compiler Interface
<pathelement location="${build-quick.dir}/classes/reflect"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${build-quick.dir}/classes/scaladoc"/>
+ <pathelement location="${build-quick.dir}/classes/interactive"/>
<pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${sbt.interface.jar}"/>
<path refid="forkjoin.classpath"/>
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
index 3a68794c97..860dfd72b2 100644
--- a/src/compiler/scala/reflect/reify/Errors.scala
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -21,6 +21,11 @@ trait Errors {
throw new ReificationException(defaultErrorPosition, msg)
}
+ def CannotReifyCompoundTypeTreeWithNonEmptyBody(ctt: CompoundTypeTree) = {
+ val msg = "implementation restriction: cannot reify refinement type trees with non-empty bodies"
+ throw new ReificationException(ctt.pos, msg)
+ }
+
def CannotReifyWeakType(details: Any) = {
val msg = "cannot create a TypeTag" + details + ": use WeakTypeTag instead"
throw new ReificationException(defaultErrorPosition, msg)
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index 50ee379c2e..bb5cb53d7d 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -180,6 +180,7 @@ trait Reshape {
private def toPreTyperCompoundTypeTree(ctt: CompoundTypeTree): Tree = {
val CompoundTypeTree(tmpl @ Template(parents, self, stats)) = ctt
+ if (stats.nonEmpty) CannotReifyCompoundTypeTreeWithNonEmptyBody(ctt)
assert(self eq emptyValDef, self)
val att = tmpl.attachments.get[CompoundTypeTreeOriginalAttachment]
val CompoundTypeTreeOriginalAttachment(parents1, stats1) = att.getOrElse(CompoundTypeTreeOriginalAttachment(parents, stats))
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index a8e3c29ff9..d9a42cd3b2 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -25,7 +25,7 @@ import transform._
import backend.icode.{ ICodes, GenICode, ICodeCheckers }
import backend.{ ScalaPrimitives, Platform, JavaPlatform }
import backend.jvm.GenASM
-import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination }
+import backend.opt.{ Inliners, InlineExceptionHandlers, ConstantOptimization, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
import scala.language.postfixOps
@@ -594,6 +594,13 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val runsRightAfter = None
} with ClosureElimination
+ // phaseName = "constopt"
+ object constantOptimization extends {
+ val global: Global.this.type = Global.this
+ val runsAfter = List("closelim")
+ val runsRightAfter = None
+ } with ConstantOptimization
+
// phaseName = "dce"
object deadCode extends {
val global: Global.this.type = Global.this
@@ -678,6 +685,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
inliner -> "optimization: do inlining",
inlineExceptionHandlers -> "optimization: inline exception handlers",
closureElimination -> "optimization: eliminate uncalled closures",
+ constantOptimization -> "optimization: optimize null and other constants",
deadCode -> "optimization: eliminate dead code",
terminal -> "The last phase in the compiler chain"
)
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index b9eb511a9a..692afbac66 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -19,18 +19,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
import global._
import definitions._
- def mkCheckInit(tree: Tree): Tree = {
- val tpe =
- if (tree.tpe != null || !tree.hasSymbolField) tree.tpe
- else tree.symbol.tpe
-
- if (!global.phase.erasedTypes && settings.warnSelectNullable.value &&
- tpe <:< NotNullClass.tpe && !tpe.isNotNull)
- mkRuntimeCall(nme.checkInitialized, List(tree))
- else
- tree
- }
-
/** Builds a fully attributed wildcard import node.
*/
def mkWildcardImport(pkg: Symbol): Import = {
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
new file mode 100644
index 0000000000..b80acc2324
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
@@ -0,0 +1,622 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author James Iry
+ */
+
+package scala.tools.nsc
+package backend.opt
+
+import scala.tools.nsc.backend.icode.analysis.LubException
+import scala.annotation.tailrec
+
+/**
+ * ConstantOptimization uses abstract interpretation to approximate for
+ * each instruction what constants a variable or stack slot might hold
+ * or cannot hold. From this it will eliminate unreachable conditionals
+ * where only one branch is reachable, e.g. to eliminate unnecessary
+ * null checks.
+ *
+ * With some more work it could be extended to
+ * - cache stable values (final fields, modules) in locals
+ * - replace the copy propagation in ClosureElilmination
+ * - fold constants
+ * - eliminate unnecessary stores and loads
+ * - propagate knowledge gathered from conditionals for further optimization
+ */
+abstract class ConstantOptimization extends SubComponent {
+ import global._
+ import icodes._
+ import icodes.opcodes._
+
+ val phaseName = "constopt"
+
+ /** Create a new phase */
+ override def newPhase(p: Phase) = new ConstantOptimizationPhase(p)
+
+ /**
+ * The constant optimization phase.
+ */
+ class ConstantOptimizationPhase(prev: Phase) extends ICodePhase(prev) {
+
+ def name = phaseName
+
+ override def apply(c: IClass) {
+ if (settings.YconstOptimization.value) {
+ val analyzer = new ConstantOptimizer
+ analyzer optimizeClass c
+ }
+ }
+ }
+
+ class ConstantOptimizer {
+ def optimizeClass(cls: IClass) {
+ log(s"Analyzing ${cls.methods.size} methods in $cls.")
+ cls.methods foreach { m =>
+ optimizeMethod(m)
+ }
+ }
+
+ def optimizeMethod(m: IMethod) {
+ if (m.hasCode) {
+ log(s"Analyzing ${m.symbol}")
+ val replacementInstructions = interpretMethod(m)
+ for (block <- m.blocks) {
+ if (replacementInstructions contains block) {
+ val instructions = replacementInstructions(block)
+ block.replaceInstruction(block.lastInstruction, instructions)
+ }
+ }
+ }
+ }
+
+ /**
+ * A single possible (or impossible) datum that can be held in Contents
+ */
+ private sealed abstract class Datum
+ /**
+ * A constant datum
+ */
+ private case class Const(c: Constant) extends Datum {
+ def isIntAssignable = c.tag >= BooleanTag && c.tag <= IntTag
+ def toInt = c.tag match {
+ case BooleanTag => if (c.booleanValue) 1 else 0
+ case _ => c.intValue
+ }
+
+ /**
+ * True if this constant would compare to other as true under primitive eq
+ */
+ override def equals(other: Any) = other match {
+ case oc @ Const(o) => (this eq oc) || (if (this.isIntAssignable && oc.isIntAssignable) this.toInt == oc.toInt else c.value == o.value)
+ case _ => false
+ }
+
+ /**
+ * Hash code consistent with equals
+ */
+ override def hashCode = if (this.isIntAssignable) this.toInt else c.hashCode
+
+ }
+ /**
+ * A datum that has been Boxed via a BOX instruction
+ */
+ private case class Boxed(c: Datum) extends Datum
+
+ /**
+ * The knowledge we have about the abstract state of one location in terms
+ * of what constants it might or cannot hold. Forms a lower
+ * lattice where lower elements in the lattice indicate less knowledge.
+ *
+ * With the following partial ordering (where '>' indicates more precise knowledge)
+ *
+ * Possible(xs) > Possible(xs + y)
+ * Possible(xs) > Impossible(ys)
+ * Impossible(xs + y) > Impossible(xs)
+ *
+ * and the following merges, which indicate merging knowledge from two paths through
+ * the code,
+ *
+ * // left must be 1 or 2, right must be 2 or 3 then we must have a 1, 2 or 3
+ * Possible(xs) merge Possible(ys) => Possible(xs union ys)
+ *
+ * // Left says can't be 2 or 3, right says can't be 3 or 4
+ * // then it's not 3 (it could be 2 from the right or 4 from the left)
+ * Impossible(xs) merge Impossible(ys) => Impossible(xs intersect ys)
+ *
+ * // Left says it can't be 2 or 3, right says it must be 3 or 4, then
+ * // it can't be 2 (left rules out 4 and right says 3 is possible)
+ * Impossible(xs) merge Possible(ys) => Impossible(xs -- ys)
+ *
+ * Intuitively, Possible(empty) says that a location can't hold anything,
+ * it's uninitialized. However, Possible(empty) never appears in the code.
+ *
+ * Conversely, Impossible(empty) says nothing is impossible, it could be
+ * anything. Impossible(empty) is given a synonym UNKNOWN and is used
+ * for, e.g., the result of an arbitrary method call.
+ */
+ private sealed abstract class Contents {
+ /**
+ * Join this Contents with another coming from another path. Join enforces
+ * the lattice structure. It is symmetrical and never moves upward in the
+ * lattice
+ */
+ final def merge(other: Contents): Contents = if (this eq other) this else (this, other) match {
+ case (Possible(possible1), Possible(possible2)) =>
+ Possible(possible1 union possible2)
+ case (Impossible(impossible1), Impossible(impossible2)) =>
+ Impossible(impossible1 intersect impossible2)
+ case (Impossible(impossible), Possible(possible)) =>
+ Impossible(impossible -- possible)
+ case (Possible(possible), Impossible(impossible)) =>
+ Impossible(impossible -- possible)
+ }
+ // TODO we could have more fine-grained knowledge, e.g. know that 0 < x < 3. But for now equality/inequality is a good start.
+ def mightEqual(other: Contents): Boolean
+ def mightNotEqual(other: Contents): Boolean
+ }
+ private def SingleImpossible(x: Datum) = new Impossible(Set(x))
+
+ /**
+ * The location is known to have one of a set of values.
+ */
+ private case class Possible(possible: Set[Datum]) extends Contents {
+ assert(possible.nonEmpty, "Contradiction: had an empty possible set indicating an uninitialized location")
+ def mightEqual(other: Contents): Boolean = (this eq other) || (other match {
+ // two Possibles might be equal if they have any possible members in common
+ case Possible(possible2) => (possible intersect possible2).nonEmpty
+ // a possible can be equal to an impossible if the impossible doesn't rule
+ // out all the possibilities
+ case Impossible(possible2) => (possible -- possible2).nonEmpty
+ })
+ def mightNotEqual(other: Contents): Boolean = (this ne other) && (other match {
+ // two Possibles might not be equal if either has possible members that the other doesn't
+ case Possible(possible2) => (possible -- possible2).nonEmpty || (possible2 -- possible).nonEmpty
+ case Impossible(_) => true
+ })
+ }
+ private def SinglePossible(x: Datum) = new Possible(Set(x))
+
+ /**
+ * The location is known to not have any of a set of values value (e.g null).
+ */
+ private case class Impossible(impossible: Set[Datum]) extends Contents {
+ def mightEqual(other: Contents): Boolean = (this eq other) || (other match {
+ case Possible(_) => other mightEqual this
+ case _ => true
+ })
+ def mightNotEqual(other: Contents): Boolean = (this eq other) || (other match {
+ case Possible(_) => other mightNotEqual this
+ case _ => true
+ })
+ }
+
+ /**
+ * Our entire knowledge about the contents of all variables and the stack. It forms
+ * a lattice primarily driven by the lattice structure of Contents.
+ *
+ * In addition to the rules of contents, State has the following properties:
+ * - The merge of two sets of locals holds the merges of locals found in the intersection
+ * of the two sets of locals. Locals not found in a
+ * locals map are thus possibly uninitialized and attempting to load them results
+ * in an error.
+ * - The stack heights of two states must match otherwise it's an error to merge them
+ *
+ * State is immutable in order to aid in structure sharing of local maps and stacks
+ */
+ private case class State(locals: Map[Local, Contents], stack: List[Contents]) {
+ def mergeLocals(olocals: Map[Local, Contents]): Map[Local, Contents] = if (locals eq olocals) locals else Map((for {
+ key <- (locals.keySet intersect olocals.keySet).toSeq
+ } yield (key, locals(key) merge olocals(key))): _*)
+
+ def merge(other: State): State = if (this eq other) this else {
+ @tailrec def mergeStacks(l: List[Contents], r: List[Contents], out: List[Contents]): List[Contents] = (l, r) match {
+ case (Nil, Nil) => out.reverse
+ case (l, r) if l eq r => out.reverse ++ l
+ case (lhead :: ltail, rhead :: rtail) => mergeStacks(ltail, rtail, (lhead merge rhead) :: out)
+ case _ => sys.error("Mismatched stack heights")
+ }
+
+ val newLocals = mergeLocals(other.locals)
+
+ val newStack = if (stack eq other.stack) stack else mergeStacks(stack, other.stack, Nil)
+ State(newLocals, newStack)
+ }
+
+ /**
+ * Peek at the top of the stack without modifying it. Error if the stack is empty
+ */
+ def peek(n: Int): Contents = stack(n)
+ /**
+ * Push contents onto a stack
+ */
+ def push(contents: Contents): State = this copy (stack = contents :: stack)
+ /**
+ * Drop n elements from the stack
+ */
+ def drop(number: Int): State = this copy (stack = stack drop number)
+ /**
+ * Store the top of the stack into the specified local. An error if the stack
+ * is empty
+ */
+ def store(variable: Local): State = {
+ val contents = stack.head
+ val newVariables = locals + ((variable, contents))
+ new State(newVariables, stack.tail)
+ }
+ /**
+ * Load the specified local onto the top of the stack. An error the the local is uninitialized.
+ */
+ def load(variable: Local): State = {
+ val contents: Contents = locals.getOrElse(variable, sys.error(s"$variable is not initialized"))
+ push(contents)
+ }
+ /**
+ * A copy of this State with an empty stack
+ */
+ def cleanStack: State = if (stack.isEmpty) this else this copy (stack = Nil)
+ }
+
+ // some precomputed constants
+ private val NULL = Const(Constant(null: Any))
+ private val UNKNOWN = Impossible(Set.empty)
+ private val NOT_NULL = SingleImpossible(NULL)
+ private val CONST_UNIT = SinglePossible(Const(Constant(())))
+ private val CONST_FALSE = SinglePossible(Const(Constant(false)))
+ private val CONST_ZERO_BYTE = SinglePossible(Const(Constant(0: Byte)))
+ private val CONST_ZERO_SHORT = SinglePossible(Const(Constant(0: Short)))
+ private val CONST_ZERO_CHAR = SinglePossible(Const(Constant(0: Char)))
+ private val CONST_ZERO_INT = SinglePossible(Const(Constant(0: Int)))
+ private val CONST_ZERO_LONG = SinglePossible(Const(Constant(0: Long)))
+ private val CONST_ZERO_FLOAT = SinglePossible(Const(Constant(0.0f)))
+ private val CONST_ZERO_DOUBLE = SinglePossible(Const(Constant(0.0d)))
+ private val CONST_NULL = SinglePossible(NULL)
+
+ /**
+ * Given a TypeKind, figure out what '0' for it means in order to interpret CZJUMP
+ */
+ private def getZeroOf(k: TypeKind): Contents = k match {
+ case UNIT => CONST_UNIT
+ case BOOL => CONST_FALSE
+ case BYTE => CONST_ZERO_BYTE
+ case SHORT => CONST_ZERO_SHORT
+ case CHAR => CONST_ZERO_CHAR
+ case INT => CONST_ZERO_INT
+ case LONG => CONST_ZERO_LONG
+ case FLOAT => CONST_ZERO_FLOAT
+ case DOUBLE => CONST_ZERO_DOUBLE
+ case REFERENCE(_) => CONST_NULL
+ case ARRAY(_) => CONST_NULL
+ case BOXED(_) => CONST_NULL
+ case ConcatClass => abort("no zero of ConcatClass")
+ }
+
+ // normal locals can't be null, so we use null to mean the magic 'this' local
+ private val THIS_LOCAL: Local = null
+
+ /**
+ * interpret a single instruction to find its impact on the abstract state
+ */
+ private def interpretInst(in: State, inst: Instruction): State = {
+ // pop the consumed number of values off the `in` state's stack, producing a new state
+ def dropConsumed: State = in drop inst.consumed
+
+ inst match {
+ case THIS(_) =>
+ in load THIS_LOCAL
+
+ case CONSTANT(k) =>
+ // treat NaN as UNKNOWN because NaN must never equal NaN
+ val const = if (k.isNaN) UNKNOWN
+ else SinglePossible(Const(k))
+ in push const
+
+ case LOAD_ARRAY_ITEM(_) | LOAD_FIELD(_, _) | CALL_PRIMITIVE(_) =>
+ dropConsumed push UNKNOWN
+
+ case LOAD_LOCAL(local) =>
+ // TODO if a local is known to hold a constant then we can replace this instruction with a push of that constant
+ in load local
+
+ case STORE_LOCAL(local) =>
+ in store local
+
+ case STORE_THIS(_) =>
+ // if a local is already known to have a constant and we're replacing with the same constant then we can
+ // replace this with a drop
+ in store THIS_LOCAL
+
+ case CALL_METHOD(_, _) =>
+ // TODO we could special case implementations of equals that are known, e.g. String#equals
+ // We could turn Possible(string constants).equals(Possible(string constants) into an eq check
+ // We could turn nonConstantString.equals(constantString) into constantString.equals(nonConstantString)
+ // and eliminate the null check that likely precedes this call
+ val initial = dropConsumed
+ (0 until inst.produced).foldLeft(initial) { case (know, _) => know push UNKNOWN }
+
+ case BOX(_) =>
+ val value = in peek 0
+ // we simulate boxing by, um, boxing the possible/impossible contents
+ // so if we have Possible(1,2) originally then we'll end up with
+ // a Possible(Boxed(1), Boxed(2))
+ // Similarly, if we know the input is not a 0 then we'll know the
+ // output is not a Boxed(0)
+ val newValue = value match {
+ case Possible(values) => Possible(values map Boxed)
+ case Impossible(values) => Impossible(values map Boxed)
+ }
+ dropConsumed push newValue
+
+ case UNBOX(_) =>
+ val value = in peek 0
+ val newValue = value match {
+ // if we have a Possible, then all the possibilities
+ // should themselves be Boxes. In that
+ // case we can merge them to figure out what the UNBOX will produce
+ case Possible(inners) =>
+ assert(inners.nonEmpty, "Empty possible set indicating an uninitialized location")
+ val sanitized: Set[Contents] = (inners map {
+ case Boxed(content) => SinglePossible(content)
+ case _ => UNKNOWN
+ })
+ sanitized reduce (_ merge _)
+ // if we have an impossible then the thing that's impossible
+ // should be a box. We'll unbox that to see what we get
+ case unknown@Impossible(inners) =>
+ if (inners.isEmpty) {
+ unknown
+ } else {
+ val sanitized: Set[Contents] = (inners map {
+ case Boxed(content) => SingleImpossible(content)
+ case _ => UNKNOWN
+ })
+ sanitized reduce (_ merge _)
+ }
+ }
+ dropConsumed push newValue
+
+ case LOAD_MODULE(_) | NEW(_) | LOAD_EXCEPTION(_) =>
+ in push NOT_NULL
+
+ case CREATE_ARRAY(_, _) =>
+ dropConsumed push NOT_NULL
+
+ case IS_INSTANCE(_) =>
+ // TODO IS_INSTANCE is going to be followed by a C(Z)JUMP
+ // and if IS_INSTANCE/C(Z)JUMP the branch for "true" can
+ // know that whatever was checked was not a null
+ // see the TODO on CJUMP for more information about propagating null
+ // information
+ // TODO if the top of stack is guaranteed null then we can eliminate this IS_INSTANCE check and
+ // replace with a constant false, but how often is a knowable null checked for instanceof?
+ // TODO we could track type information and statically know to eliminate IS_INSTANCE
+ // which might be a nice win under specialization
+ dropConsumed push UNKNOWN // it's actually a Possible(true, false) but since the following instruction
+ // will be a conditional jump comparing to true or false there
+ // nothing to be gained by being more precise
+
+ case CHECK_CAST(_) =>
+ // TODO we could track type information and statically know to eliminate CHECK_CAST
+ // but that's probably not a huge win
+ in
+
+ case DUP(_) =>
+ val value = in peek 0
+ in push value
+
+ case DROP(_) | MONITOR_ENTER() | MONITOR_EXIT() | STORE_ARRAY_ITEM(_) | STORE_FIELD(_, _) =>
+ dropConsumed
+
+ case SCOPE_ENTER(_) | SCOPE_EXIT(_) =>
+ in
+
+ case JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | RETURN(_) | THROW(_) | SWITCH(_, _) =>
+ dumpClassesAndAbort("Unexpected block ending instruction: " + inst)
+ }
+ }
+ /**
+ * interpret the last instruction of a block which will be jump, a conditional branch, a throw, or a return.
+ * It will result in a map from target blocks to the input state computed for that block. It
+ * also computes a replacement list of instructions
+ */
+ private def interpretLast(in: State, inst: Instruction): (Map[BasicBlock, State], List[Instruction]) = {
+ def canSwitch(in1: Contents, tagSet: List[Int]) = {
+ in1 mightEqual Possible(tagSet.toSet map { tag: Int => Const(Constant(tag)) })
+ }
+
+ /**
+ * common code for interpreting CJUMP and CZJUMP
+ */
+ def interpretConditional(kind: TypeKind, val1: Contents, val2: Contents, success: BasicBlock, failure: BasicBlock, cond: TestOp): (Map[BasicBlock, State], List[Instruction]) = {
+ // TODO use reaching analysis to update the state in the two branches
+ // e.g. if the comparison was checking null equality on local x
+ // then the in the success branch we know x is null and
+ // on the failure branch we know it is not
+ // in fact, with copy propagation we could propagate that knowledge
+ // back through a chain of locations
+ //
+ // TODO if we do all that we need to be careful in the
+ // case that success and failure are the same target block
+ // because we're using a Map and don't want one possible state to clobber the other
+ // alternative mayb we should just replace the conditional with a jump if both targets are the same
+
+ def mightEqual = val1 mightEqual val2
+ def mightNotEqual = val1 mightNotEqual val2
+ def guaranteedEqual = mightEqual && !mightNotEqual
+
+ def succPossible = cond match {
+ case EQ => mightEqual
+ case NE => mightNotEqual
+ case LT | GT => !guaranteedEqual // if the two are guaranteed to be equal then they can't be LT/GT
+ case LE | GE => true
+ }
+
+ def failPossible = cond match {
+ case EQ => mightNotEqual
+ case NE => mightEqual
+ case LT | GT => true
+ case LE | GE => !guaranteedEqual // if the two are guaranteed to be equal then they must be LE/GE
+ }
+
+ val out = in drop inst.consumed
+
+ var result = Map[BasicBlock, State]()
+ if (succPossible) {
+ result += ((success, out))
+ }
+
+ if (failPossible) {
+ result += ((failure, out))
+ }
+
+ val replacements = if (result.size == 1) List.fill(inst.consumed)(DROP(kind)) :+ JUMP(result.keySet.head)
+ else inst :: Nil
+
+ (result, replacements)
+ }
+
+ inst match {
+ case JUMP(whereto) =>
+ (Map((whereto, in)), inst :: Nil)
+
+ case CJUMP(success, failure, cond, kind) =>
+ val in1 = in peek 0
+ val in2 = in peek 1
+ interpretConditional(kind, in1, in2, success, failure, cond)
+
+ case CZJUMP(success, failure, cond, kind) =>
+ val in1 = in peek 0
+ val in2 = getZeroOf(kind)
+ interpretConditional(kind, in1, in2, success, failure, cond)
+
+ case SWITCH(tags, labels) =>
+ val in1 = in peek 0
+ val newStuff = tags zip labels filter { case (tagSet, _) => canSwitch(in1, tagSet) }
+ val (reachableTags, reachableNormalLabels) = (tags zip labels filter { case (tagSet, _) => canSwitch(in1, tagSet) }).unzip
+ val reachableLabels = if (labels.lengthCompare(tags.length) > 0) {
+ // if we've got an extra label then it's the default
+ val defaultLabel = labels.last
+ // see if the default is reachable by seeing if the input might be out of the set
+ // of all tags
+ val allTags = Possible(tags.flatten.toSet map { tag: Int => Const(Constant(tag)) })
+ if (in1 mightNotEqual allTags) {
+ reachableNormalLabels :+ defaultLabel
+ } else {
+ reachableNormalLabels
+ }
+ } else {
+ reachableNormalLabels
+ }
+ // TODO similar to the comment in interpretConditional, we should update our the State going into each
+ // branch based on which tag is being matched. Also, just like interpretConditional, if target blocks
+ // are the same we need to merge State rather than clobber
+
+ // alternative, maybe we should simplify the SWITCH to not have same target labels
+ val newState = in drop inst.consumed
+ val result = Map(reachableLabels map { label => (label, newState) }: _*)
+ if (reachableLabels.size == 1) (result, DROP(INT) :: JUMP(reachableLabels.head) :: Nil)
+ else (result, inst :: Nil)
+
+ // these instructions don't have target blocks
+ // (exceptions are assumed to be reachable from all instructions)
+ case RETURN(_) | THROW(_) =>
+ (Map.empty, inst :: Nil)
+
+ case _ =>
+ dumpClassesAndAbort("Unexpected non-block ending instruction: " + inst)
+ }
+ }
+
+ /**
+ * Analyze a single block to find how it transforms an input state into a states for its successor blocks
+ * Also computes a list of instructions to be used to replace its last instruction
+ */
+ private def interpretBlock(in: State, block: BasicBlock): (Map[BasicBlock, State], Map[BasicBlock, State], List[Instruction]) = {
+ debuglog(s"interpreting block $block")
+ // number of instructions excluding the last one
+ val normalCount = block.size - 1
+
+ var exceptionState = in.cleanStack
+ var normalExitState = in
+ var idx = 0
+ while (idx < normalCount) {
+ val inst = block(idx)
+ normalExitState = interpretInst(normalExitState, inst)
+ if (normalExitState.locals ne exceptionState.locals)
+ exceptionState.copy(locals = exceptionState mergeLocals normalExitState.locals)
+ idx += 1
+ }
+
+ val pairs = block.exceptionSuccessors map { b => (b, exceptionState) }
+ val exceptionMap = Map(pairs: _*)
+
+ val (normalExitMap, newInstructions) = interpretLast(normalExitState, block.lastInstruction)
+
+ (normalExitMap, exceptionMap, newInstructions)
+ }
+
+ /**
+ * Analyze a single method to find replacement instructions
+ */
+ private def interpretMethod(m: IMethod): Map[BasicBlock, List[Instruction]] = {
+ import scala.collection.mutable.{ Set => MSet, Map => MMap }
+
+ debuglog(s"interpreting method $m")
+ var iterations = 0
+
+ // initially we know that 'this' is not null and the params are initialized to some unknown value
+ val initThis: Iterator[(Local, Contents)] = if (m.isStatic) Iterator.empty else Iterator.single((THIS_LOCAL, NOT_NULL))
+ val initOtherLocals: Iterator[(Local, Contents)] = m.params.iterator map { param => (param, UNKNOWN) }
+ val initialLocals: Map[Local, Contents] = Map((initThis ++ initOtherLocals).toSeq: _*)
+ val initialState = State(initialLocals, Nil)
+
+ // worklist of basic blocks to process, initially the start block
+ val worklist = MSet(m.startBlock)
+ // worklist of exception basic blocks. They're kept in a separate set so they can be
+ // processed after normal flow basic blocks. That's because exception basic blocks
+ // are more likely to have multiple predecessors and queueing them for later
+ // increases the chances that they'll only need to be interpreted once
+ val exceptionlist = MSet[BasicBlock]()
+ // our current best guess at what the input state is for each block
+ // initially we only know about the start block
+ val inputState = MMap[BasicBlock, State]((m.startBlock, initialState))
+
+ // update the inputState map based on new information from interpreting a block
+ // When the input state of a block changes, add it back to the work list to be
+ // reinterpreted
+ def updateInputStates(outputStates: Map[BasicBlock, State], worklist: MSet[BasicBlock]) {
+ for ((block, newState) <- outputStates) {
+ val oldState = inputState get block
+ val updatedState = oldState map (x => x merge newState) getOrElse newState
+ if (oldState != Some(updatedState)) {
+ worklist add block
+ inputState(block) = updatedState
+ }
+ }
+ }
+
+ // the instructions to be used as the last instructions on each block
+ val replacements = MMap[BasicBlock, List[Instruction]]()
+
+ while (worklist.nonEmpty || exceptionlist.nonEmpty) {
+ if (worklist.isEmpty) {
+ // once the worklist is empty, start processing exception blocks
+ val block = exceptionlist.head
+ exceptionlist remove block
+ worklist add block
+ } else {
+ iterations += 1
+ val block = worklist.head
+ worklist remove block
+ val (normalExitMap, exceptionMap, newInstructions) = interpretBlock(inputState(block), block)
+
+ updateInputStates(normalExitMap, worklist)
+ updateInputStates(exceptionMap, exceptionlist)
+ replacements(block) = newInstructions
+ }
+ }
+
+ debuglog(s"method $m with ${m.blocks.size} reached fixpoint in $iterations iterations")
+ replacements.toMap
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index 0c72ce1d8e..4d086e787e 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -248,11 +248,11 @@ class MutableSettings(val errorFn: String => Unit)
private def checkDir(dir: AbstractFile, name: String, allowJar: Boolean = false): AbstractFile = (
if (dir != null && dir.isDirectory)
dir
-// was: else if (allowJar && dir == null && Path.isJarOrZip(name, false))
else if (allowJar && dir == null && Jar.isJarOrZip(name, examineFile = false))
new PlainFile(Path(name))
else
- throw new FatalError(name + " does not exist or is not a directory")
+// throw new FatalError(name + " does not exist or is not a directory")
+ dir
)
/** Set the single output directory. From now on, all files will
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 9469113238..ee9a3aed2a 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -38,7 +38,7 @@ trait ScalaSettings extends AbsScalaSettings
protected def futureSettings = List[BooleanSetting]()
/** Enabled under -optimise. */
- protected def optimiseSettings = List[BooleanSetting](inline, inlineHandlers, Xcloselim, Xdce)
+ protected def optimiseSettings = List[BooleanSetting](inline, inlineHandlers, Xcloselim, Xdce, YconstOptimization)
/** Internal use - syntax enhancements. */
private class EnableSettings[T <: BooleanSetting](val s: T) {
@@ -128,6 +128,7 @@ trait ScalaSettings extends AbsScalaSettings
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
val Yshow = PhasesSetting ("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
val Xcloselim = BooleanSetting ("-Yclosure-elim", "Perform closure elimination.")
+ val YconstOptimization = BooleanSetting ("-Yconst-opt", "Perform optimization with constant values.")
val Ycompacttrees = BooleanSetting ("-Ycompact-trees", "Use compact tree printer when displaying trees.")
val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL.")
val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination.")
@@ -166,7 +167,6 @@ trait ScalaSettings extends AbsScalaSettings
val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
- val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").
withDeprecationMessage("This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.")
diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
index 9338d9e5b5..d173aaa848 100644
--- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
@@ -45,6 +45,7 @@ trait StandardScalaSettings {
val unchecked = BooleanSetting ("-unchecked", "Enable additional warnings where generated code depends on assumptions.")
val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.")
val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.")
+ val usemanifestcp = BooleanSetting ("-usemanifestcp", "Utilize the manifest in classpath resolution.")
val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing.")
val version = BooleanSetting ("-version", "Print product version and exit.")
}
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index 2649a150ad..791d44153c 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -19,7 +19,6 @@ trait Warnings {
// present form, but have the potential to offer useful info.
protected def allWarnings = lintWarnings ++ List(
warnDeadCode,
- warnSelectNullable,
warnValueDiscard,
warnNumericWiden
)
@@ -46,21 +45,20 @@ trait Warnings {
allWarnings foreach (_.value = true)
}
)
+ private lazy val warnSelectNullable = BooleanSetting("-Xcheck-null", "This option is obsolete and does nothing.")
// Individual warnings.
- val warnSelectNullable = BooleanSetting ("-Xcheck-null", "Warn upon selection of nullable reference.")
val warnAdaptedArgs = BooleanSetting ("-Ywarn-adapted-args", "Warn if an argument list is modified to match the receiver.")
val warnDeadCode = BooleanSetting ("-Ywarn-dead-code", "Warn when dead code is identified.")
val warnValueDiscard = BooleanSetting ("-Ywarn-value-discard", "Warn when non-Unit expression results are unused.")
val warnNumericWiden = BooleanSetting ("-Ywarn-numeric-widen", "Warn when numerics are widened.")
val warnNullaryUnit = BooleanSetting ("-Ywarn-nullary-unit", "Warn when nullary methods return Unit.")
val warnInaccessible = BooleanSetting ("-Ywarn-inaccessible", "Warn about inaccessible types in method signatures.")
- val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override",
- "Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.")
+ val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override", "Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.")
val warnInferAny = BooleanSetting ("-Ywarn-infer-any", "Warn when a type argument is inferred to be `Any`.")
// Backward compatibility.
- @deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt
- @deprecated("Use warnSelectNullable", "2.11.0") def Xchecknull = warnSelectNullable // used by ide
- @deprecated("Use warnDeadCode", "2.11.0") def Ywarndeadcode = warnDeadCode // used by ide
+ @deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt
+ @deprecated("This option is being removed", "2.11.0") def Xchecknull = warnSelectNullable // used by ide
+ @deprecated("Use warnDeadCode", "2.11.0") def Ywarndeadcode = warnDeadCode // used by ide
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 140be0e17b..9b33ae8ba1 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -528,7 +528,7 @@ abstract class Pickler extends SubComponent {
private def writeSymInfo(sym: Symbol) {
writeRef(sym.name)
writeRef(localizedOwner(sym))
- writeLongNat((rawToPickledFlags(sym.flags & PickledFlags)))
+ writeLongNat((rawToPickledFlags(sym.rawflags & PickledFlags)))
if (sym.hasAccessBoundary) writeRef(sym.privateWithin)
writeRef(sym.info)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 395645161f..4214225399 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -34,6 +34,41 @@ abstract class Constructors extends Transform with ast.TreeDSL {
val stats = impl.body // the transformed template body
val localTyper = typer.atOwner(impl, clazz)
+ // Inspect for obvious out-of-order initialization; concrete, eager vals or vars,
+ // declared in this class, for which a reference to the member precedes its definition.
+ def checkableForInit(sym: Symbol) = (
+ (sym ne null)
+ && (sym.isVal || sym.isVar)
+ && !(sym hasFlag LAZY | DEFERRED | SYNTHETIC)
+ )
+ val uninitializedVals = mutable.Set[Symbol](
+ stats collect { case vd: ValDef if checkableForInit(vd.symbol) => vd.symbol.accessedOrSelf }: _*
+ )
+ if (uninitializedVals.nonEmpty)
+ log("Checking constructor for init order issues among: " + uninitializedVals.map(_.name).mkString(", "))
+
+ for (stat <- stats) {
+ // Checking the qualifier symbol is necessary to prevent a selection on
+ // another instance of the same class from potentially appearing to be a forward
+ // reference on the member in the current class.
+ def check(tree: Tree) = {
+ for (t <- tree) t match {
+ case t: RefTree if uninitializedVals(t.symbol.accessedOrSelf) && t.qualifier.symbol == clazz =>
+ unit.warning(t.pos, s"Reference to uninitialized ${t.symbol.accessedOrSelf}")
+ case _ =>
+ }
+ }
+ stat match {
+ case vd: ValDef =>
+ // doing this first allows self-referential vals, which to be a conservative
+ // warner we will do because it's possible though difficult for it to be useful.
+ uninitializedVals -= vd.symbol.accessedOrSelf
+ if (!vd.symbol.isLazy)
+ check(vd.rhs)
+ case _: MemberDef => // skip other member defs
+ case t => check(t) // constructor body statement
+ }
+ }
val specializedFlag: Symbol = clazz.info.decl(nme.SPECIALIZED_INSTANCE)
val shouldGuard = (specializedFlag != NoSymbol) && !clazz.hasFlag(SPECIALIZED)
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 988e80aa77..f7e3310f88 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -1060,7 +1060,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else if (needsInitFlag(sym))
mkCheckedAccessor(clazz, accessedRef, fieldOffset(sym), sym.pos, sym)
else
- gen.mkCheckInit(accessedRef)
+ accessedRef
})
}
else if (sym.isModule && !(sym hasFlag LIFTED | BRIDGE)) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 4b84c21112..921747c080 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -268,7 +268,7 @@ trait Implicits {
*/
object Function1 {
val Sym = FunctionClass(1)
- def unapply(tp: Type) = tp match {
+ def unapply(tp: Type) = tp baseType Sym match {
case TypeRef(_, Sym, arg1 :: arg2 :: _) => Some((arg1, arg2))
case _ => None
}
@@ -431,10 +431,8 @@ trait Implicits {
val start = if (Statistics.canEnable) Statistics.startTimer(matchesPtNanos) else null
val result = normSubType(tp, pt) || isView && {
pt match {
- case TypeRef(_, Function1.Sym, arg1 :: arg2 :: Nil) =>
- matchesPtView(tp, arg1, arg2, undet)
- case _ =>
- false
+ case Function1(arg1, arg2) => matchesPtView(tp, arg1, arg2, undet)
+ case _ => false
}
}
if (Statistics.canEnable) Statistics.stopTimer(matchesPtNanos, start)
@@ -575,21 +573,21 @@ trait Implicits {
)
def fail(reason: String): SearchResult = failure(itree, reason)
+ def fallback = typed1(itree, EXPRmode, wildPt)
try {
- val itree1 =
- if (isView) {
- val arg1 :: arg2 :: _ = pt.typeArgs
+ val itree1 = if (!isView) fallback else pt match {
+ case Function1(arg1, arg2) =>
typed1(
atPos(itree.pos)(Apply(itree, List(Ident("<argument>") setType approximate(arg1)))),
EXPRmode,
approximate(arg2)
)
- }
- else
- typed1(itree, EXPRmode, wildPt)
-
- if (context.hasErrors)
+ case _ => fallback
+ }
+ if (context.hasErrors) {
+ log("implicit adapt failed: " + context.errBuffer.head.errMsg)
return fail(context.errBuffer.head.errMsg)
+ }
if (Statistics.canEnable) Statistics.incCounter(typedImplicits)
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 8c686107b4..5999a64b36 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -426,7 +426,7 @@ trait MethodSynthesis {
Nil,
Nil,
tpt,
- if (mods.isDeferred) EmptyTree else gen.mkCheckInit(fieldSelection)
+ if (mods.isDeferred) EmptyTree else fieldSelection
) setSymbol derivedSym
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 007c7c6a83..d5da4967be 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -805,23 +805,19 @@ trait Namers extends MethodSynthesis {
case _ =>
false
}
-
- val tpe1 = dropIllegalStarTypes(tpe.deconst)
- val tpe2 = tpe1.widen
-
- // This infers Foo.type instead of "object Foo"
- // See Infer#adjustTypeArgs for the polymorphic case.
- if (tpe.typeSymbolDirect.isModuleClass) tpe1
- else if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
- if (tpe2 <:< pt) tpe2 else tpe1
- else if (isHidden(tpe)) tpe2
- // In an attempt to make pattern matches involving method local vals
- // compilable into switches, for a time I had a more generous condition:
- // `if (sym.isFinal || sym.isLocal) tpe else tpe1`
- // This led to issues with expressions like classOf[List[_]] which apparently
- // depend on being deconst-ed here, so this is again the original:
- else if (!sym.isFinal) tpe1
- else tpe
+ val shouldWiden = (
+ !tpe.typeSymbolDirect.isModuleClass // Infer Foo.type instead of "object Foo"
+ && (tpe.widen <:< pt) // Don't widen our way out of conforming to pt
+ && ( sym.isVariable
+ || sym.isMethod && !sym.hasAccessorFlag
+ || isHidden(tpe)
+ )
+ )
+ dropIllegalStarTypes(
+ if (shouldWiden) tpe.widen
+ else if (sym.isFinal) tpe // "final val" allowed to retain constant type
+ else tpe.deconst
+ )
}
/** Computes the type of the body in a ValDef or DefDef, and
* assigns the type to the tpt's node. Returns the type.
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index fa141e95e1..ce8e0ed37b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -270,22 +270,25 @@ trait NamesDefaults { self: Analyzer =>
*/
def argValDefs(args: List[Tree], paramTypes: List[Type], blockTyper: Typer): List[Option[ValDef]] = {
val context = blockTyper.context
- val symPs = map2(args, paramTypes)((arg, tpe) => arg match {
+ val symPs = map2(args, paramTypes)((arg, paramTpe) => arg match {
case Ident(nme.SELECTOR_DUMMY) =>
None // don't create a local ValDef if the argument is <unapply-selector>
case _ =>
- val byName = isByNameParamType(tpe)
- val repeated = isScalaRepeatedParamType(tpe)
+ val byName = isByNameParamType(paramTpe)
+ val repeated = isScalaRepeatedParamType(paramTpe)
val argTpe = (
if (repeated) arg match {
case Typed(expr, Ident(tpnme.WILDCARD_STAR)) => expr.tpe
case _ => seqType(arg.tpe)
}
- else arg.tpe
- ).widen // have to widen or types inferred from literal defaults will be singletons
+ else
+ // Note stabilizing can lead to a non-conformant argument when existentials are involved, e.g. neg/t3507-old.scala, hence the filter.
+ gen.stableTypeFor(arg).filter(_ <:< paramTpe).getOrElse(arg.tpe)
+ // We have to deconst or types inferred from literal arguments will be Constant(_), e.g. pos/z1730.scala.
+ ).deconst
val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo (
- if (byName) functionType(Nil, argTpe) else argTpe
- )
+ if (byName) functionType(Nil, argTpe) else argTpe
+ )
Some((context.scope.enter(s), byName, repeated))
})
map2(symPs, args) {
@@ -326,11 +329,10 @@ trait NamesDefaults { self: Analyzer =>
// type the application without names; put the arguments in definition-site order
val typedApp = doTypedApply(tree, funOnly, reorderArgs(namelessArgs, argPos), mode, pt)
- if (typedApp.isErrorTyped) tree
- else typedApp match {
+ typedApp match {
// Extract the typed arguments, restore the call-site evaluation order (using
// ValDef's in the block), change the arguments to these local values.
- case Apply(expr, typedArgs) =>
+ case Apply(expr, typedArgs) if !(typedApp :: typedArgs).exists(_.isErrorTyped) => // bail out with erroneous args, see SI-7238
// typedArgs: definition-site order
val formals = formalTypes(expr.tpe.paramTypes, typedArgs.length, removeByName = false, removeRepeated = false)
// valDefs: call-site order
@@ -358,6 +360,7 @@ trait NamesDefaults { self: Analyzer =>
context.namedApplyBlockInfo =
Some((block, NamedApplyInfo(qual, targs, vargss :+ refArgs, blockTyper)))
block
+ case _ => tree
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index a349881d6d..5defa73f9e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1553,6 +1553,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
val bridges = addVarargBridges(currentOwner)
checkAllOverrides(currentOwner)
checkAnyValSubclass(currentOwner)
+ if (currentOwner.isDerivedValueClass)
+ currentOwner.primaryConstructor makeNotPrivate NoSymbol // SI-6601, must be done *after* pickler!
if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree
case dc@TypeTreeWithDeferredRefCheck() => abort("adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c45328a5d3..2ee04d6ee9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1127,16 +1127,19 @@ trait Typers extends Adaptations with Tags {
else {
if (mode.inExprModeButNot(FUNmode)) {
pt.dealias match {
- case TypeRef(_, sym, _) =>
+ // The <: Any requirement inhibits attempts to adapt continuation types
+ // to non-continuation types.
+ case TypeRef(_, sym, _) if tree.tpe <:< AnyClass.tpe =>
// note: was if (pt.typeSymbol == UnitClass) but this leads to a potentially
// infinite expansion if pt is constant type ()
- if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12)
+ if (sym == UnitClass) { // (12)
if (settings.warnValueDiscard.value)
context.unit.warning(tree.pos, "discarded non-Unit value")
return typedPos(tree.pos, mode, pt) {
Block(List(tree), Literal(Constant(())))
}
- } else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
+ }
+ else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) {
if (settings.warnNumericWiden.value)
context.unit.warning(tree.pos, "implicit numeric widening")
return typedPos(tree.pos, mode, pt) {
@@ -1538,7 +1541,7 @@ trait Typers extends Adaptations with Tags {
atPos(supertpt.pos.focus)(supercall)
} match {
case EmptyTree => MissingTypeArgumentsParentTpeError(supertpt)
- case tpt => supertpt = TypeTree(tpt.tpe) setPos supertpt.pos.focus
+ case tpt => supertpt = TypeTree(tpt.tpe) setPos supertpt.pos // SI-7224: don't .focus positions of the TypeTree of a parent that exists in source
}
}
// this is the place where we tell the typer what argss should be used for the super call
@@ -4186,11 +4189,11 @@ trait Typers extends Adaptations with Tags {
def typedArrayValue(tree: ArrayValue) = {
val elemtpt1 = typedType(tree.elemtpt, mode)
- val elems1 = tree.elems mapConserve (elem => typed(elem, mode, elemtpt1.tpe))
- treeCopy.ArrayValue(tree, elemtpt1, elems1)
- .setType(
- (if (isFullyDefined(pt) && !phase.erasedTypes) pt
- else arrayType(elemtpt1.tpe)).notNull)
+ val elems1 = tree.elems mapConserve (elem => typed(elem, mode, elemtpt1.tpe))
+ // see run/t6126 for an example where `pt` does not suffice (tagged types)
+ val tpe1 = if (isFullyDefined(pt) && !phase.erasedTypes) pt else arrayType(elemtpt1.tpe)
+
+ treeCopy.ArrayValue(tree, elemtpt1, elems1) setType tpe1
}
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
@@ -4493,35 +4496,31 @@ trait Typers extends Adaptations with Tags {
reportError
}
}
- silent(_.typed(fun, mode.forFunMode, funpt),
- if (mode.inExprMode) false else context.ambiguousErrors,
- if (mode.inExprMode) tree else context.tree) match {
+ val silentResult = silent(
+ op = _.typed(fun, mode.forFunMode, funpt),
+ reportAmbiguousErrors = !mode.inExprMode && context.ambiguousErrors,
+ newtree = if (mode.inExprMode) tree else context.tree
+ )
+ silentResult match {
case SilentResultValue(fun1) =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
if (Statistics.canEnable) Statistics.incCounter(typedApplyCount)
- def isImplicitMethod(tpe: Type) = tpe match {
- case mt: MethodType => mt.isImplicit
- case _ => false
- }
- val useTry = (
- !isPastTyper
- && fun2.isInstanceOf[Select]
- && !isImplicitMethod(fun2.tpe)
- && ((fun2.symbol eq null) || !fun2.symbol.isConstructor)
- && (mode & (EXPRmode | SNDTRYmode)) == EXPRmode
+ val noSecondTry = (
+ isPastTyper
+ || (fun2.symbol ne null) && fun2.symbol.isConstructor
+ || (fun2.tpe match { case mt: MethodType => mt.isImplicit case _ => false })
+ )
+ val isFirstTry = !noSecondTry && (
+ fun2 match {
+ case Select(_, _) => mode inExprModeButNot SNDTRYmode
+ case _ => false
+ }
)
- val res =
- if (useTry) tryTypedApply(fun2, args)
- else doTypedApply(tree, fun2, args, mode, pt)
-
- if (fun2.symbol == Array_apply && !res.isErrorTyped) {
- val checked = gen.mkCheckInit(res)
- // this check is needed to avoid infinite recursion in Duplicators
- // (calling typed1 more than once for the same tree)
- if (checked ne res) typed { atPos(tree.pos)(checked) }
- else res
- } else
- res
+ if (isFirstTry)
+ tryTypedApply(fun2, args)
+ else
+ doTypedApply(tree, fun2, args, mode, pt)
+
case SilentTypeError(err) =>
onError({issue(err); setError(tree)})
}
@@ -4737,16 +4736,6 @@ trait Typers extends Adaptations with Tags {
(stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None)
}
- def isPotentialNullDeference() = {
- !isPastTyper &&
- !sym.isConstructor &&
- !(qual.tpe <:< NotNullClass.tpe) && !qual.tpe.isNotNull &&
- !(List(Any_isInstanceOf, Any_asInstanceOf) contains result.symbol) // null.is/as is not a dereference
- }
- // unit is null here sometimes; how are we to know when unit might be null? (See bug #2467.)
- if (settings.warnSelectNullable.value && isPotentialNullDeference && unit != null)
- unit.warning(tree.pos, "potential null pointer dereference: "+tree)
-
result match {
// could checkAccessible (called by makeAccessible) potentially have skipped checking a type application in qual?
case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs.nonEmpty => // TODO: somehow the new qual is not checked in refchecks
diff --git a/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
index 7aef87f387..e4f879560c 100644
--- a/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
@@ -6,6 +6,9 @@ package scala.tools.nsc
package util
import scala.tools.nsc.io.AbstractFile
+import java.security.cert.Certificate
+import java.security.{ ProtectionDomain, CodeSource }
+import util.ScalaClassLoader
import java.net.{ URL, URLConnection, URLStreamHandler }
import scala.collection.{ mutable, immutable }
@@ -82,7 +85,17 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
if (bytes.length == 0)
throw new ClassNotFoundException(name)
else
- defineClass(name, bytes, 0, bytes.length)
+ defineClass(name, bytes, 0, bytes.length, protectionDomain)
+ }
+
+ lazy val protectionDomain = {
+ val cl = Thread.currentThread().getContextClassLoader()
+ val resource = cl.getResource("scala/runtime/package.class")
+ if (resource == null) null else {
+ val s = resource.getPath
+ val path = s.substring(0, s.lastIndexOf('!'))
+ new ProtectionDomain(new CodeSource(new URL(path), null.asInstanceOf[Array[Certificate]]), null, this, null)
+ }
}
private val packages = mutable.Map[String, Package]()
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 0104f5a57f..5f13baa107 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -13,6 +13,7 @@ import io.{ File, Directory, Path, Jar, AbstractFile }
import scala.reflect.internal.util.StringOps.splitWhere
import Jar.isJarOrZip
import File.pathSeparator
+import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
import java.net.MalformedURLException
import java.util.regex.PatternSyntaxException
@@ -121,8 +122,13 @@ object ClassPath {
private def classesInPathImpl(path: String, expand: Boolean) =
for (file <- expandPath(path, expand) ; dir <- Option(AbstractFile getDirectory file)) yield
newClassPath(dir)
+
+ def classesInManifest(used: Boolean) =
+ if (used) for (url <- manifests) yield newClassPath(AbstractFile getResources url) else Nil
}
+ def manifests = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF").filter(_.getProtocol() == "jar").toList
+
class JavaContext extends ClassPathContext[AbstractFile] {
def toBinaryName(rep: AbstractFile) = {
val name = rep.name
@@ -267,7 +273,7 @@ class SourcePath[T](dir: AbstractFile, val context: ClassPathContext[T]) extends
class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[AbstractFile]) extends ClassPath[AbstractFile] {
def name = dir.name
override def origin = dir.underlyingSource map (_.path)
- def asURLs = if (dir.file == null) Nil else List(dir.toURL)
+ def asURLs = if (dir.file == null) List(new URL(name)) else List(dir.toURL)
def asClasspathString = dir.path
val sourcepaths: IndexedSeq[AbstractFile] = IndexedSeq()
diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala
index 9f1d0317be..d8e545e6b1 100644
--- a/src/compiler/scala/tools/util/PathResolver.scala
+++ b/src/compiler/scala/tools/util/PathResolver.scala
@@ -170,6 +170,7 @@ class PathResolver(settings: Settings, context: JavaContext) {
object Calculated {
def scalaHome = Defaults.scalaHome
def useJavaClassPath = settings.usejavacp.value || Defaults.useJavaClassPath
+ def useManifestClassPath= settings.usemanifestcp.value
def javaBootClassPath = cmdLineOrElse("javabootclasspath", Defaults.javaBootClassPath)
def javaExtDirs = cmdLineOrElse("javaextdirs", Defaults.javaExtDirs)
def javaUserClassPath = if (useJavaClassPath) Defaults.javaUserClassPath else ""
@@ -209,6 +210,7 @@ class PathResolver(settings: Settings, context: JavaContext) {
classesInPath(scalaBootClassPath), // 4. The Scala boot class path.
contentsOfDirsInPath(scalaExtDirs), // 5. The Scala extension class path.
classesInExpandedPath(userClassPath), // 6. The Scala application class path.
+ classesInManifest(useManifestClassPath), // 8. The Manifest class path.
sourcesInPath(sourcePath) // 7. The Scala source path.
)
diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath
index 75a9fae19a..a990c5a1b3 100644
--- a/src/eclipse/partest/.classpath
+++ b/src/eclipse/partest/.classpath
@@ -10,5 +10,6 @@
<classpathentry kind="lib" path="lib/jline.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/asm"/>
<classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/repl"/>
<classpathentry kind="output" path="build-quick-partest"/>
</classpath>
diff --git a/src/eclipse/repl/.classpath b/src/eclipse/repl/.classpath
new file mode 100644
index 0000000000..30744da306
--- /dev/null
+++ b/src/eclipse/repl/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="repl"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/reflect"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/lib/jline.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/asm"/>
+ <classpathentry kind="output" path="build-quick-repl"/>
+</classpath>
diff --git a/src/eclipse/repl/.project b/src/eclipse/repl/.project
new file mode 100644
index 0000000000..ea188bc262
--- /dev/null
+++ b/src/eclipse/repl/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>repl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.scala-ide.sdt.core.scalabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.scala-ide.sdt.core.scalanature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>build-quick-repl</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/build/quick/classes/repl</locationURI>
+ </link>
+ <link>
+ <name>lib</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/lib</locationURI>
+ </link>
+ <link>
+ <name>repl</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/src/repl</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/src/eclipse/scaladoc/.classpath b/src/eclipse/scaladoc/.classpath
index 422b8fbb07..f12ba4bb2c 100644
--- a/src/eclipse/scaladoc/.classpath
+++ b/src/eclipse/scaladoc/.classpath
@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry combineaccessrules="false" kind="src" path="/partest"/>
<classpathentry kind="src" path="scaladoc"/>
<classpathentry combineaccessrules="false" kind="src" path="/reflect"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/lib/ant/ant.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/asm"/>
<classpathentry kind="output" path="build-quick-scaladoc"/>
</classpath>
diff --git a/src/interactive/scala/tools/nsc/interactive/RangePositions.scala b/src/interactive/scala/tools/nsc/interactive/RangePositions.scala
index c57e1da184..a24be50b33 100644
--- a/src/interactive/scala/tools/nsc/interactive/RangePositions.scala
+++ b/src/interactive/scala/tools/nsc/interactive/RangePositions.scala
@@ -7,8 +7,9 @@ package scala.tools.nsc
package interactive
@deprecated("Use scala.reflect.internal.Positions", "2.11.0")
-trait RangePositions extends scala.reflect.internal.Positions with ast.Trees with ast.Positions {
+trait RangePositions extends {
+ override val useOffsetPositions = false
+} with scala.reflect.internal.Positions with ast.Trees with ast.Positions {
self: scala.tools.nsc.Global =>
- override def useOffsetPositions = false
}
diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala
index 0d6ba2454c..9def6cb054 100644
--- a/src/library/scala/AnyVal.scala
+++ b/src/library/scala/AnyVal.scala
@@ -52,6 +52,6 @@ package scala
* as well as in [[http://docs.scala-lang.org/sips/pending/value-classes.html SIP-15: Value Classes]],
* the Scala Improvement Proposal.
*/
-abstract class AnyVal extends Any with NotNull {
+abstract class AnyVal extends Any {
def getClass(): Class[_ <: AnyVal] = null
}
diff --git a/src/library/scala/NotNull.scala b/src/library/scala/NotNull.scala
index f87416b49d..3cbe9ed4ac 100644
--- a/src/library/scala/NotNull.scala
+++ b/src/library/scala/NotNull.scala
@@ -12,4 +12,6 @@ package scala
* A marker trait for things that are not allowed to be null
* @since 2.5
*/
+
+@deprecated("This trait will be removed", "2.11.0")
trait NotNull extends Any {}
diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala
index 37b8ecfbc4..48bccde0e8 100644
--- a/src/library/scala/collection/immutable/RedBlackTree.scala
+++ b/src/library/scala/collection/immutable/RedBlackTree.scala
@@ -325,54 +325,56 @@ object RedBlackTree {
// whether the zipper was traversed left-most or right-most.
// If the trees were balanced, returns an empty zipper
- private[this] def compareDepth[A, B](left: Tree[A, B], right: Tree[A, B]): (List[Tree[A, B]], Boolean, Boolean, Int) = {
+ private[this] def compareDepth[A, B](left: Tree[A, B], right: Tree[A, B]): (NList[Tree[A, B]], Boolean, Boolean, Int) = {
+ import NList.cons
// Once a side is found to be deeper, unzip it to the bottom
- def unzip(zipper: List[Tree[A, B]], leftMost: Boolean): List[Tree[A, B]] = {
+ def unzip(zipper: NList[Tree[A, B]], leftMost: Boolean): NList[Tree[A, B]] = {
val next = if (leftMost) zipper.head.left else zipper.head.right
- next match {
- case null => zipper
- case node => unzip(node :: zipper, leftMost)
- }
+ if (next eq null) zipper
+ else unzip(cons(next, zipper), leftMost)
}
// Unzip left tree on the rightmost side and right tree on the leftmost side until one is
// found to be deeper, or the bottom is reached
def unzipBoth(left: Tree[A, B],
right: Tree[A, B],
- leftZipper: List[Tree[A, B]],
- rightZipper: List[Tree[A, B]],
- smallerDepth: Int): (List[Tree[A, B]], Boolean, Boolean, Int) = {
+ leftZipper: NList[Tree[A, B]],
+ rightZipper: NList[Tree[A, B]],
+ smallerDepth: Int): (NList[Tree[A, B]], Boolean, Boolean, Int) = {
if (isBlackTree(left) && isBlackTree(right)) {
- unzipBoth(left.right, right.left, left :: leftZipper, right :: rightZipper, smallerDepth + 1)
+ unzipBoth(left.right, right.left, cons(left, leftZipper), cons(right, rightZipper), smallerDepth + 1)
} else if (isRedTree(left) && isRedTree(right)) {
- unzipBoth(left.right, right.left, left :: leftZipper, right :: rightZipper, smallerDepth)
+ unzipBoth(left.right, right.left, cons(left, leftZipper), cons(right, rightZipper), smallerDepth)
} else if (isRedTree(right)) {
- unzipBoth(left, right.left, leftZipper, right :: rightZipper, smallerDepth)
+ unzipBoth(left, right.left, leftZipper, cons(right, rightZipper), smallerDepth)
} else if (isRedTree(left)) {
- unzipBoth(left.right, right, left :: leftZipper, rightZipper, smallerDepth)
+ unzipBoth(left.right, right, cons(left, leftZipper), rightZipper, smallerDepth)
} else if ((left eq null) && (right eq null)) {
- (Nil, true, false, smallerDepth)
+ (null, true, false, smallerDepth)
} else if ((left eq null) && isBlackTree(right)) {
val leftMost = true
- (unzip(right :: rightZipper, leftMost), false, leftMost, smallerDepth)
+ (unzip(cons(right, rightZipper), leftMost), false, leftMost, smallerDepth)
} else if (isBlackTree(left) && (right eq null)) {
val leftMost = false
- (unzip(left :: leftZipper, leftMost), false, leftMost, smallerDepth)
+ (unzip(cons(left, leftZipper), leftMost), false, leftMost, smallerDepth)
} else {
sys.error("unmatched trees in unzip: " + left + ", " + right)
}
}
- unzipBoth(left, right, Nil, Nil, 0)
+ unzipBoth(left, right, null, null, 0)
}
private[this] def rebalance[A, B](tree: Tree[A, B], newLeft: Tree[A, B], newRight: Tree[A, B]) = {
// This is like drop(n-1), but only counting black nodes
- def findDepth(zipper: List[Tree[A, B]], depth: Int): List[Tree[A, B]] = zipper match {
- case head :: tail if isBlackTree(head) =>
- if (depth == 1) zipper else findDepth(tail, depth - 1)
- case _ :: tail => findDepth(tail, depth)
- case Nil => sys.error("Defect: unexpected empty zipper while computing range")
- }
+ @tailrec
+ def findDepth(zipper: NList[Tree[A, B]], depth: Int): NList[Tree[A, B]] =
+ if (zipper eq null) {
+ sys.error("Defect: unexpected empty zipper while computing range")
+ } else if (isBlackTree(zipper.head)) {
+ if (depth == 1) zipper else findDepth(zipper.tail, depth - 1)
+ } else {
+ findDepth(zipper.tail, depth)
+ }
// Blackening the smaller tree avoids balancing problems on union;
// this can't be done later, though, or it would change the result of compareDepth
@@ -389,7 +391,7 @@ object RedBlackTree {
} else {
RedTree(tree.key, tree.value, zipFrom.head, blkNewRight)
}
- val zippedTree = zipFrom.tail.foldLeft(union: Tree[A, B]) { (tree, node) =>
+ val zippedTree = NList.foldLeft(zipFrom.tail, union: Tree[A, B]) { (tree, node) =>
if (leftMost)
balanceLeft(isBlackTree(node), node.key, node.value, tree, node.right)
else
@@ -398,6 +400,25 @@ object RedBlackTree {
zippedTree
}
}
+
+ // Null optimized list implementation for tree rebalancing. null presents Nil.
+ private[this] final class NList[A](val head: A, val tail: NList[A])
+
+ private[this] final object NList {
+
+ def cons[B](x: B, xs: NList[B]): NList[B] = new NList(x, xs)
+
+ def foldLeft[A, B](xs: NList[A], z: B)(f: (B, A) => B): B = {
+ var acc = z
+ var these = xs
+ while (these ne null) {
+ acc = f(acc, these.head)
+ these = these.tail
+ }
+ acc
+ }
+
+ }
/*
* Forcing direct fields access using the @inline annotation helps speed up
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
index 2a535a799c..397f8099eb 100644
--- a/src/library/scala/collection/mutable/BitSet.scala
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -58,6 +58,11 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int]
if (idx < nwords) elems(idx) else 0L
private def updateWord(idx: Int, w: Long) {
+ ensureCapacity(idx)
+ elems(idx) = w
+ }
+
+ private def ensureCapacity(idx: Int) {
if (idx >= nwords) {
var newlen = nwords
while (idx >= newlen) newlen = newlen * 2
@@ -65,7 +70,6 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int]
Array.copy(elems, 0, elems1, 0, nwords)
elems = elems1
}
- elems(idx) = w
}
protected def fromBitMaskNoCopy(words: Array[Long]): BitSet = new BitSet(words)
@@ -92,6 +96,51 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int]
def += (elem: Int): this.type = { add(elem); this }
def -= (elem: Int): this.type = { remove(elem); this }
+ /** Updates this bitset to the union with another bitset by performing a bitwise "or".
+ *
+ * @param other the bitset to form the union with.
+ * @return the bitset itself.
+ */
+ def |= (other: BitSet): this.type = {
+ ensureCapacity(other.nwords)
+ for (i <- 0 until other.nwords)
+ elems(i) = elems(i) | other.word(i)
+ this
+ }
+ /** Updates this bitset to the intersection with another bitset by performing a bitwise "and".
+ *
+ * @param other the bitset to form the intersection with.
+ * @return the bitset itself.
+ */
+ def &= (other: BitSet): this.type = {
+ ensureCapacity(other.nwords)
+ for (i <- 0 until other.nwords)
+ elems(i) = elems(i) & other.word(i)
+ this
+ }
+ /** Updates this bitset to the symmetric difference with another bitset by performing a bitwise "xor".
+ *
+ * @param other the bitset to form the symmetric difference with.
+ * @return the bitset itself.
+ */
+ def ^= (other: BitSet): this.type = {
+ ensureCapacity(other.nwords)
+ for (i <- 0 until other.nwords)
+ elems(i) = elems(i) ^ other.word(i)
+ this
+ }
+ /** Updates this bitset to the difference with another bitset by performing a bitwise "and-not".
+ *
+ * @param other the bitset to form the difference with.
+ * @return the bitset itself.
+ */
+ def &~= (other: BitSet): this.type = {
+ ensureCapacity(other.nwords)
+ for (i <- 0 until other.nwords)
+ elems(i) = elems(i) & ~other.word(i)
+ this
+ }
+
override def clear() {
elems = new Array[Long](elems.length)
}
diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala
index 9bed5be51b..1ab41bd296 100644
--- a/src/library/scala/collection/parallel/TaskSupport.scala
+++ b/src/library/scala/collection/parallel/TaskSupport.scala
@@ -17,28 +17,25 @@ import scala.concurrent.ExecutionContext
-/** A trait implementing the scheduling of
- * a parallel collection operation.
+/** A trait implementing the scheduling of a parallel collection operation.
*
* Parallel collections are modular in the way operations are scheduled. Each
* parallel collection is parametrized with a task support object which is
* responsible for scheduling and load-balancing tasks to processors.
- *
+ *
* A task support object can be changed in a parallel collection after it has
* been created, but only during a quiescent period, i.e. while there are no
* concurrent invocations to parallel collection methods.
*
* There are currently a few task support implementations available for
* parallel collections. The [[scala.collection.parallel.ForkJoinTaskSupport]]
- * uses a fork-join pool
- * internally and is used by default on JVM 1.6 or greater. The less efficient
- * [[scala.collection.parallel.ThreadPoolTaskSupport]] is a fallback for JVM
- * 1.5 and JVMs that do not support the fork join pools. The
- * [[scala.collection.parallel.ExecutionContextTaskSupport]] uses the
+ * uses a fork-join pool internally.
+ *
+ * The [[scala.collection.parallel.ExecutionContextTaskSupport]] uses the
* default execution context implementation found in scala.concurrent, and it
- * reuses the thread pool used in scala.concurrent (this is either a fork join
- * pool or a thread pool executor, depending on the JVM version). The
- * execution context task support is set to each parallel collection by
+ * reuses the thread pool used in scala.concurrent.
+ *
+ * The execution context task support is set to each parallel collection by
* default, so parallel collections reuse the same fork-join pool as the
* future API.
*
@@ -68,17 +65,18 @@ extends TaskSupport with AdaptiveWorkStealingForkJoinTasks
*
* @see [[scala.collection.parallel.TaskSupport]] for more information.
*/
+@deprecated("Use `ForkJoinTaskSupport` instead.", "2.11.0")
class ThreadPoolTaskSupport(val environment: ThreadPoolExecutor = ThreadPoolTasks.defaultThreadPool)
extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks
/** A task support that uses an execution context to schedule tasks.
- *
+ *
* It can be used with the default execution context implementation in the
* `scala.concurrent` package. It internally forwards the call to either a
* forkjoin based task support or a thread pool executor one, depending on
* what the execution context uses.
- *
+ *
* By default, parallel collections are parametrized with this task support
* object, so parallel collections share the same execution context backend
* as the rest of the `scala.concurrent` package.
diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala
index 441c4269c3..487b3d46d3 100644
--- a/src/library/scala/collection/parallel/Tasks.scala
+++ b/src/library/scala/collection/parallel/Tasks.scala
@@ -214,6 +214,7 @@ trait AdaptiveWorkStealingTasks extends Tasks {
/** An implementation of tasks objects based on the Java thread pooling API. */
+@deprecated("Use `ForkJoinTasks` instead.", "2.11.0")
trait ThreadPoolTasks extends Tasks {
import java.util.concurrent._
@@ -322,6 +323,7 @@ trait ThreadPoolTasks extends Tasks {
}
+@deprecated("Use `ForkJoinTasks` instead.", "2.11.0")
object ThreadPoolTasks {
import java.util.concurrent._
@@ -455,7 +457,7 @@ trait AdaptiveWorkStealingForkJoinTasks extends ForkJoinTasks with AdaptiveWorkS
}
-
+@deprecated("Use `AdaptiveWorkStealingForkJoinTasks` instead.", "2.11.0")
trait AdaptiveWorkStealingThreadPoolTasks extends ThreadPoolTasks with AdaptiveWorkStealingTasks {
class WrappedTask[R, Tp](val body: Task[R, Tp])
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index fe5a5c81e2..55954196f6 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -281,7 +281,7 @@ trait Definitions extends api.StandardDefinitions {
def Predef_AnyRef = AnyRefModule
lazy val AnyValClass: ClassSymbol = (ScalaPackageClass.info member tpnme.AnyVal orElse {
- val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, List(AnyClass.tpe, NotNullClass.tpe), ABSTRACT)
+ val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, AnyClass.tpe :: Nil, ABSTRACT)
val av_constr = anyval.newClassConstructor(NoPosition)
anyval.info.decls enter av_constr
anyval
@@ -383,7 +383,6 @@ trait Definitions extends api.StandardDefinitions {
lazy val StringAddClass = requiredClass[scala.runtime.StringAdd]
lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc") // SI-5731
lazy val StringAdd_+ = getMemberMethod(StringAddClass, nme.PLUS)
- lazy val NotNullClass = getRequiredClass("scala.NotNull")
lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber]
lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter]
lazy val DelayedInitClass = requiredClass[scala.DelayedInit]
@@ -1131,7 +1130,7 @@ trait Definitions extends api.StandardDefinitions {
/** Is type's symbol a numeric value class? */
def isNumericValueType(tp: Type): Boolean = tp match {
case TypeRef(_, sym, _) => isNumericValueClass(sym)
- case _ => false
+ case _ => false
}
// todo: reconcile with javaSignature!!!
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 1987f34474..fe46a0471e 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -307,7 +307,11 @@ class Flags extends ModifierFlags {
assert((OverloadedFlagsMask & FlagsNotPickled) == 0, flagsToString(OverloadedFlagsMask & FlagsNotPickled))
/** These flags are pickled */
- final val PickledFlags = InitialFlags & ~FlagsNotPickled
+ final val PickledFlags = (
+ (InitialFlags & ~FlagsNotPickled)
+ | notPRIVATE // for value class constructors (SI-6601), and private members referenced
+ // in @inline-marked methods publicized in SuperAccessors (see SI-6608, e6b4204604)
+ )
/** If we have a top-level class or module
* and someone asks us for a flag not in TopLevelPickledFlags,
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index 53410b29c5..f736202e13 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -248,8 +248,6 @@ trait Importers extends api.Importers { self: SymbolTable =>
AntiPolyType(importType(pre), targs map importType)
case x: from.TypeVar =>
TypeVar(importType(x.origin), importTypeConstraint(x.constr), x.typeArgs map importType, x.params map importSymbol)
- case from.NotNullType(tpe) =>
- NotNullType(importType(tpe))
case from.AnnotatedType(annots, tpe, selfsym) =>
AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym))
case from.ErrorType =>
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 6837f37445..c881de7830 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -1671,6 +1671,19 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* and is this class symbol also different from Null or Nothing? */
def isNonBottomSubClass(that: Symbol): Boolean = false
+ /** Is this class symbol Null or Nothing,
+ * and (if Null) is `that` inhabited by null?
+ * If this is Nothing, of course, it is a
+ * subclass of `that` by definition.
+ *
+ * TODO - what is implied by the fact that AnyVal now has
+ * infinitely many non-bottom subclasses, not only 9?
+ */
+ def isBottomSubClass(that: Symbol) = (
+ (this eq NothingClass)
+ || (this eq NullClass) && that.isClass && (that ne NothingClass) && !(that isNonBottomSubClass AnyValClass)
+ )
+
/** Overridden in NullClass and NothingClass for custom behavior.
*/
def isSubClass(that: Symbol) = isNonBottomSubClass(that)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index a6c5367425..a678edbe01 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -131,7 +131,6 @@ trait Types
override def isTrivial = underlying.isTrivial
override def isHigherKinded: Boolean = underlying.isHigherKinded
override def typeConstructor: Type = underlying.typeConstructor
- override def isNotNull = underlying.isNotNull
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
override def isStable: Boolean = underlying.isStable
@@ -187,7 +186,6 @@ trait Types
override def params: List[Symbol] = List()
override def paramTypes: List[Type] = List()
override def typeArgs = underlying.typeArgs
- override def notNull = maybeRewrap(underlying.notNull)
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = underlying.instantiateTypeParams(formals, actuals)
override def skolemizeExistential(owner: Symbol, origin: AnyRef) = underlying.skolemizeExistential(owner, origin)
override def normalize = maybeRewrap(underlying.normalize)
@@ -275,9 +273,6 @@ trait Types
*/
def isVolatile: Boolean = false
- /** Is this type guaranteed not to have `null` as a value? */
- def isNotNull: Boolean = false
-
/** Is this type a structural refinement type (it ''refines'' members that have not been inherited) */
def isStructuralRefinement: Boolean = false
@@ -462,13 +457,6 @@ trait Types
* the empty list for all other types */
def boundSyms: immutable.Set[Symbol] = emptySymbolSet
- /** Mixin a NotNull trait unless type already has one
- * ...if the option is given, since it is causing typing bugs.
- */
- def notNull: Type =
- if (!settings.Ynotnull.value || isNotNull || phase.erasedTypes) this
- else NotNullType(this)
-
/** Replace formal type parameter symbols with actual type arguments.
*
* Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- @M
@@ -1209,17 +1197,6 @@ trait Types
override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq
override def baseTypeSeqDepth: Int = supertype.baseTypeSeqDepth
override def baseClasses: List[Symbol] = supertype.baseClasses
- override def isNotNull = supertype.isNotNull
- }
-
- case class NotNullType(override val underlying: Type) extends SubType with RewrappingTypeProxy {
- def supertype = underlying
- protected def rewrap(newtp: Type): Type = NotNullType(newtp)
- override def isNotNull: Boolean = true
- override def notNull = this
- override def deconst: Type = underlying //todo: needed?
- override def safeToString: String = underlying.toString + " with NotNull"
- override def kind = "NotNullType"
}
/** A base class for types that represent a single value
@@ -1324,7 +1301,6 @@ trait Types
}
override def isTrivial: Boolean = sym.isPackageClass
- override def isNotNull = true
override def typeSymbol = sym
override def underlying: Type = sym.typeOfThis
override def isVolatile = false
@@ -1363,7 +1339,6 @@ trait Types
}
override def isGround = sym.isPackageClass || pre.isGround
- override def isNotNull = underlying.isNotNull
private[reflect] var underlyingCache: Type = NoType
private[reflect] var underlyingPeriod = NoPeriod
override def underlying: Type = {
@@ -1430,8 +1405,6 @@ trait Types
if (trivial == UNKNOWN) trivial = fromBoolean(thistpe.isTrivial && supertpe.isTrivial)
toBoolean(trivial)
}
- override def isNotNull = true
-
override def typeSymbol = thistpe.typeSymbol
override def underlying = supertpe
override def prefix: Type = supertpe.prefix
@@ -1544,7 +1517,6 @@ trait Types
}
override def narrow: Type = typeSymbol.thisType
- override def isNotNull: Boolean = parents exists typeIsNotNull
override def isStructuralRefinement: Boolean =
typeSymbol.isAnonOrRefinementClass && (decls exists symbolIsPossibleInRefinement)
@@ -1988,8 +1960,7 @@ trait Types
override def underlying: Type = value.tpe
assert(underlying.typeSymbol != UnitClass)
override def isTrivial: Boolean = true
- override def isNotNull = value.value != null
- override def deconst: Type = underlying
+ override def deconst: Type = underlying.deconst
override def safeToString: String =
underlying.toString + "(" + value.escapedStringValue + ")"
override def kind = "ConstantType"
@@ -2042,7 +2013,6 @@ trait Types
narrowedCache
}
- final override def isNotNull = true
override protected def finishPrefix(rest: String) = objectPrefix + rest
override def directObjectString = super.safeToString
override def toLongString = toString
@@ -2347,9 +2317,6 @@ trait Types
override def typeSymbol = sym
override def typeSymbolDirect = sym
- override def isNotNull =
- sym.isModuleClass || sym == NothingClass || (sym isNonBottomSubClass NotNullClass) || super.isNotNull
-
override def parents: List[Type] = {
val cache = parentsCache
if (parentsPeriod == currentPeriod && cache != null) cache
@@ -2958,6 +2925,12 @@ trait Types
origin: Type,
var constr: TypeConstraint
) extends Type {
+
+ // We don't want case class equality/hashing as TypeVar-s are mutable,
+ // and TypeRefs based on them get wrongly `uniqued` otherwise. See SI-7226.
+ override def hashCode(): Int = System.identityHashCode(this)
+ override def equals(other: Any): Boolean = this eq other.asInstanceOf[AnyRef]
+
def untouchable = false // by other typevars
override def params: List[Symbol] = Nil
override def typeArgs: List[Type] = Nil
@@ -4078,24 +4051,22 @@ trait Types
corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg)
}
- protected[internal] def containsNull(sym: Symbol): Boolean =
- sym.isClass && sym != NothingClass &&
- !(sym isNonBottomSubClass AnyValClass) &&
- !(sym isNonBottomSubClass NotNullClass)
-
- def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean =
- tp.typeSymbol == NothingClass ||
- tp.typeSymbol == NullClass && containsNull(sym.owner) || {
- def specializedBy(membr: Symbol): Boolean =
- membr == sym || specializesSym(tp.narrow, membr, sym.owner.thisType, sym, depth)
- val member = tp.nonPrivateMember(sym.name)
+ def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean = {
+ def directlySpecializedBy(member: Symbol): Boolean = (
+ member == sym
+ || specializesSym(tp.narrow, member, sym.owner.thisType, sym, depth)
+ )
+ // Closure reduction, else this would be simply `member exists directlySpecializedBy`
+ def specializedBy(member: Symbol): Boolean = (
if (member eq NoSymbol) false
- else if (member.isOverloaded) member.alternatives exists specializedBy
- else specializedBy(member)
- // was
- // (tp.nonPrivateMember(sym.name).alternatives exists
- // (alt => sym == alt || specializesSym(tp.narrow, alt, sym.owner.thisType, sym, depth)))
- }
+ else if (member.isOverloaded) member.alternatives exists directlySpecializedBy
+ else directlySpecializedBy(member)
+ )
+
+ ( (tp.typeSymbol isBottomSubClass sym.owner)
+ || specializedBy(tp nonPrivateMember sym.name)
+ )
+ }
/** Does member `sym1` of `tp1` have a stronger type
* than member `sym2` of `tp2`?
@@ -4508,7 +4479,6 @@ trait Types
// ----- Hoisted closures and convenience methods, for compile time reductions -------
- private[scala] val typeIsNotNull = (tp: Type) => tp.isNotNull
private[scala] val isTypeVar = (tp: Type) => tp.isInstanceOf[TypeVar]
private[scala] val typeContainsTypeVar = (tp: Type) => tp exists isTypeVar
private[scala] val typeIsNonClassType = (tp: Type) => tp.typeSymbolDirect.isNonClassType
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index 506edb861e..e7a1ea9311 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -35,7 +35,6 @@ abstract class MutableSettings extends AbsSettings {
def overrideObjects: BooleanSetting
def printtypes: BooleanSetting
def debug: BooleanSetting
- def Ynotnull: BooleanSetting
def explaintypes: BooleanSetting
def verbose: BooleanSetting
def uniqid: BooleanSetting
diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
index bdccc75d6d..5bdc5f8a73 100644
--- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
+++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
@@ -396,7 +396,7 @@ private[internal] trait GlbLubs {
indent = indent stripSuffix " "
println(indent + "lub of " + ts + " is " + res)//debug
}
- if (ts forall typeIsNotNull) res.notNull else res
+ res
}
val GlbFailure = new Throwable
@@ -536,13 +536,9 @@ private[internal] trait GlbLubs {
}
}
// if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG
-
if (Statistics.canEnable) Statistics.incCounter(nestedLubCount)
- val res = glb0(ts)
-
+ glb0(ts)
// if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG
-
- if (ts exists typeIsNotNull) res.notNull else res
}
/** All types in list must be polytypes with type parameter lists of
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 82321f61c2..d36aa0c927 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -5,6 +5,7 @@ package tpe
import scala.collection.{ mutable }
import Flags._
import util.Statistics
+import scala.annotation.tailrec
trait TypeComparers {
self: SymbolTable =>
@@ -73,14 +74,17 @@ trait TypeComparers {
// if (subsametypeRecursions == 0) undoLog.clear()
}
- def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = tp1 match {
- case TypeRef(pre1, sym1, _) =>
- tp2 match {
- case TypeRef(pre2, sym2, _) => sym1 != sym2 || isDifferentType(pre1, pre2)
- case _ => true
- }
- case _ => true
- }
+ def isDifferentTypeConstructor(tp1: Type, tp2: Type) = !isSameTypeConstructor(tp1, tp2)
+
+ private def isSameTypeConstructor(tr1: TypeRef, tr2: TypeRef): Boolean = (
+ (tr1.sym == tr2.sym)
+ && !isDifferentType(tr1.pre, tr2.pre)
+ )
+ private def isSameTypeConstructor(tp1: Type, tp2: Type): Boolean = (
+ tp1.isInstanceOf[TypeRef]
+ && tp2.isInstanceOf[TypeRef]
+ && isSameTypeConstructor(tp1.asInstanceOf[TypeRef], tp2.asInstanceOf[TypeRef])
+ )
/** Do `tp1` and `tp2` denote equivalent types? */
def isSameType(tp1: Type, tp2: Type): Boolean = try {
@@ -402,6 +406,9 @@ trait TypeComparers {
case tr2: TypeRef =>
tp1 match {
case tr1: TypeRef =>
+ // TODO - dedicate a method to TypeRef/TypeRef subtyping.
+ // These typerefs are pattern matched up and down far more
+ // than is necessary.
val sym1 = tr1.sym
val sym2 = tr2.sym
val pre1 = tr1.pre
@@ -464,33 +471,25 @@ trait TypeComparers {
def thirdTryRef(tp1: Type, tp2: TypeRef): Boolean = {
val sym2 = tp2.sym
+ def retry(lhs: Type, rhs: Type) = isSubType(lhs, rhs, depth)
+ def abstractTypeOnRight(lo: Type) = isDifferentTypeConstructor(tp2, lo) && retry(tp1, lo)
+ def classOnRight = (
+ if (isRawType(tp2)) retry(tp1, rawToExistential(tp2))
+ else if (sym2.isRefinementClass) retry(tp1, sym2.info)
+ else fourthTry
+ )
sym2 match {
- case NotNullClass => tp1.isNotNull
- case SingletonClass => tp1.isStable || fourthTry
- case _: ClassSymbol =>
- if (isRawType(tp2))
- isSubType(tp1, rawToExistential(tp2), depth)
- else if (sym2.name == tpnme.REFINE_CLASS_NAME)
- isSubType(tp1, sym2.info, depth)
- else
- fourthTry
- case _: TypeSymbol =>
- if (sym2 hasFlag DEFERRED) {
- val tp2a = tp2.bounds.lo
- isDifferentTypeConstructor(tp2, tp2a) &&
- isSubType(tp1, tp2a, depth) ||
- fourthTry
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- fourthTry
+ case SingletonClass => tp1.isStable || fourthTry
+ case _: ClassSymbol => classOnRight
+ case _: TypeSymbol if sym2.isDeferred => abstractTypeOnRight(tp2.bounds.lo) || fourthTry
+ case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
+ case _ => fourthTry
}
}
/** Third try, on the right:
* - decompose refined types.
- * - handle typerefs, existentials, and notnull types.
+ * - handle typerefs and existentials.
* - handle left+right method types, polytypes, typebounds
*/
def thirdTry = tp2 match {
@@ -501,8 +500,6 @@ trait TypeComparers {
(rt2.decls forall (specializesSym(tp1, _, depth)))
case et2: ExistentialType =>
et2.withTypeVars(isSubType(tp1, _, depth), depth) || fourthTry
- case nn2: NotNullType =>
- tp1.isNotNull && isSubType(tp1, nn2.underlying, depth)
case mt2: MethodType =>
tp1 match {
case mt1 @ MethodType(params1, res1) =>
@@ -536,46 +533,39 @@ trait TypeComparers {
}
/** Fourth try, on the left:
- * - handle typerefs, refined types, notnull and singleton types.
+ * - handle typerefs, refined types, and singleton types.
*/
- def fourthTry = tp1 match {
- case tr1 @ TypeRef(pre1, sym1, _) =>
- sym1 match {
- case NothingClass => true
- case NullClass =>
- tp2 match {
- case TypeRef(_, sym2, _) =>
- containsNull(sym2)
- case _ =>
- isSingleType(tp2) && isSubType(tp1, tp2.widen, depth)
- }
- case _: ClassSymbol =>
- if (isRawType(tp1))
- isSubType(rawToExistential(tp1), tp2, depth)
- else if (sym1.isModuleClass) tp2 match {
- case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
- case _ => false
- }
- else if (sym1.isRefinementClass)
- isSubType(sym1.info, tp2, depth)
- else false
-
- case _: TypeSymbol =>
- if (sym1 hasFlag DEFERRED) {
- val tp1a = tp1.bounds.hi
- isDifferentTypeConstructor(tp1, tp1a) && isSubType(tp1a, tp2, depth)
- } else {
- isSubType(tp1.normalize, tp2.normalize, depth)
- }
- case _ =>
- false
- }
- case RefinedType(parents1, _) =>
- parents1 exists (isSubType(_, tp2, depth))
- case _: SingletonType | _: NotNullType =>
- isSubType(tp1.underlying, tp2, depth)
- case _ =>
- false
+ def fourthTry = {
+ def retry(lhs: Type, rhs: Type) = isSubType(lhs, rhs, depth)
+ def abstractTypeOnLeft(hi: Type) = isDifferentTypeConstructor(tp1, hi) && retry(hi, tp2)
+
+ tp1 match {
+ case tr1 @ TypeRef(pre1, sym1, _) =>
+ def nullOnLeft = tp2 match {
+ case TypeRef(_, sym2, _) => sym1 isBottomSubClass sym2
+ case _ => isSingleType(tp2) && retry(tp1, tp2.widen)
+ }
+ def moduleOnLeft = tp2 match {
+ case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
+ case _ => false
+ }
+ def classOnLeft = (
+ if (isRawType(tp1)) retry(rawToExistential(tp1), tp2)
+ else if (sym1.isModuleClass) moduleOnLeft
+ else sym1.isRefinementClass && retry(sym1.info, tp2)
+ )
+ sym1 match {
+ case NothingClass => true
+ case NullClass => nullOnLeft
+ case _: ClassSymbol => classOnLeft
+ case _: TypeSymbol if sym1.isDeferred => abstractTypeOnLeft(tp1.bounds.hi)
+ case _: TypeSymbol => retry(tp1.normalize, tp2.normalize)
+ case _ => false
+ }
+ case RefinedType(parents, _) => parents exists (retry(_, tp2))
+ case _: SingletonType => retry(tp1.underlying, tp2)
+ case _ => false
+ }
}
firstTry
@@ -583,9 +573,9 @@ trait TypeComparers {
def isWeakSubType(tp1: Type, tp2: Type) =
- tp1.deconst.normalize match {
+ tp1.dealiasWiden match {
case TypeRef(_, sym1, _) if isNumericValueClass(sym1) =>
- tp2.deconst.normalize match {
+ tp2.deconst.dealias match {
case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
isNumericSubClass(sym1, sym2)
case tv2 @ TypeVar(_, _) =>
@@ -594,7 +584,7 @@ trait TypeComparers {
isSubType(tp1, tp2)
}
case tv1 @ TypeVar(_, _) =>
- tp2.deconst.normalize match {
+ tp2.deconst.dealias match {
case TypeRef(_, sym2, _) if isNumericValueClass(sym2) =>
tv1.registerBound(tp2, isLowerBound = false, isNumericBound = true)
case _ =>
@@ -604,14 +594,18 @@ trait TypeComparers {
isSubType(tp1, tp2)
}
- /** The isNumericValueType tests appear redundant, but without them
- * test/continuations-neg/function3.scala goes into an infinite loop.
- * (Even if the calls are to typeSymbolDirect.)
- */
- def isNumericSubType(tp1: Type, tp2: Type): Boolean = (
- isNumericValueType(tp1)
- && isNumericValueType(tp2)
- && isNumericSubClass(tp1.typeSymbol, tp2.typeSymbol)
- )
-
+ def isNumericSubType(tp1: Type, tp2: Type) = (
+ isNumericSubClass(primitiveBaseClass(tp1.dealiasWiden), primitiveBaseClass(tp2.dealias))
+ )
+
+ /** If the given type has a primitive class among its base classes,
+ * the symbol of that class. Otherwise, NoSymbol.
+ */
+ private def primitiveBaseClass(tp: Type): Symbol = {
+ @tailrec def loop(bases: List[Symbol]): Symbol = bases match {
+ case Nil => NoSymbol
+ case x :: xs => if (isPrimitiveValueClass(x)) x else loop(xs)
+ }
+ loop(tp.baseClasses)
+ }
}
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 51363c0f82..d225f2f087 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -174,10 +174,6 @@ private[internal] trait TypeMaps {
case tv@TypeVar(_, constr) =>
if (constr.instValid) this(constr.inst)
else tv.applyArgs(mapOverArgs(tv.typeArgs, tv.params)) //@M !args.isEmpty implies !typeParams.isEmpty
- case NotNullType(tp) =>
- val tp1 = this(tp)
- if (tp1 eq tp) tp
- else NotNullType(tp1)
case AnnotatedType(annots, atp, selfsym) =>
val annots1 = mapOverAnnotations(annots)
val atp1 = this(atp)
@@ -1135,7 +1131,6 @@ private[internal] trait TypeMaps {
case TypeBounds(_, _) => mapOver(tp)
case TypeVar(_, _) => mapOver(tp)
case AnnotatedType(_,_,_) => mapOver(tp)
- case NotNullType(_) => mapOver(tp)
case ExistentialType(_, _) => mapOver(tp)
case _ => tp
}
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index d83b4d71d9..b8a8e4d0c0 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -125,7 +125,7 @@ trait Erasure {
if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe
else if (args.head.typeSymbol.isBottomClass) ObjectArray
else typeRef(apply(pre), sym, args map applyInArray)
- else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) ErasedObject
+ else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) ErasedObject
else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass)
else if (sym.isRefinementClass) apply(mergeParents(tp.parents))
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
diff --git a/src/reflect/scala/reflect/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala
index 4d6f14c71d..8b69efc749 100644
--- a/src/reflect/scala/reflect/io/AbstractFile.scala
+++ b/src/reflect/scala/reflect/io/AbstractFile.scala
@@ -7,7 +7,7 @@
package scala.reflect
package io
-import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream }
+import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream, ByteArrayOutputStream }
import java.io.{ File => JFile }
import java.net.URL
import scala.collection.mutable.ArrayBuffer
@@ -54,6 +54,8 @@ object AbstractFile {
if (url == null || !Path.isExtensionJarOrZip(url.getPath)) null
else ZipArchive fromURL url
}
+
+ def getResources(url: URL): AbstractFile = ZipArchive fromManifestURL url
}
/**
@@ -156,16 +158,28 @@ abstract class AbstractFile extends Iterable[AbstractFile] {
@throws(classOf[IOException])
def toByteArray: Array[Byte] = {
val in = input
- var rest = sizeOption.getOrElse(0)
- val arr = new Array[Byte](rest)
- while (rest > 0) {
- val res = in.read(arr, arr.length - rest, rest)
- if (res == -1)
- throw new IOException("read error")
- rest -= res
+ sizeOption match {
+ case Some(size) =>
+ var rest = size
+ val arr = new Array[Byte](rest)
+ while (rest > 0) {
+ val res = in.read(arr, arr.length - rest, rest)
+ if (res == -1)
+ throw new IOException("read error")
+ rest -= res
+ }
+ in.close()
+ arr
+ case None =>
+ val out = new ByteArrayOutputStream()
+ var c = in.read()
+ while(c != -1) {
+ out.write(c)
+ c = in.read()
+ }
+ in.close()
+ out.toByteArray()
}
- in.close()
- arr
}
/** Returns all abstract subfiles of this abstract directory. */
diff --git a/src/reflect/scala/reflect/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala
index 3b5d3079cd..44fb41a1cd 100644
--- a/src/reflect/scala/reflect/io/Path.scala
+++ b/src/reflect/scala/reflect/io/Path.scala
@@ -56,10 +56,11 @@ object Path {
def roots: List[Path] = java.io.File.listRoots().toList map Path.apply
def apply(path: String): Path = apply(new JFile(path))
- def apply(jfile: JFile): Path =
+ def apply(jfile: JFile): Path = try {
if (jfile.isFile) new File(jfile)
else if (jfile.isDirectory) new Directory(jfile)
else new Path(jfile)
+ } catch { case ex: SecurityException => new Path(jfile) }
/** Avoiding any shell/path issues by only using alphanumerics. */
private[io] def randomPrefix = alphanumeric take 6 mkString ""
@@ -186,10 +187,10 @@ class Path private[io] (val jfile: JFile) {
// Boolean tests
def canRead = jfile.canRead()
def canWrite = jfile.canWrite()
- def exists = jfile.exists()
+ def exists = try jfile.exists() catch { case ex: SecurityException => false }
- def isFile = jfile.isFile()
- def isDirectory = jfile.isDirectory()
+ def isFile = try jfile.isFile() catch { case ex: SecurityException => false }
+ def isDirectory = try jfile.isDirectory() catch { case ex: SecurityException => false }
def isAbsolute = jfile.isAbsolute()
def isEmpty = path.length == 0
diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala
index 5414441e00..1342fde3c5 100644
--- a/src/reflect/scala/reflect/io/ZipArchive.scala
+++ b/src/reflect/scala/reflect/io/ZipArchive.scala
@@ -7,10 +7,12 @@ package scala.reflect
package io
import java.net.URL
-import java.io.{ IOException, InputStream, ByteArrayInputStream }
+import java.io.{ IOException, InputStream, ByteArrayInputStream, FilterInputStream }
import java.io.{ File => JFile }
import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream }
+import java.util.jar.Manifest
import scala.collection.{ immutable, mutable }
+import scala.collection.convert.WrapAsScala.asScalaIterator
import scala.annotation.tailrec
/** An abstraction for zip files and streams. Everything is written the way
@@ -39,6 +41,8 @@ object ZipArchive {
*/
def fromURL(url: URL): URLZipArchive = new URLZipArchive(url)
+ def fromManifestURL(url: URL): AbstractFile = new ManifestResources(url)
+
private def dirName(path: String) = splitPath(path, front = true)
private def baseName(path: String) = splitPath(path, front = false)
private def splitPath(path0: String, front: Boolean): String = {
@@ -227,3 +231,59 @@ final class URLZipArchive(val url: URL) extends ZipArchive(null) {
case _ => false
}
}
+
+final class ManifestResources(val url: URL) extends ZipArchive(null) {
+ def iterator = {
+ val root = new DirEntry("/")
+ val dirs = mutable.HashMap[String, DirEntry]("/" -> root)
+ val manifest = new Manifest(input)
+ val iter = manifest.getEntries().keySet().iterator().filter(_.endsWith(".class")).map(new ZipEntry(_))
+
+ while (iter.hasNext) {
+ val zipEntry = iter.next()
+ val dir = getDir(dirs, zipEntry)
+ if (zipEntry.isDirectory) dir
+ else {
+ class FileEntry() extends Entry(zipEntry.getName) {
+ override def lastModified = zipEntry.getTime()
+ override def input = resourceInputStream(path)
+ override def sizeOption = None
+ }
+ val f = new FileEntry()
+ dir.entries(f.name) = f
+ }
+ }
+
+ try root.iterator
+ finally dirs.clear()
+ }
+
+ def name = path
+ def path: String = url.getPath() match { case s => s.substring(0, s.lastIndexOf('!')) }
+ def input = url.openStream()
+ def lastModified =
+ try url.openConnection().getLastModified()
+ catch { case _: IOException => 0 }
+
+ override def canEqual(other: Any) = other.isInstanceOf[ManifestResources]
+ override def hashCode() = url.hashCode
+ override def equals(that: Any) = that match {
+ case x: ManifestResources => url == x.url
+ case _ => false
+ }
+
+ private def resourceInputStream(path: String): InputStream = {
+ new FilterInputStream(null) {
+ override def read(): Int = {
+ if(in == null) in = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+ if(in == null) throw new RuntimeException(path + " not found")
+ super.read();
+ }
+
+ override def close(): Unit = {
+ super.close();
+ in = null;
+ }
+ }
+ }
+}
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index 5d58fa96d6..6714bae1e0 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -33,7 +33,6 @@ private[reflect] class Settings extends MutableSettings {
val XfullLubs = new BooleanSetting(false)
val XnoPatmatAnalysis = new BooleanSetting(false)
val Xprintpos = new BooleanSetting(false)
- val Ynotnull = new BooleanSetting(false)
val Yshowsymkinds = new BooleanSetting(false)
val Yposdebug = new BooleanSetting(false)
val Yrangepos = new BooleanSetting(false)
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index cb2e3c32b8..c92777c13e 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -19,6 +19,11 @@ import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
import ScalaClassLoader.URLClassLoader
import scala.tools.nsc.util.Exceptional.unwrap
import scala.collection.{ mutable, immutable }
+import scala.reflect.BeanProperty
+import scala.util.Properties.versionString
+import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, SimpleBindings, CompiledScript, Compilable}
+import java.io.{ StringWriter, Reader }
+import java.util.Arrays
import IMain._
import java.util.concurrent.Future
import scala.reflect.runtime.{ universe => ru }
@@ -57,7 +62,7 @@ import StdReplTags._
* @author Moez A. Abdel-Gawad
* @author Lex Spoon
*/
-class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports {
+class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Settings, protected val out: JPrintWriter) extends AbstractScriptEngine(new SimpleBindings) with Compilable with Imports {
imain =>
object replOutput extends ReplOutput(settings.Yreploutdir) { }
@@ -100,7 +105,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
/** construct an interpreter that reports to Console */
+ def this(settings: Settings, out: JPrintWriter) = this(null, settings, out)
+ def this(factory: ScriptEngineFactory, settings: Settings) = this(factory, settings, new NewLinePrintWriter(new ConsoleWriter, true))
def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true))
+ def this(factory: ScriptEngineFactory) = this(factory, new Settings())
def this() = this(new Settings())
lazy val formatting: Formatting = new Formatting {
@@ -146,19 +154,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
def isInitializeComplete = _initializeComplete
- /** the public, go through the future compiler */
lazy val global: Global = {
- if (isInitializeComplete) _compiler
- else {
- // If init hasn't been called yet you're on your own.
- if (_isInitialized == null) {
- repldbg("Warning: compiler accessed before init set up. Assuming no postInit code.")
- initialize(())
- }
- // blocks until it is ; false means catastrophic failure
- if (_isInitialized.get()) _compiler
- else null
- }
+ if (!isInitializeComplete) _initialize()
+ _compiler
}
import global._
@@ -535,9 +533,82 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
*/
def interpret(line: String): IR.Result = interpret(line, synthetic = false)
def interpretSynthetic(line: String): IR.Result = interpret(line, synthetic = true)
- def interpret(line: String, synthetic: Boolean): IR.Result = {
- def loadAndRunReq(req: Request) = {
- classLoader.setAsContext()
+ def interpret(line: String, synthetic: Boolean): IR.Result = compile(line, synthetic) match {
+ case Left(result) => result
+ case Right(req) => new WrappedRequest(req).loadAndRunReq
+ }
+
+ private def compile(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
+ if (global == null) Left(IR.Error)
+ else requestFromLine(line, synthetic) match {
+ case Left(result) => Left(result)
+ case Right(req) =>
+ // null indicates a disallowed statement type; otherwise compile and
+ // fail if false (implying e.g. a type error)
+ if (req == null || !req.compile) Left(IR.Error) else Right(req)
+ }
+ }
+
+ var code = ""
+ var bound = false
+ @throws(classOf[ScriptException])
+ def compile(script: String): CompiledScript = {
+ if (!bound) {
+ quietBind("bindings", getBindings(ScriptContext.ENGINE_SCOPE))
+ bound = true
+ }
+ val cat = code + script
+ compile(cat, false) match {
+ case Left(result) => result match {
+ case IR.Incomplete => {
+ code = cat + "\n"
+ new CompiledScript {
+ def eval(context: ScriptContext): Object = null
+ def getEngine: ScriptEngine = IMain.this
+ }
+ }
+ case _ => {
+ code = ""
+ throw new ScriptException("compile-time error")
+ }
+ }
+ case Right(req) => {
+ code = ""
+ new WrappedRequest(req)
+ }
+ }
+ }
+
+ @throws(classOf[ScriptException])
+ def compile(reader: Reader): CompiledScript = {
+ val writer = new StringWriter()
+ var c = reader.read()
+ while(c != -1) {
+ writer.write(c)
+ c = reader.read()
+ }
+ reader.close()
+ compile(writer.toString())
+ }
+
+ private class WrappedRequest(val req: Request) extends CompiledScript {
+ var recorded = false
+
+ @throws(classOf[ScriptException])
+ def eval(context: ScriptContext): Object = {
+ val result = req.lineRep.evalEither match {
+ case Left(e: Exception) => throw new ScriptException(e)
+ case Left(_) => throw new ScriptException("run-time error")
+ case Right(result) => result.asInstanceOf[Object]
+ }
+ if (!recorded) {
+ recordRequest(req)
+ recorded = true
+ }
+ result
+ }
+
+ def loadAndRunReq = classLoader.asContext {
val (result, succeeded) = req.loadAndRun
/** To our displeasure, ConsoleReporter offers only printMessage,
@@ -562,15 +633,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
}
- if (global == null) IR.Error
- else requestFromLine(line, synthetic) match {
- case Left(result) => result
- case Right(req) =>
- // null indicates a disallowed statement type; otherwise compile and
- // fail if false (implying e.g. a type error)
- if (req == null || !req.compile) IR.Error
- else loadAndRunReq(req)
- }
+ def getEngine: ScriptEngine = IMain.this
}
/** Bind a specified name to a specified value. The name may
@@ -703,6 +766,14 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
lazy val evalClass = load(evalPath)
+ def evalEither = callEither(resultName) match {
+ case Left(ex) => ex match {
+ case ex: NullPointerException => Right(null)
+ case ex => Left(unwrap(ex))
+ }
+ case Right(result) => Right(result)
+ }
+
def compile(source: String): Boolean = compileAndSaveRun("<console>", source)
/** The innermost object inside the wrapper, found by
@@ -738,6 +809,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
mostRecentWarnings = warnings
}
private def evalMethod(name: String) = evalClass.getMethods filter (_.getName == name) match {
+ case Array() => null
case Array(method) => method
case xs => sys.error("Internal error: eval object " + evalClass + ", " + xs.mkString("\n", "\n", ""))
}
@@ -897,6 +969,16 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
override def toString = "Request(line=%s, %s trees)".format(line, trees.size)
}
+ def createBindings: Bindings = new SimpleBindings
+
+ @throws(classOf[ScriptException])
+ def eval(script: String, context: ScriptContext): Object = compile(script).eval(context)
+
+ @throws(classOf[ScriptException])
+ def eval(reader: Reader, context: ScriptContext): Object = compile(reader).eval(context)
+
+ override def finalize = close
+
/** Returns the name of the most recent interpreter result.
* Mostly this exists so you can conveniently invoke methods on
* the previous result.
@@ -1068,6 +1150,48 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** Utility methods for the Interpreter. */
object IMain {
+ class Factory extends ScriptEngineFactory {
+ @BeanProperty
+ val engineName = "Scala Interpreter"
+
+ @BeanProperty
+ val engineVersion = "1.0"
+
+ @BeanProperty
+ val extensions: JList[String] = Arrays.asList("scala")
+
+ @BeanProperty
+ val languageName = "Scala"
+
+ @BeanProperty
+ val languageVersion = versionString
+
+ def getMethodCallSyntax(obj: String, m: String, args: String*): String = null
+
+ @BeanProperty
+ val mimeTypes: JList[String] = Arrays.asList("application/x-scala")
+
+ @BeanProperty
+ val names: JList[String] = Arrays.asList("scala")
+
+ def getOutputStatement(toDisplay: String): String = null
+
+ def getParameter(key: String): Object = key match {
+ case ScriptEngine.ENGINE => engineName
+ case ScriptEngine.ENGINE_VERSION => engineVersion
+ case ScriptEngine.LANGUAGE => languageName
+ case ScriptEngine.LANGUAGE_VERSION => languageVersion
+ case ScriptEngine.NAME => names.get(0)
+ case _ => null
+ }
+
+ def getProgram(statements: String*): String = null
+
+ def getScriptEngine: ScriptEngine = new IMain(this, new Settings() {
+ usemanifestcp.value = true
+ })
+ }
+
// The two name forms this is catching are the two sides of this assignment:
//
// $line3.$read.$iw.$iw.Bippy =
diff --git a/src/scalap/scala/tools/scalap/JavaWriter.scala b/src/scalap/scala/tools/scalap/JavaWriter.scala
index d64c54a0ea..772cf6eacd 100644
--- a/src/scalap/scala/tools/scalap/JavaWriter.scala
+++ b/src/scalap/scala/tools/scalap/JavaWriter.scala
@@ -17,16 +17,15 @@ class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer
def flagsToStr(clazz: Boolean, flags: Int): String = {
val buffer = new StringBuffer()
- var x: StringBuffer = buffer
if (((flags & 0x0007) == 0) &&
((flags & 0x0002) != 0))
- x = buffer.append("private ")
+ buffer.append("private ")
if ((flags & 0x0004) != 0)
- x = buffer.append("protected ")
+ buffer.append("protected ")
if ((flags & 0x0010) != 0)
- x = buffer.append("final ")
+ buffer.append("final ")
if ((flags & 0x0400) != 0)
- x = if (clazz) buffer.append("abstract ")
+ if (clazz) buffer.append("abstract ")
else buffer.append("/*deferred*/ ")
buffer.toString()
}
diff --git a/test/files/jvm/constant-optimization/Foo_1.flags b/test/files/jvm/constant-optimization/Foo_1.flags
new file mode 100644
index 0000000000..86f52af447
--- /dev/null
+++ b/test/files/jvm/constant-optimization/Foo_1.flags
@@ -0,0 +1 @@
+-Ynooptimise -Yconst-opt \ No newline at end of file
diff --git a/test/files/jvm/constant-optimization/Foo_1.scala b/test/files/jvm/constant-optimization/Foo_1.scala
new file mode 100644
index 0000000000..cb67ad4e90
--- /dev/null
+++ b/test/files/jvm/constant-optimization/Foo_1.scala
@@ -0,0 +1,9 @@
+class Foo_1 {
+ def foo() {
+ // constant optimization should eliminate all branches
+ val i = 1
+ val x = if (i != 1) null else "good"
+ val y = if (x == null) "good" else x + ""
+ println(y)
+ }
+} \ No newline at end of file
diff --git a/test/files/jvm/constant-optimization/Test.scala b/test/files/jvm/constant-optimization/Test.scala
new file mode 100644
index 0000000000..283aa6f47a
--- /dev/null
+++ b/test/files/jvm/constant-optimization/Test.scala
@@ -0,0 +1,27 @@
+
+import scala.tools.partest.BytecodeTest
+import scala.tools.asm
+import asm.tree.InsnList
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ val comparisons = Set(asm.Opcodes.IF_ACMPEQ, asm.Opcodes.IF_ACMPNE, asm.Opcodes.IF_ICMPEQ, asm.Opcodes.IF_ICMPGE, asm.Opcodes.IF_ICMPGT, asm.Opcodes.IF_ICMPLE,
+ asm.Opcodes.IF_ICMPLT, asm.Opcodes.IF_ICMPNE, asm.Opcodes.IFEQ, asm.Opcodes.IFGE, asm.Opcodes.IFGT, asm.Opcodes.IFLE, asm.Opcodes.IFLT,
+ asm.Opcodes.IFNE, asm.Opcodes.IFNONNULL, asm.Opcodes.IFNULL)
+
+ def show: Unit = {
+ val classNode = loadClassNode("Foo_1")
+ val methodNode = getMethod(classNode, "foo")
+ // after optimization there should be no comparisons left
+ val expected = 0
+
+ val got = countComparisons(methodNode.instructions)
+ assert(got == expected, s"expected $expected but got $got comparisons")
+ }
+
+ def countComparisons(insnList: InsnList): Int = {
+ def isComparison(node: asm.tree.AbstractInsnNode): Boolean =
+ (comparisons contains node.getOpcode)
+ insnList.iterator.asScala count isComparison
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/constructor-init-order.check b/test/files/neg/constructor-init-order.check
new file mode 100644
index 0000000000..9ab6ac5923
--- /dev/null
+++ b/test/files/neg/constructor-init-order.check
@@ -0,0 +1,9 @@
+constructor-init-order.scala:7: warning: Reference to uninitialized value baz
+ val bar1 = baz // warn
+ ^
+constructor-init-order.scala:17: warning: Reference to uninitialized variable baz
+ var bar1 = baz // warn
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+two warnings found
+one error found
diff --git a/test/files/neg/constructor-init-order.flags b/test/files/neg/constructor-init-order.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/constructor-init-order.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/constructor-init-order.scala b/test/files/neg/constructor-init-order.scala
new file mode 100644
index 0000000000..fe8fec87ad
--- /dev/null
+++ b/test/files/neg/constructor-init-order.scala
@@ -0,0 +1,23 @@
+trait Foo0 {
+ val quux1: String
+ val quux2 = quux1 // warning here is "future work"
+}
+
+class Foo1 extends Foo0 {
+ val bar1 = baz // warn
+ val bar2 = lazybaz // no warn
+ val bar3 = defbaz // no warn
+ val baz = "oops"
+ lazy val lazybaz = "ok"
+ def defbaz = "ok"
+ val quux1 = "oops"
+}
+
+class Foo2 {
+ var bar1 = baz // warn
+ var bar2 = lazybaz // no warn
+ var bar3 = defbaz // no warn
+ var baz = "oops"
+ lazy val lazybaz = "ok"
+ def defbaz = "ok"
+}
diff --git a/test/files/neg/t0764.scala b/test/files/neg/t0764.scala
index 9aebe04b79..f2cc65cf7d 100644
--- a/test/files/neg/t0764.scala
+++ b/test/files/neg/t0764.scala
@@ -2,13 +2,13 @@ class Top[A] {
type AType = A
}
-trait Node extends NotNull { outer =>
+trait Node { outer =>
type T <: Node
def prepend = new Node { type T = outer.type }
}
class Main[NextType <: Node](value: Node { type T = NextType })
extends Top[Node { type T = NextType }] {
-
+
new Main[AType]( (value: AType).prepend )
}
diff --git a/test/files/neg/t3977.check b/test/files/neg/t3977.check
index 9da118ee91..72335a0926 100644
--- a/test/files/neg/t3977.check
+++ b/test/files/neg/t3977.check
@@ -1,4 +1,4 @@
t3977.scala:12: error: could not find implicit value for parameter w: False#If[E]
- new NotNull
+ new NoNull
^
one error found
diff --git a/test/files/neg/t3977.scala b/test/files/neg/t3977.scala
index f55a832c52..11a8cdba4b 100644
--- a/test/files/neg/t3977.scala
+++ b/test/files/neg/t3977.scala
@@ -7,7 +7,7 @@ trait False extends Bool {
}
class Field[E, N <: Bool](implicit val w: N#If[E]) {
- type NotNull = Field[E, False]
+ type NoNull = Field[E, False]
- new NotNull
-} \ No newline at end of file
+ new NoNull
+}
diff --git a/test/files/neg/t6446-additional.check b/test/files/neg/t6446-additional.check
index 53dd383941..24201c07c2 100755
--- a/test/files/neg/t6446-additional.check
+++ b/test/files/neg/t6446-additional.check
@@ -25,7 +25,8 @@ superaccessors 6 add super accessors in traits and nested classes
inliner 23 optimization: do inlining
inlinehandlers 24 optimization: inline exception handlers
closelim 25 optimization: eliminate uncalled closures
- dce 26 optimization: eliminate dead code
- jvm 27 generate JVM bytecode
- ploogin 28 A sample phase that does so many things it's kind of hard...
- terminal 29 The last phase in the compiler chain
+ constopt 26 optimization: optimize null and other constants
+ dce 27 optimization: eliminate dead code
+ jvm 28 generate JVM bytecode
+ ploogin 29 A sample phase that does so many things it's kind of hard...
+ terminal 30 The last phase in the compiler chain
diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check
index f976bf480e..6e5bdcf07c 100755
--- a/test/files/neg/t6446-missing.check
+++ b/test/files/neg/t6446-missing.check
@@ -26,6 +26,7 @@ superaccessors 6 add super accessors in traits and nested classes
inliner 23 optimization: do inlining
inlinehandlers 24 optimization: inline exception handlers
closelim 25 optimization: eliminate uncalled closures
- dce 26 optimization: eliminate dead code
- jvm 27 generate JVM bytecode
- terminal 28 The last phase in the compiler chain
+ constopt 26 optimization: optimize null and other constants
+ dce 27 optimization: eliminate dead code
+ jvm 28 generate JVM bytecode
+ terminal 29 The last phase in the compiler chain
diff --git a/test/files/neg/t6446-show-phases.check b/test/files/neg/t6446-show-phases.check
index 5bbe43990c..a1bf408506 100644
--- a/test/files/neg/t6446-show-phases.check
+++ b/test/files/neg/t6446-show-phases.check
@@ -25,6 +25,7 @@ superaccessors 6 add super accessors in traits and nested classes
inliner 23 optimization: do inlining
inlinehandlers 24 optimization: inline exception handlers
closelim 25 optimization: eliminate uncalled closures
- dce 26 optimization: eliminate dead code
- jvm 27 generate JVM bytecode
- terminal 28 The last phase in the compiler chain
+ constopt 26 optimization: optimize null and other constants
+ dce 27 optimization: eliminate dead code
+ jvm 28 generate JVM bytecode
+ terminal 29 The last phase in the compiler chain
diff --git a/test/files/neg/t6601.check b/test/files/neg/t6601.check
new file mode 100644
index 0000000000..1410e1b11a
--- /dev/null
+++ b/test/files/neg/t6601.check
@@ -0,0 +1,4 @@
+AccessPrivateConstructor_2.scala:2: error: constructor PrivateConstructor in class PrivateConstructor cannot be accessed in class AccessPrivateConstructor
+ new PrivateConstructor("") // Scalac should forbid accessing to the private constructor!
+ ^
+one error found
diff --git a/test/files/neg/t6601/AccessPrivateConstructor_2.scala b/test/files/neg/t6601/AccessPrivateConstructor_2.scala
new file mode 100644
index 0000000000..816bc10d79
--- /dev/null
+++ b/test/files/neg/t6601/AccessPrivateConstructor_2.scala
@@ -0,0 +1,3 @@
+class AccessPrivateConstructor {
+ new PrivateConstructor("") // Scalac should forbid accessing to the private constructor!
+}
diff --git a/test/files/neg/t6601/PrivateConstructor_1.scala b/test/files/neg/t6601/PrivateConstructor_1.scala
new file mode 100644
index 0000000000..f09d7ad068
--- /dev/null
+++ b/test/files/neg/t6601/PrivateConstructor_1.scala
@@ -0,0 +1 @@
+class PrivateConstructor private(val s: String) extends AnyVal
diff --git a/test/files/neg/t7235.check b/test/files/neg/t7235.check
new file mode 100644
index 0000000000..357a3dfd83
--- /dev/null
+++ b/test/files/neg/t7235.check
@@ -0,0 +1,4 @@
+t7235.scala:9: error: implementation restriction: cannot reify refinement type trees with non-empty bodies
+ val Block(List(ValDef(_, _, tpt: CompoundTypeTree, _)), _) = reify{ val x: C { def x: Int } = ??? }.tree
+ ^
+one error found
diff --git a/test/files/neg/t7235.scala b/test/files/neg/t7235.scala
new file mode 100644
index 0000000000..cfebad3fae
--- /dev/null
+++ b/test/files/neg/t7235.scala
@@ -0,0 +1,14 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+class C
+
+object Test extends App {
+ val Block(List(ValDef(_, _, tpt: CompoundTypeTree, _)), _) = reify{ val x: C { def x: Int } = ??? }.tree
+ println(tpt)
+ println(tpt.templ.parents)
+ println(tpt.templ.self)
+ println(tpt.templ.body)
+}
diff --git a/test/files/neg/t7238.check b/test/files/neg/t7238.check
new file mode 100644
index 0000000000..b87f83ff65
--- /dev/null
+++ b/test/files/neg/t7238.check
@@ -0,0 +1,6 @@
+t7238.scala:6: error: type mismatch;
+ found : Seq[Any]
+ required: Seq[String]
+ c.c()(Seq[Any](): _*)
+ ^
+one error found
diff --git a/test/files/neg/t7238.scala b/test/files/neg/t7238.scala
new file mode 100644
index 0000000000..d42dc8d385
--- /dev/null
+++ b/test/files/neg/t7238.scala
@@ -0,0 +1,7 @@
+trait Main {
+ trait C {
+ def c(x: Any = 0)(bs: String*)
+ }
+ def c: C
+ c.c()(Seq[Any](): _*)
+}
diff --git a/test/files/pos/switch-small.flags b/test/files/pos/switch-small.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/pos/switch-small.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/pos/t3108.scala b/test/files/pos/t3108.scala
deleted file mode 100644
index 6a1da73220..0000000000
--- a/test/files/pos/t3108.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-object A {
- val a: NotNull = ""
- val b: NotNull = 41
-}
-
diff --git a/test/files/pos/t3417.scala b/test/files/pos/t3417.scala
deleted file mode 100644
index d2de1608aa..0000000000
--- a/test/files/pos/t3417.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-trait X extends NotNull {
- def foo = 1
-}
-
-trait Y extends Object with NotNull {
- def bar = 1
-}
-
-class Z extends NotNull
-
-class W extends Object with NotNull
diff --git a/test/files/pos/t7226.scala b/test/files/pos/t7226.scala
new file mode 100644
index 0000000000..06f0c95dc4
--- /dev/null
+++ b/test/files/pos/t7226.scala
@@ -0,0 +1,26 @@
+trait HK {
+ type Rep[X]
+
+ // okay
+ def unzip2[A, B](ps: Rep[List[(A, B)]])
+ unzip2(null.asInstanceOf[Rep[List[(Int, String)]]])
+
+ // okay
+ def unzipHK[A, B, C[_]](ps: Rep[C[(A, B)]])
+ unzipHK(null.asInstanceOf[Rep[List[(Int, String)]]])
+
+ def unzipHKRet0[A, C[_]](ps: C[A]): C[Int]
+ def ls: List[String]
+ unzipHKRet0(ls)
+
+ // fail
+ def unzipHKRet[A, C[_]](ps: Rep[C[A]]): Rep[C[Int]]
+ def rls: Rep[List[String]]
+ unzipHKRet(rls)
+}
+
+trait HK1 {
+ type Rep[A]
+ def unzip1[A, B, C[_]](ps: Rep[C[(A, B)]]): (Rep[C[A]], Rep[C[B]])
+ def doUnzip1[A, B](ps: Rep[List[(A, B)]]) = unzip1(ps)
+}
diff --git a/test/files/pos/t7228.scala b/test/files/pos/t7228.scala
new file mode 100644
index 0000000000..5d936f6529
--- /dev/null
+++ b/test/files/pos/t7228.scala
@@ -0,0 +1,75 @@
+object AdaptWithWeaklyConformantType {
+ implicit class D(d: Double) { def double = d*2 }
+
+ val x1: Int = 1
+ var x2: Int = 2
+ val x3 = 3
+ var x4 = 4
+ final val x5 = 5
+ final var x6 = 6
+
+ def f1 = x1.double
+ def f2 = x2.double
+ def f3 = x3.double
+ def f4 = x4.double
+ def f5 = x5.double
+ def f6 = x6.double
+}
+
+object AdaptAliasWithWeaklyConformantType {
+ implicit class D(d: Double) { def double = d*2 }
+ type T = Int
+
+ val x1: T = 1
+ var x2: T = 2
+ val x3 = (3: T)
+ var x4 = (4: T)
+ final val x5 = (5: T)
+ final var x6 = (6: T)
+
+ def f1 = x1.double
+ def f2 = x2.double
+ def f3 = x3.double
+ def f4 = x4.double
+ def f5 = x5.double
+ def f6 = x6.double
+}
+
+object AdaptToAliasWithWeaklyConformantType {
+ type U = Double
+ implicit class D(d: U) { def double = d*2 }
+
+ val x1: Int = 1
+ var x2: Int = 2
+ val x3 = (3: Int)
+ var x4 = (4: Int)
+ final val x5 = (5: Int)
+ final var x6 = (6: Int)
+
+ def f1 = x1.double
+ def f2 = x2.double
+ def f3 = x3.double
+ def f4 = x4.double
+ def f5 = x5.double
+ def f6 = x6.double
+}
+
+object AdaptAliasToAliasWithWeaklyConformantType {
+ type U = Double
+ type T = Int
+ implicit class D(d: U) { def double = d*2 }
+
+ val x1: T = 1
+ var x2: T = 2
+ val x3 = (3: T)
+ var x4 = (4: T)
+ final val x5 = (5: T)
+ final var x6 = (6: T)
+
+ def f1 = x1.double
+ def f2 = x2.double
+ def f3 = x3.double
+ def f4 = x4.double
+ def f5 = x5.double
+ def f6 = x6.double
+}
diff --git a/test/files/pos/t7234.scala b/test/files/pos/t7234.scala
new file mode 100644
index 0000000000..59a233d835
--- /dev/null
+++ b/test/files/pos/t7234.scala
@@ -0,0 +1,15 @@
+trait Main {
+ trait A {
+ type B
+ }
+ trait C {
+ def c(a: A, x: Int = 0)(b: a.B)
+ }
+ def c: C
+ def d(a: A, x: Int = 0)(b: a.B)
+
+ def ok1(a: A)(b: a.B) = c.c(a, 42)(b)
+ def ok2(a: A)(b: a.B) = d(a)(b)
+
+ def fail(a: A)(b: a.B) = c.c(a)(b)
+}
diff --git a/test/files/pos/t7234b.scala b/test/files/pos/t7234b.scala
new file mode 100644
index 0000000000..fee98e87a8
--- /dev/null
+++ b/test/files/pos/t7234b.scala
@@ -0,0 +1,20 @@
+trait Main {
+ trait A {
+ type B
+ def b: B
+ }
+ trait C {
+ def c(a: A, x: Int = 0)(b: => a.B, bs: a.B*)
+ def d(a: A = null, x: Int = 0)(b1: => a.B = a.b, b2: a.B = a.b)
+ }
+ def c: C
+ def ok(a: A)(b: a.B) = c.c(a, 42)(b)
+ def fail(a: A)(b: a.B) = c.c(a)(b)
+ def fail2(a: A)(b: a.B) = c.c(a)(b, b)
+ def fail3(a: A)(b: a.B) = c.c(a)(b, Seq[a.B](b): _*)
+
+ def fail4(a: A)(b: a.B) = c.d(a)()
+ def fail5(a: A)(b: a.B) = c.d(a)(b1 = a.b)
+ def fail6(a: A)(b: a.B) = c.d(a)(b2 = a.b)
+ def fail7(a: A)(b: a.B) = c.d()()
+}
diff --git a/test/files/presentation/hyperlinks.check b/test/files/presentation/hyperlinks.check
index 85d295dd7d..1051b67e85 100644
--- a/test/files/presentation/hyperlinks.check
+++ b/test/files/presentation/hyperlinks.check
@@ -1,4 +1,4 @@
-reload: NameDefaultTests.scala, PatMatTests.scala
+reload: NameDefaultTests.scala, PatMatTests.scala, SuperTypes.scala
askHyperlinkPos for `someOtherInt` at (14,24) NameDefaultTests.scala
================================================================================
@@ -44,3 +44,138 @@ askHyperlinkPos for `y` at (25,21) PatMatTests.scala
================================================================================
[response] found askHyperlinkPos for `y` at (23,13) PatMatTests.scala
================================================================================
+
+askHyperlinkPos for `BadPos` at (10,26) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `BadPos` at (2,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `BadPos` at (11,26) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `BadPos` at (2,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `Trait` at (12,25) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `Trait` at (6,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `SubTrait` at (13,28) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `SubTrait` at (7,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `Trait` at (14,25) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `Trait` at (6,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `LateralTrait` at (14,48) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `LateralTrait` at (8,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `Base` at (15,24) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `Base` at (4,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `Trait` at (15,40) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `Trait` at (6,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `LateralTrait` at (15,63) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `LateralTrait` at (8,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PBase` at (19,29) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PBase` at (17,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (20,33) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PBase` at (21,36) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PBase` at (17,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (23,27) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PSubTrait` at (24,30) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PSubTrait` at (20,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (25,27) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PLateralTrait` at (25,56) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PLateralTrait` at (21,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PBase` at (26,26) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PBase` at (17,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (26,48) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PLateralTrait` at (26,77) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PLateralTrait` at (21,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `BadPos` at (28,23) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `BadPos` at (2,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (29,23) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PSubTrait` at (30,26) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PSubTrait` at (20,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (31,23) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PLateralTrait` at (31,52) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PLateralTrait` at (21,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PBase` at (32,22) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PBase` at (17,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PTrait` at (32,44) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PTrait` at (19,7) SuperTypes.scala
+================================================================================
+
+askHyperlinkPos for `PLateralTrait` at (32,73) SuperTypes.scala
+================================================================================
+[response] found askHyperlinkPos for `PLateralTrait` at (21,7) SuperTypes.scala
+================================================================================
diff --git a/test/files/presentation/hyperlinks/src/SuperTypes.scala b/test/files/presentation/hyperlinks/src/SuperTypes.scala
new file mode 100644
index 0000000000..15d16069fd
--- /dev/null
+++ b/test/files/presentation/hyperlinks/src/SuperTypes.scala
@@ -0,0 +1,32 @@
+/** This tests that hyperlinking works for super types. See SI-7224 */
+class BadPos[A](a: A)
+
+class Base
+
+trait Trait extends Base
+trait SubTrait extends Trait
+trait LateralTrait extends Base
+
+object obj1 extends BadPos/*#*/(new Object)
+object obj2 extends BadPos/*#*/[AnyRef](new Object)
+object obj3 extends Trait/*#*/
+object obj4 extends SubTrait/*#*/
+object obj5 extends Trait/*#*/ with LateralTrait/*#*/
+object obj6 extends Base/*#*/ with Trait/*#*/ with LateralTrait/*#*/
+
+class PBase[A]
+
+trait PTrait[A] extends PBase/*#*/[A]
+trait PSubTrait[A] extends PTrait/*#*/[A]
+trait PLateralTrait[A] extends PBase/*#*/[A]
+
+object pobj2 extends PTrait/*#*/[Int]
+object pobj3 extends PSubTrait/*#*/[Int]
+object pobj4 extends PTrait/*#*/[Int] with PLateralTrait/*#*/[Int]
+object pobj5 extends PBase/*#*/[Int] with PTrait/*#*/[Int] with PLateralTrait/*#*/[Int]
+
+class c1 extends BadPos/*#*/(new Object)
+class c2 extends PTrait/*#*/[Int]
+class c3 extends PSubTrait/*#*/[Int]
+class c4 extends PTrait/*#*/[Int] with PLateralTrait/*#*/[Int]
+class c5 extends PBase/*#*/[Int] with PTrait/*#*/[Int] with PLateralTrait/*#*/[Int]
diff --git a/test/files/run/bitsets.check b/test/files/run/bitsets.check
index 3f01d2a400..41c2ccdcb8 100644
--- a/test/files/run/bitsets.check
+++ b/test/files/run/bitsets.check
@@ -37,6 +37,11 @@ m2_r1 = true
m2_r2 = true
m2_r3 = true
+b1:BitSet(5, 6, 7)
+b2:BitSet(5)
+b3:BitSet(5, 7)
+b4:BitSet(7)
+b0:BitSet(5, 6, 7)
is0 = BitSet()
is1 = BitSet()
is2 = BitSet(2)
diff --git a/test/files/run/bitsets.scala b/test/files/run/bitsets.scala
index bdeb1fd811..0ea43fcb95 100644
--- a/test/files/run/bitsets.scala
+++ b/test/files/run/bitsets.scala
@@ -81,6 +81,27 @@ object TestMutable2 {
println
}
+object TestMutable3 {
+ import scala.collection.mutable.BitSet
+
+ val b0 = BitSet(5, 6)
+ val b1 = BitSet(7)
+ val b2 = BitSet(1, 5)
+ val b3 = BitSet(6, 7)
+ val b4 = BitSet(6, 7)
+
+ b1 |= b0
+ println(s"b1:$b1")
+ b2 &= b0
+ println(s"b2:$b2")
+ b3 ^= b0
+ println(s"b3:$b3")
+ b4 &~= b0
+ println(s"b4:$b4")
+ b0 ^= b0 |= b1
+ println(s"b0:$b0")
+}
+
object TestImmutable {
import scala.collection.immutable.BitSet
@@ -155,6 +176,7 @@ object TestImmutable2 {
object Test extends App {
TestMutable
TestMutable2
+ TestMutable3
TestImmutable
TestImmutable2
}
diff --git a/test/files/run/blame_eye_triple_eee.check b/test/files/run/blame_eye_triple_eee.check
new file mode 100644
index 0000000000..5e46d91a8f
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee.check
@@ -0,0 +1,9 @@
+if (NaN == NaN) is good
+if (x == x) is good
+if (x == NaN) is good
+if (NaN != NaN) is good
+if (x != x) is good
+if (NaN != x) is good
+x matching was good
+NaN matching was good
+loop with NaN was goood
diff --git a/test/files/run/blame_eye_triple_eee.flags b/test/files/run/blame_eye_triple_eee.flags
new file mode 100644
index 0000000000..c9b68d70dc
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee.flags
@@ -0,0 +1 @@
+-optimise
diff --git a/test/files/run/blame_eye_triple_eee.scala b/test/files/run/blame_eye_triple_eee.scala
new file mode 100644
index 0000000000..1640aead40
--- /dev/null
+++ b/test/files/run/blame_eye_triple_eee.scala
@@ -0,0 +1,61 @@
+object Test extends App {
+ import Double.NaN
+
+ // NaN must not equal NaN no matter what optimizations are applied
+ // All the following will seem redundant, but to an optimizer
+ // they can appear different
+
+ val x = NaN
+
+ if (NaN == NaN)
+ println("if (NaN == NaN) is broken")
+ else
+ println("if (NaN == NaN) is good")
+
+ if (x == x)
+ println("if (x == x) is broken")
+ else
+ println("if (x == x) is good")
+
+ if (x == NaN)
+ println("if (x == NaN) is broken")
+ else
+ println("if (x == NaN) is good")
+
+ if (NaN != NaN)
+ println("if (NaN != NaN) is good")
+ else
+ println("if (NaN != NaN) broken")
+
+ if (x != x)
+ println("if (x != x) is good")
+ else
+ println("if (x != x) broken")
+
+ if (NaN != x)
+ println("if (NaN != x) is good")
+ else
+ println("if (NaN != x) is broken")
+
+ x match {
+ case 0.0d => println("x matched 0!")
+ case NaN => println("x matched NaN!")
+ case _ => println("x matching was good")
+ }
+
+ NaN match {
+ case 0.0d => println("NaN matched 0!")
+ case NaN => println("NaN matched NaN!")
+ case _ => println("NaN matching was good")
+ }
+
+ var z = 0.0d
+ var i = 0
+ while (i < 10) {
+ if (i % 2 == 0) z = NaN
+ else z = NaN
+ i += 1
+ }
+ if (z.isNaN && i == 10) println("loop with NaN was goood")
+ else println("loop with NaN was broken")
+}
diff --git a/test/files/run/constant-optimization.check b/test/files/run/constant-optimization.check
new file mode 100644
index 0000000000..957ffc5a87
--- /dev/null
+++ b/test/files/run/constant-optimization.check
@@ -0,0 +1,5 @@
+testBothReachable: good
+testOneReachable: good
+testAllReachable: good
+testOneUnreachable: good
+testDefaultUnreachable: good
diff --git a/test/files/run/constant-optimization.flags b/test/files/run/constant-optimization.flags
new file mode 100644
index 0000000000..c9b68d70dc
--- /dev/null
+++ b/test/files/run/constant-optimization.flags
@@ -0,0 +1 @@
+-optimise
diff --git a/test/files/run/constant-optimization.scala b/test/files/run/constant-optimization.scala
new file mode 100644
index 0000000000..5d13272f3b
--- /dev/null
+++ b/test/files/run/constant-optimization.scala
@@ -0,0 +1,61 @@
+object Test extends App {
+ def testBothReachable() {
+ val i = util.Random.nextInt
+ val x = if (i % 2 == 0) null else "good"
+ val y = if (x == null) "good" else x + ""
+ println(s"testBothReachable: $y")
+ }
+
+ def testOneReachable() {
+ val i = 1
+ val x = if (i != 1) null else "good"
+ val y = if (x == null) "good" else x + ""
+ println(s"testOneReachable: $y")
+ }
+
+ def testAllReachable() {
+ val i = util.Random.nextInt
+ val y = (i % 2) match {
+ case 0 => "good"
+ case 1 => "good"
+ case _ => "good"
+ }
+ println(s"testAllReachable: $y")
+ }
+
+ def testOneUnreachable() {
+ val i = util.Random.nextInt
+ val x = if (i % 2 == 0) {
+ 1
+ } else {
+ 2
+ }
+ val y = x match {
+ case 0 => "good"
+ case 1 => "good"
+ case _ => "good"
+ }
+ println(s"testOneUnreachable: $y")
+ }
+
+ def testDefaultUnreachable() {
+ val i = util.Random.nextInt
+ val x = if (i % 2 == 0) {
+ 1
+ } else {
+ 2
+ }
+ val y = x match {
+ case 1 => "good"
+ case 2 => "good"
+ case _ => "good"
+ }
+ println(s"testDefaultUnreachable: $y")
+ }
+
+ testBothReachable()
+ testOneReachable()
+ testAllReachable()
+ testOneUnreachable()
+ testDefaultUnreachable()
+}
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index d472c569d2..61b947214c 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -25,7 +25,8 @@ superaccessors 6 add super accessors in traits and nested classes
inliner 23 optimization: do inlining
inlinehandlers 24 optimization: inline exception handlers
closelim 25 optimization: eliminate uncalled closures
- dce 26 optimization: eliminate dead code
- jvm 27 generate JVM bytecode
- terminal 28 The last phase in the compiler chain
+ constopt 26 optimization: optimize null and other constants
+ dce 27 optimization: eliminate dead code
+ jvm 28 generate JVM bytecode
+ terminal 29 The last phase in the compiler chain
diff --git a/test/files/run/t5710-1.check b/test/files/run/t5710-1.check
new file mode 100644
index 0000000000..eac2025aeb
--- /dev/null
+++ b/test/files/run/t5710-1.check
@@ -0,0 +1 @@
+evaluated = (abc,abc)
diff --git a/test/files/run/t5710-1.scala b/test/files/run/t5710-1.scala
new file mode 100644
index 0000000000..12bd858e06
--- /dev/null
+++ b/test/files/run/t5710-1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ val code = reify {
+ val (x, y) = ("abc": Any) match { case x => (x, x) }
+ (x, y)
+ };
+
+ val toolbox = cm.mkToolBox()
+ val evaluated = toolbox.eval(code.tree)
+ println("evaluated = " + evaluated)
+} \ No newline at end of file
diff --git a/test/files/run/t5710-2.check b/test/files/run/t5710-2.check
new file mode 100644
index 0000000000..eac2025aeb
--- /dev/null
+++ b/test/files/run/t5710-2.check
@@ -0,0 +1 @@
+evaluated = (abc,abc)
diff --git a/test/files/run/t5710-2.scala b/test/files/run/t5710-2.scala
new file mode 100644
index 0000000000..6d2129cca2
--- /dev/null
+++ b/test/files/run/t5710-2.scala
@@ -0,0 +1,15 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ val code = reify {
+ val (x, y) = "abc" match { case x => (x, x) }
+ (x, y)
+ };
+
+ val toolbox = cm.mkToolBox()
+ val evaluated = toolbox.eval(code.tree)
+ println("evaluated = " + evaluated)
+} \ No newline at end of file
diff --git a/test/files/run/t6608.check b/test/files/run/t6608.check
new file mode 100644
index 0000000000..15628b322e
--- /dev/null
+++ b/test/files/run/t6608.check
@@ -0,0 +1 @@
+(C$$yyy,true)
diff --git a/test/files/run/t6608.scala b/test/files/run/t6608.scala
new file mode 100644
index 0000000000..2f956bfb35
--- /dev/null
+++ b/test/files/run/t6608.scala
@@ -0,0 +1,16 @@
+import reflect.runtime.universe
+
+class C {
+ private val yyy: Any = 1
+ @inline def foo = yyy
+}
+
+object Test extends App {
+ import universe._
+ val access = typeOf[C].declarations
+ .toList
+ .filter(_.name.toString.endsWith("yyy"))
+ .map(x => (x.name, x.isPrivate))
+ println(access.head)
+}
+
diff --git a/test/files/run/t6646.check b/test/files/run/t6646.check
index b0b7ad32f3..15715dae91 100644
--- a/test/files/run/t6646.check
+++ b/test/files/run/t6646.check
@@ -1,4 +1,4 @@
-Found NotNull
+Found NoNull
Found lower
Found 2
A single ident is always a pattern
diff --git a/test/files/run/t6646.scala b/test/files/run/t6646.scala
index 150b0df11e..a377ac274e 100644
--- a/test/files/run/t6646.scala
+++ b/test/files/run/t6646.scala
@@ -1,14 +1,14 @@
sealed trait ColumnOption
-case object NotNull extends ColumnOption
+case object NoNull extends ColumnOption
case object PrimaryKey extends ColumnOption
case object lower extends ColumnOption
object Test {
def main(args: Array[String]) {
- val l = List(PrimaryKey, NotNull, lower)
+ val l = List(PrimaryKey, NoNull, lower)
// withFilter must be generated in these
- for (option @ NotNull <- l) println("Found " + option)
+ for (option @ NoNull <- l) println("Found " + option)
for (option @ `lower` <- l) println("Found " + option)
for ((`lower`, i) <- l.zipWithIndex) println("Found " + i)
diff --git a/test/files/run/t7235.check b/test/files/run/t7235.check
new file mode 100644
index 0000000000..9cb9c55a0c
--- /dev/null
+++ b/test/files/run/t7235.check
@@ -0,0 +1,4 @@
+C
+List(C)
+private val _ = _
+List()
diff --git a/test/files/run/t7235.scala b/test/files/run/t7235.scala
new file mode 100644
index 0000000000..6039189716
--- /dev/null
+++ b/test/files/run/t7235.scala
@@ -0,0 +1,14 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+class C
+
+object Test extends App {
+ val Block(List(ValDef(_, _, tpt: CompoundTypeTree, _)), _) = reify{ val x: C{} = ??? }.tree
+ println(tpt)
+ println(tpt.templ.parents)
+ println(tpt.templ.self)
+ println(tpt.templ.body)
+}
diff --git a/test/pending/pos/no-widen-locals.flags b/test/pending/pos/no-widen-locals.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/pending/pos/no-widen-locals.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/pos/no-widen-locals.scala b/test/pending/pos/no-widen-locals.scala
index 013e63f0a2..013e63f0a2 100644
--- a/test/files/pos/no-widen-locals.scala
+++ b/test/pending/pos/no-widen-locals.scala