summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala38
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala7
-rw-r--r--src/library/scala/concurrent/Future.scala87
-rw-r--r--src/library/scala/concurrent/Promise.scala18
-rw-r--r--src/library/scala/concurrent/impl/Future.scala4
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala73
-rw-r--r--src/library/scala/util/Try.scala36
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala10
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala34
-rw-r--r--src/reflect/scala/reflect/runtime/ReflectionUtils.scala32
-rw-r--r--test/files/jvm/future-spec/FutureTests.scala19
-rw-r--r--test/files/jvm/future-spec/PromiseTests.scala14
-rw-r--r--test/files/jvm/future-spec/TryTests.scala118
-rw-r--r--test/files/jvm/future-spec/main.scala4
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala152
-rw-r--r--test/files/jvm/try-type-tests.scala144
-rw-r--r--test/files/neg/t5687.check8
-rw-r--r--test/files/neg/t5687.scala55
-rw-r--r--test/files/neg/t6040.check7
-rw-r--r--test/files/neg/t6040.scala1
-rw-r--r--test/files/pos/t6040.scala3
-rw-r--r--test/files/pos/t6145.scala11
-rw-r--r--test/files/pos/t6205.scala18
-rw-r--r--test/files/run/applydynamic_sip.flags1
-rw-r--r--test/files/run/reflection-enclosed-basic.check18
-rw-r--r--test/files/run/reflection-enclosed-basic.scala46
-rw-r--r--test/files/run/reflection-enclosed-inner-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-inner-basic.scala52
-rw-r--r--test/files/run/reflection-enclosed-inner-inner-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-inner-inner-basic.scala58
-rw-r--r--test/files/run/reflection-enclosed-inner-nested-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-inner-nested-basic.scala55
-rw-r--r--test/files/run/reflection-enclosed-nested-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-nested-basic.scala52
-rw-r--r--test/files/run/reflection-enclosed-nested-inner-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-nested-inner-basic.scala54
-rw-r--r--test/files/run/reflection-enclosed-nested-nested-basic.check20
-rw-r--r--test/files/run/reflection-enclosed-nested-nested-basic.scala54
-rw-r--r--test/files/run/reflection-modulemirror-inner-good.check3
-rw-r--r--test/files/run/reflection-modulemirror-nested-good.check3
-rw-r--r--test/files/run/reflection-repl-classes.check35
-rw-r--r--test/files/run/reflection-repl-classes.scala22
-rw-r--r--test/files/run/reflection-repl-elementary.check (renamed from test/files/run/reflection-repl.check)0
-rw-r--r--test/files/run/reflection-repl-elementary.scala (renamed from test/files/run/reflection-repl.scala)0
-rw-r--r--test/files/run/reflection-sanitychecks.check4
-rw-r--r--test/files/run/t4536.flags1
-rw-r--r--test/files/run/t5040.flags1
48 files changed, 1098 insertions, 401 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index f5e392a60c..1b502025c2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -230,17 +230,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
removeCPSAdaptAnnotations(origPt)
else origPt
- // we've packed the type for each case in typedMatch so that if all cases have the same existential case, we get a clean lub
- // here, we should open up the existential again
// relevant test cases: pos/existentials-harmful.scala, pos/gadt-gilles.scala, pos/t2683.scala, pos/virtpatmat_exist4.scala
- // TODO: fix skolemizeExistential (it should preserve annotations, right?)
- val pt = repeatedToSeq(ptUnCPS.skolemizeExistential(context.owner, context.tree) withAnnotations ptUnCPS.annotations)
+ // pt is the skolemized version
+ val pt = repeatedToSeq(ptUnCPS)
+
+ // val packedPt = repeatedToSeq(typer.packedType(match_, context.owner))
// the alternative to attaching the default case override would be to simply
// append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...)
val matchFailGenOverride = match_.attachments.get[DefaultOverrideMatchAttachment].map{case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)}
- val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag treeInfo.SYNTH_CASE_FLAGS
+ val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag treeInfo.SYNTH_CASE_FLAGS
// pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental
val combined = combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride)
@@ -1076,8 +1076,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def outerTest(testedBinder: Symbol, expectedTp: Type): Tree = {
val expectedOuter = expectedTp.prefix match {
- case ThisType(clazz) => THIS(clazz)
- case pre => REF(pre.prefix, pre.termSymbol)
+ case ThisType(clazz) => THIS(clazz)
+ case pre if pre != NoType => REF(pre.prefix, pre.termSymbol)
+ case _ => TRUE_typed // fallback for SI-6183
}
// ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix`
@@ -1359,7 +1360,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// local / context-free
def _asInstanceOf(b: Symbol, tp: Type): Tree
- def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree
+ def _asInstanceOf(t: Tree, tp: Type): Tree
def _equals(checker: Tree, binder: Symbol): Tree
def _isInstanceOf(b: Symbol, tp: Type): Tree
def and(a: Tree, b: Tree): Tree
@@ -1417,7 +1418,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp)
// the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
- def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp)
+ def _asInstanceOf(t: Tree, tp: Type): Tree = if (t.tpe != NoType && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp)
def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp)
def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false)
// if (typesConform(b.info, tpX)) { patmatDebug("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE }
@@ -3514,7 +3515,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
*/
def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = {
val matchEnd = newSynthCaseLabel("matchEnd")
- val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations //
+ val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations
matchEnd setInfo MethodType(List(matchRes), restpe)
def newCaseSym = newSynthCaseLabel("case") setInfo MethodType(Nil, restpe)
@@ -3525,7 +3526,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val nextCase = newCaseSym
_currCase = nextCase
- LabelDef(currCase, Nil, mkCase(new OptimizedCasegen(matchEnd, nextCase, restpe)))
+ LabelDef(currCase, Nil, mkCase(new OptimizedCasegen(matchEnd, nextCase)))
}
// must compute catchAll after caseLabels (side-effects nextCase)
@@ -3550,14 +3551,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
)
}
- class OptimizedCasegen(matchEnd: Symbol, nextCase: Symbol, restpe: Type) extends CommonCodegen with Casegen {
+ class OptimizedCasegen(matchEnd: Symbol, nextCase: Symbol) extends CommonCodegen with Casegen {
def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree =
optimizedCodegen.matcher(scrut, scrutSym, restpe)(cases, matchFailGen)
// only used to wrap the RHS of a body
// res: T
// returns MatchMonad[T]
- def one(res: Tree): Tree = matchEnd APPLY (_asInstanceOf(res, restpe)) // need cast for GADT magic
+ def one(res: Tree): Tree = matchEnd APPLY (res) // a jump to a case label is special-cased in typedApply
protected def zero: Tree = nextCase APPLY ()
// prev: MatchMonad[T]
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 063f615e17..d05368bd5f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1551,10 +1551,15 @@ trait Typers extends Modes with Adaptations with Tags {
*/
def validateParentClasses(parents: List[Tree], selfType: Type) {
val pending = ListBuffer[AbsTypeError]()
- def validateParentClass(parent: Tree, superclazz: Symbol) {
+ @inline def validateDynamicParent(parent: Symbol) =
+ if (parent == DynamicClass) checkFeature(parent.pos, DynamicsFeature)
+
+ def validateParentClass(parent: Tree, superclazz: Symbol) =
if (!parent.isErrorTyped) {
val psym = parent.tpe.typeSymbol.initialize
+
checkStablePrefixClassType(parent)
+
if (psym != superclazz) {
if (psym.isTrait) {
val ps = psym.info.parents
@@ -1564,6 +1569,7 @@ trait Typers extends Modes with Adaptations with Tags {
pending += ParentNotATraitMixinError(parent, psym)
}
}
+
if (psym.isFinal)
pending += ParentFinalInheritanceError(parent, psym)
@@ -1586,12 +1592,17 @@ trait Typers extends Modes with Adaptations with Tags {
pending += ParentSelfTypeConformanceError(parent, selfType)
if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
}
+
if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
pending += ParentInheritedTwiceError(parent, psym)
+
+ validateDynamicParent(psym)
}
+
+ if (!parents.isEmpty && parents.forall(!_.isErrorTyped)) {
+ val superclazz = parents.head.tpe.typeSymbol
+ for (p <- parents) validateParentClass(p, superclazz)
}
- if (!parents.isEmpty && parents.forall(!_.isErrorTyped))
- for (p <- parents) validateParentClass(p, parents.head.tpe.typeSymbol)
/*
if (settings.Xshowcls.value != "" &&
@@ -3041,7 +3052,19 @@ trait Typers extends Modes with Adaptations with Tags {
// target of a call. Since this information is no longer available from
// typedArg, it is recorded here.
checkDead.updateExpr(fun)
- val args1 = typedArgs(args, forArgMode(fun, mode), paramTypes, formals)
+
+ val args1 =
+ // no expected type when jumping to a match label -- anything goes (this is ok since we're typing the translation of well-typed code)
+ // ... except during erasure: we must take the expected type into account as it drives the insertion of casts!
+ // I've exhausted all other semi-clean approaches I could think of in balancing GADT magic, SI-6145, CPS type-driven transforms and other existential trickiness
+ // (the right thing to do -- packing existential types -- runs into limitations in subtyping existential types,
+ // casting breaks SI-6145,
+ // not casting breaks GADT typing as it requires sneaking ill-typed trees past typer)
+ if (!phase.erasedTypes && fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol))
+ typedArgs(args, forArgMode(fun, mode))
+ else
+ typedArgs(args, forArgMode(fun, mode), paramTypes, formals)
+
// instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
// val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
// precise(foo) : foo.type => foo.type
@@ -5029,10 +5052,11 @@ trait Typers extends Modes with Adaptations with Tags {
if (isPatternMode) {
val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe)
- val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, pt, canRemedy = uncheckedTypeExtractor.nonEmpty)
- // println(s"Typed($expr, ${tpt.tpe}) : $pt --> $ownType (${isFullyDefined(ownType)}, ${makeFullyDefined(ownType)})")
+
// make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038)
- treeTyped setType (if (isFullyDefined(ownType)) ownType else makeFullyDefined(ownType)) //ownType
+ val ptDefined = if (isFullyDefined(pt)) pt else makeFullyDefined(pt)
+ val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, ptDefined, canRemedy = uncheckedTypeExtractor.nonEmpty)
+ treeTyped setType ownType
uncheckedTypeExtractor match {
case None => treeTyped
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index 8081bb32da..1be6050303 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -12,6 +12,7 @@ package scala.concurrent
import java.util.concurrent.{ ExecutorService, Executor }
import scala.concurrent.util.Duration
import scala.annotation.implicitNotFound
+import scala.util.Try
/**
* An `ExecutionContext` is an abstraction over an entity that can execute program logic.
@@ -27,6 +28,12 @@ trait ExecutionContext {
*/
def reportFailure(t: Throwable): Unit
+ /** Prepares for the execution of a task. Returns the prepared
+ * execution context. A valid implementation of `prepare` is one
+ * that simply returns `this`.
+ */
+ def prepare(): ExecutionContext = this
+
}
/**
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index d24fdbf005..bc0b437a33 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -117,7 +117,7 @@ trait Future[+T] extends Awaitable[T] {
* $callbackInContext
*/
def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete {
- case Right(v) if pf isDefinedAt v => pf(v)
+ case Success(v) if pf isDefinedAt v => pf(v)
case _ =>
}(executor)
@@ -135,7 +135,7 @@ trait Future[+T] extends Awaitable[T] {
* $callbackInContext
*/
def onFailure[U](callback: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete {
- case Left(t) if NonFatal(t) && callback.isDefinedAt(t) => callback(t)
+ case Failure(t) if NonFatal(t) && callback.isDefinedAt(t) => callback(t)
case _ =>
}(executor)
@@ -148,7 +148,7 @@ trait Future[+T] extends Awaitable[T] {
* $multipleCallbacks
* $callbackInContext
*/
- def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit
+ def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit
/* Miscellaneous */
@@ -169,7 +169,7 @@ trait Future[+T] extends Awaitable[T] {
* if it contains a valid result, or `Some(Failure(error))` if it contains
* an exception.
*/
- def value: Option[Either[Throwable, T]]
+ def value: Option[Try[T]]
/* Projections */
@@ -190,8 +190,8 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[Throwable]()
onComplete {
- case Left(t) => p success t
- case Right(v) => p failure (new NoSuchElementException("Future.failed not completed with a throwable."))
+ case Failure(t) => p success t
+ case Success(v) => p failure (new NoSuchElementException("Future.failed not completed with a throwable."))
}
p.future
@@ -205,7 +205,7 @@ trait Future[+T] extends Awaitable[T] {
* Will not be called if the future fails.
*/
def foreach[U](f: T => U)(implicit executor: ExecutionContext): Unit = onComplete {
- case Right(r) => f(r)
+ case Success(r) => f(r)
case _ => // do nothing
}(executor)
@@ -227,8 +227,8 @@ trait Future[+T] extends Awaitable[T] {
case result =>
try {
result match {
- case Left(t) => p failure f(t)
- case Right(r) => p success s(r)
+ case Failure(t) => p failure f(t)
+ case Success(r) => p success s(r)
}
} catch {
case NonFatal(t) => p failure t
@@ -251,8 +251,8 @@ trait Future[+T] extends Awaitable[T] {
case result =>
try {
result match {
- case Right(r) => p success f(r)
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
+ case Success(r) => p success f(r)
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
}
} catch {
case NonFatal(t) => p failure t
@@ -273,12 +273,12 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[S]()
onComplete {
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
- case Right(v) =>
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
+ case Success(v) =>
try {
f(v).onComplete({
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
- case Right(v) => p success v
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
+ case Success(v) => p success v
})(internalExecutor)
} catch {
case NonFatal(t) => p failure t
@@ -308,11 +308,11 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[T]()
onComplete {
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, T]]
- case Right(v) =>
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[T]]
+ case Success(v) =>
try {
if (pred(v)) p success v
- else p failure new NoSuchElementException("Future.filter predicate is not satisfied by: " + v)
+ else p failure new NoSuchElementException("Future.filter predicate is not satisfied")
} catch {
case NonFatal(t) => p failure t
}
@@ -357,8 +357,8 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[S]()
onComplete {
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
- case Right(v) =>
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
+ case Success(v) =>
try {
if (pf.isDefinedAt(v)) p success pf(v)
else p failure new NoSuchElementException("Future.collect partial function is not defined at: " + v)
@@ -377,22 +377,15 @@ trait Future[+T] extends Awaitable[T] {
* Example:
*
* {{{
- * future (6 / 0) recover { case e: ArithmeticException ⇒ 0 } // result: 0
- * future (6 / 0) recover { case e: NotFoundException ⇒ 0 } // result: exception
- * future (6 / 2) recover { case e: ArithmeticException ⇒ 0 } // result: 3
+ * future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0
+ * future (6 / 0) recover { case e: NotFoundException => 0 } // result: exception
+ * future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
* }}}
*/
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] = {
val p = Promise[U]()
- onComplete {
- case Left(t) if pf isDefinedAt t =>
- try { p success pf(t) }
- catch {
- case NonFatal(t) => p failure t
- }
- case otherwise => p complete otherwise
- }(executor)
+ onComplete { case tr => p.complete(tr recover pf) }(executor)
p.future
}
@@ -414,7 +407,7 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[U]()
onComplete {
- case Left(t) if pf isDefinedAt t =>
+ case Failure(t) if pf isDefinedAt t =>
try {
p completeWith pf(t)
} catch {
@@ -438,8 +431,8 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[(T, U)]()
this onComplete {
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, (T, U)]]
- case Right(r) =>
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[(T, U)]]
+ case Success(r) =>
that onSuccess {
case r2 => p success ((r, r2))
}
@@ -468,8 +461,8 @@ trait Future[+T] extends Awaitable[T] {
def fallbackTo[U >: T](that: Future[U]): Future[U] = {
val p = Promise[U]()
onComplete {
- case r @ Right(_) ⇒ p complete r
- case _ ⇒ p completeWith that
+ case s @ Success(_) => p complete s
+ case _ => p completeWith that
}
p.future
}
@@ -485,12 +478,12 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[S]()
onComplete {
- case l: Left[_, _] => p complete l.asInstanceOf[Left[Throwable, S]]
- case Right(t) =>
+ case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
+ case Success(t) =>
p complete (try {
- Right(boxedType(tag.runtimeClass).cast(t).asInstanceOf[S])
+ Success(boxedType(tag.runtimeClass).cast(t).asInstanceOf[S])
} catch {
- case e: ClassCastException => Left(e)
+ case e: ClassCastException => Failure(e)
})
}
@@ -520,7 +513,7 @@ trait Future[+T] extends Awaitable[T] {
* }
* }}}
*/
- def andThen[U](pf: PartialFunction[Either[Throwable, T], U])(implicit executor: ExecutionContext): Future[T] = {
+ def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
onComplete {
@@ -545,7 +538,7 @@ trait Future[+T] extends Awaitable[T] {
*/
def either[U >: T](that: Future[U]): Future[U] = {
val p = Promise[U]()
- val completePromise: PartialFunction[Either[Throwable, U], _] = { case result => p tryComplete result }
+ val completePromise: PartialFunction[Try[U], _] = { case result => p tryComplete result }
this onComplete completePromise
that onComplete completePromise
@@ -615,7 +608,7 @@ object Future {
def firstCompletedOf[T](futures: TraversableOnce[Future[T]])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
- val completeFirst: Either[Throwable, T] => Unit = p tryComplete _
+ val completeFirst: Try[T] => Unit = p tryComplete _
futures.foreach(_ onComplete completeFirst)
p.future
@@ -629,14 +622,14 @@ object Future {
else {
val result = Promise[Option[T]]()
val ref = new AtomicInteger(futures.size)
- val search: Either[Throwable, T] => Unit = v => try {
+ val search: Try[T] => Unit = v => try {
v match {
- case Right(r) => if (predicate(r)) result tryComplete Right(Some(r))
- case _ =>
+ case Success(r) => if (predicate(r)) result tryComplete Success(Some(r))
+ case _ =>
}
} finally {
if (ref.decrementAndGet == 0) {
- result tryComplete Right(None)
+ result tryComplete Success(None)
}
}
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 5d1b2c00b6..b873939c15 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -8,6 +8,8 @@
package scala.concurrent
+import scala.util.{ Try, Success, Failure }
+
/** Promise is an object which can be completed with a value or failed
* with an exception.
*
@@ -49,7 +51,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def complete(result: Either[Throwable, T]): this.type =
+ def complete(result: Try[T]): this.type =
if (tryComplete(result)) this else throw new IllegalStateException("Promise already completed.")
/** Tries to complete the promise with either a value or the exception.
@@ -58,7 +60,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def tryComplete(result: Either[Throwable, T]): Boolean
+ def tryComplete(result: Try[T]): Boolean
/** Completes this promise with the specified future, once that future is completed.
*
@@ -84,7 +86,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def success(v: T): this.type = complete(Right(v))
+ def success(v: T): this.type = complete(Success(v))
/** Tries to complete the promise with a value.
*
@@ -92,7 +94,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def trySuccess(value: T): Boolean = tryComplete(Right(value))
+ def trySuccess(value: T): Boolean = tryComplete(Success(value))
/** Completes the promise with an exception.
*
@@ -102,7 +104,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def failure(t: Throwable): this.type = complete(Left(t))
+ def failure(t: Throwable): this.type = complete(Failure(t))
/** Tries to complete the promise with an exception.
*
@@ -110,7 +112,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def tryFailure(t: Throwable): Boolean = tryComplete(Left(t))
+ def tryFailure(t: Throwable): Boolean = tryComplete(Failure(t))
}
@@ -129,14 +131,14 @@ object Promise {
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
- def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception))
+ def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
- def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Right(result))
+ def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 098008e958..d92691901f 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -12,7 +12,7 @@ package scala.concurrent.impl
import scala.concurrent.ExecutionContext
import scala.util.control.NonFatal
-
+import scala.util.{Try, Success, Failure}
private[concurrent] object Future {
@@ -21,7 +21,7 @@ private[concurrent] object Future {
override def run() = {
promise complete {
- try Right(body) catch { case NonFatal(e) => Left(e) }
+ try Success(body) catch { case NonFatal(e) => Failure(e) }
}
}
}
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index c2df9ac296..b19bed004b 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -15,42 +15,46 @@ import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, Timeou
import scala.concurrent.util.Duration
import scala.annotation.tailrec
import scala.util.control.NonFatal
-
+import scala.util.{ Try, Success, Failure }
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with scala.concurrent.Future[T] {
def future: this.type = this
}
-private class CallbackRunnable[T](val executor: ExecutionContext, val onComplete: (Either[Throwable, T]) => Any) extends Runnable with OnCompleteRunnable {
+/* Precondition: `executor` is prepared, i.e., `executor` has been returned from invocation of `prepare` on some other `ExecutionContext`.
+ */
+private class CallbackRunnable[T](val executor: ExecutionContext, val onComplete: Try[T] => Any) extends Runnable with OnCompleteRunnable {
// must be filled in before running it
- var value: Either[Throwable, T] = null
+ var value: Try[T] = null
override def run() = {
require(value ne null) // must set value to non-null before running!
try onComplete(value) catch { case NonFatal(e) => executor reportFailure e }
}
- def executeWithValue(v: Either[Throwable, T]): Unit = {
+ def executeWithValue(v: Try[T]): Unit = {
require(value eq null) // can't complete it twice
value = v
+ // Note that we cannot prepare the ExecutionContext at this point, since we might
+ // already be running on a different thread!
executor.execute(this)
}
}
private[concurrent] object Promise {
- private def resolveEither[T](source: Either[Throwable, T]): Either[Throwable, T] = source match {
- case Left(t) => resolver(t)
- case _ => source
+ private def resolveTry[T](source: Try[T]): Try[T] = source match {
+ case Failure(t) => resolver(t)
+ case _ => source
}
- private def resolver[T](throwable: Throwable): Either[Throwable, T] = throwable match {
- case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value.asInstanceOf[T])
- case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t))
- case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t))
- case e: Error => Left(new ExecutionException("Boxed Error", e))
- case t => Left(t)
+ private def resolver[T](throwable: Throwable): Try[T] = throwable match {
+ case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value.asInstanceOf[T])
+ case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t))
+ case t: InterruptedException => Failure(new ExecutionException("Boxed InterruptedException", t))
+ case e: Error => Failure(new ExecutionException("Boxed Error", e))
+ case t => Failure(t)
}
/** Default promise implementation.
@@ -88,25 +92,25 @@ private[concurrent] object Promise {
@throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T =
ready(atMost).value.get match {
- case Left(e) => throw e
- case Right(r) => r
+ case Failure(e) => throw e
+ case Success(r) => r
}
- def value: Option[Either[Throwable, T]] = getState match {
- case c: Either[_, _] => Some(c.asInstanceOf[Either[Throwable, T]])
- case _ => None
+ def value: Option[Try[T]] = getState match {
+ case c: Try[_] => Some(c.asInstanceOf[Try[T]])
+ case _ => None
}
override def isCompleted(): Boolean = getState match { // Cheaper than boxing result into Option due to "def value"
- case _: Either[_, _] => true
- case _ => false
+ case _: Try[_] => true
+ case _ => false
}
- def tryComplete(value: Either[Throwable, T]): Boolean = {
- val resolved = resolveEither(value)
+ def tryComplete(value: Try[T]): Boolean = {
+ val resolved = resolveTry(value)
(try {
@tailrec
- def tryComplete(v: Either[Throwable, T]): List[CallbackRunnable[T]] = {
+ def tryComplete(v: Try[T]): List[CallbackRunnable[T]] = {
getState match {
case raw: List[_] =>
val cur = raw.asInstanceOf[List[CallbackRunnable[T]]]
@@ -124,13 +128,14 @@ private[concurrent] object Promise {
}
}
- def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit = {
- val runnable = new CallbackRunnable[T](executor, func)
+ def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
+ val preparedEC = executor.prepare
+ val runnable = new CallbackRunnable[T](preparedEC, func)
@tailrec //Tries to add the callback, if already completed, it dispatches the callback to be executed
def dispatchOrAddCallback(): Unit =
getState match {
- case r: Either[_, _] => runnable.executeWithValue(r.asInstanceOf[Either[Throwable, T]])
+ case r: Try[_] => runnable.executeWithValue(r.asInstanceOf[Try[T]])
case listeners: List[_] => if (updateState(listeners, runnable :: listeners)) () else dispatchOrAddCallback()
}
dispatchOrAddCallback()
@@ -141,25 +146,23 @@ private[concurrent] object Promise {
*
* Useful in Future-composition when a value to contribute is already available.
*/
- final class KeptPromise[T](suppliedValue: Either[Throwable, T]) extends Promise[T] {
+ final class KeptPromise[T](suppliedValue: Try[T]) extends Promise[T] {
- val value = Some(resolveEither(suppliedValue))
+ val value = Some(resolveTry(suppliedValue))
override def isCompleted(): Boolean = true
- def tryComplete(value: Either[Throwable, T]): Boolean = false
+ def tryComplete(value: Try[T]): Boolean = false
- def onComplete[U](func: Either[Throwable, T] => U)(implicit executor: ExecutionContext): Unit = {
+ def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit = {
val completedAs = value.get
- (new CallbackRunnable(executor, func)).executeWithValue(completedAs)
+ val preparedEC = executor.prepare
+ (new CallbackRunnable(preparedEC, func)).executeWithValue(completedAs)
}
def ready(atMost: Duration)(implicit permit: CanAwait): this.type = this
- def result(atMost: Duration)(implicit permit: CanAwait): T = value.get match {
- case Left(e) => throw e
- case Right(r) => r
- }
+ def result(atMost: Duration)(implicit permit: CanAwait): T = value.get.get
}
}
diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala
index f85bac0b84..f381a18b0c 100644
--- a/src/library/scala/util/Try.scala
+++ b/src/library/scala/util/Try.scala
@@ -54,6 +54,7 @@ import language.implicitConversions
*
* `Try` comes to the Scala standard library after years of use as an integral part of Twitter's stack.
*
+ * @author based on Twitter's original implementation in com.twitter.util.
* @since 2.10
*/
sealed abstract class Try[+T] {
@@ -102,7 +103,7 @@ sealed abstract class Try[+T] {
* Applies the given function `f` if this is a `Failure`, otherwise returns this if this is a `Success`.
* This is like `flatMap` for the exception.
*/
- def rescue[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U]
+ def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U]
/**
* Applies the given function `f` if this is a `Failure`, otherwise returns this if this is a `Success`.
@@ -116,17 +117,6 @@ sealed abstract class Try[+T] {
def toOption = if (isSuccess) Some(get) else None
/**
- * Returns an empty `Seq` (usually a `List`) if this is a `Failure` or a `Seq` containing the value if this is a `Success`.
- */
- def toSeq = if (isSuccess) Seq(get) else Seq()
-
- /**
- * Returns the given function applied to the value from this `Success` or returns this if this is a `Failure`.
- * Alias for `flatMap`.
- */
- def andThen[U](f: T => Try[U]): Try[U] = flatMap(f)
-
- /**
* Transforms a nested `Try`, ie, a `Try` of type `Try[Try[T]]`,
* into an un-nested `Try`, ie, a `Try` of type `Try[T]`.
*/
@@ -141,7 +131,7 @@ sealed abstract class Try[+T] {
/** Completes this `Try` by applying the function `f` to this if this is of type `Failure`, or conversely, by applying
* `s` if this is a `Success`.
*/
- def transform[U](f: Throwable => Try[U], s: T => Try[U]): Try[U] = this match {
+ def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] = this match {
case Success(v) => s(v)
case Failure(e) => f(e)
}
@@ -150,20 +140,6 @@ sealed abstract class Try[+T] {
object Try {
- implicit def try2either[T](tr: Try[T]): Either[Throwable, T] = {
- tr match {
- case Success(v) => Right(v)
- case Failure(t) => Left(t)
- }
- }
-
- implicit def either2try[T](ei: Either[Throwable, T]): Try[T] = {
- ei match {
- case Right(v) => Success(v)
- case Left(t) => Failure(t)
- }
- }
-
def apply[T](r: => T): Try[T] = {
try { Success(r) } catch {
case NonFatal(e) => Failure(e)
@@ -175,7 +151,7 @@ object Try {
final case class Failure[+T](val exception: Throwable) extends Try[T] {
def isFailure: Boolean = true
def isSuccess: Boolean = false
- def rescue[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] =
+ def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] =
if (f.isDefinedAt(exception)) f(exception) else this
def get: T = throw exception
def flatMap[U](f: T => Try[U]): Try[U] = Failure[U](exception)
@@ -201,12 +177,12 @@ final case class Failure[+T](val exception: Throwable) extends Try[T] {
final case class Success[+T](value: T) extends Try[T] {
def isFailure: Boolean = false
def isSuccess: Boolean = true
- def rescue[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = Success(value)
+ def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U] = Success(value)
def get = value
def flatMap[U](f: T => Try[U]): Try[U] =
try f(value)
catch {
- case e: Throwable => Failure(e)
+ case NonFatal(e) => Failure(e)
}
def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value
def foreach[U](f: T => U): Unit = f(value)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index e9a9ce1aa0..b6305e773a 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -2202,7 +2202,15 @@ trait Types extends api.Types { self: SymbolTable =>
override protected def normalizeImpl =
if (typeParamsMatchArgs) betaReduce.normalize
else if (isHigherKinded) super.normalizeImpl
- else ErrorType
+ else {
+ // if we are overriding a type alias in an erroneous way, don't just
+ // return an ErrorType since that will result in useless error msg.
+ // Instead let's try to recover from it and rely on refcheck reporting the correct error,
+ // if that fails fallback to the old behaviour.
+ val overriddenSym = sym.nextOverriddenSymbol
+ if (overriddenSym != NoSymbol) pre.memberType(overriddenSym).normalize
+ else ErrorType
+ }
// isHKSubType0 introduces synthetic type params so that
// betaReduce can first apply sym.info to typeArgs before calling
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 2bf57d61cc..4ce2cda04a 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -18,7 +18,7 @@ import collection.mutable.{ HashMap, ListBuffer }
import internal.Flags._
//import scala.tools.nsc.util.ScalaClassLoader
//import scala.tools.nsc.util.ScalaClassLoader._
-import ReflectionUtils.{singletonInstance}
+import ReflectionUtils.{staticSingletonInstance, innerSingletonInstance}
import language.existentials
import scala.runtime.{ScalaRunTime, BoxesRunTime}
import scala.reflect.internal.util.Collections._
@@ -403,8 +403,11 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def erasure = symbol.moduleClass.asClass
def isStatic = true
def instance = {
- if (!symbol.owner.isPackageClass) throw new Error("inner and nested modules are not supported yet")
- singletonInstance(classLoader, symbol.fullName)
+ if (symbol.owner.isPackageClass)
+ staticSingletonInstance(classLoader, symbol.fullName)
+ else
+ if (outer == null) staticSingletonInstance(classToJava(symbol.moduleClass.asClass))
+ else innerSingletonInstance(outer, symbol.name)
}
def companion: Option[ClassMirror] = symbol.companionClass match {
case cls: ClassSymbol => Some(new JavaClassMirror(outer, cls))
@@ -1089,12 +1092,25 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
noClass
else if (clazz.owner.isPackageClass)
javaClass(clazz.javaClassName)
- else if (clazz.owner.isClass)
- classToJava(clazz.owner.asClass)
- .getDeclaredClasses
- .find(_.getSimpleName == clazz.name.toString)
- .getOrElse(noClass)
- else
+ else if (clazz.owner.isClass) {
+ val childOfClass = !clazz.owner.isModuleClass
+ val childOfTopLevel = clazz.owner.owner.isPackageClass
+ val childOfTopLevelObject = clazz.owner.isModuleClass && childOfTopLevel
+
+ // suggested in https://issues.scala-lang.org/browse/SI-4023?focusedCommentId=54759#comment-54759
+ var ownerClazz = classToJava(clazz.owner.asClass)
+ if (childOfTopLevelObject) ownerClazz = Class.forName(ownerClazz.getName stripSuffix "$", true, ownerClazz.getClassLoader)
+ val ownerChildren = ownerClazz.getDeclaredClasses
+
+ var fullNameOfJavaClass = ownerClazz.getName
+ if (childOfClass || childOfTopLevel) fullNameOfJavaClass += "$"
+ fullNameOfJavaClass += clazz.name
+ if (clazz.isModuleClass) fullNameOfJavaClass += "$"
+
+ // println(s"ownerChildren = ${ownerChildren.toList}")
+ // println(s"fullNameOfJavaClass = $fullNameOfJavaClass")
+ ownerChildren.find(_.getName == fullNameOfJavaClass).getOrElse(noClass)
+ } else
noClass
}
diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
index 2c7be6e317..e87c6b339b 100644
--- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
+++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
@@ -6,7 +6,7 @@
package scala.reflect.runtime
import java.lang.{Class => jClass}
-import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException }
+import java.lang.reflect.{ Method, InvocationTargetException, UndeclaredThrowableException }
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
*/
@@ -63,25 +63,25 @@ object ReflectionUtils {
}
}
- def singletonInstance(cl: ClassLoader, className: String): AnyRef = {
+ def staticSingletonInstance(cl: ClassLoader, className: String): AnyRef = {
val name = if (className endsWith "$") className else className + "$"
val clazz = java.lang.Class.forName(name, true, cl)
- val singleton = clazz getField "MODULE$" get null
- singleton
+ staticSingletonInstance(clazz)
}
- // Retrieves the MODULE$ field for the given class name.
- def singletonInstanceOpt(cl: ClassLoader, className: String): Option[AnyRef] =
- try Some(singletonInstance(cl, className))
- catch { case _: ClassNotFoundException => None }
+ def staticSingletonInstance(clazz: Class[_]): AnyRef = clazz getField "MODULE$" get null
- def invokeFactory(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): AnyRef = {
- val singleton = singletonInstance(cl, className)
- val method = singleton.getClass.getMethod(methodName, classOf[ClassLoader])
- method.invoke(singleton, args: _*)
- }
+ def innerSingletonInstance(outer: AnyRef, className: String): AnyRef = {
+ val accessorName = if (className endsWith "$") className.substring(0, className.length - 1) else className
+ def singletonAccessor(clazz: Class[_]): Option[Method] =
+ if (clazz == null) None
+ else {
+ val declaredAccessor = clazz.getDeclaredMethods.filter(_.getName == accessorName).headOption
+ declaredAccessor orElse singletonAccessor(clazz.getSuperclass)
+ }
- def invokeFactoryOpt(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): Option[AnyRef] =
- try Some(invokeFactory(cl, className, methodName, args: _*))
- catch { case _: ClassNotFoundException => None }
+ val accessor = singletonAccessor(outer.getClass) getOrElse { throw new NoSuchMethodException(s"${outer.getClass.getName}.$accessorName") }
+ accessor setAccessible true
+ accessor invoke outer
+ }
}
diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala
index 30e1a722bf..31bb8c4e44 100644
--- a/test/files/jvm/future-spec/FutureTests.scala
+++ b/test/files/jvm/future-spec/FutureTests.scala
@@ -6,6 +6,7 @@ import scala.concurrent.util.duration._
import scala.concurrent.util.Duration.Inf
import scala.collection._
import scala.runtime.NonLocalReturnControl
+import scala.util.{Try,Success,Failure}
@@ -197,7 +198,7 @@ object FutureTests extends MinimalScalaTest {
} andThen {
case _ => q.add(2)
} andThen {
- case Right(0) => q.add(Int.MaxValue)
+ case Success(0) => q.add(Int.MaxValue)
} andThen {
case _ => q.add(3);
}
@@ -260,13 +261,13 @@ object FutureTests extends MinimalScalaTest {
}
val futures = (0 to 9) map {
- idx => async(idx, idx * 200)
+ idx => async(idx, idx * 20)
}
val folded = Future.fold(futures)(0)(_ + _)
Await.result(folded, timeout) mustBe (45)
val futuresit = (0 to 9) map {
- idx => async(idx, idx * 200)
+ idx => async(idx, idx * 20)
}
val foldedit = Future.fold(futures)(0)(_ + _)
Await.result(foldedit, timeout) mustBe (45)
@@ -279,7 +280,7 @@ object FutureTests extends MinimalScalaTest {
add
}
def futures = (0 to 9) map {
- idx => async(idx, idx * 200)
+ idx => async(idx, idx * 20)
}
val folded = futures.foldLeft(Future(0)) {
case (fr, fa) => for (r <- fr; a <- fa) yield (r + a)
@@ -295,7 +296,7 @@ object FutureTests extends MinimalScalaTest {
add
}
def futures = (0 to 9) map {
- idx => async(idx, idx * 100)
+ idx => async(idx, idx * 10)
}
val folded = Future.fold(futures)(0)(_ + _)
intercept[IllegalArgumentException] {
@@ -326,7 +327,7 @@ object FutureTests extends MinimalScalaTest {
"shouldReduceResults" in {
def async(idx: Int) = future {
- Thread.sleep(idx * 200)
+ Thread.sleep(idx * 20)
idx
}
val timeout = 10000 millis
@@ -348,7 +349,7 @@ object FutureTests extends MinimalScalaTest {
}
val timeout = 10000 millis
def futures = (1 to 10) map {
- idx => async(idx, idx * 100)
+ idx => async(idx, idx * 10)
}
val failed = Future.reduce(futures)(_ + _)
intercept[IllegalArgumentException] {
@@ -472,7 +473,7 @@ object FutureTests extends MinimalScalaTest {
p1.future.isCompleted mustBe (false)
f4.isCompleted mustBe (false)
- p1 complete Right("Hello")
+ p1 complete Success("Hello")
Await.ready(latch(7), TestLatch.DefaultTimeout)
@@ -509,7 +510,7 @@ object FutureTests extends MinimalScalaTest {
}
"should not throw when Await.ready" in {
- val expected = try Right(5 / 0) catch { case a: ArithmeticException => Left(a) }
+ val expected = try Success(5 / 0) catch { case a: ArithmeticException => Failure(a) }
val f = future(5).map(_ / 0)
Await.ready(f, defaultTimeout).value.get.toString mustBe expected.toString
}
diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala
index d15bb31f36..d9aaa1d5ed 100644
--- a/test/files/jvm/future-spec/PromiseTests.scala
+++ b/test/files/jvm/future-spec/PromiseTests.scala
@@ -6,7 +6,7 @@ import scala.concurrent.util.duration._
import scala.concurrent.util.Duration.Inf
import scala.collection._
import scala.runtime.NonLocalReturnControl
-
+import scala.util.{Try,Success,Failure}
object PromiseTests extends MinimalScalaTest {
@@ -48,27 +48,27 @@ object PromiseTests extends MinimalScalaTest {
"A successful Promise" should {
val result = "test value"
- val promise = Promise[String]().complete(Right(result))
+ val promise = Promise[String]().complete(Success(result))
promise.isCompleted mustBe (true)
futureWithResult(_(promise.future, result))
}
"A failed Promise" should {
val message = "Expected Exception"
- val promise = Promise[String]().complete(Left(new RuntimeException(message)))
+ val promise = Promise[String]().complete(Failure(new RuntimeException(message)))
promise.isCompleted mustBe (true)
futureWithException[RuntimeException](_(promise.future, message))
}
"An interrupted Promise" should {
val message = "Boxed InterruptedException"
- val future = Promise[String]().complete(Left(new InterruptedException(message))).future
+ val future = Promise[String]().complete(Failure(new InterruptedException(message))).future
futureWithException[ExecutionException](_(future, message))
}
"A NonLocalReturnControl failed Promise" should {
val result = "test value"
- val future = Promise[String]().complete(Left(new NonLocalReturnControl[String]("test", result))).future
+ val future = Promise[String]().complete(Failure(new NonLocalReturnControl[String]("test", result))).future
futureWithResult(_(future, result))
}
@@ -76,7 +76,7 @@ object PromiseTests extends MinimalScalaTest {
"be completed" in { f((future, _) => future.isCompleted mustBe (true)) }
- "contain a value" in { f((future, result) => future.value mustBe (Some(Right(result)))) }
+ "contain a value" in { f((future, result) => future.value mustBe (Some(Success(result)))) }
"return when ready with 'Await.ready'" in { f((future, result) => Await.ready(future, defaultTimeout).isCompleted mustBe (true)) }
@@ -159,7 +159,7 @@ object PromiseTests extends MinimalScalaTest {
"contain a value" in {
f((future, message) => {
- future.value.get.left.get.getMessage mustBe (message)
+ future.value.get.failed.get.getMessage mustBe (message)
})
}
diff --git a/test/files/jvm/future-spec/TryTests.scala b/test/files/jvm/future-spec/TryTests.scala
new file mode 100644
index 0000000000..82ca12276f
--- /dev/null
+++ b/test/files/jvm/future-spec/TryTests.scala
@@ -0,0 +1,118 @@
+// This is a port of the com.twitter.util Try spec.
+// --
+// It lives in the future-spec directory simply because it requires a specs-like
+// DSL which has already been minimally implemented for the future spec tests.
+
+import scala.util.{Try,Success,Failure}
+
+object TryTests extends MinimalScalaTest {
+ class MyException extends Exception
+ val e = new Exception("this is an exception")
+
+ "Try()" should {
+ "catch exceptions and lift into the Try type" in {
+ Try[Int](1) mustEqual Success(1)
+ Try[Int] { throw e } mustEqual Failure(e)
+ }
+ }
+
+ "Try" should {
+ "recoverWith" in {
+ val myException = new MyException
+ Success(1) recoverWith { case _ => Success(2) } mustEqual Success(1)
+ Failure(e) recoverWith { case _ => Success(2) } mustEqual Success(2)
+ Failure(e) recoverWith { case _ => Failure(e) } mustEqual Failure(e)
+ }
+
+ "getOrElse" in {
+ Success(1) getOrElse 2 mustEqual 1
+ Failure(e) getOrElse 2 mustEqual 2
+ }
+
+ "orElse" in {
+ Success(1) orElse Success(2) mustEqual Success(1)
+ Failure(e) orElse Success(2) mustEqual Success(2)
+ }
+
+ "map" in {
+ "when there is no exception" in {
+ Success(1) map(1+) mustEqual Success(2)
+ Failure[Int](e) map(1+) mustEqual Failure(e)
+ }
+
+ "when there is an exception" in {
+ Success(1) map(_ => throw e) mustEqual Failure(e)
+
+ val e2 = new Exception
+ Failure[Int](e) map(_ => throw e2) mustEqual Failure(e)
+ }
+ }
+
+ "flatMap" in {
+ "when there is no exception" in {
+ Success(1) flatMap(x => Success(1 + x)) mustEqual Success(2)
+ Failure[Int](e) flatMap(x => Success(1 + x)) mustEqual Failure(e)
+ }
+
+ "when there is an exception" in {
+ Success(1).flatMap[Int](_ => throw e) mustEqual Failure(e)
+
+ val e2 = new Exception
+ Failure[Int](e).flatMap[Int](_ => throw e2) mustEqual Failure(e)
+ }
+ }
+
+ "flatten" in {
+ "is a Success(Success)" in {
+ Success(Success(1)).flatten mustEqual Success(1)
+ }
+
+ "is a Success(Failure)" in {
+ val e = new Exception
+ Success(Failure(e)).flatten mustEqual Failure(e)
+ }
+
+ "is a Throw" in {
+ val e = new Exception
+ Failure[Try[Int]](e).flatten mustEqual Failure(e)
+ }
+ }
+
+ "for" in {
+ "with no Failure values" in {
+ val result = for {
+ i <- Success(1)
+ j <- Success(1)
+ } yield (i + j)
+ result mustEqual Success(2)
+ }
+
+ "with Failure values" in {
+ "throws before" in {
+ val result = for {
+ i <- Failure[Int](e)
+ j <- Success(1)
+ } yield (i + j)
+ result mustEqual Failure(e)
+ }
+
+ "throws after" in {
+ val result = for {
+ i <- Success(1)
+ j <- Failure[Int](e)
+ } yield (i + j)
+ result mustEqual Failure(e)
+ }
+
+ "returns the FIRST Failure" in {
+ val e2 = new Exception
+ val result = for {
+ i <- Failure[Int](e)
+ j <- Failure[Int](e2)
+ } yield (i + j)
+ result mustEqual Failure(e)
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/jvm/future-spec/main.scala b/test/files/jvm/future-spec/main.scala
index 45b59d5d20..57183d8cea 100644
--- a/test/files/jvm/future-spec/main.scala
+++ b/test/files/jvm/future-spec/main.scala
@@ -12,6 +12,7 @@ object Test {
def main(args: Array[String]) {
FutureTests.check()
PromiseTests.check()
+ TryTests.check()
}
}
@@ -47,7 +48,7 @@ trait MinimalScalaTest extends Output {
snippet
bufferPrintln("[OK] Test passed.")
} catch {
- case e =>
+ case e: Throwable =>
bufferPrintln("[FAILED] " + e)
bufferPrintln(e.getStackTrace().mkString("\n"))
throwables += e
@@ -59,6 +60,7 @@ trait MinimalScalaTest extends Output {
implicit def objectops(obj: Any) = new {
def mustBe(other: Any) = assert(obj == other, obj + " is not " + other)
+ def mustEqual(other: Any) = mustBe(other)
}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 43d4c9dc71..ffb5608fd2 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -601,10 +601,10 @@ trait FutureProjections extends TestBase {
throw cause
}
f.failed onComplete {
- case Right(t) =>
+ case Success(t) =>
assert(t == cause)
done()
- case Left(t) =>
+ case Failure(t) =>
assert(false)
}
}
@@ -626,9 +626,9 @@ trait FutureProjections extends TestBase {
done =>
val f = future { 0 }
f.failed onComplete {
- case Right(t) =>
+ case Success(t) =>
assert(false)
- case Left(t) =>
+ case Failure(t) =>
assert(t.isInstanceOf[NoSuchElementException])
done()
}
@@ -803,81 +803,6 @@ trait Exceptions extends TestBase {
}
-// trait TryEitherExtractor extends TestBase {
-
-// import scala.util.{Try, Success, Failure}
-
-// def testSuccessMatch(): Unit = once {
-// done =>
-// val thisIsASuccess = Success(42)
-// thisIsASuccess match {
-// case Success(v) =>
-// done()
-// assert(v == 42)
-// case Failure(e) =>
-// done()
-// assert(false)
-// case other =>
-// done()
-// assert(false)
-// }
-// }
-
-// def testRightMatch(): Unit = once {
-// done =>
-// val thisIsNotASuccess: Right[Throwable, Int] = Right(43)
-// thisIsNotASuccess match {
-// case Success(v) =>
-// done()
-// assert(v == 43)
-// case Failure(e) =>
-// done()
-// assert(false)
-// case other =>
-// done()
-// assert(false)
-// }
-// }
-
-// def testFailureMatch(): Unit = once {
-// done =>
-// val thisIsAFailure = Failure(new Exception("I'm an exception"))
-// thisIsAFailure match {
-// case Success(v) =>
-// done()
-// assert(false)
-// case Failure(e) =>
-// done()
-// assert(e.getMessage == "I'm an exception")
-// case other =>
-// done()
-// assert(false)
-// }
-// }
-
-// def testLeftMatch(): Unit = once {
-// done =>
-// val thisIsNotAFailure: Left[Throwable, Int] = Left(new Exception("I'm an exception"))
-// thisIsNotAFailure match {
-// case Success(v) =>
-// done()
-// assert(false)
-// case Failure(e) =>
-// done()
-// assert(e.getMessage == "I'm an exception")
-// case other =>
-// done()
-// assert(false)
-// }
-
-// }
-
-// testSuccessMatch()
-// testRightMatch()
-// testFailureMatch()
-// testLeftMatch()
-// }
-
trait CustomExecutionContext extends TestBase {
import scala.concurrent.{ ExecutionContext, Awaitable }
@@ -975,13 +900,13 @@ trait CustomExecutionContext extends TestBase {
} flatMap { x =>
Promise.successful(x + 1).future.map(addOne).map(addOne)
} onComplete {
- case Left(t) =>
+ case Failure(t) =>
try {
throw new AssertionError("error in test: " + t.getMessage, t)
} finally {
done()
}
- case Right(x) =>
+ case Success(x) =>
assertEC()
assert(x == 14)
done()
@@ -1001,6 +926,66 @@ trait CustomExecutionContext extends TestBase {
testCallbackChainCustomEC()
}
+trait ExecutionContextPrepare extends TestBase {
+ val theLocal = new ThreadLocal[String] {
+ override protected def initialValue(): String = ""
+ }
+
+ class PreparingExecutionContext extends ExecutionContext {
+ def delegate = ExecutionContext.global
+
+ override def execute(runnable: Runnable): Unit =
+ delegate.execute(runnable)
+
+ override def prepare(): ExecutionContext = {
+ // save object stored in ThreadLocal storage
+ val localData = theLocal.get
+ new PreparingExecutionContext {
+ override def execute(runnable: Runnable): Unit = {
+ val wrapper = new Runnable {
+ override def run(): Unit = {
+ // now we're on the new thread
+ // put localData into theLocal
+ theLocal.set(localData)
+ runnable.run()
+ }
+ }
+ delegate.execute(wrapper)
+ }
+ }
+ }
+
+ override def reportFailure(t: Throwable): Unit =
+ delegate.reportFailure(t)
+ }
+
+ implicit val ec = new PreparingExecutionContext
+
+ def testOnComplete(): Unit = once {
+ done =>
+ theLocal.set("secret")
+ val fut = future { 42 }
+ fut onComplete {
+ case _ =>
+ assert(theLocal.get == "secret")
+ done()
+ }
+ }
+
+ def testMap(): Unit = once {
+ done =>
+ theLocal.set("secret2")
+ val fut = future { 42 }
+ fut map { x =>
+ assert(theLocal.get == "secret2")
+ done()
+ }
+ }
+
+ testOnComplete()
+ testMap()
+}
+
object Test
extends App
with FutureCallbacks
@@ -1009,12 +994,9 @@ with FutureProjections
with Promises
with BlockContexts
with Exceptions
-// with TryEitherExtractor
with CustomExecutionContext
+with ExecutionContextPrepare
{
System.exit(0)
}
-
-
-
diff --git a/test/files/jvm/try-type-tests.scala b/test/files/jvm/try-type-tests.scala
index eecbb0ae57..17811f64c5 100644
--- a/test/files/jvm/try-type-tests.scala
+++ b/test/files/jvm/try-type-tests.scala
@@ -59,12 +59,12 @@ trait TryStandard {
def testRescueSuccess(): Unit = {
val t = Success(1)
- t.rescue{ case x => assert(false); Try() }
+ t.recoverWith{ case x => assert(false); Try() }
}
def testRescueFailure(): Unit = {
val t = Failure(new Exception("foo"))
- val n = t.rescue{ case x => Try(1) }
+ val n = t.recoverWith{ case x => Try(1) }
assert(n.get == 1)
}
@@ -103,6 +103,20 @@ trait TryStandard {
}
}
+ def testSuccessTransform(): Unit = {
+ val s = Success(1)
+ val succ = (x: Int) => Success(x * 10)
+ val fail = (x: Throwable) => Success(0)
+ assert(s.transform(succ, fail).get == 10)
+ }
+
+ def testFailureTransform(): Unit = {
+ val f = Failure(new Exception("foo"))
+ val succ = (x: Int) => Success(x * 10)
+ val fail = (x: Throwable) => Success(0)
+ assert(f.transform(succ, fail).get == 0)
+ }
+
testForeachSuccess()
testForeachFailure()
testFlatMapSuccess()
@@ -119,132 +133,12 @@ trait TryStandard {
testFlattenSuccess()
testFailedSuccess()
testFailedFailure()
-}
-
-// tests that implicit conversions from Try to Either behave as expected
-trait TryImplicitConversionTry2Either {
-
- def testTry2RightMap(): Unit = {
- val t = Success(1)
- val n = t.right.map(x => x * 100)
- assert(n == Right(100))
- }
-
- def testTry2LeftMap(): Unit = {
- val e = new Exception("foo")
- val t = Failure(e)
- val n = t.left.map(x => x)
- assert(n == Left(e))
- }
-
- def testTry2FoldSuccess(): Unit = {
- val t = Success(1)
- val n = t.fold(x => assert(false), y => y * 200)
- assert(n == 200)
- }
-
- def testTry2FoldFailure(): Unit = {
- val e = new Exception("foo")
- val t = Failure(e)
- val n = t.fold(x => x, y => assert(false))
- assert(n == e)
- }
-
- def testTry2SwapSuccess(): Unit = {
- val t = Success(1)
- val n = t.swap
- assert(n == Left(1))
- }
-
- def testTry2SwapFailure(): Unit = {
- val e = new Exception("foo")
- val t = Failure(e)
- val n = t.swap
- assert(n == Right(e))
- }
-
- // def testTry2MergeSucccess(): Unit = {
- // val t: Try[Int] = Success(1)
- // val n = (t: Either[Any, Any]).t.merge // connecting two implicit conversions
- // assert(n == 1)
- // }
-
- // def testTry2MergeFailure(): Unit = {
- // val e = new Exception("foo")
- // val t = Failure(e)
- // val n = (t: Either[Any, Any]).merge // connecting two implicit conversions
- // assert(n == e)
- // }
-
- testTry2RightMap()
- testTry2LeftMap()
- testTry2FoldSuccess()
- testTry2FoldFailure()
- testTry2SwapSuccess()
- testTry2SwapFailure()
- // testTry2MergeSucccess()
- // testTry2MergeFailure()
-}
-
-// tests that implicit conversions from Either to Try behave as expected
-trait TryImplicitConversionEither2Try {
-
- def testRight2FilterSuccessTrue(): Unit = {
- def expectsTry[U <% Try[Int]](rght: U): Try[Int] = {
- val n = rght.filter(x => x > 0) // this should be converted to a Try
- n
- }
- val r = Right(1)
- val n = expectsTry(r)
- assert(n == Success(1))
- }
-
- def testRight2FilterSuccessFalse(): Unit = {
- def expectsTry[U <% Try[Int]](rght: U): Try[Int] = {
- val n = rght.filter(x => x < 0) // this should be converted to a Try
- n
- }
- val r = Right(1)
- val n = expectsTry(r)
- n match {
- case Failure(e: NoSuchElementException) => assert(true)
- case _ => assert(false)
- }
- }
-
- def testLeft2FilterFailure(): Unit = {
- def expectsTry[U <% Try[Int]](rght: U): Try[Int] = {
- val n = rght.filter(x => x > 0) // this should be converted to a Try
- n
- }
- val r = Left(new Exception("foo"))
- val n = expectsTry(r)
- n match {
- case Failure(e: Exception) => assert(true)
- case _ => assert(false)
- }
- }
-
- def testRight2GetSuccess(): Unit = {
- def expectsTry[U <% Try[Int]](rght: U): Int = {
- val n = rght.get // this should be converted to a Try
- n
- }
- val r = Right(1)
- val n = expectsTry(r)
- assert(n == 1)
- }
-
- testRight2FilterSuccessTrue()
- testRight2FilterSuccessFalse()
- testLeft2FilterFailure()
- testRight2GetSuccess()
+ testSuccessTransform()
+ testFailureTransform()
}
object Test
extends App
-with TryStandard
-with TryImplicitConversionTry2Either
-with TryImplicitConversionEither2Try {
+with TryStandard {
System.exit(0)
} \ No newline at end of file
diff --git a/test/files/neg/t5687.check b/test/files/neg/t5687.check
new file mode 100644
index 0000000000..5096077ee5
--- /dev/null
+++ b/test/files/neg/t5687.check
@@ -0,0 +1,8 @@
+t5687.scala:4: error: type arguments [T] do not conform to class Template's type parameter bounds [T <: AnyRef]
+ type Repr[T]<:Template[T]
+ ^
+t5687.scala:20: error: overriding type Repr in class Template with bounds[T] <: Template[T];
+ type Repr has incompatible type
+ type Repr = CurveTemplate[T]
+ ^
+two errors found
diff --git a/test/files/neg/t5687.scala b/test/files/neg/t5687.scala
new file mode 100644
index 0000000000..90a9ae265c
--- /dev/null
+++ b/test/files/neg/t5687.scala
@@ -0,0 +1,55 @@
+abstract class Template[T <: AnyRef](private val t: T) {
+
+// type Repr[A<:AnyRef]<:Template[T]
+ type Repr[T]<:Template[T]
+
+ def access1(timeout: Int): Repr[T] = this.asInstanceOf[Repr[T]]
+ def access2: Repr[T] = this.asInstanceOf[Repr[T]]
+ val access3: Repr[T] = this.asInstanceOf[Repr[T]]
+ def access4(v: Repr[T]): Repr[T] = this.asInstanceOf[Repr[T]]
+ def access5(x: X): Repr[T] = this.asInstanceOf[Repr[T]]
+ def access5(x: Y): Repr[T] = this.asInstanceOf[Repr[T]]
+
+ def withReadModifiers(readModifiers:Int): Repr[T] = this.asInstanceOf[Repr[T]]
+}
+
+class Curve
+
+class CurveTemplate [T <: Curve](t: T) extends Template(t) {
+// type Repr[A<: AnyRef] = CurveTemplate[T]
+ type Repr = CurveTemplate[T]
+}
+
+class Base
+class X extends Base
+class Y extends Base
+
+
+object Example {
+ def test1() {
+ new CurveTemplate(new Curve).access1(10)
+
+ new CurveTemplate(new Curve).access2
+
+ new CurveTemplate(new Curve).access3
+
+ new CurveTemplate(new Curve).access4(null)
+
+ new CurveTemplate(new Curve).access5(new X)
+
+ ()
+
+ }
+
+ def test2() {
+ new CurveTemplate(new Curve).access1(10).withReadModifiers(1)
+
+ new CurveTemplate(new Curve).access2.withReadModifiers(1)
+
+ new CurveTemplate(new Curve).access3.withReadModifiers(1)
+
+ new CurveTemplate(new Curve).access4(null).withReadModifiers(1)
+
+ new CurveTemplate(new Curve).access5(new X).withReadModifiers(1)
+ }
+}
diff --git a/test/files/neg/t6040.check b/test/files/neg/t6040.check
new file mode 100644
index 0000000000..f44a81c471
--- /dev/null
+++ b/test/files/neg/t6040.check
@@ -0,0 +1,7 @@
+error: extension of type scala.Dynamic needs to be enabled
+by making the implicit value language.dynamics visible.
+This can be achieved by adding the import clause 'import language.dynamics'
+or by setting the compiler option -language:dynamics.
+See the Scala docs for value scala.language.dynamics for a discussion
+why the feature needs to be explicitly enabled.
+one error found
diff --git a/test/files/neg/t6040.scala b/test/files/neg/t6040.scala
new file mode 100644
index 0000000000..b8f7dab7a4
--- /dev/null
+++ b/test/files/neg/t6040.scala
@@ -0,0 +1 @@
+class X extends Dynamic \ No newline at end of file
diff --git a/test/files/pos/t6040.scala b/test/files/pos/t6040.scala
new file mode 100644
index 0000000000..9c00ecd8e1
--- /dev/null
+++ b/test/files/pos/t6040.scala
@@ -0,0 +1,3 @@
+import language.dynamics
+
+class X extends Dynamic \ No newline at end of file
diff --git a/test/files/pos/t6145.scala b/test/files/pos/t6145.scala
new file mode 100644
index 0000000000..28334d4420
--- /dev/null
+++ b/test/files/pos/t6145.scala
@@ -0,0 +1,11 @@
+object Test {
+ // the existential causes a cast and the cast makes searchClass not be in tail position
+ // can we get rid of the useless cast?
+ @annotation.tailrec
+ final def searchClass: Class[_] = {
+ "packageName" match {
+ case _ =>
+ searchClass
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t6205.scala b/test/files/pos/t6205.scala
new file mode 100644
index 0000000000..02d924fe85
--- /dev/null
+++ b/test/files/pos/t6205.scala
@@ -0,0 +1,18 @@
+// original code by reporter
+class A[T]
+class Test1 {
+ def x(backing: Map[A[_], Any]) =
+ for( (k: A[kt], v) <- backing)
+ yield (k: A[kt])
+}
+
+// this tests same thing as above, but independent of library classes,
+// earlier expansions eliminated as well as variance (everything's invariant)
+case class Holder[A](a: A)
+class Mapped[A] { def map[T](f: Holder[A] => T): Iterable[T] = ??? }
+class Test2 {
+ def works(backing: Mapped[A[_]]): Iterable[A[_]]
+ = backing.map(x =>
+ x match {case Holder(k: A[kt]) => (k: A[kt])}
+ )
+} \ No newline at end of file
diff --git a/test/files/run/applydynamic_sip.flags b/test/files/run/applydynamic_sip.flags
new file mode 100644
index 0000000000..1141f97507
--- /dev/null
+++ b/test/files/run/applydynamic_sip.flags
@@ -0,0 +1 @@
+-language:dynamics
diff --git a/test/files/run/reflection-enclosed-basic.check b/test/files/run/reflection-enclosed-basic.check
new file mode 100644
index 0000000000..41f6a72f1c
--- /dev/null
+++ b/test/files/run/reflection-enclosed-basic.check
@@ -0,0 +1,18 @@
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-basic.scala b/test/files/run/reflection-enclosed-basic.scala
new file mode 100644
index 0000000000..1dcb6c2a27
--- /dev/null
+++ b/test/files/run/reflection-enclosed-basic.scala
@@ -0,0 +1,46 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+class B1 { override def toString = "B1"; def foo = 1 }
+private class B2 { override def toString = "B2"; def foo = 2 }
+object B3 { override def toString = "B3"; def foo = 3 }
+private object B4 { override def toString = "B4"; def foo = 4 }
+object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+
+object Test extends App {
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testNestedClass(name: String) = {
+ val sym = cm.staticClass(name)
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedClass("B1")
+ testNestedClass("B2")
+
+ def testNestedModule(name: String) = {
+ val sym = cm.staticModule(name)
+ println(sym)
+ val moduleMirror = cm.reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedModule("B3")
+ testNestedModule("B4")
+ testNestedModule("B5")
+ testNestedModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-inner-basic.check b/test/files/run/reflection-enclosed-inner-basic.check
new file mode 100644
index 0000000000..984fb1ff12
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-basic.check
@@ -0,0 +1,20 @@
+class B
+List(constructor B, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-inner-basic.scala b/test/files/run/reflection-enclosed-inner-basic.scala
new file mode 100644
index 0000000000..2b2c701993
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-basic.scala
@@ -0,0 +1,52 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+class B {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+}
+
+object Test extends App {
+ val b = cm.classSymbol(classTag[B].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testInnerClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflect(new B).reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerClass("B1")
+ testInnerClass("B2")
+
+ def testInnerModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val moduleMirror = cm.reflect(new B).reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerModule("B3")
+ testInnerModule("B4")
+ testInnerModule("B5")
+ testInnerModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-inner-inner-basic.check b/test/files/run/reflection-enclosed-inner-inner-basic.check
new file mode 100644
index 0000000000..8987f31b18
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-inner-basic.check
@@ -0,0 +1,20 @@
+class BB
+List(constructor BB, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-inner-inner-basic.scala b/test/files/run/reflection-enclosed-inner-inner-basic.scala
new file mode 100644
index 0000000000..1b9e19d37d
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-inner-basic.scala
@@ -0,0 +1,58 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+class B {
+ class BB {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+ }
+}
+
+object Test extends App {
+ val b = cm.classSymbol(classTag[B#BB].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testInnerClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val outer1 = new B
+ val outer2 = new outer1.BB
+ val ctorMirror = cm.reflect(outer2).reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerClass("B1")
+ testInnerClass("B2")
+
+ def testInnerModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val outer1 = new B
+ val outer2 = new outer1.BB
+ val moduleMirror = cm.reflect(outer2).reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerModule("B3")
+ testInnerModule("B4")
+ testInnerModule("B5")
+ testInnerModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-inner-nested-basic.check b/test/files/run/reflection-enclosed-inner-nested-basic.check
new file mode 100644
index 0000000000..0f5176a6e7
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-nested-basic.check
@@ -0,0 +1,20 @@
+object BB
+List(constructor BB, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-inner-nested-basic.scala b/test/files/run/reflection-enclosed-inner-nested-basic.scala
new file mode 100644
index 0000000000..2800ee2548
--- /dev/null
+++ b/test/files/run/reflection-enclosed-inner-nested-basic.scala
@@ -0,0 +1,55 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+class B {
+ object BB {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+ }
+}
+
+object Test extends App {
+ val outer1 = new B()
+ val b = cm.moduleSymbol(classTag[outer1.BB.type].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testNestedClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflect(outer1.BB).reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedClass("B1")
+ testNestedClass("B2")
+
+ def testNestedModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val moduleMirror = cm.reflect(outer1.BB).reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedModule("B3")
+ testNestedModule("B4")
+ testNestedModule("B5")
+ testNestedModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-nested-basic.check b/test/files/run/reflection-enclosed-nested-basic.check
new file mode 100644
index 0000000000..b0e61149f8
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-basic.check
@@ -0,0 +1,20 @@
+object B
+List(constructor B, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-nested-basic.scala b/test/files/run/reflection-enclosed-nested-basic.scala
new file mode 100644
index 0000000000..8b740c2da2
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-basic.scala
@@ -0,0 +1,52 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+object B {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+}
+
+object Test extends App {
+ val b = cm.moduleSymbol(classTag[B.type].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testNestedClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedClass("B1")
+ testNestedClass("B2")
+
+ def testNestedModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val moduleMirror = cm.reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedModule("B3")
+ testNestedModule("B4")
+ testNestedModule("B5")
+ testNestedModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-nested-inner-basic.check b/test/files/run/reflection-enclosed-nested-inner-basic.check
new file mode 100644
index 0000000000..add7a81c0a
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-inner-basic.check
@@ -0,0 +1,20 @@
+class BB
+List(constructor BB, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-nested-inner-basic.scala b/test/files/run/reflection-enclosed-nested-inner-basic.scala
new file mode 100644
index 0000000000..7466733d37
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-inner-basic.scala
@@ -0,0 +1,54 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+object B {
+ class BB {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+ }
+}
+
+object Test extends App {
+ val b = cm.classSymbol(classTag[B.BB].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testInnerClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflect(new B.BB).reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerClass("B1")
+ testInnerClass("B2")
+
+ def testInnerModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val moduleMirror = cm.reflect(new B.BB).reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testInnerModule("B3")
+ testInnerModule("B4")
+ testInnerModule("B5")
+ testInnerModule("B6")
+}
diff --git a/test/files/run/reflection-enclosed-nested-nested-basic.check b/test/files/run/reflection-enclosed-nested-nested-basic.check
new file mode 100644
index 0000000000..0f5176a6e7
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-nested-basic.check
@@ -0,0 +1,20 @@
+object BB
+List(constructor BB, class B1, class B2, object B3, object B4, object B5, object B6)
+class B1
+B1
+1
+class B2
+B2
+2
+object B3
+B3
+3
+object B4
+B4
+4
+object B5
+B5
+5
+object B6
+B6
+6
diff --git a/test/files/run/reflection-enclosed-nested-nested-basic.scala b/test/files/run/reflection-enclosed-nested-nested-basic.scala
new file mode 100644
index 0000000000..8335ea482a
--- /dev/null
+++ b/test/files/run/reflection-enclosed-nested-nested-basic.scala
@@ -0,0 +1,54 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.{classTag, ClassTag}
+
+object B {
+ object BB {
+ class B1 { override def toString = "B1"; def foo = 1 }
+ private class B2 { override def toString = "B2"; def foo = 2 }
+ object B3 { override def toString = "B3"; def foo = 3 }
+ private object B4 { override def toString = "B4"; def foo = 4 }
+ object B5 extends B1 { override def toString = "B5"; override def foo = 5 }
+ private object B6 extends B2 { override def toString = "B6"; override def foo = 6 }
+ }
+}
+
+object Test extends App {
+ val b = cm.moduleSymbol(classTag[B.BB.type].runtimeClass)
+ println(b)
+ println(b.typeSignature.declarations.toList)
+
+ def testMethodInvocation(instance: Any) = {
+ val instanceMirror = cm.reflect(instance)
+ val method = instanceMirror.symbol.typeSignature.declaration(newTermName("foo")).asMethod
+ val methodMirror = instanceMirror.reflectMethod(method)
+ println(methodMirror())
+ }
+
+ def testNestedClass(name: String) = {
+ val sym = b.typeSignature.declaration(newTypeName(name)).asClass
+ println(sym)
+ val ctor = sym.typeSignature.declaration(newTermName("<init>")).asMethod
+ val ctorMirror = cm.reflectClass(sym).reflectConstructor(ctor)
+ val instance = ctorMirror()
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedClass("B1")
+ testNestedClass("B2")
+
+ def testNestedModule(name: String) = {
+ val sym = b.typeSignature.declaration(newTermName(name)).asModule
+ println(sym)
+ val moduleMirror = cm.reflectModule(sym)
+ val instance = moduleMirror.instance
+ println(instance)
+ testMethodInvocation(instance)
+ }
+
+ testNestedModule("B3")
+ testNestedModule("B4")
+ testNestedModule("B5")
+ testNestedModule("B6")
+}
diff --git a/test/files/run/reflection-modulemirror-inner-good.check b/test/files/run/reflection-modulemirror-inner-good.check
index 0bf38a73d1..fe658e7087 100644
--- a/test/files/run/reflection-modulemirror-inner-good.check
+++ b/test/files/run/reflection-modulemirror-inner-good.check
@@ -1,2 +1 @@
-inner and nested modules are not supported yet
-()
+R
diff --git a/test/files/run/reflection-modulemirror-nested-good.check b/test/files/run/reflection-modulemirror-nested-good.check
index 0bf38a73d1..fe658e7087 100644
--- a/test/files/run/reflection-modulemirror-nested-good.check
+++ b/test/files/run/reflection-modulemirror-nested-good.check
@@ -1,2 +1 @@
-inner and nested modules are not supported yet
-()
+R
diff --git a/test/files/run/reflection-repl-classes.check b/test/files/run/reflection-repl-classes.check
new file mode 100644
index 0000000000..1c7f86c90c
--- /dev/null
+++ b/test/files/run/reflection-repl-classes.check
@@ -0,0 +1,35 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> class A
+defined class A
+
+scala>
+
+scala> class B {
+ def foo(x: A) = 1
+}
+defined class B
+
+scala>
+
+scala> object defs {
+ val cm = reflect.runtime.currentMirror
+ val u = cm.universe
+ val im = cm.reflect(new B)
+ val method = im.symbol.typeSignature.member(u.newTermName("foo")).asMethod
+ val mm = im.reflectMethod(method)
+}
+defined module defs
+
+scala> import defs._
+import defs._
+
+scala>
+
+scala> mm(new A)
+res0: Any = 1
+
+scala>
diff --git a/test/files/run/reflection-repl-classes.scala b/test/files/run/reflection-repl-classes.scala
new file mode 100644
index 0000000000..80e332cde3
--- /dev/null
+++ b/test/files/run/reflection-repl-classes.scala
@@ -0,0 +1,22 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |class A
+ |
+ |class B {
+ | def foo(x: A) = 1
+ |}
+ |
+ |object defs {
+ | val cm = reflect.runtime.currentMirror
+ | val u = cm.universe
+ | val im = cm.reflect(new B)
+ | val method = im.symbol.typeSignature.member(u.newTermName("foo")).asMethod
+ | val mm = im.reflectMethod(method)
+ |}
+ |import defs._
+ |
+ |mm(new A)
+ |""".stripMargin
+}
diff --git a/test/files/run/reflection-repl.check b/test/files/run/reflection-repl-elementary.check
index 341dd10ab0..341dd10ab0 100644
--- a/test/files/run/reflection-repl.check
+++ b/test/files/run/reflection-repl-elementary.check
diff --git a/test/files/run/reflection-repl.scala b/test/files/run/reflection-repl-elementary.scala
index 72b65a1a70..72b65a1a70 100644
--- a/test/files/run/reflection-repl.scala
+++ b/test/files/run/reflection-repl-elementary.scala
diff --git a/test/files/run/reflection-sanitychecks.check b/test/files/run/reflection-sanitychecks.check
index a1df486b51..821457a999 100644
--- a/test/files/run/reflection-sanitychecks.check
+++ b/test/files/run/reflection-sanitychecks.check
@@ -6,7 +6,7 @@ method #2: 14
constructor #1: scala.ScalaReflectionException: expected a constructor of class D, you provided method bar
constructor #2: scala.ScalaReflectionException: expected a constructor of class D, you provided constructor C
class: CC
-object: java.lang.Error: inner and nested modules are not supported yet
+object: CO
=========members of D in a mirror of D=========
field #1: 21
@@ -16,7 +16,7 @@ method #2: 14
constructor #1: scala.ScalaReflectionException: expected a constructor of class D, you provided method bar
constructor #2: an instance of class D
class: CC
-object: java.lang.Error: inner and nested modules are not supported yet
+object: CO
=========members of E in a mirror of D=========
field #1: scala.ScalaReflectionException: expected a member of class D, you provided value E.foo
diff --git a/test/files/run/t4536.flags b/test/files/run/t4536.flags
new file mode 100644
index 0000000000..1141f97507
--- /dev/null
+++ b/test/files/run/t4536.flags
@@ -0,0 +1 @@
+-language:dynamics
diff --git a/test/files/run/t5040.flags b/test/files/run/t5040.flags
new file mode 100644
index 0000000000..1141f97507
--- /dev/null
+++ b/test/files/run/t5040.flags
@@ -0,0 +1 @@
+-language:dynamics