summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2012-08-14 08:56:26 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-08-14 09:37:19 +0200
commit3ccaa1026e7e74d99fe39c9608e28c48b422e2c9 (patch)
treea1187b22900d5904f9ba6e5664440a8248491f5a
parent48d9fb7307fb6519fe786a7d9be97996c5812fb7 (diff)
parent12baa2ea399b4f281c62fd20479c1e626f244d03 (diff)
downloadscala-3ccaa1026e7e74d99fe39c9608e28c48b422e2c9.tar.gz
scala-3ccaa1026e7e74d99fe39c9608e28c48b422e2c9.tar.bz2
scala-3ccaa1026e7e74d99fe39c9608e28c48b422e2c9.zip
Merge branch '2.10.x'
Conflicts: src/compiler/scala/tools/nsc/Global.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala test/files/neg/t6048.check
-rw-r--r--build.xml2
-rw-r--r--docs/LICENSE2
-rw-r--r--project/Versions.scala2
-rw-r--r--src/build/pack.xml39
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenSymbols.scala3
-rw-r--r--src/compiler/scala/reflect/reify/utils/SymbolTables.scala21
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala41
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala402
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala143
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala56
-rw-r--r--src/library/scala/collection/IterableLike.scala3
-rw-r--r--src/library/scala/collection/SeqLike.scala1
-rw-r--r--src/library/scala/collection/TraversableLike.scala5
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala13
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala32
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala15
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala18
-rw-r--r--src/library/scala/collection/immutable/Stream.scala1
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqLike.scala1
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala1
-rw-r--r--src/library/scala/collection/parallel/ParSeqLike.scala3
-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/reflect/base/FlagSets.scala7
-rw-r--r--src/library/scala/reflect/base/Trees.scala4
-rw-r--r--src/library/scala/util/Try.scala36
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala13
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala75
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala10
-rw-r--r--src/reflect/scala/reflect/internal/FlagSets.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala3
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala59
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala10
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala8
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala22
-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/catch-all.check6
-rw-r--r--test/files/neg/macro-invalidsig-context-bounds.check8
-rw-r--r--test/files/neg/macro-invalidsig-implicit-params.check8
-rw-r--r--test/files/neg/newpat_unreachable.check29
-rw-r--r--test/files/neg/newpat_unreachable.flags1
-rw-r--r--test/files/neg/newpat_unreachable.scala29
-rw-r--r--test/files/neg/nonlocal-warning.check2
-rw-r--r--test/files/neg/pat_unreachable.check8
-rw-r--r--test/files/neg/pat_unreachable.scala8
-rw-r--r--test/files/neg/t4425.check5
-rw-r--r--test/files/neg/t4425.flags1
-rw-r--r--test/files/neg/t5148.check5
-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/neg/t6048.check7
-rw-r--r--test/files/neg/t6214.check4
-rw-r--r--test/files/neg/t6214.scala7
-rw-r--r--test/files/pos/inline-access-levels.flags1
-rw-r--r--test/files/pos/inline-access-levels/A_1.scala10
-rw-r--r--test/files/pos/inline-access-levels/Test_2.scala11
-rw-r--r--test/files/pos/t5756.scala6
-rw-r--r--test/files/pos/t6022b.scala20
-rw-r--r--test/files/pos/t6040.scala3
-rw-r--r--test/files/pos/t6145.scala11
-rw-r--r--test/files/pos/t6184.scala7
-rw-r--r--test/files/pos/t6201.scala13
-rw-r--r--test/files/pos/t6204-a.scala9
-rw-r--r--test/files/pos/t6204-b.scala10
-rw-r--r--test/files/pos/t6205.scala18
-rw-r--r--test/files/run/applydynamic_sip.flags1
-rw-r--r--test/files/run/inline-ex-handlers.check170
-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
-rw-r--r--test/files/run/t6197.check0
-rw-r--r--test/files/run/t6197.scala21
-rw-r--r--test/files/run/t6198.check0
-rw-r--r--test/files/run/t6198.scala24
-rw-r--r--test/files/run/t6223.check4
-rw-r--r--test/files/run/t6223.scala11
-rw-r--r--test/scaladoc/run/SI-5933.check1
-rw-r--r--test/scaladoc/run/SI-5933.scala43
120 files changed, 2133 insertions, 861 deletions
diff --git a/build.xml b/build.xml
index de73ffc51c..d95c6ab19c 100644
--- a/build.xml
+++ b/build.xml
@@ -225,7 +225,7 @@ PROPERTIES
<property name="dists.dir" value="${basedir}/dists"/>
- <property name="copyright.string" value="Copyright 2002-2011, LAMP/EPFL"/>
+ <property name="copyright.string" value="Copyright 2002-2012, LAMP/EPFL"/>
<property name="partest.version.number" value="0.9.2"/>
<!-- These are NOT the flags used to run SuperSabbus, but the ones written
diff --git a/docs/LICENSE b/docs/LICENSE
index 38d16361bd..de950bdf57 100644
--- a/docs/LICENSE
+++ b/docs/LICENSE
@@ -1,6 +1,6 @@
SCALA LICENSE
-Copyright (c) 2002-2011 EPFL, Lausanne, unless otherwise specified.
+Copyright (c) 2002-2012 EPFL, Lausanne, unless otherwise specified.
All rights reserved.
This software was developed by the Programming Methods Laboratory of the
diff --git a/project/Versions.scala b/project/Versions.scala
index b588ec55ac..cc0ab7ff2b 100644
--- a/project/Versions.scala
+++ b/project/Versions.scala
@@ -67,7 +67,7 @@ object Versions {
IO.write(f, "version.number = "+versions.canonical+"\n"+
"osgi.number = "+versions.osgi+"\n"+
"maven.number = "+versions.maven+"\n"+
- "copyright.string = Copyright 2002-2011, LAMP/EPFL")
+ "copyright.string = Copyright 2002-2012, LAMP/EPFL")
def makeCanonicalVersion(isRelease: Boolean, mvnVersion: String, base: BaseBuildNumber, gitDate: String, gitSha: String): String =
if(isRelease) mvnVersion
diff --git a/src/build/pack.xml b/src/build/pack.xml
index 564d290967..1735b93f3f 100644
--- a/src/build/pack.xml
+++ b/src/build/pack.xml
@@ -29,10 +29,15 @@ MAIN DISTRIBUTION PACKAGING
<tarfileset dir="${dist.dir}" prefix="${dist.name}" excludes="bin/**"/>
</tar>
<gzip src="${dists.dir}/archives/${dist.name}.tar" destfile="${dists.dir}/archives/${dist.name}.tgz"/>
- <exec executable="xz" failifexecutionfails="false">
- <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}.tar"/>
- </exec>
- <move file="${dists.dir}/archives/${dist.name}.tar.xz" tofile="${dists.dir}/archives/${dist.name}.txz" failonerror="false"/>
+ <if>
+ <not><equals arg1="${archives.skipxz}" arg2="true" /></not>
+ <then>
+ <exec executable="xz" failifexecutionfails="false">
+ <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}.tar"/>
+ </exec>
+ <move file="${dists.dir}/archives/${dist.name}.tar.xz" tofile="${dists.dir}/archives/${dist.name}.txz" failonerror="false"/>
+ </then>
+ </if>
<delete file="${dists.dir}/archives/${dist.name}.tar" />
<checksum fileext=".md5">
<fileset dir="${dists.dir}/archives">
@@ -54,10 +59,15 @@ MAIN DISTRIBUTION PACKAGING
<tarfileset dir="${dist.dir}/doc/scala-devel-docs" prefix="${dist.name}-devel-docs"/>
</tar>
<gzip src="${dists.dir}/archives/${dist.name}-devel-docs.tar" destfile="${dists.dir}/archives/${dist.name}-devel-docs.tgz"/>
- <exec executable="xz" failifexecutionfails="false">
- <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-devel-docs.tar"/>
- </exec>
- <move file="${dists.dir}/archives/${dist.name}-devel-docs.tar.xz" tofile="${dists.dir}/archives/${dist.name}-devel-docs.txz" failonerror="false"/>
+ <if>
+ <not><equals arg1="${archives.skipxz}" arg2="true" /></not>
+ <then>
+ <exec executable="xz" failifexecutionfails="false">
+ <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-devel-docs.tar"/>
+ </exec>
+ <move file="${dists.dir}/archives/${dist.name}-devel-docs.tar.xz" tofile="${dists.dir}/archives/${dist.name}-devel-docs.txz" failonerror="false"/>
+ </then>
+ </if>
<delete file="${dists.dir}/archives/${dist.name}-devel-docs.tar" />
<checksum fileext=".md5">
<fileset dir="${dists.dir}/archives">
@@ -84,10 +94,15 @@ MAIN DISTRIBUTION PACKAGING
</tarfileset>
</tar>
<gzip src="${dists.dir}/archives/${dist.name}-sources.tar" destfile="${dists.dir}/archives/${dist.name}-sources.tgz"/>
- <exec executable="xz" failifexecutionfails="false">
- <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-sources.tar"/>
- </exec>
- <move file="${dists.dir}/archives/${dist.name}-sources.tar.xz" tofile="${dists.dir}/archives/${dist.name}-sources.txz" failonerror="false"/>
+ <if>
+ <not><equals arg1="${archives.skipxz}" arg2="true" /></not>
+ <then>
+ <exec executable="xz" failifexecutionfails="false">
+ <arg line="-k -9e -S .xz ${dists.dir}/archives/${dist.name}-sources.tar"/>
+ </exec>
+ <move file="${dists.dir}/archives/${dist.name}-sources.tar.xz" tofile="${dists.dir}/archives/${dist.name}-sources.txz" failonerror="false"/>
+ </then>
+ </if>
<delete file="${dists.dir}/archives/${dist.name}-sources.tar" />
<checksum fileext=".md5">
<fileset dir="${dists.dir}/archives">
diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
index 59651bcdf9..7f066a2cc3 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala
@@ -36,7 +36,8 @@ trait GenSymbols {
else if (sym.isEmptyPackageClass)
mirrorMirrorSelect(nme.EmptyPackageClass)
else if (sym.isModuleClass)
- Select(Select(reify(sym.sourceModule), nme.asModule), nme.moduleClass)
+ if (sym.sourceModule.isLocatable) Select(Select(reify(sym.sourceModule), nme.asModule), nme.moduleClass)
+ else reifySymDef(sym)
else if (sym.isPackage)
mirrorMirrorCall(nme.staticPackage, reify(sym.fullName))
else if (sym.isLocatable) {
diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
index a7ac299317..3892c86dd3 100644
--- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
+++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
@@ -174,15 +174,18 @@ trait SymbolTables {
if (sym.annotations.isEmpty) EmptyTree
else Apply(Select(currtab.symRef(sym), nme.setAnnotations), List(reifier.reify(sym.annotations)))
} else {
- import scala.reflect.internal.Flags._
- if (sym hasFlag LOCKED) {
- // [Eugene] better to have a symbol without a type signature, than to crash with a CyclicReference
- EmptyTree
- } else {
- val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(sym.info))
- if (sym.annotations.isEmpty) rset
- else reifier.mirrorBuildCall(nme.setAnnotations, rset, reifier.mkList(sym.annotations map reifier.reifyAnnotationInfo))
- }
+ // SI-6204 don't reify signatures for incomplete symbols, because this might lead to cyclic reference errors
+ val signature =
+ if (sym.isInitialized) {
+ if (sym.isCapturedVariable) capturedVariableType(sym)
+ else sym.info
+ } else NoType
+ val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(signature))
+ // `Symbol.annotations` doesn't initialize the symbol, so we don't need to do anything special here
+ // also since we call `sym.info` a few lines above, by now the symbol will be initialized (if possible)
+ // so the annotations will be filled in and will be waiting to be reified (unless symbol initialization is prohibited as described above)
+ if (sym.annotations.isEmpty) rset
+ else reifier.mirrorBuildCall(nme.setAnnotations, rset, reifier.mkList(sym.annotations map reifier.reifyAnnotationInfo))
}
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 3f4c51748c..6ecdbf1f3f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -219,10 +219,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// not deprecated yet, but a method called "error" imported into
// nearly every trait really must go. For now using globalError.
- def error(msg: String) = globalError(msg)
- def globalError(msg: String) = reporter.error(NoPosition, msg)
- def inform(msg: String) = reporter.echo(msg)
- def warning(msg: String) = reporter.warning(NoPosition, msg)
+ def error(msg: String) = globalError(msg)
+ def inform(msg: String) = reporter.echo(msg)
+ override def globalError(msg: String) = reporter.error(NoPosition, msg)
+ override def warning(msg: String) =
+ if (settings.fatalWarnings.value) globalError(msg)
+ else reporter.warning(NoPosition, msg)
// Getting in front of Predef's asserts to supplement with more info.
// This has the happy side effect of masking the one argument forms
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 687106de09..5828a6200e 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -661,13 +661,15 @@ abstract class Inliners extends SubComponent {
*
* TODO handle more robustly the case of a trait var changed at the source-level from public to private[this]
* (eg by having ICodeReader use unpickler, see SI-5442).
- * */
+
+ DISABLED
+
def potentiallyPublicized(f: Symbol): Boolean = {
(m.sourceFile eq NoSourceFile) && f.name.containsChar('$')
}
+ */
- def checkField(f: Symbol) = check(f, potentiallyPublicized(f) ||
- (f.isPrivate && !canMakePublic(f)))
+ def checkField(f: Symbol) = check(f, f.isPrivate && !canMakePublic(f))
def checkSuper(n: Symbol) = check(n, n.isPrivate || !n.isClassConstructor)
def checkMethod(n: Symbol) = check(n, n.isPrivate)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index d76d72bf70..e4338a6421 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -728,8 +728,7 @@ abstract class ICodeReader extends ClassfileParser {
import analysis.typeFlowLattice.IState
/** Abstract interpretation for one instruction. */
- override def interpret(in: typeFlowLattice.Elem, i: Instruction): typeFlowLattice.Elem = {
- var out = IState(new VarBinding(in.vars), new TypeStack(in.stack))
+ override def mutatingInterpret(out: typeFlowLattice.Elem, i: Instruction): typeFlowLattice.Elem = {
val bindings = out.vars
val stack = out.stack
import stack.push
@@ -737,12 +736,10 @@ abstract class ICodeReader extends ClassfileParser {
case DUP_X1 =>
val (one, two) = stack.pop2
push(one); push(two); push(one);
- out = IState(bindings, stack)
case DUP_X2 =>
val (one, two, three) = stack.pop3
push(one); push(three); push(two); push(one);
- out = IState(bindings, stack)
case DUP2_X1 =>
val (one, two) = stack.pop2
@@ -752,7 +749,6 @@ abstract class ICodeReader extends ClassfileParser {
val three = stack.pop
push(two); push(one); push(three); push(two); push(one);
}
- out = IState(bindings, stack)
case DUP2_X2 =>
val (one, two) = stack.pop2
@@ -771,10 +767,9 @@ abstract class ICodeReader extends ClassfileParser {
push(two); push(one); push(four); push(one); push(three); push(two); push(one);
}
}
- out = IState(bindings, stack)
case _ =>
- out = super.interpret(in, i)
+ super.mutatingInterpret(out, i)
}
out
}
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 108c5ced6f..436867257a 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -1,5 +1,5 @@
/* NSC -- new Scala compiler
- * Copyrights 2005-2011 LAMP/EPFL
+ * Copyright 2005-2012 LAMP/EPFL
* @author Martin Odersky
*/
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index f7d7f35f69..34f5ac611c 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -497,16 +497,10 @@ abstract class ExplicitOuter extends InfoTransform
else atPos(tree.pos)(outerPath(outerValue, currentClass.outerClass, sym)) // (5)
case Select(qual, name) =>
- /** return closest enclosing method, unless shadowed by an enclosing class;
- * no use of closures here in the interest of speed.
- */
- def closestEnclMethod(from: Symbol): Symbol =
- if (from.isSourceMethod) from
- else if (from.isClass) NoSymbol
- else closestEnclMethod(from.owner)
-
+ // make not private symbol acessed from inner classes, as well as
+ // symbols accessed from @inline methods
if (currentClass != sym.owner ||
- (closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass))
+ (sym.owner.enclMethod hasAnnotation ScalaInlineClass))
sym.makeNotPrivate(sym.owner)
val qsym = qual.tpe.widen.typeSymbol
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 32ddd37877..21ed10dfdf 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -28,9 +28,6 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
/** the following two members override abstract members in Transform */
val phaseName: String = "extmethods"
- /** The following flags may be set by this phase: */
- override def phaseNewFlags: Long = notPRIVATE
-
def newTransformer(unit: CompilationUnit): Transformer =
new Extender(unit)
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 651f172fe2..e6c886b6d6 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -452,7 +452,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def survivingParams(params: List[Symbol], env: TypeEnv) =
params filter {
p =>
- !p.isSpecialized ||
+ !p.isSpecialized ||
!env.contains(p) ||
!isPrimitiveValueType(env(p))
}
@@ -506,16 +506,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* was both already used for a map and mucho long. So "sClass" is the
* specialized subclass of "clazz" throughout this file.
*/
-
+
// SI-5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is
// to force .info on them, as their lazy type will be evaluated and the symbols will be eliminated. Unfortunately
// evaluating the info after creating the specialized class will mess the specialized class signature, so we'd
- // better evaluate it before creating the new class symbol
+ // better evaluate it before creating the new class symbol
val clazzName = specializedName(clazz, env0).toTypeName
- val bytecodeClazz = clazz.owner.info.decl(clazzName)
+ val bytecodeClazz = clazz.owner.info.decl(clazzName)
// debuglog("Specializing " + clazz + ", but found " + bytecodeClazz + " already there")
bytecodeClazz.info
-
+
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long, newName: Name = null) =
@@ -652,11 +652,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
info(specMember) = Implementation(original)
typeEnv(specMember) = env ++ typeEnv(m)
- }
- else debuglog({
+ } else {
val om = forwardToOverload(m)
- "normalizedMember " + m + " om: " + om + " " + pp(typeEnv(om))
- })
+ debuglog("normalizedMember " + m + " om: " + om + " " + pp(typeEnv(om)))
+ }
}
else
debuglog("conflicting env for " + m + " env: " + env)
@@ -762,7 +761,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
val subclasses = specializations(clazz.info.typeParams) filter satisfiable
subclasses foreach {
env =>
@@ -1006,7 +1005,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Fails if such an environment cannot be found.
*
* If `strict` is true, a UnifyError is thrown if unification is impossible.
- *
+ *
* If `tparams` is true, then the methods tries to unify over type params in polytypes as well.
*/
private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean, tparams: Boolean = false): TypeEnv = (tp1, tp2) match {
@@ -1185,7 +1184,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|| specializedTypeVars(t1).nonEmpty
|| specializedTypeVars(t2).nonEmpty)
}
-
+
env forall { case (tvar, tpe) =>
matches(tvar.info.bounds.lo, tpe) && matches(tpe, tvar.info.bounds.hi) || {
if (warnings)
@@ -1201,7 +1200,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
def satisfiabilityConstraints(env: TypeEnv): Option[TypeEnv] = {
val noconstraints = Some(emptyEnv)
def matches(tpe1: Type, tpe2: Type): Option[TypeEnv] = {
@@ -1232,7 +1231,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} with typechecker.Duplicators {
private val (castfrom, castto) = casts.unzip
private object CastMap extends SubstTypeMap(castfrom.toList, castto.toList)
-
+
class BodyDuplicator(_context: Context) extends super.BodyDuplicator(_context) {
override def castType(tree: Tree, pt: Type): Tree = {
// log(" expected type: " + pt)
@@ -1249,9 +1248,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
ntree
}
}
-
+
protected override def newBodyDuplicator(context: Context) = new BodyDuplicator(context)
-
+
}
/** A tree symbol substituter that substitutes on type skolems.
@@ -1359,7 +1358,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
def reportError[T](body: =>T)(handler: TypeError => T): T =
try body
catch {
@@ -1396,7 +1395,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else None
} else None
}
-
+
curTree = tree
tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
@@ -1570,7 +1569,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
})
debuglog("created special overload tree " + t)
debuglog("created " + t)
- reportError {
+ reportError {
localTyper.typed(t)
} {
_ => super.transform(tree)
@@ -1629,9 +1628,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
super.transform(tree)
}
}
-
+
/** Duplicate the body of the given method `tree` to the new symbol `source`.
- *
+ *
* Knowing that the method can be invoked only in the `castmap` type environment,
* this method will insert casts for all the expressions of types mappend in the
* `castmap`.
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 68a2c6d2ba..1e5f8cb604 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -198,6 +198,69 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
import typer.{typed, context, silent, reallyExists}
// import typer.infer.containsUnchecked
+ // Why is it so difficult to say "here's a name and a context, give me any
+ // matching symbol in scope" ? I am sure this code is wrong, but attempts to
+ // use the scopes of the contexts in the enclosing context chain discover
+ // nothing. How to associate a name with a symbol would would be a wonderful
+ // linkage for which to establish a canonical acquisition mechanism.
+ def matchingSymbolInScope(pat: Tree): Symbol = {
+ def declarationOfName(tpe: Type, name: Name): Symbol = tpe match {
+ case PolyType(tparams, restpe) => tparams find (_.name == name) getOrElse declarationOfName(restpe, name)
+ case MethodType(params, restpe) => params find (_.name == name) getOrElse declarationOfName(restpe, name)
+ case ClassInfoType(_, _, clazz) => clazz.rawInfo member name
+ case _ => NoSymbol
+ }
+ pat match {
+ case Bind(name, _) =>
+ context.enclosingContextChain.foldLeft(NoSymbol: Symbol)((res, ctx) =>
+ res orElse declarationOfName(ctx.owner.rawInfo, name))
+ case _ => NoSymbol
+ }
+ }
+
+ // Issue better warnings than "unreachable code" when people mis-use
+ // variable patterns thinking they bind to existing identifiers.
+ //
+ // Possible TODO: more deeply nested variable patterns, like
+ // case (a, b) => 1 ; case (c, d) => 2
+ // However this is a pain (at least the way I'm going about it)
+ // and I have to think these detailed errors are primarily useful
+ // for beginners, not people writing nested pattern matches.
+ def checkMatchVariablePatterns(m: Match) {
+ // A string describing the first variable pattern
+ var vpat: String = null
+ // Using an iterator so we can recognize the last case
+ val it = m.cases.iterator
+
+ def addendum(pat: Tree) = {
+ matchingSymbolInScope(pat) match {
+ case NoSymbol => ""
+ case sym =>
+ val desc = if (sym.isParameter) s"parameter ${sym.nameString} of" else sym + " in"
+ s"\nIf you intended to match against $desc ${sym.owner}, you must use backticks, like: case `${sym.nameString}` =>"
+ }
+ }
+
+ while (it.hasNext) {
+ val cdef = it.next
+ // If a default case has been seen, then every succeeding case is unreachable.
+ if (vpat != null)
+ context.unit./*error*/warning(cdef.body.pos, "unreachable code due to " + vpat + addendum(cdef.pat))
+ // If this is a default case and more cases follow, warn about this one so
+ // we have a reason to mention its pattern variable name and any corresponding
+ // symbol in scope. Errors will follow from the remaining cases, at least
+ // once we make the above warning an error.
+ else if (it.hasNext && (treeInfo isDefaultCase cdef)) {
+ val vpatName = cdef.pat match {
+ case Bind(name, _) => s" '$name'"
+ case _ => ""
+ }
+ vpat = s"variable pattern$vpatName on line ${cdef.pat.pos.line}"
+ context.unit.warning(cdef.pos, s"patterns after a variable pattern cannot match (SLS 8.1.1)" + addendum(cdef.pat))
+ }
+ }
+ }
+
/** Implement a pattern match by turning its cases (including the implicit failure case)
* into the corresponding (monadic) extractors, and combining them with the `orElse` combinator.
*
@@ -210,6 +273,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
*/
def translateMatch(match_ : Match): Tree = {
val Match(selector, cases) = match_
+ checkMatchVariablePatterns(match_)
// we don't transform after uncurry
// (that would require more sophistication when generating trees,
@@ -230,17 +294,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)
@@ -663,8 +727,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// binder has type paramType
def treeMaker(binder: Symbol, pos: Position): TreeMaker = {
+ val paramAccessors = binder.constrParamAccessors
+ // binders corresponding to mutable fields should be stored (SI-5158, SI-6070)
+ val mutableBinders =
+ if (paramAccessors exists (_.isMutable))
+ subPatBinders.zipWithIndex.collect{ case (binder, idx) if paramAccessors(idx).isMutable => binder }
+ else Nil
+
// checks binder ne null before chaining to the next extractor
- ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder))
+ ProductExtractorTreeMaker(binder, lengthGuard(binder))(subPatBinders, subPatRefs(binder), mutableBinders)
}
// reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
@@ -926,10 +997,27 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
atPos(pos)(casegen.flatMapCond(cond, res, nextBinder, substitution(next)))
}
- trait PreserveSubPatBinders extends NoNewBinders {
+ // unless we're optimizing, emit local variable bindings for all subpatterns of extractor/case class patterns
+ protected val debugInfoEmitVars = !settings.optimise.value
+
+ trait PreserveSubPatBinders extends TreeMaker {
val subPatBinders: List[Symbol]
val subPatRefs: List[Tree]
+ // unless `debugInfoEmitVars`, this set should contain the bare minimum for correctness
+ // mutable case class fields need to be stored regardless (SI-5158, SI-6070) -- see override in ProductExtractorTreeMaker
+ def storedBinders: Set[Symbol] = if (debugInfoEmitVars) subPatBinders.toSet else Set.empty
+
+ def emitVars = storedBinders.nonEmpty
+
+ private lazy val (stored, substed) = (subPatBinders, subPatRefs).zipped.partition{ case (sym, _) => storedBinders(sym) }
+
+ protected lazy val localSubstitution: Substitution = if (!emitVars) Substitution(subPatBinders, subPatRefs)
+ else {
+ val (subPatBindersSubstituted, subPatRefsSubstituted) = substed.unzip
+ Substitution(subPatBindersSubstituted.toList, subPatRefsSubstituted.toList)
+ }
+
/** The substitution that specifies the trees that compute the values of the subpattern binders.
*
* We pretend to replace the subpattern binders by subpattern refs
@@ -939,7 +1027,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
Substitution(subPatBinders, subPatRefs) >> super.subPatternsAsSubstitution
import CODE._
- def bindSubPats(in: Tree): Tree = Block(map2(subPatBinders, subPatRefs)(VAL(_) === _), in)
+ def bindSubPats(in: Tree): Tree = if (!emitVars) in
+ else {
+ val (subPatBindersStored, subPatRefsStored) = stored.unzip
+ Block(map2(subPatBindersStored.toList, subPatRefsStored.toList)(VAL(_) === _), in)
+ }
}
/**
@@ -1000,11 +1092,16 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
*/
case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])(
val subPatBinders: List[Symbol],
- val subPatRefs: List[Tree]) extends FunTreeMaker with PreserveSubPatBinders {
+ val subPatRefs: List[Tree],
+ val mutableBinders: List[Symbol]) extends FunTreeMaker with PreserveSubPatBinders {
import CODE._
val nextBinder = prevBinder // just passing through
+ // mutable binders must be stored to avoid unsoundness or seeing mutation of fields after matching (SI-5158, SI-6070)
+ // (the implementation could be optimized by duplicating code from `super.storedBinders`, but this seems more elegant)
+ override def storedBinders: Set[Symbol] = super.storedBinders ++ mutableBinders.toSet
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
val nullCheck = REF(prevBinder) OBJ_NE NULL
val cond = extraCond map (nullCheck AND _) getOrElse nullCheck
@@ -1043,8 +1140,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`
@@ -1326,7 +1424,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
@@ -1384,7 +1482,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 }
@@ -1753,20 +1851,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
class Prop
case class Eq(p: Var, q: Const) extends Prop
- type Const <: AbsConst
- trait AbsConst {
- // when we know V = C, which other equalities must hold
- // in general, equality to some type implies equality to its supertypes
- // (this multi-valued kind of equality is necessary for unreachability)
- // note that we use subtyping as a model for implication between instanceof tests
- // i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T]
- // unfortunately this is not true in general (see e.g. SI-6022)
- def implies(other: Const): Boolean
-
- // does V = C preclude V having value `other`? V = null is an exclusive assignment,
- // but V = 1 does not preclude V = Int, or V = Any
- def excludes(other: Const): Boolean
- }
+ type Const
type TypeConst <: Const
def TypeConst: TypeConstExtractor
@@ -1801,8 +1886,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def propForEqualsTo(c: Const): Prop
// populated by registerEquality
- // once equalitySyms has been called, must not call registerEquality anymore
- def equalitySyms: List[Sym]
+ // once implications has been called, must not call registerEquality anymore
+ def implications: List[(Sym, List[Sym], List[Sym])]
}
// would be nice to statically check whether a prop is equational or pure,
@@ -1901,19 +1986,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
var eqAxioms: Prop = True
@inline def addAxiom(p: Prop) = eqAxioms = And(eqAxioms, p)
- case class ExcludedPair(a: Const, b: Const) {
- override def equals(o: Any) = o match {
- case ExcludedPair(aa, bb) => (a == aa && b == bb) || (a == bb && b == aa)
- case _ => false
- }
- // make ExcludedPair(a, b).hashCode == ExcludedPair(b, a).hashCode
- override def hashCode = a.hashCode ^ b.hashCode
- }
-
patmatDebug("removeVarEq vars: "+ vars)
vars.foreach { v =>
- val excludedPair = new collection.mutable.HashSet[ExcludedPair]
-
// if v.domainSyms.isEmpty, we must consider the domain to be infinite
// otherwise, since the domain fully partitions the type of the value,
// exactly one of the types (and whatever it implies, imposed separately) must be chosen
@@ -1928,27 +2002,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
else addAxiom(symForStaticTp)
}
- val syms = v.equalitySyms
- patmatDebug("eqSyms "+(v, syms))
- syms foreach { sym =>
- // if we've already excluded the pair at some point (-A \/ -B), then don't exclude the symmetric one (-B \/ -A)
- // (nor the positive implications -B \/ A, or -A \/ B, which would entail the equality axioms falsifying the whole formula)
- val todo = syms filterNot (b => (b.const == sym.const) || excludedPair(ExcludedPair(b.const, sym.const)))
- val (excluded, notExcluded) = todo partition (b => sym.const.excludes(b.const))
- val implied = notExcluded filter (b => sym.const.implies(b.const))
-
- patmatDebug("eq axioms for: "+ sym.const)
- patmatDebug("excluded: "+ excluded)
- patmatDebug("implied: "+ implied)
-
- // when this symbol is true, what must hold...
- implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym)))
-
+ v.implications foreach { case (sym, implied, excluded) =>
+ // when sym is true, what must hold...
+ implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym)))
// ... and what must not?
- excluded foreach {excludedSym =>
- excludedPair += ExcludedPair(sym.const, excludedSym.const)
- addAxiom(Or(Not(sym), Not(excludedSym)))
- }
+ excluded foreach (excludedSym => addAxiom(Or(Not(sym), Not(excludedSym))))
}
}
@@ -2244,22 +2302,121 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
observed; allConsts
}
- // accessing after calling registerNull will result in inconsistencies
- lazy val domainSyms: Option[Set[Sym]] = domain map { _ map symForEqualsTo }
-
- lazy val symForStaticTp: Option[Sym] = symForEqualsTo.get(TypeConst(staticTpCheckable))
-
// populate equalitySyms
// don't care about the result, but want only one fresh symbol per distinct constant c
def registerEquality(c: Const): Unit = {ensureCanModify; symForEqualsTo getOrElseUpdate(c, Sym(this, c))}
- // don't access until all potential equalities have been registered using registerEquality
- lazy val equalitySyms = {observed; symForEqualsTo.values.toList}
-
// return the symbol that represents this variable being equal to the constant `c`, if it exists, otherwise False (for robustness)
// (registerEquality(c) must have been called prior, either when constructing the domain or from outside)
def propForEqualsTo(c: Const): Prop = {observed; symForEqualsTo.getOrElse(c, False)}
+ // [implementation NOTE: don't access until all potential equalities have been registered using registerEquality]p
+ /** the information needed to construct the boolean proposition that encods the equality proposition (V = C)
+ *
+ * that models a type test pattern `_: C` or constant pattern `C`, where the type test gives rise to a TypeConst C,
+ * and the constant pattern yields a ValueConst C
+ *
+ * for exhaustivity, we really only need implication (e.g., V = 1 implies that V = 1 /\ V = Int, if both tests occur in the match,
+ * and thus in this variable's equality symbols), but reachability also requires us to model things like V = 1 precluding V = "1"
+ */
+ lazy val implications = {
+ /** when we know V = C, which other equalities must hold
+ *
+ * in general, equality to some type implies equality to its supertypes
+ * (this multi-valued kind of equality is necessary for unreachability)
+ * note that we use subtyping as a model for implication between instanceof tests
+ * i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T]
+ * unfortunately this is not true in general (see e.g. SI-6022)
+ */
+ def implies(lower: Const, upper: Const): Boolean =
+ // values and null
+ lower == upper ||
+ // type implication
+ (lower != NullConst && !upper.isValue &&
+ instanceOfTpImplies(if (lower.isValue) lower.wideTp else lower.tp, upper.tp))
+
+ // if(r) patmatDebug("implies : "+(lower, lower.tp, upper, upper.tp))
+ // else patmatDebug("NOT implies: "+(lower, upper))
+
+
+ /** does V = C preclude V having value `other`?
+ (1) V = null is an exclusive assignment,
+ (2) V = A and V = B, for A and B value constants, are mutually exclusive unless A == B
+ we err on the safe side, for example:
+ - assume `val X = 1; val Y = 1`, then
+ (2: Int) match { case X => case Y => <falsely considered reachable> }
+ - V = 1 does not preclude V = Int, or V = Any, it could be said to preclude V = String, but we don't model that
+
+ (3) for types we could try to do something fancy, but be conservative and just say no
+ */
+ def excludes(a: Const, b: Const): Boolean =
+ a != b && ((a == NullConst || b == NullConst) || (a.isValue && b.isValue))
+
+ // if(r) patmatDebug("excludes : "+(a, a.tp, b, b.tp))
+ // else patmatDebug("NOT excludes: "+(a, b))
+
+/*
+[ HALF BAKED FANCINESS: //!equalitySyms.exists(common => implies(common.const, a) && implies(common.const, b)))
+ when type tests are involved, we reason (conservatively) under a closed world assumption,
+ since we are really only trying to counter the effects of the symbols that we introduce to model type tests
+ we don't aim to model the whole subtyping hierarchy, simply to encode enough about subtyping to do unreachability properly
+
+ consider the following hierarchy:
+
+ trait A
+ trait B
+ trait C
+ trait AB extends B with A
+
+ // two types are mutually exclusive if there is no equality symbol whose constant implies both
+ object Test extends App {
+ def foo(x: Any) = x match {
+ case _ : C => println("C")
+ case _ : AB => println("AB")
+ case _ : (A with B) => println("AB'")
+ case _ : B => println("B")
+ case _ : A => println("A")
+ }
+
+ of course this kind of reasoning is not true in general,
+ but we can safely pretend types are mutually exclusive as long as there are no counter-examples in the match we're analyzing}
+*/
+
+ val excludedPair = new collection.mutable.HashSet[ExcludedPair]
+
+ case class ExcludedPair(a: Const, b: Const) {
+ override def equals(o: Any) = o match {
+ case ExcludedPair(aa, bb) => (a == aa && b == bb) || (a == bb && b == aa)
+ case _ => false
+ }
+ // make ExcludedPair(a, b).hashCode == ExcludedPair(b, a).hashCode
+ override def hashCode = a.hashCode ^ b.hashCode
+ }
+
+ equalitySyms map { sym =>
+ // if we've already excluded the pair at some point (-A \/ -B), then don't exclude the symmetric one (-B \/ -A)
+ // (nor the positive implications -B \/ A, or -A \/ B, which would entail the equality axioms falsifying the whole formula)
+ val todo = equalitySyms filterNot (b => (b.const == sym.const) || excludedPair(ExcludedPair(b.const, sym.const)))
+ val (excluded, notExcluded) = todo partition (b => excludes(sym.const, b.const))
+ val implied = notExcluded filter (b => implies(sym.const, b.const))
+
+ patmatDebug("eq axioms for: "+ sym.const)
+ patmatDebug("excluded: "+ excluded)
+ patmatDebug("implied: "+ implied)
+
+ excluded foreach { excludedSym => excludedPair += ExcludedPair(sym.const, excludedSym.const)}
+
+ (sym, implied, excluded)
+ }
+ }
+
+ // accessing after calling registerNull will result in inconsistencies
+ lazy val domainSyms: Option[Set[Sym]] = domain map { _ map symForEqualsTo }
+
+ lazy val symForStaticTp: Option[Sym] = symForEqualsTo.get(TypeConst(staticTpCheckable))
+
+ // don't access until all potential equalities have been registered using registerEquality
+ private lazy val equalitySyms = {observed; symForEqualsTo.values.toList}
// don't call until all equalities have been registered and registerNull has been called (if needed)
def describe = toString + ": " + staticTp + domain.map(_.mkString(" ::= ", " | ", "// "+ symForEqualsTo.keys)).getOrElse(symForEqualsTo.keys.mkString(" ::= ", " | ", " | ...")) + " // = " + path
@@ -2315,42 +2472,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- sealed abstract class Const extends AbsConst {
+ sealed abstract class Const {
def tp: Type
- protected def wideTp: Type
+ def wideTp: Type
def isAny = wideTp.typeSymbol == AnyClass
-
- final def implies(other: Const): Boolean = {
- val r = (this, other) match {
- case (_: ValueConst, _: ValueConst) => this == other // hashconsed
- case (_: ValueConst, _: TypeConst) => instanceOfTpImplies(tp, other.tp)
- case (_: TypeConst, _) => instanceOfTpImplies(tp, other.tp)
- case _ => false
- }
- // if(r) patmatDebug("implies : "+(this, other))
- // else patmatDebug("NOT implies: "+(this, other))
- r
- }
-
- // does V = C preclude V having value `other`? V = null is an exclusive assignment,
- // but V = 1 does not preclude V = Int, or V = Any
- final def excludes(other: Const): Boolean = {
- val r = (this, other) match {
- case (_, NullConst) => true
- case (NullConst, _) => true
- // this causes false negative for unreachability, but that's ok:
- // example: val X = 1; val Y = 1; (2: Int) match { case X => case Y => /* considered reachable */ }
- case (_: ValueConst, _: ValueConst) => this != other
- case (_: ValueConst, _: TypeConst) => !(instanceOfTpImplies(tp, other.tp) || instanceOfTpImplies(other.tp, wideTp))
- case (_: TypeConst, _: ValueConst) => !(instanceOfTpImplies(other.tp, tp) || instanceOfTpImplies(tp, other.wideTp))
- case (_: TypeConst, _: TypeConst) => !(instanceOfTpImplies(tp, other.tp) || instanceOfTpImplies(other.tp, tp))
- case _ => false
- }
- // if(r) patmatDebug("excludes : "+(this, this.tp, other, other.tp))
- // else patmatDebug("NOT excludes: "+(this, other))
- r
- }
+ def isValue: Boolean //= tp.isStable
// note: use reference equality on Const since they're hash-consed (doing type equality all the time is too expensive)
// the equals inherited from AnyRef does just this
@@ -2362,15 +2489,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// e.g., when we know some value must be of type T, can it still be of type S? (this is the positive formulation of what `excludes` on Const computes)
// since we're talking values, there must have been a class involved in creating it, so rephrase our types in terms of classes
// (At least conceptually: `true` is an instance of class `Boolean`)
- private def widenToClass(tp: Type) = {
- // getOrElse to err on the safe side -- all BTS should end in Any, right?
- val wideTp = tp.widen
- val clsTp =
- if (wideTp.typeSymbol.isClass) wideTp
- else wideTp.baseTypeSeq.toList.find(_.typeSymbol.isClass).getOrElse(AnyClass.tpe)
- // patmatDebug("Widening to class: "+ (tp, clsTp, tp.widen, tp.widen.baseTypeSeq, tp.widen.baseTypeSeq.toList.find(_.typeSymbol.isClass)))
- clsTp
- }
+ private def widenToClass(tp: Type): Type =
+ if (tp.typeSymbol.isClass) tp
+ else tp.baseType(tp.baseClasses.head)
object TypeConst extends TypeConstExtractor {
def apply(tp: Type) = {
@@ -2387,7 +2508,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
private[this] val id: Int = Const.nextTypeId
val wideTp = widenToClass(tp)
-
+ def isValue = false
override def toString = tp.toString //+"#"+ id
}
@@ -2431,14 +2552,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const {
// patmatDebug("VC"+(tp, wideTp, toString))
- assert(!(tp =:= NullTp))
+ assert(!(tp =:= NullTp)) // TODO: assert(!tp.isStable)
private[this] val id: Int = Const.nextValueId
+ def isValue = true
}
lazy val NullTp = ConstantType(Constant(null))
case object NullConst extends Const {
def tp = NullTp
- protected def wideTp = NullTp
+ def wideTp = NullTp
def isValue = true
override def toString = "null"
@@ -2509,7 +2631,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
var reachable = true
var caseIndex = 0
- patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables) map (_.describe) mkString ("\n")))
+ patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsCNF))
// invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
@@ -2524,10 +2646,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
current = current.tail
val model = findModelFor(andFormula(eqFreePropToSolvable(current.head), prefix))
- // patmatDebug("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
- // if (ok) patmatDebug("reached: "+ modelString(model))
+ // patmatDebug("trying to reach:\n"+ cnfString(eqFreePropToSolvable(current.head)) +"\nunder prefix:\n"+ cnfString(prefix))
+ // if (NoModel ne model) patmatDebug("reached: "+ modelString(model))
- reachable = model ne NoModel
+ reachable = NoModel ne model
}
}
@@ -2589,17 +2711,19 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// TODO: this is subject to the availability of TypeTags (since an abstract type with a type tag is checkable at run time)
def checkableType(tp: Type): Type = {
// TODO: this is extremely rough...
- object toCheckable extends TypeMap {
- def apply(tp: Type) = tp match {
- case TypeRef(pre, sym, a :: as) if sym ne ArrayClass =>
- // replace type args by existentials, since they can't be checked
- // TODO: when type tags are available, we will check -- when this is implemented, can we take that into account here?
- // TODO: don't reuse sym.typeParams, they have bounds (and those must not be considered)
- newExistentialType(sym.typeParams, sym.tpe).asSeenFrom(pre, sym.owner)
- case _ => mapOver(tp)
+ // replace type args by wildcards, since they can't be checked (don't use existentials: overkill)
+ // TODO: when type tags are available, we will check -- when this is implemented, can we take that into account here?
+ // similar to typer.infer.approximateAbstracts
+ object typeArgsToWildcardsExceptArray extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) if args.nonEmpty && (sym ne ArrayClass) =>
+ TypeRef(pre, sym, args map (_ => WildcardType))
+ case _ =>
+ mapOver(tp)
}
}
- val res = toCheckable(tp)
+
+ val res = typeArgsToWildcardsExceptArray(tp)
patmatDebug("checkable "+(tp, res))
res
}
@@ -2815,7 +2939,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// node in the tree that describes how to construct a counter-example
case class VariableAssignment(variable: Var, equalTo: List[Const], notEqualTo: List[Const], fields: collection.mutable.Map[Symbol, VariableAssignment]) {
// need to prune since the model now incorporates all super types of a constant (needed for reachability)
- private lazy val uniqueEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && (better implies subsumed)))
+ private lazy val uniqueEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && instanceOfTpImplies(better.tp, subsumed.tp)))
private lazy val prunedEqualTo = uniqueEqualTo filterNot (subsumed => variable.staticTpCheckable <:< subsumed.tp)
private lazy val ctor = (prunedEqualTo match { case List(TypeConst(tp)) => tp case _ => variable.staticTpCheckable }).typeSymbol.primaryConstructor
private lazy val ctorParams = if (ctor == NoSymbol || ctor.paramss.isEmpty) Nil else ctor.paramss.head
@@ -3324,16 +3448,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case Some(cds) => cds
}
- val allReachable =
- if (unchecked) true
- else {
- val unreachables = unreachableCase(caseDefsWithGuards)
- unreachables foreach {cd => reportUnreachable(cd.body.pos)}
- // a switch with duplicate cases yields a verify error,
- // and a switch with duplicate cases and guards cannot soundly be rewritten to an unguarded switch
- // (even though the verify error would disappear, the behaviour would change)
- unreachables.isEmpty
- }
+ val allReachable = unchecked || {
+ // a switch with duplicate cases yields a verify error,
+ // and a switch with duplicate cases and guards cannot soundly be rewritten to an unguarded switch
+ // (even though the verify error would disappear, the behaviour would change)
+ unreachableCase(caseDefsWithGuards) map (cd => reportUnreachable(cd.body.pos)) isEmpty
+ }
if (!allReachable) Nil
else if (noGuards(caseDefsWithGuards)) {
@@ -3481,7 +3601,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)
@@ -3492,7 +3612,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)
@@ -3517,14 +3637,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/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 02a556e918..5e511591f3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -34,6 +34,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
/** the following two members override abstract members in Transform */
val phaseName: String = "superaccessors"
+ /** The following flags may be set by this phase: */
+ override def phaseNewFlags: Long = notPRIVATE
+
protected def newTransformer(unit: CompilationUnit): Transformer =
new SuperAccTransformer(unit)
@@ -192,9 +195,11 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
super.transform(tree)
+
case ModuleDef(_, _, _) =>
checkCompanionNameClashes(sym)
super.transform(tree)
+
case Template(_, _, body) =>
val ownAccDefs = new ListBuffer[Tree]
accDefs(currentOwner) = ownAccDefs
@@ -221,72 +226,85 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
typeDef.symbol.deSkolemize.setFlag(SPECIALIZED)
typeDef
- case sel @ Select(qual @ This(_), name) =>
- // warn if they are selecting a private[this] member which
- // also exists in a superclass, because they may be surprised
- // to find out that a constructor parameter will shadow a
- // field. See SI-4762.
- if (settings.lint.value) {
- if (sym.isPrivateLocal && sym.paramss.isEmpty) {
- qual.symbol.ancestors foreach { parent =>
- parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 =>
- if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) {
- unit.warning(sel.pos,
- sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name
- + " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within "
- + sym.owner + " - you may want to give them distinct names."
- )
+ case sel @ Select(qual, name) =>
+ /** return closest enclosing method, unless shadowed by an enclosing class;
+ * no use of closures here in the interest of speed.
+ */
+ def closestEnclMethod(from: Symbol): Symbol =
+ if (from.isSourceMethod) from
+ else if (from.isClass) NoSymbol
+ else closestEnclMethod(from.owner)
+
+ if (closestEnclMethod(currentOwner) hasAnnotation definitions.ScalaInlineClass)
+ sym.makeNotPrivate(sym.owner)
+
+ qual match {
+ case This(_) =>
+ // warn if they are selecting a private[this] member which
+ // also exists in a superclass, because they may be surprised
+ // to find out that a constructor parameter will shadow a
+ // field. See SI-4762.
+ if (settings.lint.value) {
+ if (sym.isPrivateLocal && sym.paramss.isEmpty) {
+ qual.symbol.ancestors foreach { parent =>
+ parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 =>
+ if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) {
+ unit.warning(sel.pos,
+ sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name
+ + " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within "
+ + sym.owner + " - you may want to give them distinct names.")
+ }
+ }
}
}
}
- }
- }
- // direct calls to aliases of param accessors to the superclass in order to avoid
- // duplicating fields.
- if (sym.isParamAccessor && sym.alias != NoSymbol) {
- val result = (localTyper.typedPos(tree.pos) {
- Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias)
- }).asInstanceOf[Select]
- debuglog("alias replacement: " + tree + " ==> " + result);//debug
- localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true))
- }
- else {
- /** A trait which extends a class and accesses a protected member
- * of that class cannot implement the necessary accessor method
- * because its implementation is in an implementation class (e.g.
- * Foo$class) which inherits nothing, and jvm access restrictions
- * require the call site to be in an actual subclass. So non-trait
- * classes inspect their ancestors for any such situations and
- * generate the accessors. See SI-2296.
- */
- // FIXME - this should be unified with needsProtectedAccessor, but some
- // subtlety which presently eludes me is foiling my attempts.
- val shouldEnsureAccessor = (
- currentClass.isTrait
- && sym.isProtected
- && sym.enclClass != currentClass
- && !sym.owner.isTrait
- && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
- && (qual.symbol.info.member(sym.name) ne NoSymbol)
- )
- if (shouldEnsureAccessor) {
- log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass)
- ensureAccessor(sel)
- }
- else
- mayNeedProtectedAccessor(sel, List(EmptyTree), false)
- }
+ // direct calls to aliases of param accessors to the superclass in order to avoid
+ // duplicating fields.
+ if (sym.isParamAccessor && sym.alias != NoSymbol) {
+ val result = (localTyper.typedPos(tree.pos) {
+ Select(Super(qual, tpnme.EMPTY) setPos qual.pos, sym.alias)
+ }).asInstanceOf[Select]
+ debuglog("alias replacement: " + tree + " ==> " + result); //debug
+ localTyper.typed(gen.maybeMkAsInstanceOf(transformSuperSelect(result), sym.tpe, sym.alias.tpe, true))
+ } else {
+ /**
+ * A trait which extends a class and accesses a protected member
+ * of that class cannot implement the necessary accessor method
+ * because its implementation is in an implementation class (e.g.
+ * Foo$class) which inherits nothing, and jvm access restrictions
+ * require the call site to be in an actual subclass. So non-trait
+ * classes inspect their ancestors for any such situations and
+ * generate the accessors. See SI-2296.
+ */
+ // FIXME - this should be unified with needsProtectedAccessor, but some
+ // subtlety which presently eludes me is foiling my attempts.
+ val shouldEnsureAccessor = (
+ currentClass.isTrait
+ && sym.isProtected
+ && sym.enclClass != currentClass
+ && !sym.owner.isTrait
+ && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
+ && (qual.symbol.info.member(sym.name) ne NoSymbol))
+ if (shouldEnsureAccessor) {
+ log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass)
+ ensureAccessor(sel)
+ } else
+ mayNeedProtectedAccessor(sel, List(EmptyTree), false)
+ }
- case sel @ Select(Super(_, mix), name) =>
- if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
- if (!settings.overrideVars.value)
- unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
- }
- else if (isDisallowed(sym)) {
- unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
+ case Super(_, mix) =>
+ if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
+ if (!settings.overrideVars.value)
+ unit.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf)
+ } else if (isDisallowed(sym)) {
+ unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
+ }
+ transformSuperSelect(sel)
+
+ case _ =>
+ mayNeedProtectedAccessor(sel, List(EmptyTree), true)
}
- transformSuperSelect(sel)
case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension =>
treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, withInvalidOwner(transform(rhs)))
@@ -294,9 +312,6 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case TypeApply(sel @ Select(qual, name), args) =>
mayNeedProtectedAccessor(sel, args, true)
- case sel @ Select(qual, name) =>
- mayNeedProtectedAccessor(sel, List(EmptyTree), true)
-
case Assign(lhs @ Select(qual, name), rhs) =>
if (lhs.symbol.isVariable &&
lhs.symbol.isJavaDefined &&
@@ -311,10 +326,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Apply(fn, args) =>
assert(fn.tpe != null, tree)
treeCopy.Apply(tree, transform(fn), transformArgs(fn.tpe.params, args))
+
case Function(vparams, body) =>
withInvalidOwner {
treeCopy.Function(tree, vparams, transform(body))
}
+
case _ =>
super.transform(tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 7eb53ca7de..6ef45dd56e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -92,8 +92,8 @@ trait Typers extends Modes with Adaptations with Tags {
// when true:
// - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope)
// - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction
- // this is disabled by: -Xoldpatmat, scaladoc or interactive compilation
- @inline private def newPatternMatching = !settings.XoldPatmat.value && !forScaladoc && !forInteractive // && (phase.id < currentRun.uncurryPhase.id)
+ // this is disabled by: -Xoldpatmat or interactive compilation (we run it for scaladoc due to SI-5933)
+ @inline private def newPatternMatching = !settings.XoldPatmat.value && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id)
abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors {
import context0.unit
@@ -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 != "" &&
@@ -1817,7 +1828,7 @@ trait Typers extends Modes with Adaptations with Tags {
checkNonCyclic(vdef, tpt1)
if (sym.hasAnnotation(definitions.VolatileAttr) && !sym.isMutable)
- VolatileValueError(vdef)
+ VolatileValueError(vdef)
val rhs1 =
if (vdef.rhs.isEmpty) {
@@ -2630,7 +2641,6 @@ trait Typers extends Modes with Adaptations with Tags {
def includesTargetPos(tree: Tree) =
tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos)
val localTarget = stats exists includesTargetPos
- val statsErrors = scala.collection.mutable.LinkedHashSet[AbsTypeError]()
def typedStat(stat: Tree): Tree = {
if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat))
OnlyDeclarationsError(stat)
@@ -2649,7 +2659,6 @@ trait Typers extends Modes with Adaptations with Tags {
stat
} else {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) {
- context.flushBuffer()
this
} else newTyper(context.make(stat, exprOwner))
// XXX this creates a spurious dead code warning if an exception is thrown
@@ -2666,7 +2675,6 @@ trait Typers extends Modes with Adaptations with Tags {
"a pure expression does nothing in statement position; " +
"you may be omitting necessary parentheses"
)
- statsErrors ++= localTyper.context.errBuffer
result
}
}
@@ -2749,12 +2757,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
}
- val stats1 = withSavedContext(context) {
- val result = stats mapConserve typedStat
- context.flushBuffer()
- result
- }
- context.updateBuffer(statsErrors)
+ val stats1 = stats mapConserve typedStat
if (phase.erasedTypes) stats1
else {
checkNoDoubleDefs(stats1)
@@ -3038,7 +3041,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
@@ -4958,7 +4973,7 @@ trait Typers extends Modes with Adaptations with Tags {
var catches1 = typedCases(catches, ThrowableClass.tpe, pt)
for (cdef <- catches1 if cdef.guard.isEmpty) {
- def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded}: Throwable` to clear this warning.")
+ def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
cdef.pat match {
case Bind(name, i@Ident(_)) if unbound(i) => warn(name)
@@ -5025,10 +5040,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/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index 2e9599058f..ac6d754f9e 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -171,7 +171,7 @@ self =>
* fewer elements than size.
*/
def sliding(size: Int): Iterator[Repr] = sliding(size, 1)
-
+
/** Groups elements in fixed size blocks by passing a "sliding window"
* over them (as opposed to partitioning them, as is done in grouped.)
* @see [[scala.collection.Iterator]], method `sliding`
@@ -293,6 +293,7 @@ self =>
override /*TraversableLike*/ def view = new IterableView[A, Repr] {
protected lazy val underlying = self.repr
+ override def isEmpty = self.isEmpty
override def iterator = self.iterator
}
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 416aa916b4..81db2d583a 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -627,6 +627,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
override def view = new SeqView[A, Repr] {
protected lazy val underlying = self.repr
+ override def isEmpty = self.isEmpty
override def iterator = self.iterator
override def length = self.length
override def apply(idx: Int) = self.apply(idx)
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 641dd095da..0345f05355 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -86,7 +86,7 @@ trait TraversableLike[+A, +Repr] extends Any
def repr: Repr = this.asInstanceOf[Repr]
final def isTraversableAgain: Boolean = true
-
+
/** The underlying collection seen as an instance of `$Coll`.
* By default this is implemented as the current collection object itself,
* but this can be overridden.
@@ -174,7 +174,7 @@ trait TraversableLike[+A, +Repr] extends Any
*
* @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
* @inheritdoc
- *
+ *
* Example:
* {{{
* scala> val x = List(1)
@@ -655,6 +655,7 @@ trait TraversableLike[+A, +Repr] extends Any
def view = new TraversableView[A, Repr] {
protected lazy val underlying = self.repr
override def foreach[U](f: A => U) = self foreach f
+ override def isEmpty = self.isEmpty
}
/** Creates a non-strict view of a slice of this $coll.
diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala
index bf4f8205d6..7fbcf1374b 100644
--- a/src/library/scala/collection/TraversableViewLike.scala
+++ b/src/library/scala/collection/TraversableViewLike.scala
@@ -59,7 +59,7 @@ trait ViewMkString[+A] {
* $viewInfo
*
* All views for traversable collections are defined by creating a new `foreach` method.
- *
+ *
* @author Martin Odersky
* @version 2.8
* @since 2.8
@@ -162,7 +162,7 @@ trait TraversableViewLike[+A,
// if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That]
// else super.flatMap[B, That](f)(bf)
}
- override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) =
+ override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) =
newFlatMapped(asTraversable)
private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This]
@@ -193,6 +193,15 @@ trait TraversableViewLike[+A,
override def span(p: A => Boolean): (This, This) = (newTakenWhile(p), newDroppedWhile(p))
override def splitAt(n: Int): (This, This) = (newTaken(n), newDropped(n))
+ // Without this, isEmpty tests go back to the Traversable default, which
+ // involves starting a foreach, which can force the first element of the
+ // view. This is just a backstop - it's overridden at all the "def view"
+ // instantiation points in the collections where the Coll type is known.
+ override def isEmpty = underlying match {
+ case x: GenTraversableOnce[_] => x.isEmpty
+ case _ => super.isEmpty
+ }
+
override def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[This, B, That]): That =
newForced(thisSeq.scanLeft(z)(op)).asInstanceOf[That]
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 2cf9985523..0b297aeb45 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -72,19 +72,8 @@ class HashMap[A, +B] extends AbstractMap[A, B]
}
private[collection] def computeHash(key: A) = improve(elemHashCode(key))
-
- protected type MergeFunction[A1, B1] = ((A1, B1), (A1, B1)) => (A1, B1);
-
- import HashMap.Merger
- protected def liftMerger[A1, B1](mergef: MergeFunction[A1, B1]): Merger[A1, B1] = if (mergef == null) null else new Merger[A1, B1] {
- self =>
- def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv1, kv2)
- val invert: Merger[A1, B1] = new Merger[A1, B1] {
- def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv2, kv1)
- def invert: Merger[A1, B1] = self
- }
- }
+ import HashMap.{Merger, MergeFunction, liftMerger}
private[collection] def get0(key: A, hash: Int, level: Int): Option[B] = None
@@ -130,11 +119,26 @@ class HashMap[A, +B] extends AbstractMap[A, B]
*/
object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
- private[immutable] abstract class Merger[A, B] {
+ private abstract class Merger[A, B] {
def apply(kv1: (A, B), kv2: (A, B)): (A, B)
def invert: Merger[A, B]
}
-
+
+ private type MergeFunction[A1, B1] = ((A1, B1), (A1, B1)) => (A1, B1)
+
+ private def liftMerger[A1, B1](mergef: MergeFunction[A1, B1]): Merger[A1, B1] =
+ if (mergef == null) defaultMerger.asInstanceOf[Merger[A1, B1]] else liftMerger0(mergef)
+
+ private[this] val defaultMerger : Merger[Any, Any] = liftMerger0((a,b) => a)
+
+ private[this] def liftMerger0[A1, B1](mergef: MergeFunction[A1, B1]): Merger[A1, B1] = new Merger[A1, B1] {
+ self =>
+ def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv1, kv2)
+ val invert: Merger[A1, B1] = new Merger[A1, B1] {
+ def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv2, kv1)
+ def invert: Merger[A1, B1] = self
+ }
+ }
/** $mapCanBuildFromInfo */
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B]
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index c60fdc3bf1..ef0173337c 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -151,10 +151,12 @@ object HashSet extends ImmutableSetFactory[HashSet] {
override def removed0(key: A, hash: Int, level: Int): HashSet[A] =
if (hash == this.hash) {
val ks1 = ks - key
- if (!ks1.isEmpty)
- new HashSetCollision1(hash, ks1)
- else
+ if(ks1.isEmpty)
HashSet.empty[A]
+ else if(ks1.tail.isEmpty)
+ new HashSet1(ks1.head, hash)
+ else
+ new HashSetCollision1(hash, ks1)
} else this
override def iterator: Iterator[A] = ks.iterator
@@ -236,7 +238,12 @@ object HashSet extends ImmutableSetFactory[HashSet] {
Array.copy(elems, 0, elemsNew, 0, offset)
Array.copy(elems, offset + 1, elemsNew, offset, elems.length - offset - 1)
val sizeNew = size - sub.size
- new HashTrieSet(bitmapNew, elemsNew, sizeNew)
+ // if we have only one child, which is not a HashTrieSet but a self-contained set like
+ // HashSet1 or HashSetCollision1, return the child instead
+ if (elemsNew.length == 1 && !elemsNew(0).isInstanceOf[HashTrieSet[_]])
+ elemsNew(0)
+ else
+ new HashTrieSet(bitmapNew, elemsNew, sizeNew)
} else
HashSet.empty[A]
} else {
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
index ce3abaacb7..4dd0d62fc0 100644
--- a/src/library/scala/collection/immutable/ListSet.scala
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -116,8 +116,8 @@ class ListSet[A] extends AbstractSet[A]
def hasNext = that.nonEmpty
def next: A =
if (hasNext) {
- val res = that.elem
- that = that.next
+ val res = that.head
+ that = that.tail
res
}
else Iterator.empty.next
@@ -126,18 +126,18 @@ class ListSet[A] extends AbstractSet[A]
/**
* @throws Predef.NoSuchElementException
*/
- protected def elem: A = throw new NoSuchElementException("Set has no elements");
+ override def head: A = throw new NoSuchElementException("Set has no elements");
/**
* @throws Predef.NoSuchElementException
*/
- protected def next: ListSet[A] = throw new NoSuchElementException("Next of an empty set");
+ override def tail: ListSet[A] = throw new NoSuchElementException("Next of an empty set");
override def stringPrefix = "ListSet"
/** Represents an entry in the `ListSet`.
*/
- protected class Node(override protected val elem: A) extends ListSet[A] with Serializable {
+ protected class Node(override val head: A) extends ListSet[A] with Serializable {
override private[ListSet] def unchecked_outer = self
/** Returns the number of elements in this set.
@@ -162,7 +162,7 @@ class ListSet[A] extends AbstractSet[A]
*/
override def contains(e: A) = containsInternal(this, e)
@tailrec private def containsInternal(n: ListSet[A], e: A): Boolean =
- !n.isEmpty && (n.elem == e || containsInternal(n.unchecked_outer, e))
+ !n.isEmpty && (n.head == e || containsInternal(n.unchecked_outer, e))
/** This method creates a new set with an additional element.
*/
@@ -170,10 +170,10 @@ class ListSet[A] extends AbstractSet[A]
/** `-` can be used to remove a single element from a set.
*/
- override def -(e: A): ListSet[A] = if (e == elem) self else {
- val tail = self - e; new tail.Node(elem)
+ override def -(e: A): ListSet[A] = if (e == head) self else {
+ val tail = self - e; new tail.Node(head)
}
- override protected def next: ListSet[A] = self
+ override def tail: ListSet[A] = self
}
}
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 9f5f98ddf4..1bf1e20694 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -916,6 +916,7 @@ self =>
override def view = new StreamView[A, Stream[A]] {
protected lazy val underlying = self.repr
+ override def isEmpty = self.isEmpty
override def iterator = self.iterator
override def length = self.length
override def apply(idx: Int) = self.apply(idx)
diff --git a/src/library/scala/collection/mutable/IndexedSeqLike.scala b/src/library/scala/collection/mutable/IndexedSeqLike.scala
index 2ff7ac8272..5d4b4de7b2 100644
--- a/src/library/scala/collection/mutable/IndexedSeqLike.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqLike.scala
@@ -53,6 +53,7 @@ trait IndexedSeqLike[A, +Repr] extends scala.collection.IndexedSeqLike[A, Repr]
*/
override def view = new IndexedSeqView[A, Repr] {
protected lazy val underlying = self.repr
+ override def isEmpty = self.isEmpty
override def iterator = self.iterator
override def length = self.length
override def apply(idx: Int) = self.apply(idx)
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index 4feff34751..5d8610a7b7 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -848,6 +848,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
override def seq = self.seq.view
def splitter = self.splitter
def size = splitter.remaining
+ override def isEmpty = size == 0
}
override def toArray[U >: T: ClassTag]: Array[U] = {
diff --git a/src/library/scala/collection/parallel/ParSeqLike.scala b/src/library/scala/collection/parallel/ParSeqLike.scala
index be5ab03ba7..27e8eeb174 100644
--- a/src/library/scala/collection/parallel/ParSeqLike.scala
+++ b/src/library/scala/collection/parallel/ParSeqLike.scala
@@ -44,7 +44,7 @@ trait ParSeqLike[+T, +Repr <: ParSeq[T], +Sequential <: Seq[T] with SeqLike[T, S
extends scala.collection.GenSeqLike[T, Repr]
with ParIterableLike[T, Repr, Sequential] {
self =>
-
+
type SuperParIterator = IterableSplitter[T]
/** A more refined version of the iterator found in the `ParallelIterable` trait,
@@ -330,6 +330,7 @@ self =>
def apply(idx: Int) = self(idx)
override def seq = self.seq.view
def splitter = self.splitter
+ override def isEmpty = size == 0
}
/* tasks */
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/reflect/base/FlagSets.scala b/src/library/scala/reflect/base/FlagSets.scala
index 43de9970c0..96cdbe894c 100644
--- a/src/library/scala/reflect/base/FlagSets.scala
+++ b/src/library/scala/reflect/base/FlagSets.scala
@@ -13,11 +13,4 @@ trait FlagSets { self: Universe =>
/** The empty set of flags */
val NoFlags: FlagSet
-
- /** The base API all flag bearers support */
- trait HasFlagsBase {
- def flags: FlagSet
- def hasFlag(flags: FlagSet): Boolean
- }
}
-
diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala
index 7fa3c90e7d..70993fd77f 100644
--- a/src/library/scala/reflect/base/Trees.scala
+++ b/src/library/scala/reflect/base/Trees.scala
@@ -1359,7 +1359,9 @@ trait Trees { self: Universe =>
implicit val ModifiersTag: ClassTag[Modifiers]
/** ... */
- abstract class ModifiersBase extends HasFlagsBase {
+ abstract class ModifiersBase {
+ def flags: FlagSet // default: NoFlags
+ def hasFlag(flag: FlagSet): Boolean
def privateWithin: Name // default: EmptyTypeName
def annotations: List[Tree] // default: List()
def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers =
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/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 604e53e64c..0f2806214f 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -9,6 +9,7 @@ package scala.tools.partest
package nest
import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io }
+import scala.tools.nsc.io.{ File => SFile }
import scala.tools.nsc.interactive.RangePositions
import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
import scala.tools.nsc.util.{ ClassPath, FakePos }
@@ -94,7 +95,17 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
val logFile = basename(log.getName)
val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
- val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0)
+
+ // slurp local flags (e.g., "A_1.flags")
+ val fstFile = SFile(files(0))
+ def isInGroup(num: Int) = fstFile.stripExtension endsWith ("_" + num)
+ val inGroup = (1 to 9) flatMap (group => if (isInGroup(group)) List(group) else List())
+ val localFlagsList = if (inGroup.nonEmpty) {
+ val localArgString = (fstFile.parent / (fstFile.stripExtension + ".flags")) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
+ localArgString.split(' ').toList.filter(_.length > 0)
+ } else List()
+
+ val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0) ::: localFlagsList
val args = allOpts.toList
NestUI.verbose("scalac options: "+allOpts)
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index 6d105c9d20..36836e84a9 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -9,7 +9,6 @@ trait FlagSets { self: Universe =>
trait FlagOps extends Any {
def | (right: FlagSet): FlagSet
- def hasFlag(flags: FlagSet): Boolean
}
implicit def addFlagOps(left: FlagSet): FlagOps
@@ -18,84 +17,86 @@ trait FlagSets { self: Universe =>
type FlagValues >: Null <: FlagValuesApi
+ // Q: I have a pretty flag. Can I put it here?
+ // A: Only if there's a tree that cannot be built without it.
+ // If you want to put a flag here so that it can be tested against,
+ // introduce an `isXXX` method in one of the `api.Symbols` classes instead.
+
trait FlagValuesApi {
- /** Flag indicating that symbol or tree represents a trait */
+ /** Flag indicating that tree represents a trait */
val TRAIT: FlagSet
- /** Flag indicating that symbol or tree represents a module or its internal module class */
- val MODULE: FlagSet
+ /** Flag indicating that a tree is an interface (i.e. a trait which defines only abstract methods) */
+ val INTERFACE: FlagSet
- /** Flag indicating that symbol or tree represents a mutable variable */
+ /** Flag indicating that tree represents a mutable variable */
val MUTABLE: FlagSet
- /** Flag indicating that symbol or tree represents a package or its internal package class */
- val PACKAGE: FlagSet
-
- /** Flag indicating that symbol or tree represents a method */
- val METHOD: FlagSet
-
- /** Flag indicating that symbol or tree represents a macro definition. */
+ /** Flag indicating that tree represents a macro definition. */
val MACRO: FlagSet
- /** Flag indicating that symbol or tree represents an abstract type, method, or value */
+ /** Flag indicating that tree represents an abstract type, method, or value */
val DEFERRED: FlagSet
- /** Flag indicating that symbol or tree represents an abstract class */
+ /** Flag indicating that tree represents an abstract class */
val ABSTRACT: FlagSet
- /** Flag indicating that symbol or tree has `final` modifier set */
+ /** Flag indicating that tree has `final` modifier set */
val FINAL: FlagSet
- /** Flag indicating that symbol or tree has `sealed` modifier set */
+ /** Flag indicating that tree has `sealed` modifier set */
val SEALED: FlagSet
- /** Flag indicating that symbol or tree has `implicit` modifier set */
+ /** Flag indicating that tree has `implicit` modifier set */
val IMPLICIT: FlagSet
- /** Flag indicating that symbol or tree has `lazy` modifier set */
+ /** Flag indicating that tree has `lazy` modifier set */
val LAZY: FlagSet
- /** Flag indicating that symbol or tree has `override` modifier set */
+ /** Flag indicating that tree has `override` modifier set */
val OVERRIDE: FlagSet
- /** Flag indicating that symbol or tree has `private` modifier set */
+ /** Flag indicating that tree has `private` modifier set */
val PRIVATE: FlagSet
- /** Flag indicating that symbol or tree has `protected` modifier set */
+ /** Flag indicating that tree has `protected` modifier set */
val PROTECTED: FlagSet
- /** Flag indicating that symbol or tree has `case` modifier set */
+ /** Flag indicating that tree represents a member local to current class
+ * (i.e. private[this] or protected[this].
+ * This requires having either PRIVATE or PROTECTED set as well.
+ */
+ val LOCAL: FlagSet
+
+ /** Flag indicating that tree has `case` modifier set */
val CASE: FlagSet
- /** Flag indicating that symbol or tree has `abstract` and `override` modifiers set */
+ /** Flag indicating that tree has `abstract` and `override` modifiers set */
val ABSOVERRIDE: FlagSet
- /** Flag indicating that symbol or tree represents a by-name parameter */
+ /** Flag indicating that tree represents a by-name parameter */
val BYNAMEPARAM: FlagSet
- /** Flag indicating that symbol or tree represents a class or parameter.
+ /** Flag indicating that tree represents a class or parameter.
* Both type and value parameters carry the flag. */
val PARAM: FlagSet
- /** Flag indicating that symbol or tree represents a field of a class
- * that was generated from a parameter of that class */
- val PARAMACCESSOR: FlagSet
-
- /** Flag indicating that symbol or tree represents a field of a case class
- * that corresponds to a parameter in the first parameter list of the
- * primary constructor of that class */
- val CASEACCESSOR: FlagSet
-
- /** Flag indicating that symbol or tree represents a contravariant
+ /** Flag indicating that tree represents a covariant
* type parameter (marked with `+`). */
val COVARIANT: FlagSet
- /** Flag indicating that symbol or tree represents a contravariant
+ /** Flag indicating that tree represents a contravariant
* type parameter (marked with `-`). */
val CONTRAVARIANT: FlagSet
- /** Flag indicating that parameter has a default value */
+ /** Flag indicating that tree represents a parameter that has a default value */
val DEFAULTPARAM: FlagSet
+
+ /** Flag indicating that tree represents an early definition */
+ val PRESUPER: FlagSet
+
+ /** Flag indicating that tree represents a variable or a member initialized to the default value */
+ val DEFAULTINIT: FlagSet
}
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index 448382973a..fda76c7b95 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -13,7 +13,7 @@ trait Symbols extends base.Symbols { self: Universe =>
override type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi
/** The API of symbols */
- trait SymbolApi extends SymbolBase with HasFlagsBase { this: Symbol =>
+ trait SymbolApi extends SymbolBase { this: Symbol =>
/** The position of this symbol
*/
@@ -110,10 +110,10 @@ trait Symbols extends base.Symbols { self: Universe =>
*
* The java access levels translate as follows:
*
- * java private: hasFlag(PRIVATE) && (privateWithin == NoSymbol)
- * java package: !hasFlag(PRIVATE | PROTECTED) && (privateWithin == enclosingPackage)
- * java protected: hasFlag(PROTECTED) && (privateWithin == enclosingPackage)
- * java public: !hasFlag(PRIVATE | PROTECTED) && (privateWithin == NoSymbol)
+ * java private: isPrivate && (privateWithin == NoSymbol)
+ * java package: !isPrivate && !isProtected && (privateWithin == enclosingPackage)
+ * java protected: isProtected && (privateWithin == enclosingPackage)
+ * java public: !isPrivate && !isProtected && (privateWithin == NoSymbol)
*/
def privateWithin: Symbol
diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala
index 6e77741355..b03d01c944 100644
--- a/src/reflect/scala/reflect/internal/FlagSets.scala
+++ b/src/reflect/scala/reflect/internal/FlagSets.scala
@@ -13,7 +13,6 @@ trait FlagSets extends api.FlagSets { self: SymbolTable =>
private class FlagOpsImpl(left: Long) extends FlagOps {
def | (right: Long): Long = left | right
- def hasFlag(right: Long): Boolean = (left & right) != 0
}
val NoFlags: FlagSet = 0L
@@ -22,10 +21,8 @@ trait FlagSets extends api.FlagSets { self: SymbolTable =>
object Flag extends FlagValues {
val TRAIT : FlagSet = Flags.TRAIT
- val MODULE : FlagSet = Flags.MODULE
+ val INTERFACE : FlagSet = Flags.INTERFACE
val MUTABLE : FlagSet = Flags.MUTABLE
- val PACKAGE : FlagSet = Flags.PACKAGE
- val METHOD : FlagSet = Flags.METHOD
val MACRO : FlagSet = Flags.MACRO
val DEFERRED : FlagSet = Flags.DEFERRED
val ABSTRACT : FlagSet = Flags.ABSTRACT
@@ -36,15 +33,15 @@ trait FlagSets extends api.FlagSets { self: SymbolTable =>
val OVERRIDE : FlagSet = Flags.OVERRIDE
val PRIVATE : FlagSet = Flags.PRIVATE
val PROTECTED : FlagSet = Flags.PROTECTED
+ val LOCAL : FlagSet = Flags.LOCAL
val CASE : FlagSet = Flags.CASE
val ABSOVERRIDE : FlagSet = Flags.ABSOVERRIDE
val BYNAMEPARAM : FlagSet = Flags.BYNAMEPARAM
val PARAM : FlagSet = Flags.PARAM
- val PARAMACCESSOR : FlagSet = Flags.PARAMACCESSOR
- val CASEACCESSOR : FlagSet = Flags.CASEACCESSOR
val COVARIANT : FlagSet = Flags.COVARIANT
val CONTRAVARIANT : FlagSet = Flags.CONTRAVARIANT
val DEFAULTPARAM : FlagSet = Flags.DEFAULTPARAM
- val INTERFACE : FlagSet = Flags.INTERFACE
+ val PRESUPER : FlagSet = Flags.PRESUPER
+ val DEFAULTINIT : FlagSet = Flags.DEFAULTINIT
}
}
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 2e2e63a4b4..bde7f7ac51 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -247,7 +247,7 @@ trait Mirrors extends api.Mirrors {
// is very beneficial for a handful of bootstrap symbols to have
// first class identities
sealed trait WellKnownSymbol extends Symbol {
- this initFlags TopLevelCreationFlags
+ this initFlags (TopLevelCreationFlags | STATIC)
}
// Features common to RootClass and RootPackage, the roots of all
// type and term symbols respectively.
@@ -276,7 +276,6 @@ trait Mirrors extends api.Mirrors {
override def isRoot = true
override def isEffectiveRoot = true
- override def isStatic = true
override def isNestedClass = false
}
// The empty package, which holds all top level types without given packages.
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index e3e2063b05..0c86e4fba0 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -670,7 +670,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
if (flags == NoFlags) nme.NoFlags.toString
else {
val s_flags = new collection.mutable.ListBuffer[String]
- for (i <- 0 to 63 if (flags hasFlag (1L << i)))
+ def hasFlag(left: Long, right: Long): Boolean = (left & right) != 0
+ for (i <- 0 to 63 if hasFlag(flags, 1L << i))
s_flags += flagToString(1L << i).replace("<", "").replace(">", "").toUpperCase
s_flags mkString " | "
}
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index c21391e305..f761b856cb 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -43,7 +43,9 @@ abstract class SymbolTable extends macros.Universe
lazy val treeBuild = gen
def log(msg: => AnyRef): Unit
- def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
+ def warning(msg: String): Unit = Console.err.println(msg)
+ def globalError(msg: String): Unit = abort(msg)
+ def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
@deprecated("Give us a reason", "2.10.0")
def abort(): Nothing = abort("unknown error")
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index d811815bdd..e8a011d4f9 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -80,8 +80,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def toType: Type = tpe
def toTypeIn(site: Type): Type = site.memberType(this)
def toTypeConstructor: Type = typeConstructor
- def setFlags(flags: FlagSet): this.type = setInternalFlags(flags)
- def setInternalFlags(flag: Long): this.type = { setFlag(flag); this }
def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this }
def getAnnotations: List[AnnotationInfo] = { initialize; annotations }
def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
@@ -392,6 +390,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case x: TermName => newErrorValue(x)
}
+ /** Creates a placeholder symbol for when a name is encountered during
+ * unpickling for which there is no corresponding classfile. This defers
+ * failure to the point when that name is used for something, which is
+ * often to the point of never.
+ */
+ def newStubSymbol(name: Name): Symbol = name match {
+ case n: TypeName => new StubClassSymbol(this, n)
+ case _ => new StubTermSymbol(this, name.toTermName)
+ }
+
@deprecated("Use the other signature", "2.10.0")
def newClass(pos: Position, name: TypeName): Symbol = newClass(name, pos)
@deprecated("Use the other signature", "2.10.0")
@@ -884,7 +892,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ owner attribute --------------------------------------------------------------
def owner: Symbol = {
- Statistics.incCounter(ownerCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(ownerCount)
rawowner
}
@@ -2285,7 +2293,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private[this] var _rawname: TermName = initName
def rawname = _rawname
def name = {
- Statistics.incCounter(nameCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(nameCount)
_rawname
}
def name_=(name: Name) {
@@ -2427,12 +2435,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
flatOwnerInfo.decl(name.toTypeName).suchThat(sym => sym.isClass && (sym isCoDefinedWith this))
override def owner = {
- Statistics.incCounter(ownerCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(ownerCount)
if (!isMethod && needsFlatClasses) rawowner.owner
else rawowner
}
override def name: TermName = {
- Statistics.incCounter(nameCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(nameCount)
if (!isMethod && needsFlatClasses) {
if (flatname eq null)
flatname = nme.flattenedName(rawowner.name, rawname)
@@ -2526,7 +2534,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def rawname = _rawname
def name = {
- Statistics.incCounter(nameCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(nameCount)
_rawname
}
final def asNameType(n: Name) = n.toTypeName
@@ -2655,7 +2663,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* info for T in Test1 should be >: Nothing <: Test3[_]
*/
- Statistics.incCounter(typeSymbolCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(typeSymbolCount)
}
implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol])
@@ -2834,7 +2842,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
override def owner: Symbol = {
- Statistics.incCounter(ownerCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(ownerCount)
if (needsFlatClasses) rawowner.owner else rawowner
}
@@ -2878,7 +2886,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def children = childSet
override def addChild(sym: Symbol) { childSet = childSet + sym }
- Statistics.incCounter(classSymbolCount)
+ if (Statistics.hotEnabled) Statistics.incCounter(classSymbolCount)
}
implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol])
@@ -2972,6 +2980,37 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| info.parents.exists(_.typeSymbol hasTransOwner sym)
)
}
+ trait StubSymbol extends Symbol {
+ protected def stubWarning = {
+ val from = if (associatedFile == null) "" else s" - referenced from ${associatedFile.canonicalPath}"
+ s"$kindString $nameString$locationString$from (a classfile may be missing)"
+ }
+ private def fail[T](alt: T): T = {
+ // Avoid issuing lots of redundant errors
+ if (!hasFlag(IS_ERROR)) {
+ globalError(s"bad symbolic reference to " + stubWarning)
+ if (settings.debug.value)
+ (new Throwable).printStackTrace
+
+ this setFlag IS_ERROR
+ }
+ alt
+ }
+ // This one doesn't call fail because SpecializeTypes winds up causing
+ // isMonomorphicType to be called, which calls this, which would fail us
+ // in all the scenarios we're trying to keep from failing.
+ override def originalInfo = NoType
+ override def associatedFile = owner.associatedFile
+ override def info = fail(NoType)
+ override def rawInfo = fail(NoType)
+ override def companionSymbol = fail(NoSymbol)
+
+ locally {
+ debugwarn("creating stub symbol for " + stubWarning)
+ }
+ }
+ class StubClassSymbol(owner0: Symbol, name0: TypeName) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol
+ class StubTermSymbol(owner0: Symbol, name0: TermName) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol
trait FreeSymbol extends Symbol {
def origin: String
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index e92cfba1c5..51dc2567f8 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -236,7 +236,7 @@ abstract class TreeInfo {
case _ =>
tree
}
-
+
/** Is tree a self or super constructor call? */
def isSelfOrSuperConstrCall(tree: Tree) = {
// stripNamedApply for SI-3584: adaptToImplicitMethod in Typers creates a special context
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 220869e4d2..94d51b7455 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -160,7 +160,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
new ThisSubstituter(clazz, to) transform this
def hasSymbolWhich(f: Symbol => Boolean) =
- hasSymbol && symbol != null && f(symbol)
+ (symbol ne null) && (symbol ne NoSymbol) && f(symbol)
def isErroneous = (tpe ne null) && tpe.isErroneous
def isTyped = (tpe ne null) && !tpe.isErroneous
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 7df34a14e2..5709ddf128 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/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index cbe9c1d729..3d95cb9c1d 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -230,9 +230,11 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
fromName(nme.expandedName(name.toTermName, owner)) orElse {
// (3) Try as a nested object symbol.
nestedObjectSymbol orElse {
- // (4) Otherwise, fail.
- //System.err.println("missing "+name+" in "+owner+"/"+owner.id+" "+owner.info.decls)
- adjust(errorMissingRequirement(name, owner))
+ // (4) Call the mirror's "missing" hook.
+ adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse {
+ // (5) Create a stub symbol to defer hard failure a little longer.
+ owner.newStubSymbol(name)
+ }
}
}
}
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 4074dd9e93..8d9711dedd 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -22,17 +22,15 @@ abstract class Universe extends scala.reflect.api.Universe {
/** The extended API of symbols that's supported in macro context universes
*/
- trait SymbolContextApi extends SymbolApi with AttachableApi { this: Symbol =>
+ trait SymbolContextApi extends SymbolApi with AttachableApi { self: Symbol =>
- def setFlags(flags: FlagSet): this.type
+ def setTypeSignature(tpe: Type): Symbol
- def setTypeSignature(tpe: Type): this.type
+ def setAnnotations(annots: AnnotationInfo*): Symbol
- def setAnnotations(annots: AnnotationInfo*): this.type
+ def setName(name: Name): Symbol
- def setName(name: Name): this.type
-
- def setPrivateWithin(sym: Symbol): this.type
+ def setPrivateWithin(sym: Symbol): Symbol
}
// Tree extensions ---------------------------------------------------------------
@@ -41,20 +39,20 @@ abstract class Universe extends scala.reflect.api.Universe {
/** The extended API of trees that's supported in macro context universes
*/
- trait TreeContextApi extends TreeApi with AttachableApi { this: Tree =>
+ trait TreeContextApi extends TreeApi with AttachableApi { self: Tree =>
/** ... */
def pos_=(pos: Position): Unit
/** ... */
- def setPos(newpos: Position): this.type
+ def setPos(newpos: Position): Tree
/** ... */
def tpe_=(t: Type): Unit
/** Set tpe to give `tp` and return this.
*/
- def setType(tp: Type): this.type
+ def setType(tp: Type): Tree
/** Like `setType`, but if this is a previously empty TypeTree that
* fact is remembered so that resetAllAttrs will snap back.
@@ -73,13 +71,13 @@ abstract class Universe extends scala.reflect.api.Universe {
* and therefore should be abandoned if the current line of type
* inquiry doesn't work out.
*/
- def defineType(tp: Type): this.type
+ def defineType(tp: Type): Tree
/** ... */
def symbol_=(sym: Symbol): Unit
/** ... */
- def setSymbol(sym: Symbol): this.type
+ def setSymbol(sym: Symbol): Tree
}
override type SymTree >: Null <: Tree with SymTreeContextApi
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/catch-all.check b/test/files/neg/catch-all.check
index d59e826f03..aaf51480c3 100644
--- a/test/files/neg/catch-all.check
+++ b/test/files/neg/catch-all.check
@@ -1,10 +1,10 @@
-catch-all.scala:2: warning: This catches all Throwables. If this is really intended, use `case _: Throwable` to clear this warning.
+catch-all.scala:2: warning: This catches all Throwables. If this is really intended, use `case _ : Throwable` to clear this warning.
try { "warn" } catch { case _ => }
^
-catch-all.scala:4: warning: This catches all Throwables. If this is really intended, use `case x: Throwable` to clear this warning.
+catch-all.scala:4: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
try { "warn" } catch { case x => }
^
-catch-all.scala:6: warning: This catches all Throwables. If this is really intended, use `case x: Throwable` to clear this warning.
+catch-all.scala:6: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
try { "warn" } catch { case _: RuntimeException => ; case x => }
^
error: No warnings can be incurred under -Xfatal-warnings.
diff --git a/test/files/neg/macro-invalidsig-context-bounds.check b/test/files/neg/macro-invalidsig-context-bounds.check
index 894eabc442..6c9482e537 100644
--- a/test/files/neg/macro-invalidsig-context-bounds.check
+++ b/test/files/neg/macro-invalidsig-context-bounds.check
@@ -1,4 +1,4 @@
-Impls_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences
- def foo[U: c.AbsTypeTag: Numeric](c: Ctx) = {
- ^
-one error found
+Impls_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences
+ def foo[U: c.AbsTypeTag: Numeric](c: Ctx) = {
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-implicit-params.check b/test/files/neg/macro-invalidsig-implicit-params.check
index 029b8a4634..98b3167b7a 100644
--- a/test/files/neg/macro-invalidsig-implicit-params.check
+++ b/test/files/neg/macro-invalidsig-implicit-params.check
@@ -1,4 +1,4 @@
-Impls_Macros_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences
- def foo_targs[T, U: c.AbsTypeTag](c: Ctx)(implicit x: c.Expr[Int]) = {
- ^
-one error found
+Impls_Macros_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences
+ def foo_targs[T, U: c.AbsTypeTag](c: Ctx)(implicit x: c.Expr[Int]) = {
+ ^
+one error found
diff --git a/test/files/neg/newpat_unreachable.check b/test/files/neg/newpat_unreachable.check
new file mode 100644
index 0000000000..a928e3853a
--- /dev/null
+++ b/test/files/neg/newpat_unreachable.check
@@ -0,0 +1,29 @@
+newpat_unreachable.scala:6: warning: patterns after a variable pattern cannot match (SLS 8.1.1)
+If you intended to match against parameter b of method contrivedExample, you must use backticks, like: case `b` =>
+ case b => println("matched b")
+ ^
+newpat_unreachable.scala:7: warning: unreachable code due to variable pattern 'b' on line 6
+If you intended to match against parameter c of method contrivedExample, you must use backticks, like: case `c` =>
+ case c => println("matched c")
+ ^
+newpat_unreachable.scala:8: warning: unreachable code due to variable pattern 'b' on line 6
+If you intended to match against value d in class A, you must use backticks, like: case `d` =>
+ case d => println("matched d")
+ ^
+newpat_unreachable.scala:9: warning: unreachable code due to variable pattern 'b' on line 6
+ case _ => println("matched neither")
+ ^
+newpat_unreachable.scala:22: warning: patterns after a variable pattern cannot match (SLS 8.1.1)
+If you intended to match against parameter b of method g, you must use backticks, like: case `b` =>
+ case b => 1
+ ^
+newpat_unreachable.scala:23: warning: unreachable code due to variable pattern 'b' on line 22
+If you intended to match against parameter c of method h, you must use backticks, like: case `c` =>
+ case c => 2
+ ^
+newpat_unreachable.scala:24: warning: unreachable code due to variable pattern 'b' on line 22
+ case _ => 3
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+7 warnings found
+one error found
diff --git a/test/files/neg/newpat_unreachable.flags b/test/files/neg/newpat_unreachable.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/newpat_unreachable.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/newpat_unreachable.scala b/test/files/neg/newpat_unreachable.scala
new file mode 100644
index 0000000000..c9cc85cec6
--- /dev/null
+++ b/test/files/neg/newpat_unreachable.scala
@@ -0,0 +1,29 @@
+object Test {
+ class A {
+ val d = 55
+
+ def contrivedExample[A, B, C](a: A, b: B, c: C): Unit = a match {
+ case b => println("matched b")
+ case c => println("matched c")
+ case d => println("matched d")
+ case _ => println("matched neither")
+ }
+
+ def correctExample[A, B, C](a: A, b: B, c: C): Unit = a match {
+ case `b` => println("matched b")
+ case `c` => println("matched c")
+ case `d` => println("matched d")
+ case _ => println("matched neither")
+ }
+
+ def f[A](a: A) = {
+ def g[B](b: B) = {
+ def h[C](c: C) = a match {
+ case b => 1
+ case c => 2
+ case _ => 3
+ }
+ }
+ }
+ }
+}
diff --git a/test/files/neg/nonlocal-warning.check b/test/files/neg/nonlocal-warning.check
index efb3efaaa2..5202df655a 100644
--- a/test/files/neg/nonlocal-warning.check
+++ b/test/files/neg/nonlocal-warning.check
@@ -1,4 +1,4 @@
-nonlocal-warning.scala:4: warning: This catches all Throwables. If this is really intended, use `case x: Throwable` to clear this warning.
+nonlocal-warning.scala:4: warning: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning.
catch { case x => 11 }
^
nonlocal-warning.scala:2: warning: catch block may intercept non-local return from method foo
diff --git a/test/files/neg/pat_unreachable.check b/test/files/neg/pat_unreachable.check
index 4e1463d591..c5706b7fad 100644
--- a/test/files/neg/pat_unreachable.check
+++ b/test/files/neg/pat_unreachable.check
@@ -4,4 +4,10 @@ pat_unreachable.scala:5: error: unreachable code
pat_unreachable.scala:9: error: unreachable code
case Seq(x, y) => List(x, y)
^
-two errors found
+pat_unreachable.scala:23: error: unreachable code
+ case c => println("matched c")
+ ^
+pat_unreachable.scala:24: error: unreachable code
+ case _ => println("matched neither")
+ ^
+four errors found
diff --git a/test/files/neg/pat_unreachable.scala b/test/files/neg/pat_unreachable.scala
index fc0fd41920..1f402e5212 100644
--- a/test/files/neg/pat_unreachable.scala
+++ b/test/files/neg/pat_unreachable.scala
@@ -8,7 +8,7 @@ object Test extends App {
case Seq(x, y, _*) => x::y::Nil
case Seq(x, y) => List(x, y)
}
-
+
def not_unreachable(xs:Seq[Char]) = xs match {
case Seq(x, y, _*) => x::y::Nil
case Seq(x) => List(x)
@@ -17,4 +17,10 @@ object Test extends App {
case Seq(x, y) => x::y::Nil
case Seq(x, y, z, _*) => List(x,y)
}
+
+ def contrivedExample[A, B, C](a: A, b: B, c: C): Unit = a match {
+ case b => println("matched b")
+ case c => println("matched c")
+ case _ => println("matched neither")
+ }
}
diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check
index a6a1a1fad4..0f2fe6f2d1 100644
--- a/test/files/neg/t4425.check
+++ b/test/files/neg/t4425.check
@@ -1,5 +1,4 @@
-t4425.scala:3: error: error during expansion of this match (this is a scalac bug).
-The underlying error was: value _1 is not a member of object Foo.X
+t4425.scala:3: error: isInstanceOf cannot test if value types are references.
42 match { case _ X _ => () }
- ^
+ ^
one error found
diff --git a/test/files/neg/t4425.flags b/test/files/neg/t4425.flags
new file mode 100644
index 0000000000..1182725e86
--- /dev/null
+++ b/test/files/neg/t4425.flags
@@ -0,0 +1 @@
+-optimize \ No newline at end of file
diff --git a/test/files/neg/t5148.check b/test/files/neg/t5148.check
index 96eb1fd364..6edfdf2b1e 100644
--- a/test/files/neg/t5148.check
+++ b/test/files/neg/t5148.check
@@ -1,2 +1,3 @@
-error: bad reference while unpickling Imports.class: term memberHandlers not found in scala.tools.nsc.interpreter.IMain
-one error found
+error: bad symbolic reference to value global in class IMain - referenced from t5148.scala (a classfile may be missing)
+error: bad symbolic reference to value memberHandlers in class IMain - referenced from t5148.scala (a classfile may be missing)
+two errors found
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/neg/t6048.check b/test/files/neg/t6048.check
index 319e3fa620..5e11d24fde 100644
--- a/test/files/neg/t6048.check
+++ b/test/files/neg/t6048.check
@@ -4,9 +4,12 @@ t6048.scala:3: warning: unreachable code
t6048.scala:8: warning: unreachable code
case _ if false => x // unreachable
^
-t6048.scala:14: warning: unreachable code
+t6048.scala:13: warning: patterns after a variable pattern cannot match (SLS 8.1.1)
+ case _ => x
+ ^
+t6048.scala:14: warning: unreachable code due to variable pattern on line 13
case 5 if true => x // unreachable
^
error: No warnings can be incurred under -Xfatal-warnings.
-three warnings found
+four warnings found
one error found
diff --git a/test/files/neg/t6214.check b/test/files/neg/t6214.check
new file mode 100644
index 0000000000..6349a3e71c
--- /dev/null
+++ b/test/files/neg/t6214.check
@@ -0,0 +1,4 @@
+t6214.scala:5: error: missing parameter type
+ m { s => case class Foo() }
+ ^
+one error found
diff --git a/test/files/neg/t6214.scala b/test/files/neg/t6214.scala
new file mode 100644
index 0000000000..734acda35e
--- /dev/null
+++ b/test/files/neg/t6214.scala
@@ -0,0 +1,7 @@
+object Test {
+ def m(f: String => Unit) = 0
+ def m(f: Int => Unit) = 0
+ def foo {
+ m { s => case class Foo() }
+ }
+}
diff --git a/test/files/pos/inline-access-levels.flags b/test/files/pos/inline-access-levels.flags
new file mode 100644
index 0000000000..882f40f050
--- /dev/null
+++ b/test/files/pos/inline-access-levels.flags
@@ -0,0 +1 @@
+-optimise -Xfatal-warnings -Yinline-warnings
diff --git a/test/files/pos/inline-access-levels/A_1.scala b/test/files/pos/inline-access-levels/A_1.scala
new file mode 100644
index 0000000000..479fe0fc71
--- /dev/null
+++ b/test/files/pos/inline-access-levels/A_1.scala
@@ -0,0 +1,10 @@
+package test
+
+object A {
+
+ private var x: Int = 0
+
+ @inline def actOnX(f: Int => Int) = {
+ x = f(x)
+ }
+}
diff --git a/test/files/pos/inline-access-levels/Test_2.scala b/test/files/pos/inline-access-levels/Test_2.scala
new file mode 100644
index 0000000000..12c9eb540f
--- /dev/null
+++ b/test/files/pos/inline-access-levels/Test_2.scala
@@ -0,0 +1,11 @@
+package test
+
+object Test {
+
+ def main(args: Array[String]) {
+
+ A.actOnX(_ + 1)
+
+ }
+
+}
diff --git a/test/files/pos/t5756.scala b/test/files/pos/t5756.scala
new file mode 100644
index 0000000000..45960fa8bd
--- /dev/null
+++ b/test/files/pos/t5756.scala
@@ -0,0 +1,6 @@
+import scala.reflect.runtime.universe._
+
+object Test extends App {
+ def tagme[T: TypeTag](x: T) = typeTag[T]
+ val foo = tagme{object Bar; Bar}
+} \ No newline at end of file
diff --git a/test/files/pos/t6022b.scala b/test/files/pos/t6022b.scala
new file mode 100644
index 0000000000..6ceb928162
--- /dev/null
+++ b/test/files/pos/t6022b.scala
@@ -0,0 +1,20 @@
+trait A
+trait B
+trait C
+trait AB extends B with A
+
+// two types are mutually exclusive if there is no equality symbol whose constant implies both
+object Test extends App {
+ def foo(x: Any) = x match {
+ case _ : C => println("C")
+ case _ : AB => println("AB")
+ case _ : (A with B) => println("AB'")
+ case _ : B => println("B")
+ case _ : A => println("A")
+ }
+
+ foo(new A {})
+ foo(new B {})
+ foo(new AB{})
+ foo(new C {})
+}
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/t6184.scala b/test/files/pos/t6184.scala
new file mode 100644
index 0000000000..83a1306aca
--- /dev/null
+++ b/test/files/pos/t6184.scala
@@ -0,0 +1,7 @@
+trait Foo[TroubleSome] {
+ type T <: Foo[TroubleSome]
+
+ this match {
+ case e: Foo[_]#T => ???
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t6201.scala b/test/files/pos/t6201.scala
new file mode 100644
index 0000000000..366c1f26eb
--- /dev/null
+++ b/test/files/pos/t6201.scala
@@ -0,0 +1,13 @@
+class Test {
+ class Foo1 {
+ def must(x: scala.xml.Elem) = ()
+ }
+
+ class Foo2 {
+ def must(x: Int) = ()
+ }
+ implicit def toFoo1(s: scala.xml.Elem) = new Foo1()
+ implicit def toFoo2(s: scala.xml.Elem) = new Foo2()
+
+ def is: Unit = { (<a>{"a"}</a>).must(<a>{"b"}</a>) }
+} \ No newline at end of file
diff --git a/test/files/pos/t6204-a.scala b/test/files/pos/t6204-a.scala
new file mode 100644
index 0000000000..bd8d5c437e
--- /dev/null
+++ b/test/files/pos/t6204-a.scala
@@ -0,0 +1,9 @@
+import scala.reflect.runtime.universe._
+
+object Bish {
+ def m {
+ object Bash {
+ typeOf[Option[_]]
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t6204-b.scala b/test/files/pos/t6204-b.scala
new file mode 100644
index 0000000000..86094d1a19
--- /dev/null
+++ b/test/files/pos/t6204-b.scala
@@ -0,0 +1,10 @@
+import scala.reflect.runtime.universe._
+
+object Bosh {
+ def Besh {
+ new {
+ val t = typeOf[Option[_]]
+ val x = t
+ }
+ }
+} \ 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/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index 25e1b2a4dd..a4c9f215e8 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -13,6 +13,10 @@
< 92 JUMP 2
<
< 2:
+383c382
+< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
+---
+> locals: value args, variable result, value ex6, value x4, value x5, value x
385c384
< blocks: [1,2,3,4,5,8,11,13,14,16]
---
@@ -34,11 +38,21 @@
< 101 JUMP 4
<
< 4:
-515c520
+438,441d442
+< 106 LOAD_LOCAL(value x5)
+< 106 CALL_METHOD MyException.message (dynamic)
+< 106 STORE_LOCAL(value message)
+< 106 SCOPE_ENTER value message
+443c444,445
+< 106 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+515c517
< blocks: [1,2,3,4,6,7,8,9,10]
---
> blocks: [1,2,3,4,6,7,8,9,10,11,12,13]
-544c549,554
+544c546,551
< 306 THROW(MyException)
---
> ? JUMP 11
@@ -47,7 +61,7 @@
> ? LOAD_LOCAL(variable monitor4)
> 305 MONITOR_EXIT
> ? JUMP 12
-550c560,566
+550c557,563
< ? THROW(Throwable)
---
> ? JUMP 12
@@ -57,7 +71,7 @@
> 304 MONITOR_EXIT
> ? STORE_LOCAL(value t)
> ? JUMP 13
-556c572,585
+556c569,582
< ? THROW(Throwable)
---
> ? STORE_LOCAL(value t)
@@ -74,19 +88,19 @@
> 310 CALL_PRIMITIVE(EndConcat)
> 310 CALL_METHOD scala.Predef.println (dynamic)
> 310 JUMP 2
-580c609
+580c606
< catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6
---
> catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6
-583c612
+583c609
< catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3
---
> catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3
-615c644
+615c641
< blocks: [1,2,3,4,5,6,7,9,10]
---
> blocks: [1,2,3,4,5,6,7,9,10,11,12]
-639c668,674
+639c665,671
< 78 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -96,7 +110,7 @@
> 81 LOAD_LOCAL(value e)
> ? STORE_LOCAL(variable exc1)
> ? JUMP 12
-668c703,717
+668c700,714
< 81 THROW(Exception)
---
> ? STORE_LOCAL(variable exc1)
@@ -114,15 +128,19 @@
> 84 STORE_LOCAL(variable result)
> 84 LOAD_LOCAL(variable exc1)
> 84 THROW(Throwable)
-690c739
+690c736
< catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3
-716c765
+714c760
+< locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
+---
+> locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
+716c762
< blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31]
---
> blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34]
-740c789,796
+740c786,793
< 172 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -133,12 +151,27 @@
> 170 STORE_LOCAL(value x4)
> 170 SCOPE_ENTER value x4
> 170 JUMP 18
-798c854,855
+787,790d839
+< 175 LOAD_LOCAL(value x5)
+< 175 CALL_METHOD MyException.message (dynamic)
+< 175 STORE_LOCAL(value message)
+< 175 SCOPE_ENTER value message
+792c841,842
+< 176 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+796c846,847
+< 177 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+798c849,850
< 177 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
> ? JUMP 33
-802c859,866
+802c854,861
< 170 THROW(Throwable)
---
> ? STORE_LOCAL(value ex6)
@@ -149,17 +182,32 @@
> 169 STORE_LOCAL(value x4)
> 169 SCOPE_ENTER value x4
> 169 JUMP 5
-837c901,902
+826,829d884
+< 180 LOAD_LOCAL(value x5)
+< 180 CALL_METHOD MyException.message (dynamic)
+< 180 STORE_LOCAL(value message)
+< 180 SCOPE_ENTER value message
+831c886,887
+< 181 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+835c891,892
+< 182 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+837c894,895
< 182 THROW(MyException)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-841c906,907
+841c899,900
< 169 THROW(Throwable)
---
> ? STORE_LOCAL(variable exc2)
> ? JUMP 34
-842a909,921
+842a902,914
> 34:
> 184 LOAD_MODULE object Predef
> 184 CONSTANT("finally")
@@ -173,19 +221,23 @@
> 185 LOAD_LOCAL(variable exc2)
> 185 THROW(Throwable)
>
-863c942
+863c935
< catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4
---
> catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4
-866c945
+866c938
< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3
-892c971
+890c962
+< locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
+---
+> locals: value args, variable result, value e, value ex6, value x4, value x5, value x
+892c964
< blocks: [1,2,3,6,7,8,11,14,16,17,19]
---
> blocks: [1,2,3,6,7,8,11,14,16,17,19,20]
-916c995,1002
+916c988,995
< 124 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -196,15 +248,29 @@
> 122 STORE_LOCAL(value x4)
> 122 SCOPE_ENTER value x4
> 122 JUMP 7
-979c1065
+945,948d1023
+< 127 LOAD_LOCAL(value x5)
+< 127 CALL_METHOD MyException.message (dynamic)
+< 127 STORE_LOCAL(value message)
+< 127 SCOPE_ENTER value message
+950c1025,1026
+< 127 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+979c1055
< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3
---
> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19, 20) starting at: 3
-1005c1091
+1003c1079
+< locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
+---
+> locals: value args, variable result, value ex6, value x4, value x5, value x, value e
+1005c1081
< blocks: [1,2,3,4,5,8,11,15,16,17,19]
---
> blocks: [1,2,3,5,8,11,15,16,17,19,20]
-1029c1115,1124
+1029c1105,1114
< 148 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -217,15 +283,25 @@
> 154 LOAD_LOCAL(value x4)
> 154 IS_INSTANCE REF(class MyException)
> 154 CZJUMP (BOOL)NE ? 5 : 11
-1050,1052d1144
+1050,1052d1134
< 145 JUMP 4
<
< 4:
-1288c1380
+1066,1069d1147
+< 154 LOAD_LOCAL(value x5)
+< 154 CALL_METHOD MyException.message (dynamic)
+< 154 STORE_LOCAL(value message)
+< 154 SCOPE_ENTER value message
+1071c1149,1150
+< 154 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+1288c1367
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1312c1404,1411
+1312c1391,1398
< 38 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -236,16 +312,20 @@
> 42 CONSTANT("IllegalArgumentException")
> 42 CALL_METHOD scala.Predef.println (dynamic)
> 42 JUMP 2
-1361c1460
+1359c1445
+< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
+---
+> locals: value args, variable result, value ex6, value x4, value x5, value x
+1361c1447
< blocks: [1,2,3,4,5,8,11,13,14,16,17,19]
---
> blocks: [1,2,3,5,8,11,13,14,16,17,19,20]
-1385c1484,1485
+1385c1471,1472
< 203 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
> ? JUMP 20
-1405c1505,1514
+1405c1492,1501
< 209 THROW(MyException)
---
> ? STORE_LOCAL(value ex6)
@@ -258,15 +338,25 @@
> 212 LOAD_LOCAL(value x4)
> 212 IS_INSTANCE REF(class MyException)
> 212 CZJUMP (BOOL)NE ? 5 : 11
-1418,1420d1526
+1418,1420d1513
< 200 JUMP 4
<
< 4:
-1483c1589
+1434,1437d1526
+< 212 LOAD_LOCAL(value x5)
+< 212 CALL_METHOD MyException.message (dynamic)
+< 212 STORE_LOCAL(value message)
+< 212 SCOPE_ENTER value message
+1439c1528,1529
+< 213 LOAD_LOCAL(value message)
+---
+> ? LOAD_LOCAL(value x5)
+> ? CALL_METHOD MyException.message (dynamic)
+1483c1573
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1507c1613,1620
+1507c1597,1604
< 58 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -277,11 +367,11 @@
> 62 CONSTANT("RuntimeException")
> 62 CALL_METHOD scala.Predef.println (dynamic)
> 62 JUMP 2
-1556c1669
+1556c1653
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1576c1689,1694
+1576c1673,1678
< 229 THROW(MyException)
---
> ? JUMP 5
@@ -290,19 +380,19 @@
> ? LOAD_LOCAL(variable monitor1)
> 228 MONITOR_EXIT
> 228 THROW(Throwable)
-1582c1700
+1582c1684
< ? THROW(Throwable)
---
> 228 THROW(Throwable)
-1610c1728
+1610c1712
< locals: value args, variable result, variable monitor2, variable monitorResult1
---
> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1612c1730
+1612c1714
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1635c1753,1761
+1635c1737,1745
< 245 THROW(MyException)
---
> ? STORE_LOCAL(value exception$1)
@@ -314,7 +404,7 @@
> ? LOAD_LOCAL(variable monitor2)
> 244 MONITOR_EXIT
> 244 THROW(Throwable)
-1641c1767
+1641c1751
< ? THROW(Throwable)
---
> 244 THROW(Throwable)
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
diff --git a/test/files/run/t6197.check b/test/files/run/t6197.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t6197.check
diff --git a/test/files/run/t6197.scala b/test/files/run/t6197.scala
new file mode 100644
index 0000000000..5ab4b002d7
--- /dev/null
+++ b/test/files/run/t6197.scala
@@ -0,0 +1,21 @@
+import scala.collection.immutable._
+
+object Test extends App {
+
+ // test that a HashTrieSet with one leaf element is not created!
+ val x = HashSet.empty + 1 + 2
+ if(x.getClass.getSimpleName != "HashTrieSet")
+ println("A hash set containing two non-colliding values should be a HashTrieSet")
+
+ val y = x - 1
+ if(y.getClass.getSimpleName != "HashSet1")
+ println("A hash set containing one element should always use HashSet1")
+
+ // it is pretty hard to test that the case where a HashTrieSet has one element which
+ // is itself of type HashTrieS t. That is because the improve hash function makes it very difficult
+ // to find keys that will have hashes that are close together.
+ //
+ // However, it is also not necessary. Removing the ability of a HashTrieSet to have
+ // one child of type HashTrieSet completely breaks the HashSet, so that many other
+ // tests fail
+}
diff --git a/test/files/run/t6198.check b/test/files/run/t6198.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t6198.check
diff --git a/test/files/run/t6198.scala b/test/files/run/t6198.scala
new file mode 100644
index 0000000000..5aa8f1c1cf
--- /dev/null
+++ b/test/files/run/t6198.scala
@@ -0,0 +1,24 @@
+import scala.collection.immutable._
+
+object Test extends App {
+ // test that ListSet.tail does not use a builder
+ // we can't test for O(1) behavior, so the best we can do is to
+ // check that ls.tail always returns the same instance
+ val ls = ListSet.empty[Int] + 1 + 2
+
+ if(ls.tail ne ls.tail)
+ println("ListSet.tail should not use a builder!")
+
+ // class that always causes hash collisions
+ case class Collision(value:Int) { override def hashCode = 0 }
+
+ // create a set that should have a collison
+ val x = HashSet.empty + Collision(0) + Collision(1)
+ if(x.getClass.getSimpleName != "HashSetCollision1")
+ println("HashSet of size >1 with collisions should use HashSetCollision")
+
+ // remove the collision again by removing all but one element
+ val y = x - Collision(0)
+ if(y.getClass.getSimpleName != "HashSet1")
+ println("HashSet of size 1 should use HashSet1" + y.getClass)
+}
diff --git a/test/files/run/t6223.check b/test/files/run/t6223.check
new file mode 100644
index 0000000000..90ec019407
--- /dev/null
+++ b/test/files/run/t6223.check
@@ -0,0 +1,4 @@
+bar
+bar$mcI$sp
+bar$mIc$sp
+bar$mIcI$sp
diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala
new file mode 100644
index 0000000000..4ab7c832e6
--- /dev/null
+++ b/test/files/run/t6223.scala
@@ -0,0 +1,11 @@
+class Foo[@specialized(Int) A](a:A) {
+ def bar[@specialized(Int) B](f:A => B) = new Foo(f(a))
+}
+
+object Test {
+ def main(args:Array[String]) {
+ val f = new Foo(333)
+ val ms = f.getClass().getDeclaredMethods()
+ ms.foreach(m => println(m.getName))
+ }
+}
diff --git a/test/scaladoc/run/SI-5933.check b/test/scaladoc/run/SI-5933.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/SI-5933.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/SI-5933.scala b/test/scaladoc/run/SI-5933.scala
new file mode 100644
index 0000000000..087116fa71
--- /dev/null
+++ b/test/scaladoc/run/SI-5933.scala
@@ -0,0 +1,43 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ // Test code
+ override def code = """
+ // This example should compile without errors, and the pattern match should be correctly displayed
+
+ import language.higherKinds
+
+ abstract class Base[M[_, _]] {
+ def foo[A, B]: M[(A, B), Any]
+ }
+
+ class Derived extends Base[PartialFunction] {
+ def foo[A, B] /*: PartialFunction[(A, B) => Any]*/ = { case (a, b) => (a: A, b: B) }
+ }
+
+ object Test {
+ lazy val lx = { println("hello"); 3 }
+ def test1(x: Int = lx) = ???
+ def test2(x: Int = lx match { case 0 => 1; case 3 => 4 }) = ???
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val Test = rootPackage._object("Test")
+ val test1 = Test._method("test1")
+ val test2 = Test._method("test2")
+
+ def assertEqual(s1: String, s2: String) = assert(s1 == s2, s1 + " == " + s2)
+
+ assertEqual(test1.valueParams(0)(0).defaultValue.get.expression, "lx")
+ assertEqual(test2.valueParams(0)(0).defaultValue.get.expression, "lx match { case 0 => 1; case 3 => 4 }")
+ }
+} \ No newline at end of file