summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala137
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala82
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala15
-rw-r--r--src/library/scala/annotation/meta/companionClass.scala17
-rw-r--r--src/library/scala/annotation/meta/companionMethod.scala17
-rw-r--r--src/library/scala/annotation/meta/companionObject.scala14
-rw-r--r--src/library/scala/concurrent/Awaitable.scala9
-rw-r--r--src/library/scala/concurrent/Future.scala23
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala2
-rw-r--r--src/library/scala/concurrent/package.scala10
13 files changed, 218 insertions, 136 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 6ef6751720..dc8f59b0af 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -905,7 +905,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val GetterTargetClass = getMetaAnnotation("getter")
lazy val ParamTargetClass = getMetaAnnotation("param")
lazy val SetterTargetClass = getMetaAnnotation("setter")
- // TODO: module, moduleClass? package, packageObject?
+ lazy val ClassTargetClass = getMetaAnnotation("companionClass")
+ lazy val ObjectTargetClass = getMetaAnnotation("companionObject")
+ lazy val MethodTargetClass = getMetaAnnotation("companionMethod") // TODO: module, moduleClass? package, packageObject?
private def getMetaAnnotation(name: String) = getRequiredClass("scala.annotation.meta." + name)
def isMetaAnnotation(sym: Symbol): Boolean = metaAnnotations(sym) || (
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index ff0bdf7580..4a05b28867 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -832,7 +832,7 @@ trait ContextErrors {
implicit val context0 = context
object SymValidateErrors extends Enumeration {
- val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject,
+ val ImplicitConstr, ImplicitNotTermOrClass, ImplicitAtToplevel,
OverrideClass, SealedNonClass, AbstractNonClass,
OverrideConstr, AbstractOverride, LazyAndEarlyInit,
ByNameParameter, AbstractVar = Value
@@ -898,10 +898,10 @@ trait ContextErrors {
case ImplicitConstr =>
"`implicit' modifier not allowed for constructors"
- case ImplicitNotTerm =>
- "`implicit' modifier can be used only for values, variables and methods"
+ case ImplicitNotTermOrClass =>
+ "`implicit' modifier can be used only for values, variables, methods and classes"
- case ImplicitTopObject =>
+ case ImplicitAtToplevel =>
"`implicit' modifier cannot be used for top-level objects"
case OverrideClass =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 3d8c2ea564..875c83969e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -65,7 +65,24 @@ trait MethodSynthesis {
MethodType(params, symbols.last.typeConstructor)
}
- }
+
+ /** The annotations amongst those found on the original symbol which
+ * should be propagated to this kind of accessor.
+ */
+ def deriveAnnotations(initial: List[AnnotationInfo], category: Symbol, keepClean: Boolean): List[AnnotationInfo] = {
+ initial filter { ann =>
+ // There are no meta-annotation arguments attached to `ann`
+ if (ann.metaAnnotations.isEmpty) {
+ // A meta-annotation matching `annotKind` exists on `ann`'s definition.
+ (ann.defaultTargets contains category) ||
+ // `ann`'s definition has no meta-annotations, and `keepClean` is true.
+ (ann.defaultTargets.isEmpty && keepClean)
+ }
+ // There are meta-annotation arguments, and one of them matches `annotKind`
+ else ann.metaAnnotations exists (_ matches category)
+ }
+ }
+ }
import synthesisUtil._
class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) {
@@ -155,28 +172,23 @@ trait MethodSynthesis {
/** There are two key methods in here.
*
- * 1) enterGetterSetter is called from Namer with a ValDef which
- * may need accessors. Some setup is performed. In general this
- * creates symbols and enters them into the scope of the owner.
+ * 1) Enter methods such as enterGetterSetterare called
+ * from Namer with a tree which may generate further trees such as accessors or
+ * implicit wrappers. Some setup is performed. In general this creates symbols
+ * and enters them into the scope of the owner.
*
- * 2) finishGetterSetter is called from Typer when a Template is typed.
+ * 2) addDerivedTrees is called from Typer when a Template is typed.
* It completes the job, returning a list of trees with their symbols
- * set to those created in enterGetterSetter. Those trees then become
+ * set to those created in the enter methods. Those trees then become
* part of the typed template.
*/
trait MethodSynth {
self: Namer =>
import NamerErrorGen._
-
- /** TODO - synthesize method.
- */
- def enterImplicitClass(tree: ClassDef) {
- /** e.g.
- val ClassDef(mods, name, tparams, impl) = tree
- val converter = ImplicitClassConverter(tree).createAndEnterSymbol()
- ...
- */
+
+ def enterImplicitWrapper(tree: ClassDef) {
+ ImplicitClassWrapper(tree).createAndEnterSymbol()
}
def enterGetterSetter(tree: ValDef) {
@@ -203,7 +215,8 @@ trait MethodSynthesis {
enterBeans(tree)
}
- def finishGetterSetter(typer: Typer, stat: Tree): List[Tree] = stat match {
+
+ def addDerivedTrees(typer: Typer, stat: Tree): List[Tree] = stat match {
case vd @ ValDef(mods, name, tpt, rhs) if !noFinishGetterSetter(vd) && !vd.symbol.isLazy =>
// If we don't save the annotations, they seem to wander off.
val annotations = stat.symbol.initialize.annotations
@@ -211,9 +224,19 @@ trait MethodSynthesis {
map (acc => atPos(vd.pos.focus)(acc derive annotations))
filterNot (_ eq EmptyTree)
)
+ case cd @ ClassDef(mods, _, _, _) if mods.isImplicit =>
+ val annotations = stat.symbol.initialize.annotations
+ // TODO: need to shuffle annotations between wrapper and class.
+ val wrapper = ImplicitClassWrapper(cd)
+ val meth = wrapper.derivedSym
+ val mdef = context.unit.synthetics(meth)
+ context.unit.synthetics -= meth
+ meth setAnnotations deriveAnnotations(annotations, MethodTargetClass, false)
+ cd.symbol setAnnotations deriveAnnotations(annotations, ClassTargetClass, true)
+ List(cd, mdef)
case _ =>
List(stat)
- }
+ }
def standardAccessors(vd: ValDef): List[DerivedFromValDef] = (
if (vd.mods.isMutable && !vd.mods.isLazy) List(Getter(vd), Setter(vd))
@@ -234,35 +257,59 @@ trait MethodSynthesis {
field ::: standardAccessors(vd) ::: beanAccessors(vd)
}
+ /** This trait assembles what's needed for synthesizing derived methods.
+ * Important: Typically, instances of this trait are created TWICE for each derived
+ * symbol; once form Namers in an enter method, and once from Typers in addDerivedTrees.
+ * So it's important that creating an instance of Derived does not have a side effect,
+ * or if it has a side effect, control that it is done only once.
+ */
trait Derived {
- /** The tree from which we are deriving a synthetic member. */
+
+ /** The tree from which we are deriving a synthetic member. Typically, that's
+ * given as an argument of the instance. */
def tree: Tree
+
+ /** The name of the method */
def name: TermName
+
+ /** The flags that are retained from the original symbol */
+
def flagsMask: Long
+
+ /** The flags that the derived symbol has in addition to those retained from
+ * the original symbol*/
def flagsExtra: Long
-
- /** The tree, symbol, and type completer for the synthetic member. */
+
+ /** type completer for the synthetic member.
+ */
def completer(sym: Symbol): Type
+
+ /** The derived symbol. It is assumed that this symbol already exists and has been
+ * entered in the parent scope when derivedSym is called */
def derivedSym: Symbol
+
+ /** The definition tree of the derived symbol. */
def derivedTree: Tree
}
-
+
trait DerivedFromMemberDef extends Derived {
def tree: MemberDef
-
+ def enclClass: Symbol
+
// Final methods to make the rest easier to reason about.
final def mods = tree.mods
final def basisSym = tree.symbol
- final def enclClass = basisSym.enclClass
final def derivedFlags: Long = basisSym.flags & flagsMask | flagsExtra
}
-
+
trait DerivedFromClassDef extends DerivedFromMemberDef {
def tree: ClassDef
+ final def enclClass = basisSym.owner.enclClass
}
trait DerivedFromValDef extends DerivedFromMemberDef {
def tree: ValDef
+ final def enclClass = basisSym.enclClass
/** Which meta-annotation is associated with this kind of entity.
* Presently one of: field, getter, setter, beanGetter, beanSetter, param.
@@ -286,22 +333,6 @@ trait MethodSynthesis {
enterInScope(sym)
sym setInfo completer(sym)
}
- /** The annotations amongst those found on the original symbol which
- * should be propagated to this kind of accessor.
- */
- private def deriveAnnotations(initial: List[AnnotationInfo]): List[AnnotationInfo] = {
- initial filter { ann =>
- // There are no meta-annotation arguments attached to `ann`
- if (ann.metaAnnotations.isEmpty) {
- // A meta-annotation matching `annotKind` exists on `ann`'s definition.
- (ann.defaultTargets contains category) ||
- // `ann`'s definition has no meta-annotations, and `keepClean` is true.
- (ann.defaultTargets.isEmpty && keepClean)
- }
- // There are meta-annotation arguments, and one of them matches `annotKind`
- else ann.metaAnnotations exists (_ matches category)
- }
- }
private def logDerived(result: Tree): Tree = {
debuglog("[+derived] " + ojoin(mods.flagString, basisSym.accurateKindString, basisSym.getterName.decode)
+ " (" + derivedSym + ")\n " + result)
@@ -310,7 +341,7 @@ trait MethodSynthesis {
}
final def derive(initial: List[AnnotationInfo]): Tree = {
validate()
- derivedSym setAnnotations deriveAnnotations(initial)
+ derivedSym setAnnotations deriveAnnotations(initial, category, keepClean)
logDerived(derivedTree)
}
}
@@ -334,15 +365,21 @@ trait MethodSynthesis {
/** A synthetic method which performs the implicit conversion implied by
* the declaration of an implicit class. Yet to be written.
*/
- case class ImplicitClassConverter(tree: ClassDef) extends DerivedFromClassDef {
- def completer(sym: Symbol): Type = ???
- def derivedSym: Symbol = ???
- def derivedTree: DefDef = ???
- def flagsExtra: Long = ???
- def flagsMask: Long = ???
- def name: TermName = ???
- }
-
+ case class ImplicitClassWrapper(tree: ClassDef) extends DerivedFromClassDef {
+ def completer(sym: Symbol): Type = ??? // not needed
+ def createAndEnterSymbol(): Symbol = enterSyntheticSym(derivedTree)
+ def derivedSym: Symbol = {
+ val result = enclClass.info decl name
+ assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls)
+ result
+ }
+ def derivedTree: DefDef =
+ factoryMeth(mods & flagsMask | flagsExtra, name, tree, symbolic = false)
+ def flagsExtra: Long = METHOD | IMPLICIT
+ def flagsMask: Long = AccessFlags
+ def name: TermName = tree.name.toTermName
+ }
+
case class Getter(tree: ValDef) extends DerivedGetter {
def name = tree.name
def category = GetterTargetClass
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 81cf1e3fbe..129a1c7520 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -99,7 +99,7 @@ trait Namers extends MethodSynthesis {
owner.unsafeTypeParams foreach (paramContext.scope enter _)
newNamer(paramContext)
}
-
+
def enclosingNamerWithScope(scope: Scope) = {
var cx = context
while (cx != NoContext && cx.scope != scope) cx = cx.outer
@@ -666,10 +666,12 @@ trait Namers extends MethodSynthesis {
"If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead."
)
}
-
+
// Suggested location only.
- if (mods.isImplicit)
- enterImplicitClass(tree)
+ if (mods.isImplicit) {
+ log("enter implicit wrapper "+tree+", owner = "+owner)
+ enterImplicitWrapper(tree)
+ }
}
// this logic is needed in case typer was interrupted half
@@ -1404,10 +1406,10 @@ trait Namers extends MethodSynthesis {
if (sym.isImplicit) {
if (sym.isConstructor)
fail(ImplicitConstr)
- if (!sym.isTerm)
- fail(ImplicitNotTerm)
+ if (!(sym.isTerm || (sym.isClass && !sym.isTrait)))
+ fail(ImplicitNotTermOrClass)
if (sym.owner.isPackageClass)
- fail(ImplicitTopObject)
+ fail(ImplicitAtToplevel)
}
if (sym.isClass) {
if (sym.isAnyOverride && !sym.hasFlag(TRAIT))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c9679faa7d..5c342a83e2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1653,7 +1653,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val body =
if (isPastTyper || reporter.hasErrors) templ.body
- else templ.body flatMap rewrappingWrapperTrees(namer.finishGetterSetter(Typer.this, _))
+ else templ.body flatMap rewrappingWrapperTrees(namer.addDerivedTrees(Typer.this, _))
val body1 = typedStats(body, templ.symbol)
@@ -2474,54 +2474,53 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|| (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate)
)
- def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = {
+ def checkNoDoubleDefs(stats: List[Tree]): Unit = {
val scope = if (inBlock) context.scope else context.owner.info.decls
- var newStats = new ListBuffer[Tree]
- var needsCheck = true
- var moreToAdd = true
- while (moreToAdd) {
- val initSize = scope.size
- var e = scope.elems
- while ((e ne null) && e.owner == scope) {
-
- // check no double def
- if (needsCheck) {
- var e1 = scope.lookupNextEntry(e)
- while ((e1 ne null) && e1.owner == scope) {
- if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
- (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe) || e.sym.isMacro && e1.sym.isMacro))
- // default getters are defined twice when multiple overloads have defaults. an
- // error for this is issued in RefChecks.checkDefaultsInOverloaded
- if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefault &&
- !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
- log("Double definition detected:\n " +
- ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " +
- ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain)))
-
- DefDefinedTwiceError(e.sym, e1.sym)
- scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
- }
- e1 = scope.lookupNextEntry(e1)
+ var e = scope.elems
+ while ((e ne null) && e.owner == scope) {
+ var e1 = scope.lookupNextEntry(e)
+ while ((e1 ne null) && e1.owner == scope) {
+ if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
+ (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
+ // default getters are defined twice when multiple overloads have defaults. an
+ // error for this is issued in RefChecks.checkDefaultsInOverloaded
+ if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
+ !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
+ log("Double definition detected:\n " +
+ ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " +
+ ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain)))
+
+ DefDefinedTwiceError(e.sym, e1.sym)
+ scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
}
- }
-
- // add synthetics
- context.unit.synthetics get e.sym foreach { tree =>
- newStats += typedStat(tree) // might add even more synthetics to the scope
- context.unit.synthetics -= e.sym
+ e1 = scope.lookupNextEntry(e1)
}
-
e = e.next
}
- needsCheck = false
- // the type completer of a synthetic might add more synthetics. example: if the
- // factory method of a case class (i.e. the constructor) has a default.
- moreToAdd = initSize != scope.size
+ }
+
+ def addSynthetics(stats: List[Tree]): List[Tree] = {
+ val scope = if (inBlock) context.scope else context.owner.info.decls
+ var newStats = new ListBuffer[Tree]
+ var moreToAdd = true
+ while (moreToAdd) {
+ val initElems = scope.elems
+ for (sym <- scope)
+ for (tree <- context.unit.synthetics get sym) {
+ newStats += typedStat(tree) // might add even more synthetics to the scope
+ context.unit.synthetics -= sym
+ }
+ // the type completer of a synthetic might add more synthetics. example: if the
+ // factory method of a case class (i.e. the constructor) has a default.
+ moreToAdd = scope.elems ne initElems
}
if (newStats.isEmpty) stats
else {
// put default getters next to the method they belong to,
// same for companion objects. fixes #2489 and #4036.
+ // [Martin] This is pretty ugly. I think we could avoid
+ // this code by associating defaults and companion objects
+ // with the original tree instead of the new symbol.
def matches(stat: Tree, synt: Tree) = (stat, synt) match {
case (DefDef(_, statName, _, _, _, _), DefDef(mods, syntName, _, _, _, _)) =>
mods.hasDefaultFlag && syntName.toString.startsWith(statName.toString)
@@ -2551,7 +2550,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
context.updateBuffer(statsErrors)
if (phase.erasedTypes) stats1
- else checkNoDoubleDefsAndAddSynthetics(stats1)
+ else {
+ checkNoDoubleDefs(stats1)
+ addSynthetics(stats1)
+ }
}
def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 4f5b6868ae..1f79d8212d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -112,8 +112,8 @@ trait Unapplies extends ast.TreeDSL
private def toIdent(x: DefTree) = Ident(x.name) setPos x.pos.focus
- private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = {
- val tycon = REF(cdef.symbol)
+ private def classType(cdef: ClassDef, tparams: List[TypeDef], symbolic: Boolean = true): Tree = {
+ val tycon = if (symbolic) REF(cdef.symbol) else Ident(cdef.name)
if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map toIdent)
}
@@ -166,15 +166,20 @@ trait Unapplies extends ast.TreeDSL
/** The apply method corresponding to a case class
*/
- def caseModuleApplyMeth(cdef: ClassDef): DefDef = {
+ def factoryMeth(mods: Modifiers, name: TermName, cdef: ClassDef, symbolic: Boolean): DefDef = {
val tparams = cdef.tparams map copyUntypedInvariant
val cparamss = constrParamss(cdef)
+ def classtpe = classType(cdef, tparams, symbolic)
atPos(cdef.pos.focus)(
- DefDef(caseMods, nme.apply, tparams, cparamss, classType(cdef, tparams),
- New(classType(cdef, tparams), mmap(cparamss)(gen.paramToArg)))
+ DefDef(mods, name, tparams, cparamss, classtpe,
+ New(classtpe, mmap(cparamss)(gen.paramToArg)))
)
}
+ /** The apply method corresponding to a case class
+ */
+ def caseModuleApplyMeth(cdef: ClassDef): DefDef = factoryMeth(caseMods, nme.apply, cdef, symbolic = true)
+
/** The unapply method corresponding to a case class
*/
def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = {
diff --git a/src/library/scala/annotation/meta/companionClass.scala b/src/library/scala/annotation/meta/companionClass.scala
new file mode 100644
index 0000000000..8e53f6caf9
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionClass.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * When defining an implicit class, the Scala compiler creates an implicit
+ * conversion method for it. Annotations `@companionClass` and `@companionMethod`
+ * control where an annotation on the implicit class will go. By default, annotations
+ * on an implicit class end up only on the class.
+ *
+ */
+final class companionClass extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/meta/companionMethod.scala b/src/library/scala/annotation/meta/companionMethod.scala
new file mode 100644
index 0000000000..379c4f3385
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionMethod.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * When defining an implicit class, the Scala compiler creates an implicit
+ * conversion method for it. Annotations `@companionClass` and `@companionMethod`
+ * control where an annotation on the implicit class will go. By default, annotations
+ * on an implicit class end up only on the class.
+ *
+ */
+final class companionMethod extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/meta/companionObject.scala b/src/library/scala/annotation/meta/companionObject.scala
new file mode 100644
index 0000000000..d329df5c42
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionObject.scala
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * Currently unused; intended as an annotation target for classes such as case classes
+ * that automatically generate a companion object
+ */
+final class companionObject extends annotation.StaticAnnotation
diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala
index 052e6e2366..99bdfbc5a9 100644
--- a/src/library/scala/concurrent/Awaitable.scala
+++ b/src/library/scala/concurrent/Awaitable.scala
@@ -10,18 +10,23 @@ package scala.concurrent
-import scala.annotation.implicitNotFound
import scala.concurrent.util.Duration
trait Awaitable[+T] {
+ /**
+ * Should throw [[scala.concurrent.TimeoutException]] if it times out
+ * This method should not be called directly.
+ */
+ @throws(classOf[TimeoutException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type
/**
- * Throws exceptions if cannot produce a T within the specified time
+ * Throws exceptions if it cannot produce a T within the specified time.
* This method should not be called directly.
*/
+ @throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 5f703ac23b..5bc9ad783f 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -82,7 +82,6 @@ import scala.collection.generic.CanBuildFrom
* }}}
*/
trait Future[+T] extends Awaitable[T] {
-self =>
/* Callbacks */
@@ -132,7 +131,7 @@ self =>
/** Creates a new promise.
*/
- def newPromise[S]: Promise[S]
+ protected def newPromise[S]: Promise[S]
/** Returns whether the future has already been completed with
* a value or an exception.
@@ -168,14 +167,11 @@ self =>
* and throws a corresponding exception if the original future fails.
*/
def failed: Future[Throwable] = {
- def noSuchElem(v: T) =
- new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + v)
-
val p = newPromise[Throwable]
onComplete {
case Left(t) => p success t
- case Right(v) => p failure noSuchElem(v)
+ case Right(v) => p failure (new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + v))
}
p.future
@@ -411,21 +407,16 @@ self =>
* {{{
* val f = future { sys.error("failed") }
* val g = future { 5 }
- * val h = f orElse g
+ * val h = f fallbackTo g
* await(h, 0) // evaluates to 5
* }}}
*/
def fallbackTo[U >: T](that: Future[U]): Future[U] = {
val p = newPromise[U]
-
onComplete {
- case Left(t) => that onComplete {
- case Left(_) => p failure t
- case Right(v) => p success v
- }
- case Right(v) => p success v
+ case r @ Right(_) ⇒ p complete r
+ case _ ⇒ p completeWith that
}
-
p.future
}
@@ -497,14 +488,14 @@ self =>
* }}}
*/
def either[U >: T](that: Future[U]): Future[U] = {
- val p = self.newPromise[U]
+ val p = newPromise[U]
val completePromise: PartialFunction[Either[Throwable, U], _] = {
case Left(t) => p tryFailure t
case Right(v) => p trySuccess v
}
- self onComplete completePromise
+ this onComplete completePromise
that onComplete completePromise
p.future
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 52c834359d..c5062267dc 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -84,7 +84,7 @@ private[scala] class ExecutionContextImpl(es: AnyRef) extends ExecutionContext w
}
-object ExecutionContextImpl {
+private[concurrent] object ExecutionContextImpl {
private[concurrent] def currentExecutionContext: ThreadLocal[ExecutionContext] = new ThreadLocal[ExecutionContext] {
override protected def initialValue = null
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index e2ae17498f..b06c6f3c63 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -31,16 +31,6 @@ package concurrent {
def result[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable.result(atMost)
}
- /** A timeout exception.
- *
- * Futures are failed with a timeout exception when their timeout expires.
- *
- * Each timeout exception contains an origin future which originally timed out.
- */
- class FutureTimeoutException(origin: Future[_], message: String) extends TimeoutException(message) {
- def this(origin: Future[_]) = this(origin, "Future timed out.")
- }
-
final class DurationOps private[concurrent] (x: Int) {
// TODO ADD OTHERS
def ns = util.Duration.fromNanos(0)