summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala59
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala34
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala33
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala79
-rw-r--r--src/compiler/scala/tools/nsc/transform/PostErasure.scala60
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala14
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala2
-rw-r--r--src/library/scala/concurrent/Future.scala12
-rw-r--r--src/library/scala/math/BigInt.scala2
-rw-r--r--src/reflect/scala/reflect/api/ImplicitTags.scala108
-rw-r--r--src/reflect/scala/reflect/api/Types.scala105
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala133
-rw-r--r--src/reflect/scala/reflect/internal/util/Statistics.scala2
-rw-r--r--test/disabled/jvm/scala-concurrent-tck-akka.scala391
-rw-r--r--test/disabled/presentation/akka/src/akka/dispatch/Future.scala832
-rw-r--r--test/disabled/presentation/akka/src/pi.scala108
-rw-r--r--test/files/jvm/value-class-boxing.check7
-rw-r--r--test/files/jvm/value-class-boxing/Analyzed_1.scala17
-rw-r--r--test/files/jvm/value-class-boxing/test.scala15
-rw-r--r--test/files/pos/annotated-original/C_2.scala7
-rw-r--r--test/files/pos/annotated-original/M_1.scala7
-rw-r--r--test/files/pos/t5744/Macros_1.scala22
-rw-r--r--test/files/pos/t5744/Test_2.scala6
-rw-r--r--test/files/pos/t7091.scala7
-rwxr-xr-xtest/files/presentation/doc/doc.scala22
-rw-r--r--test/files/presentation/ide-t1000567.check1
-rw-r--r--test/files/presentation/ide-t1000567/Runner.scala15
-rw-r--r--test/files/presentation/ide-t1000567/src/a/a.scala5
-rw-r--r--test/files/presentation/ide-t1000567/src/b/b.scala5
-rw-r--r--test/files/presentation/memory-leaks/MemoryLeaksTest.scala2
-rw-r--r--test/files/run/all-overridden.check1
-rw-r--r--test/files/run/all-overridden.scala11
-rw-r--r--test/files/run/annotatedRetyping.check6
-rw-r--r--test/files/run/annotatedRetyping.scala62
44 files changed, 569 insertions, 1686 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index f53f99a279..6a0f4407fc 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -14,6 +14,65 @@ package ast
abstract class TreeInfo extends scala.reflect.internal.TreeInfo {
val global: Global
import global._
+ import definitions._
+
+ // arg1.op(arg2) returns (arg1, op.symbol, arg2)
+ object BinaryOp {
+ def unapply(t: Tree): Option[(Tree, Symbol, Tree)] = t match {
+ case Apply(sel @ Select(arg1, _), arg2 :: Nil) => Some((arg1, sel.symbol, arg2))
+ case _ => None
+ }
+ }
+ // recv.op[T1, ...] returns (recv, op.symbol, type argument types)
+ object TypeApplyOp {
+ def unapply(t: Tree): Option[(Tree, Symbol, List[Type])] = t match {
+ case TypeApply(sel @ Select(recv, _), targs) => Some((recv, sel.symbol, targs map (_.tpe)))
+ case _ => None
+ }
+ }
+
+ // x.asInstanceOf[T] returns (x, typeOf[T])
+ object AsInstanceOf {
+ def unapply(t: Tree): Option[(Tree, Type)] = t match {
+ case Apply(TypeApplyOp(recv, Object_asInstanceOf, tpe :: Nil), Nil) => Some((recv, tpe))
+ case _ => None
+ }
+ }
+
+ // Extractors for value classes.
+ object ValueClass {
+ def isValueClass(tpe: Type) = enteringErasure(tpe.typeSymbol.isDerivedValueClass)
+ def valueUnbox(tpe: Type) = enteringErasure(tpe.typeSymbol.derivedValueClassUnbox)
+
+ // B.unbox. Returns B.
+ object Unbox {
+ def unapply(t: Tree): Option[Tree] = t match {
+ case Apply(sel @ Select(ref, _), Nil) if valueUnbox(ref.tpe) == sel.symbol => Some(ref)
+ case _ => None
+ }
+ }
+ // new B(v). Returns B and v.
+ object Box {
+ def unapply(t: Tree): Option[(Tree, Type)] = t match {
+ case Apply(sel @ Select(New(tpt), nme.CONSTRUCTOR), v :: Nil) => Some((v, tpt.tpe.finalResultType))
+ case _ => None
+ }
+ }
+ // (new B(v)).unbox. returns v.
+ object BoxAndUnbox {
+ def unapply(t: Tree): Option[Tree] = t match {
+ case Unbox(Box(v, tpe)) if isValueClass(tpe) => Some(v)
+ case _ => None
+ }
+ }
+ // new B(v1) op new B(v2) where op is == or !=. Returns v1, op, v2.
+ object BoxAndCompare {
+ def unapply(t: Tree): Option[(Tree, Symbol, Tree)] = t match {
+ case BinaryOp(Box(v1, tpe1), op @ (Object_== | Object_!=), Box(v2, tpe2)) if isValueClass(tpe1) && tpe1 =:= tpe2 => Some((v1, op, v2))
+ case _ => None
+ }
+ }
+ }
/** Is tree legal as a member definition of an interface?
*/
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 3025e4c440..1554be6ebb 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -133,24 +133,16 @@ trait Scanners extends ScannersCommon {
/** Should doc comments be built? */
def buildDocs: Boolean = forScaladoc
- /** buffer for the documentation comment
+ /** holder for the documentation comment
*/
- var docBuffer: StringBuilder = null
- var docPos: Position = null
+ var docComment: DocComment = null
- /** Return current docBuffer and set docBuffer to null */
def flushDoc: DocComment = {
- val ret = if (docBuffer != null) DocComment(docBuffer.toString, docPos) else null
- docBuffer = null
+ val ret = docComment
+ docComment = null
ret
}
- /** add the given character to the documentation buffer
- */
- protected def putDocChar(c: Char) {
- if (docBuffer ne null) docBuffer.append(c)
- }
-
protected def foundComment(value: String, start: Int, end: Int) = ()
protected def foundDocComment(value: String, start: Int, end: Int) = ()
@@ -227,11 +219,11 @@ trait Scanners extends ScannersCommon {
while (!sepRegions.isEmpty && sepRegions.head != RBRACE)
sepRegions = sepRegions.tail
if (!sepRegions.isEmpty) sepRegions = sepRegions.tail
- docBuffer = null
+ docComment = null
case RBRACKET | RPAREN =>
if (!sepRegions.isEmpty && sepRegions.head == lastToken)
sepRegions = sepRegions.tail
- docBuffer = null
+ docComment = null
case ARROW =>
if (!sepRegions.isEmpty && sepRegions.head == lastToken)
sepRegions = sepRegions.tail
@@ -537,7 +529,7 @@ trait Scanners extends ScannersCommon {
nextChar()
} while ((ch != CR) && (ch != LF) && (ch != SU))
} else {
- docBuffer = null
+ docComment = null
var openComments = 1
appendToComment()
nextChar()
@@ -545,24 +537,23 @@ trait Scanners extends ScannersCommon {
var buildingDocComment = false
if (ch == '*' && buildDocs) {
buildingDocComment = true
- docBuffer = new StringBuilder("/**")
}
while (openComments > 0) {
do {
do {
if (ch == '/') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
if (ch == '*') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
openComments += 1
}
}
if (ch != '*' && ch != SU) {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
}
} while (ch != '*' && ch != SU)
while (ch == '*') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
}
} while (ch != '/' && ch != SU)
if (ch == '/') nextChar()
@@ -1297,7 +1288,8 @@ trait Scanners extends ScannersCommon {
}
override def foundDocComment(value: String, start: Int, end: Int) {
- docPos = new RangePosition(unit.source, start, start, end)
+ val docPos = new RangePosition(unit.source, start, start, end)
+ docComment = new DocComment(value, docPos)
unit.comment(docPos, value)
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 5497719f89..add932441d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -567,7 +567,7 @@ abstract class TreeBuilder {
if (contextBounds.isEmpty) vparamss
else {
val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM)
- def makeEvidenceParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshTermName(nme.EVIDENCE_PARAM_PREFIX), tpt, EmptyTree)
+ def makeEvidenceParam(tpt: Tree) = ValDef(mods | IMPLICIT | SYNTHETIC, freshTermName(nme.EVIDENCE_PARAM_PREFIX), tpt, EmptyTree)
val evidenceParams = contextBounds map makeEvidenceParam
val vparamssLast = if(vparamss.nonEmpty) vparamss.last else Nil
diff --git a/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
index 216157e19a..8d80333195 100755
--- a/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
+++ b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
@@ -10,15 +10,15 @@ import comment._
trait MemberLookupBase {
val global: Global
- val settings: doc.Settings
-
import global._
+
def internalLink(sym: Symbol, site: Symbol): Option[LinkTo]
def chooseLink(links: List[LinkTo]): LinkTo
def toString(link: LinkTo): String
+ def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal]
+ def warnNoLink: Boolean
import global._
- import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
import rootMirror.{RootPackage, EmptyPackage}
private def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
@@ -83,7 +83,7 @@ trait MemberLookupBase {
}
links match {
case Nil =>
- if (!settings.docNoLinkWarnings.value)
+ if (warnNoLink)
reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
// (4) if we still haven't found anything, create a tooltip
Tooltip(query)
@@ -95,7 +95,7 @@ trait MemberLookupBase {
if (link == chosen) " [chosen]" else ""
toString(link) + chosenInfo + "\n"
}
- if (!settings.docNoLinkWarnings.value) {
+ if (warnNoLink) {
val allLinks = links.map(linkToString).mkString
reporter.warning(pos,
s"""The link target \"$query\" is ambiguous. Several members fit the target:
@@ -199,29 +199,6 @@ trait MemberLookupBase {
members.reverse
}
-
- def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
- val sym1 =
- if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
- else if (sym.isPackage)
- /* Get package object which has associatedFile ne null */
- sym.info.member(newTermName("package"))
- else sym
- sym1.associatedFile.underlyingSource flatMap { src =>
- val path = src.path
- settings.extUrlMapping get path map { url =>
- LinkToExternal(name, url + "#" + name)
- }
- } orElse {
- // Deprecated option.
- settings.extUrlPackageMapping find {
- case (pkg, _) => name startsWith pkg
- } map {
- case (_, url) => LinkToExternal(name, url + "#" + name)
- }
- }
- }
-
def externalSignature(sym: Symbol) = {
sym.info // force it, otherwise we see lazy types
(sym.nameString + sym.signatureString).replaceAll("\\s", "")
diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
index c7a767f992..23259a4ae8 100644
--- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
@@ -9,6 +9,7 @@ trait MemberLookup extends base.MemberLookupBase {
thisFactory: ModelFactory =>
import global._
+ import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
findTemplateMaybe(sym) match {
@@ -35,4 +36,28 @@ trait MemberLookup extends base.MemberLookupBase {
mbr.sym.signatureString + " in " + inTpl.sym.toString
case _ => link.toString
}
+
+ override def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
+ val sym1 =
+ if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
+ else if (sym.isPackage)
+ /* Get package object which has associatedFile ne null */
+ sym.info.member(newTermName("package"))
+ else sym
+ Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
+ val path = src.path
+ settings.extUrlMapping get path map { url =>
+ LinkToExternal(name, url + "#" + name)
+ }
+ } orElse {
+ // Deprecated option.
+ settings.extUrlPackageMapping find {
+ case (pkg, _) => name startsWith pkg
+ } map {
+ case (_, url) => LinkToExternal(name, url + "#" + name)
+ }
+ }
+ }
+
+ override def warnNoLink = !settings.docNoLinkWarnings.value
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 9bb2d552be..b0318f40c4 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -69,7 +69,6 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
if (verboseIDE) println("[%s][%s]".format(projectName, msg))
override def forInteractive = true
- override def forScaladoc = settings.isScaladoc
/** A map of all loaded files to the rich compilation units that correspond to them.
*/
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
index 034a844e2e..5cda0e53fb 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
@@ -7,7 +7,7 @@ import reporters.{Reporter => CompilerReporter}
/** Trait encapsulating the creation of a presentation compiler's instance.*/
private[tests] trait PresentationCompilerInstance extends TestSettings {
protected val settings = new Settings
- protected val docSettings = new doc.Settings(_ => ())
+ protected val withDocComments = false
protected val compilerReporter: CompilerReporter = new InteractiveReporter {
override def compiler = PresentationCompilerInstance.this.compiler
@@ -15,7 +15,9 @@ private[tests] trait PresentationCompilerInstance extends TestSettings {
protected lazy val compiler: Global = {
prepareSettings(settings)
- new Global(settings, compilerReporter)
+ new Global(settings, compilerReporter) {
+ override def forScaladoc = withDocComments
+ }
}
/**
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index f380b9d04f..8287c1f631 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -21,6 +21,7 @@ abstract class Erasure extends AddInterfaces
import global._
import definitions._
import CODE._
+ import treeInfo._
val phaseName: String = "erasure"
@@ -357,41 +358,10 @@ abstract class Erasure extends AddInterfaces
override def newTyper(context: Context) = new Eraser(context)
- private def safeToRemoveUnbox(cls: Symbol): Boolean =
- (cls == definitions.NullClass) || isBoxedValueClass(cls)
-
- /** An extractor object for unboxed expressions (maybe subsumed by posterasure?) */
- object Unboxed {
- def unapply(tree: Tree): Option[Tree] = tree match {
- case Apply(fn, List(arg)) if isUnbox(fn.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) =>
- Some(arg)
- case Apply(
- TypeApply(
- cast @ Select(
- Apply(
- sel @ Select(arg, acc),
- List()),
- asinstanceof),
- List(tpt)),
- List())
- if cast.symbol == Object_asInstanceOf &&
- tpt.tpe.typeSymbol.isDerivedValueClass &&
- sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox =>
- Some(arg)
- case _ =>
- None
- }
- }
-
- /** An extractor object for boxed expressions (maybe subsumed by posterasure?) */
- object Boxed {
- def unapply(tree: Tree): Option[Tree] = tree match {
- case Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)) if (tpt.tpe.typeSymbol.isDerivedValueClass) =>
- Some(arg)
- case LabelDef(name, params, Boxed(rhs)) =>
- Some(treeCopy.LabelDef(tree, name, params, rhs) setType rhs.tpe)
- case _ =>
- None
+ private def isSafelyRemovableUnbox(fn: Tree, arg: Tree): Boolean = {
+ isUnbox(fn.symbol) && {
+ val cls = arg.tpe.typeSymbol
+ (cls == definitions.NullClass) || isBoxedValueClass(cls)
}
}
@@ -578,12 +548,7 @@ abstract class Erasure extends AddInterfaces
val tree1 = tree.tpe match {
case ErasedValueType(tref) =>
val clazz = tref.sym
- tree match {
- case Unboxed(arg) if arg.tpe.typeSymbol == clazz =>
- log("shortcircuiting unbox -> box "+arg); arg
- case _ =>
- New(clazz, cast(tree, underlyingOfValueClass(clazz)))
- }
+ New(clazz, cast(tree, underlyingOfValueClass(clazz)))
case _ =>
tree.tpe.typeSymbol match {
case UnitClass =>
@@ -599,7 +564,7 @@ abstract class Erasure extends AddInterfaces
* This is important for specialization: calls to the super constructor should not box/unbox specialized
* fields (see TupleX). (ID)
*/
- case Apply(boxFun, List(arg)) if isUnbox(tree.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) =>
+ case Apply(boxFun, List(arg)) if isSafelyRemovableUnbox(tree, arg) =>
log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}")
arg
case _ =>
@@ -634,24 +599,18 @@ abstract class Erasure extends AddInterfaces
case _ =>
val tree1 = pt match {
case ErasedValueType(tref) =>
- tree match {
- case Boxed(arg) if arg.tpe.isInstanceOf[ErasedValueType] =>
- log("shortcircuiting box -> unbox "+arg)
- arg
- case _ =>
- val clazz = tref.sym
- log("not boxed: "+tree)
- lazy val underlying = underlyingOfValueClass(clazz)
- val tree0 =
- if (tree.tpe.typeSymbol == NullClass &&
- isPrimitiveValueClass(underlying.typeSymbol)) {
- // convert `null` directly to underlying type, as going
- // via the unboxed type would yield a NPE (see SI-5866)
- unbox1(tree, underlying)
- } else
- Apply(Select(adaptToType(tree, clazz.tpe), clazz.derivedValueClassUnbox), List())
- cast(tree0, pt)
- }
+ val clazz = tref.sym
+ log("not boxed: "+tree)
+ lazy val underlying = underlyingOfValueClass(clazz)
+ val tree0 =
+ if (tree.tpe.typeSymbol == NullClass &&
+ isPrimitiveValueClass(underlying.typeSymbol)) {
+ // convert `null` directly to underlying type, as going
+ // via the unboxed type would yield a NPE (see SI-5866)
+ unbox1(tree, underlying)
+ } else
+ Apply(Select(adaptToType(tree, clazz.tpe), clazz.derivedValueClassUnbox), List())
+ cast(tree0, pt)
case _ =>
pt.typeSymbol match {
case UnitClass =>
diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
index a8dc47046b..2a86d711f1 100644
--- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
@@ -9,10 +9,10 @@ package transform
* performs peephole optimizations.
*/
trait PostErasure extends InfoTransform with TypingTransformers {
-
val global: Global
+
import global._
- import definitions._
+ import treeInfo._
val phaseName: String = "posterasure"
@@ -21,51 +21,33 @@ trait PostErasure extends InfoTransform with TypingTransformers {
object elimErasedValueType extends TypeMap {
def apply(tp: Type) = tp match {
- case ConstantType(Constant(tp: Type)) =>
- ConstantType(Constant(apply(tp)))
- case ErasedValueType(tref) =>
- enteringPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref))
- case _ => mapOver(tp)
+ case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp)))
+ case ErasedValueType(tref) => enteringErasure(erasure.erasedValueClassArg(tref))
+ case _ => mapOver(tp)
}
}
def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp)
class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
+ override def transform(tree: Tree) = {
+ def finish(res: Tree) = logResult(s"Posterasure reduction\n Old: $tree\n New")(res)
+
+ /** We use the name of the operation being performed and not the symbol
+ * itself because the symbol hails from the boxed class, and this transformation
+ * exists to operate directly on the values. So we are for instance looking
+ * up == on an lhs of type Int, whereas the symbol which has been passed in
+ * is from java.lang.Integer.
+ */
+ def binop(lhs: Tree, op: Symbol, rhs: Tree) =
+ finish(localTyper typed (Apply(Select(lhs, op.name) setPos tree.pos, rhs :: Nil) setPos tree.pos))
- override def transform(tree: Tree) =
super.transform(tree) setType elimErasedValueType(tree.tpe) match {
- case // new C(arg).underlying ==> arg
- Apply(sel @ Select(
- Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)),
- acc), List())
- if enteringPhase(currentRun.erasurePhase) {
- tpt.tpe.typeSymbol.isDerivedValueClass &&
- sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox
- } =>
- if (settings.debug.value) log("Removing "+tree+" -> "+arg)
- arg
- case // new C(arg1) == new C(arg2) ==> arg1 == arg2
- Apply(sel @ Select(
- Apply(Select(New(tpt1), nme.CONSTRUCTOR), List(arg1)),
- cmp),
- List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2))))
- if enteringPhase(currentRun.erasurePhase) {
- tpt1.tpe.typeSymbol.isDerivedValueClass &&
- (sel.symbol == Object_== || sel.symbol == Object_!=) &&
- tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol
- } =>
- val result = Apply(Select(arg1, cmp) setPos sel.pos, List(arg2)) setPos tree.pos
- log("shortcircuiting equality "+tree+" -> "+result)
- localTyper.typed(result)
-
- case // arg.asInstanceOf[T] ==> arg if arg.tpe == T
- Apply(TypeApply(cast @ Select(arg, asinstanceof), List(tpt)), List())
- if cast.symbol == Object_asInstanceOf && arg.tpe =:= tpt.tpe => // !!! <:< ?
- if (settings.debug.value) log("Shortening "+tree+" -> "+arg)
- arg
- case tree1 =>
- tree1
+ case AsInstanceOf(v, tpe) if v.tpe <:< tpe => finish(v) // x.asInstanceOf[X] ==> x
+ case ValueClass.BoxAndUnbox(v) => finish(v) // (new B(v)).unbox ==> v
+ case ValueClass.BoxAndCompare(v1, op, v2) => binop(v1, op, v2) // new B(v1) == new B(v2) ==> v1 == v2
+ case tree => tree
}
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 711085e6c9..b070bd1b49 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -573,8 +573,7 @@ trait Contexts { self: Analyzer =>
( superAccess
|| pre.isInstanceOf[ThisType]
|| phase.erasedTypes
- || isProtectedAccessOK(sym)
- || (sym.allOverriddenSymbols exists isProtectedAccessOK)
+ || (sym.overrideChain exists isProtectedAccessOK)
// that last condition makes protected access via self types work.
)
)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index fb8d6b934f..8829a9a92e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -331,7 +331,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
def param(tree: Tree): Symbol = (
cache.getOrElseUpdate(tree.symbol, {
val sym = tree.symbol
- makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym getFlag SYNTHETIC)
+ makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym.flags)
})
)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 60a73036f8..dd16e9de30 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -726,8 +726,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
else if (clazz.isTrait && !(clazz isSubClass AnyValClass)) {
// For non-AnyVal classes, prevent abstract methods in interfaces that override
// final members in Object; see #4431
- for (decl <- clazz.info.decls.iterator) {
- val overridden = decl.overriddenSymbol(ObjectClass)
+ for (decl <- clazz.info.decls) {
+ // Have to use matchingSymbol, not a method involving overridden symbols,
+ // because the scala type system understands that an abstract method here does not
+ // override a concrete method in Object. The jvm, however, does not.
+ val overridden = decl.matchingSymbol(ObjectClass, ObjectClass.tpe)
if (overridden.isFinal)
unit.error(decl.pos, "trait cannot redefine final method from class AnyRef")
}
@@ -1499,8 +1502,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// on Unit, in which case we had better let it slide.
val isOk = (
sym.isGetter
- || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType))
|| (sym.name containsName nme.DEFAULT_GETTER_STRING)
+ || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType))
)
if (!isOk)
unit.warning(sym.pos, s"side-effecting nullary methods are discouraged: suggest defining as `def ${sym.name.decode}()` instead")
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 0992cd7955..f2129992e5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -67,7 +67,10 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case t => t
}
acc setInfoAndEnter (tpe cloneInfo acc)
- storeAccessorDefinition(clazz, DefDef(acc, EmptyTree))
+ // Diagnostic for SI-7091
+ if (!accDefs.contains(clazz))
+ reporter.error(sel.pos, s"Internal error: unable to store accessor definition in ${clazz}. clazz.isPackage=${clazz.isPackage}. Accessor required for ${sel} (${showRaw(sel)})")
+ else storeAccessorDefinition(clazz, DefDef(acc, EmptyTree))
acc
}
@@ -288,6 +291,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
currentClass.isTrait
&& sym.isProtected
&& sym.enclClass != currentClass
+ && !sym.owner.isPackageClass // SI-7091 no accessor needed package owned (ie, top level) symbols
&& !sym.owner.isTrait
&& (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
&& (qual.symbol.info.member(sym.name) ne NoSymbol)
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index cfe962d65f..81ea5630d0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -101,14 +101,9 @@ trait TypeDiagnostics {
"\n(Note that variables need to be initialized to be defined)"
else ""
- /** Only prints the parameter names if they're not synthetic,
- * since "x$1: Int" does not offer any more information than "Int".
- */
private def methodTypeErrorString(tp: Type) = tp match {
case mt @ MethodType(params, resultType) =>
- def forString =
- if (params exists (_.isSynthetic)) params map (_.tpe)
- else params map (_.defString)
+ def forString = params map (_.defString)
forString.mkString("(", ",", ")") + resultType
case x => x.toString
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c1fcff0c4e..561ca7f382 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4070,15 +4070,11 @@ trait Typers extends Adaptations with Tags {
def resultingTypeTree(tpe: Type) = {
// we need symbol-ful originals for reification
// hence we go the extra mile to hand-craft tis guy
- val original =
- if (arg1.isType)
- arg1 match {
- case tt @ TypeTree() => Annotated(ann, tt.original)
- // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
- case _ => Annotated(ann, arg1)
- }
- else
- tree
+ val original = arg1 match {
+ case tt @ TypeTree() => Annotated(ann, tt.original)
+ // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
+ case _ => Annotated(ann, arg1)
+ }
original setType ann.tpe
TypeTree(tpe) setOriginal original setPos tree.pos.focus
}
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index 0877bfbb69..f1cfd2d69a 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -107,7 +107,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
* the identity of the buffer. It takes time linear in
* the buffer size.
*
- * @param elem the element to append.
+ * @param elem the element to prepend.
* @return the updated buffer.
*/
def +=:(elem: A): this.type = {
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 36f3be341f..0670da137c 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -299,8 +299,8 @@ trait Future[+T] extends Awaitable[T] {
* val f = future { 5 }
* val g = f filter { _ % 2 == 1 }
* val h = f filter { _ % 2 == 0 }
- * await(g, 0) // evaluates to 5
- * await(h, 0) // throw a NoSuchElementException
+ * Await.result(g, Duration.Zero) // evaluates to 5
+ * Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*/
def filter(pred: T => Boolean)(implicit executor: ExecutionContext): Future[T] = {
@@ -348,8 +348,8 @@ trait Future[+T] extends Awaitable[T] {
* val h = f collect {
* case x if x > 0 => x * 2
* }
- * await(g, 0) // evaluates to 5
- * await(h, 0) // throw a NoSuchElementException
+ * Await.result(g, Duration.Zero) // evaluates to 5
+ * Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*/
def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): Future[S] = {
@@ -454,7 +454,7 @@ trait Future[+T] extends Awaitable[T] {
* val f = future { sys.error("failed") }
* val g = future { 5 }
* val h = f fallbackTo g
- * await(h, 0) // evaluates to 5
+ * Await.result(h, Duration.Zero) // evaluates to 5
* }}}
*/
def fallbackTo[U >: T](that: Future[U]): Future[U] = {
@@ -634,7 +634,7 @@ object Future {
*
* Example:
* {{{
- * val result = Await.result(Futures.reduce(futures)(_ + _), 5 seconds)
+ * val result = Await.result(Future.reduce(futures)(_ + _), 5 seconds)
* }}}
*/
def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 8f86fd5aa7..feb538033b 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -247,7 +247,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
*/
def gcd (that: BigInt): BigInt = new BigInt(this.bigInteger.gcd(that.bigInteger))
- /** Returns a BigInt whose value is (this mod m).
+ /** Returns a BigInt whose value is (this mod that).
* This method differs from `%` in that it always returns a non-negative BigInt.
*/
def mod (that: BigInt): BigInt = new BigInt(this.bigInteger.mod(that.bigInteger))
diff --git a/src/reflect/scala/reflect/api/ImplicitTags.scala b/src/reflect/scala/reflect/api/ImplicitTags.scala
new file mode 100644
index 0000000000..3f377d6cff
--- /dev/null
+++ b/src/reflect/scala/reflect/api/ImplicitTags.scala
@@ -0,0 +1,108 @@
+package scala.reflect
+package api
+
+trait ImplicitTags {
+ self: Types =>
+
+ /** A tag that preserves the identity of the `Type` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val TypeTagg: ClassTag[Type]
+
+ /** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val SingletonTypeTag: ClassTag[SingletonType]
+
+ /** A tag that preserves the identity of the `ThisType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val ThisTypeTag: ClassTag[ThisType]
+
+ /** A tag that preserves the identity of the `SingleType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val SingleTypeTag: ClassTag[SingleType]
+
+ /** A tag that preserves the identity of the `SuperType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val SuperTypeTag: ClassTag[SuperType]
+
+ /** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val ConstantTypeTag: ClassTag[ConstantType]
+
+ /** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val TypeRefTag: ClassTag[TypeRef]
+
+ /** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val CompoundTypeTag: ClassTag[CompoundType]
+
+ /** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val RefinedTypeTag: ClassTag[RefinedType]
+
+ /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]
+
+ /** A tag that preserves the identity of the `MethodType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val MethodTypeTag: ClassTag[MethodType]
+
+ /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]
+
+ /** A tag that preserves the identity of the `PolyType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val PolyTypeTag: ClassTag[PolyType]
+
+ /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val ExistentialTypeTag: ClassTag[ExistentialType]
+
+ /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
+
+ /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val TypeBoundsTag: ClassTag[TypeBounds]
+
+ /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+ implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
+}
diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala
index 143438b8f5..e8e9e9c048 100644
--- a/src/reflect/scala/reflect/api/Types.scala
+++ b/src/reflect/scala/reflect/api/Types.scala
@@ -50,7 +50,8 @@ package api
*
* @contentDiagram hideNodes "*Api"
*/
-trait Types { self: Universe =>
+trait Types extends ImplicitTags {
+ self: Universe =>
/** The type of Scala types, and also Scala type signatures.
* (No difference is internally made between the two).
@@ -59,12 +60,6 @@ trait Types { self: Universe =>
*/
type Type >: Null <: TypeApi
- /** A tag that preserves the identity of the `Type` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeTagg: ClassTag[Type]
-
/** This constant is used as a special value that indicates that no meaningful type exists.
* @group Types
*/
@@ -256,12 +251,6 @@ trait Types { self: Universe =>
*/
type SingletonType >: Null <: Type
- /** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SingletonTypeTag: ClassTag[SingletonType]
-
/** A singleton type that describes types of the form on the left with the
* corresponding `ThisType` representation to the right:
* {{{
@@ -272,12 +261,6 @@ trait Types { self: Universe =>
*/
type ThisType >: Null <: AnyRef with SingletonType with ThisTypeApi
- /** A tag that preserves the identity of the `ThisType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ThisTypeTag: ClassTag[ThisType]
-
/** The constructor/extractor for `ThisType` instances.
* @group Extractors
*/
@@ -316,12 +299,6 @@ trait Types { self: Universe =>
*/
type SingleType >: Null <: AnyRef with SingletonType with SingleTypeApi
- /** A tag that preserves the identity of the `SingleType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SingleTypeTag: ClassTag[SingleType]
-
/** The constructor/extractor for `SingleType` instances.
* @group Extractors
*/
@@ -361,12 +338,6 @@ trait Types { self: Universe =>
*/
type SuperType >: Null <: AnyRef with SingletonType with SuperTypeApi
- /** A tag that preserves the identity of the `SuperType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val SuperTypeTag: ClassTag[SuperType]
-
/** The constructor/extractor for `SuperType` instances.
* @group Extractors
*/
@@ -406,12 +377,6 @@ trait Types { self: Universe =>
*/
type ConstantType >: Null <: AnyRef with SingletonType with ConstantTypeApi
- /** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ConstantTypeTag: ClassTag[ConstantType]
-
/** The constructor/extractor for `ConstantType` instances.
* @group Extractors
*/
@@ -450,12 +415,6 @@ trait Types { self: Universe =>
*/
type TypeRef >: Null <: AnyRef with Type with TypeRefApi
- /** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeRefTag: ClassTag[TypeRef]
-
/** The constructor/extractor for `TypeRef` instances.
* @group Extractors
*/
@@ -497,12 +456,6 @@ trait Types { self: Universe =>
*/
type CompoundType >: Null <: AnyRef with Type
- /** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val CompoundTypeTag: ClassTag[CompoundType]
-
/** The `RefinedType` type defines types of any of the forms on the left,
* with their RefinedType representations to the right.
* {{{
@@ -515,12 +468,6 @@ trait Types { self: Universe =>
*/
type RefinedType >: Null <: AnyRef with CompoundType with RefinedTypeApi
- /** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val RefinedTypeTag: ClassTag[RefinedType]
-
/** The constructor/extractor for `RefinedType` instances.
* @group Extractors
*/
@@ -567,12 +514,6 @@ trait Types { self: Universe =>
*/
type ClassInfoType >: Null <: AnyRef with CompoundType with ClassInfoTypeApi
- /** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]
-
/** The constructor/extractor for `ClassInfoType` instances.
* @group Extractors
*/
@@ -610,12 +551,6 @@ trait Types { self: Universe =>
*/
type MethodType >: Null <: AnyRef with Type with MethodTypeApi
- /** A tag that preserves the identity of the `MethodType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val MethodTypeTag: ClassTag[MethodType]
-
/** The constructor/extractor for `MethodType` instances.
* @group Extractors
*/
@@ -660,12 +595,6 @@ trait Types { self: Universe =>
*/
type NullaryMethodType >: Null <: AnyRef with Type with NullaryMethodTypeApi
- /** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]
-
/** The constructor/extractor for `NullaryMethodType` instances.
* @group Extractors
*/
@@ -696,12 +625,6 @@ trait Types { self: Universe =>
*/
type PolyType >: Null <: AnyRef with Type with PolyTypeApi
- /** A tag that preserves the identity of the `PolyType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val PolyTypeTag: ClassTag[PolyType]
-
/** The constructor/extractor for `PolyType` instances.
* @group Extractors
*/
@@ -736,12 +659,6 @@ trait Types { self: Universe =>
*/
type ExistentialType >: Null <: AnyRef with Type with ExistentialTypeApi
- /** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val ExistentialTypeTag: ClassTag[ExistentialType]
-
/** The constructor/extractor for `ExistentialType` instances.
* @group Extractors
*/
@@ -777,12 +694,6 @@ trait Types { self: Universe =>
*/
type AnnotatedType >: Null <: AnyRef with Type with AnnotatedTypeApi
- /** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
-
/** The constructor/extractor for `AnnotatedType` instances.
* @group Extractors
*/
@@ -828,12 +739,6 @@ trait Types { self: Universe =>
*/
type TypeBounds >: Null <: AnyRef with Type with TypeBoundsApi
- /** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val TypeBoundsTag: ClassTag[TypeBounds]
-
/** The constructor/extractor for `TypeBounds` instances.
* @group Extractors
*/
@@ -885,12 +790,6 @@ trait Types { self: Universe =>
*/
type BoundedWildcardType >: Null <: AnyRef with Type with BoundedWildcardTypeApi
- /** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
- * Can be used for pattern matching, instance tests, serialization and likes.
- * @group Tags
- */
- implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
-
/** The constructor/extractor for `BoundedWildcardType` instances.
* @group Extractors
*/
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 45c5279574..06f6c46fc3 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -287,7 +287,7 @@ class Flags extends ModifierFlags {
* from Modifiers. Others which may be applied at creation time are:
* SYNTHETIC.
*/
- final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM | STABLE
+ final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM | STABLE | SYNTHETIC
final val BeanPropertyFlags = DEFERRED | OVERRIDE | STATIC
final val VarianceFlags = COVARIANT | CONTRAVARIANT
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 4f6dab3e7c..fbf14e8156 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -853,12 +853,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this a term symbol only defined in a refinement (so that it needs
* to be accessed by reflection)?
*/
- def isOnlyRefinementMember: Boolean =
+ def isOnlyRefinementMember: Boolean = (
isTerm && // type members are not affected
owner.isRefinementClass && // owner must be a refinement class
(owner.info decl name) == this && // symbol must be explicitly declared in the refinement (not synthesized from glb)
- allOverriddenSymbols.isEmpty && // symbol must not override a symbol in a base class
+ !isOverridingSymbol && // symbol must not override a symbol in a base class
!isConstant // symbol must not be a constant. Question: Can we exclude @inline methods as well?
+ )
final def isStructuralRefinementMember = owner.isStructuralRefinement && isPossibleInRefinement && isPublic
final def isPossibleInRefinement = !isConstructor && !isOverridingSymbol
@@ -960,14 +961,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def ownerChain: List[Symbol] = this :: owner.ownerChain
def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain
- // All the symbols overridden by this symbol and this symbol at the head,
- // or Nil if this is NoSymbol.
- def overrideChain = (
- if (this eq NoSymbol) Nil
- else if (!owner.isClass) this :: Nil
- else this :: allOverriddenSymbols
- )
-
// Non-classes skip self and return rest of owner chain; overridden in ClassSymbol.
def enclClassChain: List[Symbol] = owner.enclClassChain
@@ -2070,81 +2063,111 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* @param ofclazz The class containing the symbol's definition
* @param site The base type from which member types are computed
*/
- final def matchingSymbol(ofclazz: Symbol, site: Type): Symbol = {
- //OPT cut down on #closures by special casing non-overloaded case
- // was: ofclazz.info.nonPrivateDecl(name) filter (sym =>
- // !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
- val result = ofclazz.info.nonPrivateDecl(name)
- def qualifies(sym: Symbol) = !sym.isTerm || (site.memberType(this) matches site.memberType(sym))
- if ((result eq NoSymbol) || !result.isOverloaded && qualifies(result)) result
- else result filter qualifies
- }
+ final def matchingSymbol(ofclazz: Symbol, site: Type): Symbol =
+ matchingSymbolInternal(site, ofclazz.info nonPrivateDecl name)
/** The non-private member of `site` whose type and name match the type of this symbol. */
final def matchingSymbol(site: Type, admit: Long = 0L): Symbol =
- site.nonPrivateMemberAdmitting(name, admit).filter(sym =>
- !sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
+ matchingSymbolInternal(site, site.nonPrivateMemberAdmitting(name, admit))
- /** The symbol, in class `ofclazz`, that is overridden by this symbol.
+ private def matchingSymbolInternal(site: Type, candidate: Symbol): Symbol = {
+ def qualifies(sym: Symbol) = !sym.isTerm || ((site memberType this) matches (site memberType sym))
+ //OPT cut down on #closures by special casing non-overloaded case
+ if (candidate.isOverloaded) candidate filter qualifies
+ else if (qualifies(candidate)) candidate
+ else NoSymbol
+ }
+
+ /** The symbol, in class `baseClass`, that is overridden by this symbol.
*
- * @param ofclazz is a base class of this symbol's owner.
+ * @param baseClass is a base class of this symbol's owner.
*/
- final def overriddenSymbol(ofclazz: Symbol): Symbol =
- if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, owner.thisType)
+ final def overriddenSymbol(baseClass: Symbol): Symbol = (
+ // concrete always overrides abstract, so don't let an abstract definition
+ // claim to be overriding an inherited concrete one.
+ matchingInheritedSymbolIn(baseClass) filter (res => res.isDeferred || !this.isDeferred)
+ )
+
+ private def matchingInheritedSymbolIn(baseClass: Symbol): Symbol =
+ if (canMatchInheritedSymbols) matchingSymbol(baseClass, owner.thisType) else NoSymbol
/** The symbol overriding this symbol in given subclass `ofclazz`.
*
* @param ofclazz is a subclass of this symbol's owner
*/
- final def overridingSymbol(ofclazz: Symbol): Symbol =
- if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType)
+ final def overridingSymbol(ofclazz: Symbol): Symbol = (
+ if (canMatchInheritedSymbols)
+ matchingSymbol(ofclazz, ofclazz.thisType)
+ else
+ NoSymbol
+ )
- /** Returns all symbols overriden by this symbol. */
- final def allOverriddenSymbols: List[Symbol] = (
- if ((this eq NoSymbol) || !owner.isClass) Nil
- else {
- def loop(xs: List[Symbol]): List[Symbol] = xs match {
- case Nil => Nil
- case x :: xs =>
- overriddenSymbol(x) match {
- case NoSymbol => loop(xs)
- case sym => sym :: loop(xs)
- }
- }
- loop(owner.ancestors)
- }
+ /** If false, this symbol cannot possibly participate in an override,
+ * either as overrider or overridee. For internal use; you should consult
+ * with isOverridingSymbol. This is used by isOverridingSymbol to escape
+ * the recursive knot.
+ */
+ private def canMatchInheritedSymbols = (
+ (this ne NoSymbol)
+ && owner.isClass
+ && !this.isClass
+ && !this.isConstructor
+ )
+
+ // All the symbols overridden by this symbol and this symbol at the head,
+ // or Nil if this is NoSymbol.
+ def overrideChain = (
+ if (this eq NoSymbol) Nil
+ else if (isOverridingSymbol) this :: allOverriddenSymbols
+ else this :: Nil
)
+ /** Returns all symbols overridden by this symbol. */
+ final def allOverriddenSymbols: List[Symbol] = {
+ def loop(xs: List[Symbol]): List[Symbol] = xs match {
+ case Nil => Nil
+ case x :: xs =>
+ overriddenSymbol(x) match {
+ case NoSymbol => loop(xs)
+ case sym => sym :: loop(xs)
+ }
+ }
+ if (isOverridingSymbol) loop(owner.ancestors) else Nil
+ }
+
/** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */
- // !!! When if ever will this answer differ from .isOverride?
- // How/where is the OVERRIDE flag managed, as compared to how checks
- // based on type membership will evaluate?
- def isOverridingSymbol = owner.isClass && (
- owner.ancestors exists (cls => matchingSymbol(cls, owner.thisType) != NoSymbol)
+ lazy val isOverridingSymbol = (
+ canMatchInheritedSymbols
+ && owner.ancestors.exists(base => overriddenSymbol(base) != NoSymbol)
)
+
/** Equivalent to allOverriddenSymbols.head (or NoSymbol if no overrides) but more efficient. */
def nextOverriddenSymbol: Symbol = {
- if ((this ne NoSymbol) && owner.isClass) owner.ancestors foreach { base =>
- val sym = overriddenSymbol(base)
- if (sym != NoSymbol)
- return sym
+ @tailrec def loop(bases: List[Symbol]): Symbol = bases match {
+ case Nil => NoSymbol
+ case base :: rest =>
+ val sym = overriddenSymbol(base)
+ if (sym == NoSymbol) loop(rest) else sym
}
- NoSymbol
+ if (isOverridingSymbol) loop(owner.ancestors) else NoSymbol
}
/** Returns all symbols overridden by this symbol, plus all matching symbols
* defined in parents of the selftype.
*/
- final def extendedOverriddenSymbols: List[Symbol] =
- if (!owner.isClass) Nil
- else owner.thisSym.ancestors map overriddenSymbol filter (_ != NoSymbol)
+ final def extendedOverriddenSymbols: List[Symbol] = (
+ if (canMatchInheritedSymbols)
+ owner.thisSym.ancestors map overriddenSymbol filter (_ != NoSymbol)
+ else
+ Nil
+ )
/** The symbol accessed by a super in the definition of this symbol when
* seen from class `base`. This symbol is always concrete.
* pre: `this.owner` is in the base class sequence of `base`.
*/
final def superSymbol(base: Symbol): Symbol = {
- var bcs = base.info.baseClasses.dropWhile(owner != _).tail
+ var bcs = base.info.baseClasses dropWhile (owner != _) drop 1
var sym: Symbol = NoSymbol
while (!bcs.isEmpty && sym == NoSymbol) {
if (!bcs.head.isImplClass)
diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala
index b078b7d4f9..0fa798058d 100644
--- a/src/reflect/scala/reflect/internal/util/Statistics.scala
+++ b/src/reflect/scala/reflect/internal/util/Statistics.scala
@@ -109,7 +109,7 @@ quant)
* Quantities with non-empty prefix are printed in the statistics info.
*/
trait Quantity {
- if (prefix.nonEmpty) {
+ if (enabled && prefix.nonEmpty) {
val key = s"${if (underlying != this) underlying.prefix else ""}/$prefix"
qs(key) = this
}
diff --git a/test/disabled/jvm/scala-concurrent-tck-akka.scala b/test/disabled/jvm/scala-concurrent-tck-akka.scala
deleted file mode 100644
index dfd906e59e..0000000000
--- a/test/disabled/jvm/scala-concurrent-tck-akka.scala
+++ /dev/null
@@ -1,391 +0,0 @@
-
-
-import akka.dispatch.{
- Future => future,
- Promise => promise
-}
-import akka.dispatch.Await.{result => await}
-
-// Duration required for await
-import akka.util.Duration
-import java.util.concurrent.TimeUnit
-import TimeUnit._
-
-import scala.concurrent.{
- TimeoutException,
- SyncVar,
- ExecutionException
-}
-//import scala.concurrent.future
-//import scala.concurrent.promise
-//import scala.concurrent.await
-
-
-
-trait TestBase {
-
- implicit val disp = akka.actor.ActorSystem().dispatcher
-
- def once(body: (() => Unit) => Unit) {
- val sv = new SyncVar[Boolean]
- body(() => sv put true)
- sv.take()
- }
-
-}
-
-
-trait FutureCallbacks extends TestBase {
-
- def testOnSuccess(): Unit = once {
- done =>
- var x = 0
- val f = future {
- x = 1
- }
- f onSuccess { case any =>
- done()
- assert(x == 1)
- }
- }
-
- def testOnSuccessWhenCompleted(): Unit = once {
- done =>
- var x = 0
- val f = future {
- x = 1
- }
- f onSuccess { case any =>
- assert(x == 1)
- x = 2
- f onSuccess { case any =>
- assert(x == 2)
- done()
- }
- }
- }
-
- def testOnSuccessWhenFailed(): Unit = once {
- done =>
- val f = future[Unit] {
- done()
- throw new Exception
- }
- f onSuccess { case any =>
- assert(false)
- }
- }
-
- def testOnFailure(): Unit = once {
- done =>
- var x = 0
- val f = future[Unit] {
- x = 1
- throw new Exception
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case _ =>
- done()
- assert(x == 1)
- }
- }
-
- def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once {
- done =>
- val f = future[Unit] {
- throw cause
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case e: ExecutionException if (e.getCause == cause) =>
- done()
- case _ =>
- done()
- assert(false)
- }
- }
-
- def testOnFailureWhenTimeoutException(): Unit = once {
- done =>
- val f = future[Unit] {
- throw new TimeoutException()
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case e: TimeoutException =>
- done()
- case other =>
- done()
- assert(false)
- }
- }
-
- testOnSuccess()
- testOnSuccessWhenCompleted()
- testOnSuccessWhenFailed()
- testOnFailure()
-// testOnFailureWhenSpecialThrowable(5, new Error)
-// testOnFailureWhenSpecialThrowable(6, new scala.util.control.ControlThrowable { })
-// testOnFailureWhenSpecialThrowable(7, new InterruptedException)
-// testOnFailureWhenTimeoutException()
-
-}
-
-
-trait FutureCombinators extends TestBase {
-
- // map: stub
- def testMapSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testMapFailure(): Unit = once {
- done =>
- done()
- }
-
- // flatMap: stub
- def testFlatMapSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testFlatMapFailure(): Unit = once {
- done =>
- done()
- }
-
- // filter: stub
- def testFilterSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testFilterFailure(): Unit = once {
- done =>
- done()
- }
-
- // foreach: stub
- def testForeachSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testForeachFailure(): Unit = once {
- done =>
- done()
- }
-
- def testRecoverSuccess(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- } recover {
- case re: RuntimeException =>
- "recovered"
- } onSuccess { case x =>
- done()
- assert(x == "recovered")
- } onFailure { case any =>
- done()
- assert(false)
- }
- }
-
- def testRecoverFailure(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- } recover {
- case te: TimeoutException => "timeout"
- } onSuccess { case x =>
- done()
- assert(false)
- } onFailure { case any =>
- done()
- assert(any == cause)
- }
- }
-
- testMapSuccess()
- testMapFailure()
- testFlatMapSuccess()
- testFlatMapFailure()
- testFilterSuccess()
- testFilterFailure()
- testForeachSuccess()
- testForeachFailure()
- testRecoverSuccess()
- testRecoverFailure()
-
-}
-
-/*
-trait FutureProjections extends TestBase {
-
- def testFailedFailureOnComplete(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- f.failed onComplete {
- case Right(t) =>
- assert(t == cause)
- done()
- case Left(t) =>
- assert(false)
- }
- }
-
- def testFailedFailureOnSuccess(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- f.failed onSuccess {
- t =>
- assert(t == cause)
- done()
- }
- }
-
- def testFailedSuccessOnComplete(): Unit = once {
- done =>
- val f = future { 0 }
- f.failed onComplete {
- case Right(t) =>
- assert(false)
- case Left(t) =>
- assert(t.isInstanceOf[NoSuchElementException])
- done()
- }
- }
-
- def testFailedSuccessOnFailure(): Unit = once {
- done =>
- val f = future { 0 }
- f.failed onFailure {
- case nsee: NoSuchElementException =>
- done()
- }
- }
-
- def testFailedFailureAwait(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- assert(await(0, f.failed) == cause)
- done()
- }
-
- def testFailedSuccessAwait(): Unit = once {
- done =>
- val f = future { 0 }
- try {
- println(await(0, f.failed))
- assert(false)
- } catch {
- case nsee: NoSuchElementException => done()
- }
- }
-
- testFailedFailureOnComplete()
- testFailedFailureOnSuccess()
- testFailedSuccessOnComplete()
- testFailedSuccessOnFailure()
- testFailedFailureAwait()
- //testFailedSuccessAwait()
-
-}
-*/
-
-trait Blocking extends TestBase {
-
- def testAwaitSuccess(): Unit = once {
- done =>
- val f = future { 0 }
- await(f, Duration(500, "ms"))
- done()
- }
-
- def testAwaitFailure(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- try {
- await(f, Duration(500, "ms"))
- assert(false)
- } catch {
- case t =>
- assert(t == cause)
- done()
- }
- }
-
- testAwaitSuccess()
- testAwaitFailure()
-
-}
-
-/*
-trait Promises extends TestBase {
-
- def testSuccess(): Unit = once {
- done =>
- val p = promise[Int]()
- val f = p.future
-
- f.onSuccess { x =>
- done()
- assert(x == 5)
- } onFailure { case any =>
- done()
- assert(false)
- }
-
- p.success(5)
- }
-
- testSuccess()
-
-}
-*/
-
-trait Exceptions extends TestBase {
-
-}
-
-
-object Test
-extends App
-with FutureCallbacks
-with FutureCombinators
-/*with FutureProjections*/
-/*with Promises*/
-with Blocking
-with Exceptions
-{
- System.exit(0)
-}
-
-
diff --git a/test/disabled/presentation/akka/src/akka/dispatch/Future.scala b/test/disabled/presentation/akka/src/akka/dispatch/Future.scala
deleted file mode 100644
index 1ad304d726..0000000000
--- a/test/disabled/presentation/akka/src/akka/dispatch/Future.scala
+++ /dev/null
@@ -1,832 +0,0 @@
-/**
- * Copyright (C) 2009-2011 Scalable Solutions AB <http://scalablesolutions.se>
- */
-
-package akka.dispatch
-
-import akka.AkkaException
-import akka.event.EventHandler
-import akka.actor.{ Actor, Channel }
-import akka.util.Duration
-import akka.japi.{ Procedure, Function => JFunc }
-
-import scala.util.continuations._
-
-import java.util.concurrent.locks.ReentrantLock
-import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable }
-import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS => MILLIS }
-import java.util.concurrent.atomic.{ AtomicBoolean }
-import java.lang.{ Iterable => JIterable }
-import java.util.{ LinkedList => JLinkedList }
-import scala.collection.mutable.Stack
-import annotation.tailrec
-
-class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
-
-object Futures {
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T]): Future[T] =
- Future(body.call)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], timeout: Long): Future[T] =
- Future(body.call, timeout)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] =
- Future(body.call)(dispatcher)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], timeout: Long, dispatcher: MessageDispatcher): Future[T] =
- Future(body.call, timeout)(dispatcher)
-
- /**
- * Returns a Future to the result of the first future in the list that is completed
- */
- def firstCompletedOf[T](futures: Iterable[Future[T]], timeout: Long = Long.MaxValue): Future[T] = {
- val futureResult = new DefaultCompletableFuture[T](timeout)
-
- val completeFirst: Future[T] => Unit = _.value.foreach(futureResult complete _)
- for (f ← futures) f onComplete completeFirst
-
- futureResult
- }
-
- /**
- * Java API.
- * Returns a Future to the result of the first future in the list that is completed
- */
- def firstCompletedOf[T <: AnyRef](futures: java.lang.Iterable[Future[T]], timeout: Long): Future[T] =
- firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)
-
- /**
- * A non-blocking fold over the specified futures.
- * The fold is performed on the thread where the last future is completed,
- * the result will be the first failure of any of the futures, or any failure in the actual fold,
- * or the result of the fold.
- * Example:
- * <pre>
- * val result = Futures.fold(0)(futures)(_ + _).await.result
- * </pre>
- */
- def fold[T, R](zero: R, timeout: Long = Actor.TIMEOUT)(futures: Iterable[Future[T]])(foldFun: (R, T) => R): Future[R] = {
- if (futures.isEmpty) {
- new AlreadyCompletedFuture[R](Right(zero))
- } else {
- val result = new DefaultCompletableFuture[R](timeout)
- val results = new ConcurrentLinkedQueue[T]()
- val allDone = futures.size
-
- val aggregate: Future[T] => Unit = f => if (!result.isCompleted) { //TODO: This is an optimization, is it premature?
- f.value.get match {
- case r: Right[Throwable, T] =>
- results add r.b
- if (results.size == allDone) { //Only one thread can get here
- try {
- result completeWithResult scala.collection.JavaConversions.collectionAsScalaIterable(results).foldLeft(zero)(foldFun)
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- result completeWithException e
- }
- finally {
- results.clear
- }
- }
- case l: Left[Throwable, T] =>
- result completeWithException l.a
- results.clear
- }
- }
-
- futures foreach { _ onComplete aggregate }
- result
- }
- }
-
- /**
- * Java API
- * A non-blocking fold over the specified futures.
- * The fold is performed on the thread where the last future is completed,
- * the result will be the first failure of any of the futures, or any failure in the actual fold,
- * or the result of the fold.
- */
- def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Long, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] =
- fold(zero, timeout)(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(fun.apply _)
-
- /**
- * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first
- * Example:
- * <pre>
- * val result = Futures.reduce(futures)(_ + _).await.result
- * </pre>
- */
- def reduce[T, R >: T](futures: Iterable[Future[T]], timeout: Long = Actor.TIMEOUT)(op: (R, T) => T): Future[R] = {
- if (futures.isEmpty)
- new AlreadyCompletedFuture[R](Left(new UnsupportedOperationException("empty reduce left")))
- else {
- val result = new DefaultCompletableFuture[R](timeout)
- val seedFound = new AtomicBoolean(false)
- val seedFold: Future[T] => Unit = f => {
- if (seedFound.compareAndSet(false, true)) { //Only the first completed should trigger the fold
- f.value.get match {
- case r: Right[Throwable, T] =>
- result.completeWith(fold(r.b, timeout)(futures.filterNot(_ eq f))(op))
- case l: Left[Throwable, T] =>
- result.completeWithException(l.a)
- }
- }
- }
- for (f ← futures) f onComplete seedFold //Attach the listener to the Futures
- result
- }
- }
-
- /**
- * Java API.
- * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first
- */
- def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Long, fun: akka.japi.Function2[R, T, T]): Future[R] =
- reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(fun.apply _)
-
- /**
- * Java API.
- * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A](in: JIterable[Future[A]], timeout: Long): Future[JLinkedList[A]] =
- scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[A]()))((fr, fa) =>
- for (r ← fr; a ← fa) yield {
- r add a
- r
- })
-
- /**
- * Java API.
- * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A](in: JIterable[Future[A]]): Future[JLinkedList[A]] = sequence(in, Actor.TIMEOUT)
-
- /**
- * Java API.
- * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel.
- */
- def traverse[A, B](in: JIterable[A], timeout: Long, fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] =
- scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[B]())) { (fr, a) =>
- val fb = fn(a)
- for (r ← fr; b ← fb) yield {
- r add b
- r
- }
- }
-
- /**
- * Java API.
- * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel.
- */
- def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = traverse(in, Actor.TIMEOUT, fn)
-
- // =====================================
- // Deprecations
- // =====================================
-
- /**
- * (Blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: futures.foreach(_.await)", "1.1")
- def awaitAll(futures: List[Future[_]]): Unit = futures.foreach(_.await)
-
- /**
- * Returns the First Future that is completed (blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(futures).await", "1.1")
- def awaitOne(futures: List[Future[_]], timeout: Long = Long.MaxValue): Future[_] = firstCompletedOf[Any](futures, timeout).await
-
- /**
- * Applies the supplied function to the specified collection of Futures after awaiting each future to be completed
- */
- @deprecated("Will be removed after 1.1, if you must block, use: futures map { f => fun(f.await) }", "1.1")
- def awaitMap[A, B](in: Traversable[Future[A]])(fun: (Future[A]) => B): Traversable[B] =
- in map { f => fun(f.await) }
-
- /**
- * Returns Future.resultOrException of the first completed of the 2 Futures provided (blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(List(f1,f2)).await.resultOrException", "1.1")
- def awaitEither[T](f1: Future[T], f2: Future[T]): Option[T] = firstCompletedOf[T](List(f1, f2)).await.resultOrException
-}
-
-object Future {
- /**
- * This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body
- * The execution is performed by the specified Dispatcher.
- */
- def apply[T](body: => T, timeout: Long = Actor.TIMEOUT)(implicit dispatcher: MessageDispatcher): Future[T] =
- dispatcher.dispatchFuture(() => body, timeout)
-
- /**
- * Construct a completable channel
- */
- def channel(timeout: Long = Actor.TIMEOUT) = new Channel[Any] {
- val future = empty[Any](timeout)
- def !(msg: Any) = future completeWithResult msg
- }
-
- /**
- * Create an empty Future with default timeout
- */
- def empty[T](timeout: Long = Actor.TIMEOUT) = new DefaultCompletableFuture[T](timeout)
-
- import scala.collection.mutable.Builder
- import scala.collection.generic.CanBuildFrom
-
- /**
- * Simple version of Futures.traverse. Transforms a Traversable[Future[A]] into a Future[Traversable[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]], timeout: Long = Actor.TIMEOUT)(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]]): Future[M[A]] =
- in.foldLeft(new DefaultCompletableFuture[Builder[A, M[A]]](timeout).completeWithResult(cbf(in)): Future[Builder[A, M[A]]])((fr, fa) => for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result)
-
- /**
- * Transforms a Traversable[A] into a Future[Traversable[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel:
- * <pre>
- * val myFutureList = Futures.traverse(myList)(x => Future(myFunc(x)))
- * </pre>
- */
- def traverse[A, B, M[_] <: Traversable[_]](in: M[A], timeout: Long = Actor.TIMEOUT)(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]]): Future[M[B]] =
- in.foldLeft(new DefaultCompletableFuture[Builder[B, M[B]]](timeout).completeWithResult(cbf(in)): Future[Builder[B, M[B]]]) { (fr, a) =>
- val fb = fn(a.asInstanceOf[A])
- for (r ← fr; b ← fb) yield (r += b)
- }.map(_.result)
-
- /**
- * Captures a block that will be transformed into 'Continuation Passing Style' using Scala's Delimited
- * Continuations plugin.
- *
- * Within the block, the result of a Future may be accessed by calling Future.apply. At that point
- * execution is suspended with the rest of the block being stored in a continuation until the result
- * of the Future is available. If an Exception is thrown while processing, it will be contained
- * within the resulting Future.
- *
- * This allows working with Futures in an imperative style without blocking for each result.
- *
- * Completing a Future using 'CompletableFuture << Future' will also suspend execution until the
- * value of the other Future is available.
- *
- * The Delimited Continuations compiler plugin must be enabled in order to use this method.
- */
- def flow[A](body: => A @cps[Future[Any]], timeout: Long = Actor.TIMEOUT): Future[A] = {
- val future = Promise[A](timeout)
- (reset(future.asInstanceOf[CompletableFuture[Any]].completeWithResult(body)): Future[Any]) onComplete { f =>
- val opte = f.exception
- if (opte.isDefined) future completeWithException (opte.get)
- }
- future
- }
-
- private[akka] val callbacksPendingExecution = new ThreadLocal[Option[Stack[() => Unit]]]() {
- override def initialValue = None
- }
-}
-
-sealed trait Future[+T] {
-
- /**
- * For use only within a Future.flow block or another compatible Delimited Continuations reset block.
- *
- * Returns the result of this Future without blocking, by suspending execution and storing it as a
- * continuation until the result is available.
- *
- * If this Future is untyped (a Future[Nothing]), a type parameter must be explicitly provided or
- * execution will fail. The normal result of getting a Future from an ActorRef using !!! will return
- * an untyped Future.
- */
- def apply[A >: T](): A @cps[Future[Any]] = shift(this flatMap (_: A => Future[Any]))
-
- /**
- * Blocks awaiting completion of this Future, then returns the resulting value,
- * or throws the completed exception
- *
- * Scala & Java API
- *
- * throws FutureTimeoutException if this Future times out when waiting for completion
- */
- def get: T = this.await.resultOrException.get
-
- /**
- * Blocks the current thread until the Future has been completed or the
- * timeout has expired. In the case of the timeout expiring a
- * FutureTimeoutException will be thrown.
- */
- def await: Future[T]
-
- /**
- * Blocks the current thread until the Future has been completed or the
- * timeout has expired. The timeout will be the least value of 'atMost' and the timeout
- * supplied at the constructuion of this Future.
- * In the case of the timeout expiring a FutureTimeoutException will be thrown.
- */
- def await(atMost: Duration): Future[T]
-
- /**
- * Blocks the current thread until the Future has been completed. Use
- * caution with this method as it ignores the timeout and will block
- * indefinitely if the Future is never completed.
- */
- @deprecated("Will be removed after 1.1, it's dangerous and can cause deadlocks, agony and insanity.", "1.1")
- def awaitBlocking: Future[T]
-
- /**
- * Tests whether this Future has been completed.
- */
- final def isCompleted: Boolean = value.isDefined
-
- /**
- * Tests whether this Future's timeout has expired.
- *
- * Note that an expired Future may still contain a value, or it may be
- * completed with a value.
- */
- def isExpired: Boolean
-
- /**
- * This Future's timeout in nanoseconds.
- */
- def timeoutInNanos: Long
-
- /**
- * The contained value of this Future. Before this Future is completed
- * the value will be None. After completion the value will be Some(Right(t))
- * if it contains a valid result, or Some(Left(error)) if it contains
- * an exception.
- */
- def value: Option[Either[Throwable, T]]
-
- /**
- * Returns the successful result of this Future if it exists.
- */
- final def result: Option[T] = {
- val v = value
- if (v.isDefined) v.get.right.toOption
- else None
- }
-
- /**
- * Returns the contained exception of this Future if it exists.
- */
- final def exception: Option[Throwable] = {
- val v = value
- if (v.isDefined) v.get.left.toOption
- else None
- }
-
- /**
- * When this Future is completed, apply the provided function to the
- * Future. If the Future has already been completed, this will apply
- * immediately.
- */
- def onComplete(func: Future[T] => Unit): Future[T]
-
- /**
- * When the future is completed with a valid result, apply the provided
- * PartialFunction to the result.
- * <pre>
- * val result = future receive {
- * case Foo => "foo"
- * case Bar => "bar"
- * }.await.result
- * </pre>
- */
- final def receive(pf: PartialFunction[Any, Unit]): Future[T] = onComplete { f =>
- val optr = f.result
- if (optr.isDefined) {
- val r = optr.get
- if (pf.isDefinedAt(r)) pf(r)
- }
- }
-
- /**
- * Creates a new Future by applying a PartialFunction to the successful
- * result of this Future if a match is found, or else return a MatchError.
- * If this Future is completed with an exception then the new Future will
- * also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a <- actor !!! Req("Hello") collect { case Res(x: Int) => x }
- * b <- actor !!! Req(a) collect { case Res(x: String) => x }
- * c <- actor !!! Req(7) collect { case Res(x: String) => x }
- * } yield b + "-" + c
- * </pre>
- */
- final def collect[A](pf: PartialFunction[Any, A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val v = ft.value.get
- fa complete {
- if (v.isLeft) v.asInstanceOf[Either[Throwable, A]]
- else {
- try {
- val r = v.right.get
- if (pf isDefinedAt r) Right(pf(r))
- else Left(new MatchError(r))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- }
- }
- }
- }
- fa
- }
-
- /**
- * Creates a new Future that will handle any matching Throwable that this
- * Future might contain. If there is no match, or if this Future contains
- * a valid result then the new Future will contain the same.
- * Example:
- * <pre>
- * Future(6 / 0) failure { case e: ArithmeticException => 0 } // result: 0
- * Future(6 / 0) failure { case e: NotFoundException => 0 } // result: exception
- * Future(6 / 2) failure { case e: ArithmeticException => 0 } // result: 3
- * </pre>
- */
- final def failure[A >: T](pf: PartialFunction[Throwable, A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val opte = ft.exception
- fa complete {
- if (opte.isDefined) {
- val e = opte.get
- try {
- if (pf isDefinedAt e) Right(pf(e))
- else Left(e)
- } catch {
- case x: Exception => Left(x)
- }
- } else ft.value.get
- }
- }
- fa
- }
-
- /**
- * Creates a new Future by applying a function to the successful result of
- * this Future. If this Future is completed with an exception then the new
- * Future will also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a: Int <- actor !!! "Hello" // returns 5
- * b: String <- actor !!! a // returns "10"
- * c: String <- actor !!! 7 // returns "14"
- * } yield b + "-" + c
- * </pre>
- */
- final def map[A](f: T => A): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- fa complete v.asInstanceOf[Either[Throwable, A]]
- else {
- fa complete (try {
- Right(f(v.right.get))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- })
- }
- }
- }
- fa
- }
-
- /**
- * Creates a new Future by applying a function to the successful result of
- * this Future, and returns the result of the function as the new Future.
- * If this Future is completed with an exception then the new Future will
- * also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a: Int <- actor !!! "Hello" // returns 5
- * b: String <- actor !!! a // returns "10"
- * c: String <- actor !!! 7 // returns "14"
- * } yield b + "-" + c
- * </pre>
- */
- final def flatMap[A](f: T => Future[A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- fa complete v.asInstanceOf[Either[Throwable, A]]
- else {
- try {
- fa.completeWith(f(v.right.get))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- fa completeWithException e
- }
- }
- }
- }
- fa
- }
-
- final def foreach(f: T => Unit): Unit = onComplete { ft =>
- val optr = ft.result
- if (optr.isDefined)
- f(optr.get)
- }
-
- final def filter(p: Any => Boolean): Future[Any] = {
- val f = new DefaultCompletableFuture[T](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- f complete v
- else {
- val r = v.right.get
- f complete (try {
- if (p(r)) Right(r)
- else Left(new MatchError(r))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- })
- }
- }
- }
- f
- }
-
- /**
- * Returns the current result, throws the exception is one has been raised, else returns None
- */
- final def resultOrException: Option[T] = {
- val v = value
- if (v.isDefined) {
- val r = v.get
- if (r.isLeft) throw r.left.get
- else r.right.toOption
- } else None
- }
-
- /* Java API */
- final def onComplete[A >: T](proc: Procedure[Future[A]]): Future[T] = onComplete(proc(_))
-
- final def map[A >: T, B](f: JFunc[A, B]): Future[B] = map(f(_))
-
- final def flatMap[A >: T, B](f: JFunc[A, Future[B]]): Future[B] = flatMap(f(_))
-
- final def foreach[A >: T](proc: Procedure[A]): Unit = foreach(proc(_))
-
- final def filter(p: JFunc[Any, Boolean]): Future[Any] = filter(p(_))
-
-}
-
-object Promise {
-
- def apply[A](timeout: Long): CompletableFuture[A] = new DefaultCompletableFuture[A](timeout)
-
- def apply[A](): CompletableFuture[A] = apply(Actor.TIMEOUT)
-
-}
-
-/**
- * Essentially this is the Promise (or write-side) of a Future (read-side).
- */
-trait CompletableFuture[T] extends Future[T] {
- /**
- * Completes this Future with the specified result, if not already completed.
- * @return this
- */
- def complete(value: Either[Throwable, T]): Future[T]
-
- /**
- * Completes this Future with the specified result, if not already completed.
- * @return this
- */
- final def completeWithResult(result: T): Future[T] = complete(Right(result))
-
- /**
- * Completes this Future with the specified exception, if not already completed.
- * @return this
- */
- final def completeWithException(exception: Throwable): Future[T] = complete(Left(exception))
-
- /**
- * Completes this Future with the specified other Future, when that Future is completed,
- * unless this Future has already been completed.
- * @return this.
- */
- final def completeWith(other: Future[T]): Future[T] = {
- other onComplete { f => complete(f.value.get) }
- this
- }
-
- final def <<(value: T): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => cont(complete(Right(value))) }
-
- final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) =>
- val fr = new DefaultCompletableFuture[Any](Actor.TIMEOUT)
- this completeWith other onComplete { f =>
- try {
- fr completeWith cont(f)
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- fr completeWithException e
- }
- }
- fr
- }
-
-}
-
-/**
- * The default concrete Future implementation.
- */
-class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends CompletableFuture[T] {
-
- def this() = this(0, MILLIS)
-
- def this(timeout: Long) = this(timeout, MILLIS)
-
- val timeoutInNanos = timeunit.toNanos(timeout)
- private val _startTimeInNanos = currentTimeInNanos
- private val _lock = new ReentrantLock
- private val _signal = _lock.newCondition
- private var _value: Option[Either[Throwable, T]] = None
- private var _listeners: List[Future[T] => Unit] = Nil
-
- /**
- * Must be called inside _lock.lock<->_lock.unlock
- */
- @tailrec
- private def awaitUnsafe(waitTimeNanos: Long): Boolean = {
- if (_value.isEmpty && waitTimeNanos > 0) {
- val start = currentTimeInNanos
- val remainingNanos = try {
- _signal.awaitNanos(waitTimeNanos)
- } catch {
- case e: InterruptedException =>
- waitTimeNanos - (currentTimeInNanos - start)
- }
- awaitUnsafe(remainingNanos)
- } else {
- _value.isDefined
- }
- }
-
- def await(atMost: Duration) = {
- _lock.lock
- if (try { awaitUnsafe(atMost.toNanos min timeLeft()) } finally { _lock.unlock }) this
- else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds")
- }
-
- def await = {
- _lock.lock
- if (try { awaitUnsafe(timeLeft()) } finally { _lock.unlock }) this
- else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds")
- }
-
- def awaitBlocking = {
- _lock.lock
- try {
- while (_value.isEmpty) {
- _signal.await
- }
- this
- } finally {
- _lock.unlock
- }
- }
-
- def isExpired: Boolean = timeLeft() <= 0
-
- def value: Option[Either[Throwable, T]] = {
- _lock.lock
- try {
- _value
- } finally {
- _lock.unlock
- }
- }
-
- def complete(value: Either[Throwable, T]): DefaultCompletableFuture[T] = {
- _lock.lock
- val notifyTheseListeners = try {
- if (_value.isEmpty && !isExpired) { //Only complete if we aren't expired
- _value = Some(value)
- val existingListeners = _listeners
- _listeners = Nil
- existingListeners
- } else Nil
- } finally {
- _signal.signalAll
- _lock.unlock
- }
-
- if (notifyTheseListeners.nonEmpty) { // Steps to ensure we don't run into a stack-overflow situation
- @tailrec
- def runCallbacks(rest: List[Future[T] => Unit], callbacks: Stack[() => Unit]) {
- if (rest.nonEmpty) {
- notifyCompleted(rest.head)
- while (callbacks.nonEmpty) { callbacks.pop().apply() }
- runCallbacks(rest.tail, callbacks)
- }
- }
-
- val pending = Future.callbacksPendingExecution.get
- if (pending.isDefined) { //Instead of nesting the calls to the callbacks (leading to stack overflow)
- pending.get.push(() => { // Linearize/aggregate callbacks at top level and then execute
- val doNotify = notifyCompleted _ //Hoist closure to avoid garbage
- notifyTheseListeners foreach doNotify
- })
- } else {
- try {
- val callbacks = Stack[() => Unit]() // Allocate new aggregator for pending callbacks
- Future.callbacksPendingExecution.set(Some(callbacks)) // Specify the callback aggregator
- runCallbacks(notifyTheseListeners, callbacks) // Execute callbacks, if they trigger new callbacks, they are aggregated
- } finally { Future.callbacksPendingExecution.set(None) } // Ensure cleanup
- }
- }
-
- this
- }
-
- def onComplete(func: Future[T] => Unit): CompletableFuture[T] = {
- _lock.lock
- val notifyNow = try {
- if (_value.isEmpty) {
- if (!isExpired) { //Only add the listener if the future isn't expired
- _listeners ::= func
- false
- } else false //Will never run the callback since the future is expired
- } else true
- } finally {
- _lock.unlock
- }
-
- if (notifyNow) notifyCompleted(func)
-
- this
- }
-
- private def notifyCompleted(func: Future[T] => Unit) {
- try {
- func(this)
- } catch {
- case e => EventHandler notify EventHandler.Error(e, this)
- }
- }
-
- @inline
- private def currentTimeInNanos: Long = MILLIS.toNanos(System.currentTimeMillis)
- @inline
- private def timeLeft(): Long = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos)
-}
-
-/**
- * An already completed Future is seeded with it's result at creation, is useful for when you are participating in
- * a Future-composition but you already have a value to contribute.
- */
-sealed class AlreadyCompletedFuture[T](suppliedValue: Either[Throwable, T]) extends CompletableFuture[T] {
- val value = Some(suppliedValue)
-
- def complete(value: Either[Throwable, T]): CompletableFuture[T] = this
- def onComplete(func: Future[T] => Unit): Future[T] = { func(this); this }
- def await(atMost: Duration): Future[T] = this
- def await: Future[T] = this
- def awaitBlocking: Future[T] = this
- def isExpired: Boolean = true
- def timeoutInNanos: Long = 0
-}
diff --git a/test/disabled/presentation/akka/src/pi.scala b/test/disabled/presentation/akka/src/pi.scala
deleted file mode 100644
index b4c644052c..0000000000
--- a/test/disabled/presentation/akka/src/pi.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-
-import akka.actor.{Actor, PoisonPill}
-import Actor._
-import akka.routing.{Routing, CyclicIterator}
-import Routing._
-
-import java.util.concurrent.CountDownLatch
-
-object Pi extends App {
-
- calculate/*#*/(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
-
- // ====================
- // ===== Messages =====
- // ====================
- sealed trait PiMessage
- case object Calculate extends PiMessage/*#*/
- case class Work(start: Int, nrOfElements: Int) extends PiMessage
- case class Result(value: Double) extends PiMessage
-
- // ==================
- // ===== Worker =====
- // ==================
- class Worker extends Actor/*#*/ {
-
- // define the work
- def calculatePiFor(start: Int, nrOfElements: Int): Double = {
- var acc = 0.0
- for (i <- start until (start + nrOfElements))
- acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
- acc
- }
-
- def receive /*?*/ = {
- case Work(start, nrOfElements) =>
- self reply/*#*/ Result(calculatePiFor(start, nrOfElements)) // perform the work // TODO: this currently returns wrong position for the symbol
- }
- }
-
- // ==================
- // ===== Master =====
- // ==================
- class Master(
- nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, latch: CountDownLatch)
- extends Actor {
-
- var pi: Double = _
- var nrOfResults: Int = _
- var start: Long = _
-
- // create the workers
- val workers = Vector.fill(nrOfWorkers)(actorOf[Worker]./*!*/start())
-
- // wrap them with a load-balancing router
- val router = Routing./*!*/loadBalancerActor(CyclicIterator(workers))./*!*/start()
-
- // message handler
- def receive = {
- case Calculate =>
- // schedule work
- //for (start <- 0 until nrOfMessages) router ! Work(start, nrOfElements)
- for (i <- 0 until nrOfMessages) router ! Work(i * nrOfElements, nrOfElements)
-
- // send a PoisonPill to all workers telling them to shut down themselves
- router./*!*/!(Broadcast(PoisonPill))
-
- // send a PoisonPill to the router, telling him to shut himself down
- router ! PoisonPill
-
- case Result(value) =>
- // handle result from the worker
- pi += value
- nrOfResults/*#*/ += 1
- if (nrOfResults == nrOfMessages) self./*!*/stop()
- }
-
- override def preStart() {
- start = System.currentTimeMillis
- }
-
- override def postStop() {
- // tell the world that the calculation is complete
- println(
- "\n\tPi estimate: \t\t%s\n\tCalculation time: \t%s millis"
- .format(pi, (System.currentTimeMillis - start)))
- latch/*#*/.countDown()
- }
- }
-
- // ==================
- // ===== Run it =====
- // ==================
- def calculate(nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) {
-
- // this latch is only plumbing to know when the calculation is completed
- val latch = new CountDownLatch(1)
-
- // create the master
- val master = actorOf(
- new Master(nrOfWorkers, nrOfMessages, nrOfElements, latch)).start()
-
- // start the calculation
- master ! Calculate
-
- // wait for master to shut down
- latch.await()
- }
-}
diff --git a/test/files/jvm/value-class-boxing.check b/test/files/jvm/value-class-boxing.check
new file mode 100644
index 0000000000..20a9fe2ba8
--- /dev/null
+++ b/test/files/jvm/value-class-boxing.check
@@ -0,0 +1,7 @@
+a2 and a1: bytecode identical
+a3 and a1: bytecode identical
+a4 and a1: bytecode identical
+b2 and b1: bytecode identical
+b3 and b1: bytecode identical
+b4 and b1: bytecode identical
+b5 and b1: bytecode identical
diff --git a/test/files/jvm/value-class-boxing/Analyzed_1.scala b/test/files/jvm/value-class-boxing/Analyzed_1.scala
new file mode 100644
index 0000000000..dec8565351
--- /dev/null
+++ b/test/files/jvm/value-class-boxing/Analyzed_1.scala
@@ -0,0 +1,17 @@
+class Wrap(val x: Int) extends AnyVal {
+ def ***(other: Bip): Wrap = new Wrap(x * other.x)
+}
+class Bip(val x: Int) extends AnyVal
+
+class SameBytecode {
+ def a1(x: Int, y: Int): Int = x + y
+ def a2(x: Wrap, y: Wrap): Wrap = new Wrap(x.x + y.x)
+ def a3(x: Int, y: Wrap): Wrap = new Wrap(x + y.x)
+ def a4(x: Int, y: Wrap): Int = x + y.x
+
+ def b1(x: Wrap, y: Int): Int = (x *** new Bip(y)).x
+ def b2(x: Wrap, y: Bip): Wrap = x *** y
+ def b3(x: Wrap, y: Int): Wrap = x *** new Bip(y)
+ def b4(x: Wrap, y: Bip): Bip = new Bip((x *** y).x)
+ def b5(x: Wrap, y: Int): Bip = new Bip((x *** new Bip(y)).x)
+}
diff --git a/test/files/jvm/value-class-boxing/test.scala b/test/files/jvm/value-class-boxing/test.scala
new file mode 100644
index 0000000000..cf331832de
--- /dev/null
+++ b/test/files/jvm/value-class-boxing/test.scala
@@ -0,0 +1,15 @@
+import scala.tools.partest.BytecodeTest
+
+object Test extends BytecodeTest {
+ def show: Unit = {
+ val classNode = loadClassNode("SameBytecode")
+ List("a2", "a3", "a4") foreach { m =>
+ print(m + " and a1: ")
+ sameBytecode(getMethod(classNode, "a1"), getMethod(classNode, m))
+ }
+ List("b2", "b3", "b4", "b5") foreach { m =>
+ print(m + " and b1: ")
+ sameBytecode(getMethod(classNode, "b1"), getMethod(classNode, m))
+ }
+ }
+}
diff --git a/test/files/pos/annotated-original/C_2.scala b/test/files/pos/annotated-original/C_2.scala
new file mode 100644
index 0000000000..36a09ffe0c
--- /dev/null
+++ b/test/files/pos/annotated-original/C_2.scala
@@ -0,0 +1,7 @@
+object Bug {
+ M.m {
+ def s = ""
+ M.m(s): @unchecked // error: macro has not been expanded.
+ ???
+ }
+}
diff --git a/test/files/pos/annotated-original/M_1.scala b/test/files/pos/annotated-original/M_1.scala
new file mode 100644
index 0000000000..01654e02cf
--- /dev/null
+++ b/test/files/pos/annotated-original/M_1.scala
@@ -0,0 +1,7 @@
+import language.experimental.macros
+import reflect.macros.Context
+
+object M {
+ def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.resetLocalAttrs(a.tree))
+ def m(a: Any) = macro impl
+}
diff --git a/test/files/pos/t5744/Macros_1.scala b/test/files/pos/t5744/Macros_1.scala
new file mode 100644
index 0000000000..288a88653d
--- /dev/null
+++ b/test/files/pos/t5744/Macros_1.scala
@@ -0,0 +1,22 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+object Macros {
+ def foo[U: Numeric](x: U) = macro foo_impl[U]
+ def bar[U: Numeric : Equiv, Y <% String](x: U)(implicit s: String) = macro bar_impl[U, Y]
+
+ def foo_impl[U](c: Context)(x: c.Expr[U])(numeric: c.Expr[Numeric[U]]) = {
+ import c.universe._
+ val plusOne = Apply(Select(numeric.tree, newTermName("plus")), List(x.tree, Literal(Constant(1))))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(plusOne))
+ c.Expr[Unit](body)
+ }
+
+ def bar_impl[U, Y](c: Context)(x: c.Expr[U])(numeric: c.Expr[Numeric[U]], equiv: c.Expr[Equiv[U]], viewAsString: c.Expr[Y => String], s: c.Expr[String]) = {
+ import c.universe._
+ val plusOne = Apply(Select(numeric.tree, newTermName("plus")), List(x.tree, Literal(Constant(1))))
+ val plusLen = Apply(Select(numeric.tree, newTermName("plus")), List(plusOne, Select(s.tree, newTermName("length"))))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(plusLen))
+ c.Expr[Unit](body)
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t5744/Test_2.scala b/test/files/pos/t5744/Test_2.scala
new file mode 100644
index 0000000000..64b57e6032
--- /dev/null
+++ b/test/files/pos/t5744/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import Macros._
+ foo(42)
+ implicit val s = ""
+ bar(43)
+} \ No newline at end of file
diff --git a/test/files/pos/t7091.scala b/test/files/pos/t7091.scala
new file mode 100644
index 0000000000..72e81a2ea8
--- /dev/null
+++ b/test/files/pos/t7091.scala
@@ -0,0 +1,7 @@
+package p1.p2
+
+protected[p2] class C(var x: Int = 0)
+
+protected[p2] trait T {
+ new C()
+}
diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala
index 21eabeb284..f9ebd09876 100755
--- a/test/files/presentation/doc/doc.scala
+++ b/test/files/presentation/doc/doc.scala
@@ -7,8 +7,6 @@ import scala.tools.nsc.util._
import scala.tools.nsc.io._
object Test extends InteractiveTest {
- override val settings: doc.Settings = docSettings
-
val tags = Seq(
"@example `\"abb\".permutations = Iterator(abb, bab, bba)`",
"@version 1.0, 09/07/2012",
@@ -29,23 +27,23 @@ object Test extends InteractiveTest {
|class User(c: %sCommented)""".stripMargin.format(comment, tags take nTags mkString "\n", caret)
override lazy val compiler = {
- new {
- override val settings = {
- prepareSettings(Test.this.settings)
- Test.this.settings
- }
- } with Global(settings, compilerReporter) with MemberLookupBase with CommentFactoryBase {
+ prepareSettings(settings)
+ new Global(settings, compilerReporter) with MemberLookupBase with CommentFactoryBase {
outer =>
-
val global: this.type = this
- def chooseLink(links: List[LinkTo]): LinkTo = links.head
- def internalLink(sym: Symbol, site: Symbol) = None
- def toString(link: LinkTo) = link.toString
override lazy val analyzer = new {
val global: outer.type = outer
} with doc.ScaladocAnalyzer
+ def chooseLink(links: List[LinkTo]): LinkTo = links.head
+ def internalLink(sym: Symbol, site: Symbol) = None
+ def toString(link: LinkTo) = link.toString
+ def warnNoLink = false
+ def findExternalLink(sym: Symbol, name: String) = None
+
+ override def forScaladoc = true
+
def getComment(sym: Symbol, source: SourceFile) = {
val docResponse = new Response[(String, String, Position)]
askDocComment(sym, sym.owner, source, docResponse)
diff --git a/test/files/presentation/ide-t1000567.check b/test/files/presentation/ide-t1000567.check
new file mode 100644
index 0000000000..6d62cb3e13
--- /dev/null
+++ b/test/files/presentation/ide-t1000567.check
@@ -0,0 +1 @@
+reload: a.scala, b.scala
diff --git a/test/files/presentation/ide-t1000567/Runner.scala b/test/files/presentation/ide-t1000567/Runner.scala
new file mode 100644
index 0000000000..77a618b60a
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/Runner.scala
@@ -0,0 +1,15 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+// also known as SI-5013
+
+object Test extends InteractiveTest {
+
+ override def runDefaultTests(): Unit = {
+ val a = sourceFiles.find(_.file.name == "a.scala").head
+ val b = sourceFiles.find(_.file.name == "b.scala").head
+ askLoadedTyped(a).get
+ askLoadedTyped(b).get
+ super.runDefaultTests()
+ }
+
+}
diff --git a/test/files/presentation/ide-t1000567/src/a/a.scala b/test/files/presentation/ide-t1000567/src/a/a.scala
new file mode 100644
index 0000000000..ee21112a3e
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/src/a/a.scala
@@ -0,0 +1,5 @@
+package a
+
+class Foo {
+ protected[Foo] var x = 0
+}
diff --git a/test/files/presentation/ide-t1000567/src/b/b.scala b/test/files/presentation/ide-t1000567/src/b/b.scala
new file mode 100644
index 0000000000..a0185b15cf
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/src/b/b.scala
@@ -0,0 +1,5 @@
+package b
+
+class Bar extends a.Foo {
+ println(x)
+}
diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
index 159097cc10..950569c880 100644
--- a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
+++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
@@ -25,7 +25,7 @@ import scala.tools.nsc.doc
object Test extends InteractiveTest {
final val mega = 1024 * 1024
- override val settings: doc.Settings = docSettings
+ override val withDocComments = true
override def execute(): Unit = memoryConsumptionTest()
diff --git a/test/files/run/all-overridden.check b/test/files/run/all-overridden.check
new file mode 100644
index 0000000000..1b620b1176
--- /dev/null
+++ b/test/files/run/all-overridden.check
@@ -0,0 +1 @@
+method g
diff --git a/test/files/run/all-overridden.scala b/test/files/run/all-overridden.scala
new file mode 100644
index 0000000000..1b798ef748
--- /dev/null
+++ b/test/files/run/all-overridden.scala
@@ -0,0 +1,11 @@
+import scala.reflect.runtime.universe._
+
+object Test {
+ trait Foo { def f: Int = 5 ; def g: Int }
+ trait Bar extends Foo { def f: Int ; def g: Int = 5 }
+
+ def main(args: Array[String]): Unit = {
+ // We should see g, but not f or $init$.
+ typeOf[Bar].declarations.toList.flatMap(_.allOverriddenSymbols) foreach println
+ }
+}
diff --git a/test/files/run/annotatedRetyping.check b/test/files/run/annotatedRetyping.check
new file mode 100644
index 0000000000..b296a80526
--- /dev/null
+++ b/test/files/run/annotatedRetyping.check
@@ -0,0 +1,6 @@
+typing List(1, 2).map(((x) => {
+ val another = scala.Tuple2(t.nt, t.tr): @testAnn match {
+ case scala.Tuple2(_, _) => 1
+ };
+ x
+}))
diff --git a/test/files/run/annotatedRetyping.scala b/test/files/run/annotatedRetyping.scala
new file mode 100644
index 0000000000..cf1b0f27b5
--- /dev/null
+++ b/test/files/run/annotatedRetyping.scala
@@ -0,0 +1,62 @@
+import scala.tools.partest._
+import scala.tools.nsc._
+
+object Test extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp"
+
+ def code = """
+ class testAnn extends annotation.Annotation
+
+ object t {
+ def nt = 1
+ def tr = "a"
+ }
+
+ class Test {
+ List(1,2).map(x => {
+ val another = ((t.nt, t.tr): @testAnn) match { case (_, _) => 1 }
+ x
+ })
+ }
+ """.trim
+
+
+ // point of this test: type-check the "Annotated" tree twice. first time the analyzer plugin types it,
+ // second time the typer.
+
+ // bug was that typedAnnotated assigned a type to the Annotated tree. The second type check would consider
+ // the tree as alreadyTyped, which is not cool, the Annotated needs to be transformed into a Typed tree.
+
+ def show() {
+ val global = newCompiler()
+ import global._
+ import analyzer._
+ import collection.{mutable => m}
+
+ object analyzerPlugin extends AnalyzerPlugin {
+ val templates: m.Map[Symbol, (Template, Typer)] = m.Map()
+ override def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type = {
+ defTree match {
+ case impl: Template =>
+ templates += typer.context.owner -> (impl, typer)
+
+ case dd: DefDef if dd.symbol.isPrimaryConstructor && templates.contains(dd.symbol.owner) =>
+ val (impl, templTyper) = templates(dd.symbol.owner)
+ for (stat <- impl.body.filterNot(_.isDef)) {
+ println("typing "+ stat)
+ val statsOwner = impl.symbol orElse templTyper.context.owner.newLocalDummy(impl.pos)
+ val tpr = analyzer.newTyper(templTyper.context.make(stat, statsOwner))
+ tpr.typed(stat)
+ }
+
+ case _ =>
+ }
+ tpe
+ }
+ }
+
+ addAnalyzerPlugin(analyzerPlugin)
+ compileString(global)(code)
+ }
+}