summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml73
-rw-r--r--classpath.SAMPLE5
-rw-r--r--src/actors/scala/actors/Actor.scala8
-rw-r--r--src/actors/scala/actors/Future.scala4
-rw-r--r--src/actors/scala/actors/Reactor.scala4
-rw-r--r--src/build/maven/scala-library-pom.xml29
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala126
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala2
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala3
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala43
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala129
-rw-r--r--src/compiler/scala/tools/cmd/FromString.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala54
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala12
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala4
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala3
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala151
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala207
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala140
-rw-r--r--src/library/scala/Function.scala7
-rw-r--r--src/library/scala/PartialFunction.scala134
-rw-r--r--src/library/scala/collection/JavaConversions.scala2
-rwxr-xr-xsrc/library/scala/collection/JavaConverters.scala2
-rw-r--r--src/library/scala/collection/convert/DecorateAsJava.scala20
-rw-r--r--src/library/scala/collection/convert/DecorateAsScala.scala21
-rw-r--r--src/library/scala/collection/convert/WrapAsJava.scala31
-rw-r--r--src/library/scala/collection/convert/WrapAsScala.scala25
-rw-r--r--src/library/scala/collection/convert/Wrappers.scala51
-rw-r--r--src/library/scala/collection/immutable/List.scala2
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala2
-rw-r--r--src/library/scala/collection/mutable/Stack.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashMap.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParVector.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala6
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashMap.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashSet.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParTrieMap.scala2
-rw-r--r--src/library/scala/math/BigDecimal.scala15
-rw-r--r--src/library/scala/math/BigInt.scala38
-rw-r--r--src/library/scala/runtime/AbstractPartialFunction.scala84
-rw-r--r--src/library/scala/util/control/Exception.scala5
-rw-r--r--test/files/neg/override-object-flag.check2
-rw-r--r--test/files/neg/override-object-no.check2
-rw-r--r--test/files/neg/t961.check2
-rw-r--r--test/files/pos/t4545.scala14
-rw-r--r--test/files/presentation/callcc-interpreter.check2
-rw-r--r--test/files/run/concurrent-map-conversions.scala36
-rw-r--r--test/files/run/finalvar.check6
-rw-r--r--test/files/run/finalvar.flags1
-rw-r--r--test/files/run/finalvar.scala37
-rw-r--r--test/files/run/is-valid-num.scala77
-rw-r--r--test/files/run/lift-and-unlift.scala6
-rw-r--r--test/files/run/numbereq.scala35
-rw-r--r--test/pending/pos/t1476.scala23
-rw-r--r--test/pending/pos/t5626.scala12
-rw-r--r--test/pending/run/t5629.check2
-rw-r--r--test/pending/run/t5629.scala25
71 files changed, 1301 insertions, 527 deletions
diff --git a/build.xml b/build.xml
index d4a6bbfbaa..c1ab09c4e4 100644
--- a/build.xml
+++ b/build.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project name="sabbus" default="build">
+<project name="sabbus" default="build" xmlns:artifact="urn:maven-artifact-ant">
<description>
SuperSabbus for Scala core, builds the scala library and compiler. It can also package it as a simple distribution, tests it for stable bootstrapping and against the Scala test suite.
</description>
@@ -238,6 +238,19 @@ INITIALISATION
</touch>
</target>
+ <!-- Add our maven ant tasks -->
+ <target name="init.maven.tasks" depends="init.jars.check">
+ <path id="maven-ant-tasks.classpath" path="${lib.dir}/ant/maven-ant-tasks-2.1.1.jar" />
+ <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
+ </target>
+
+ <!-- Resolve maven dependencies -->
+ <target name="init.maven.jars" depends="init.maven.tasks">
+ <artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset">
+ <dependency groupId="org.skife.com.typesafe.config" artifactId="typesafe-config" version="0.3.0"/>
+ </artifact:dependencies>
+ </target>
+
<!-- Determines OSGi string + maven extension. -->
<target name="init.hasbuildnum">
<condition property="version.hasbuildnum">
@@ -261,21 +274,7 @@ INITIALISATION
<target name="init.build.suffix.done" depends="init.build.release, init.build.patch.release"/>
- <target name="init" depends="init.jars, init.build.suffix.done">
- <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
- <property name="scalac.args.optimise" value=""/>
- <!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
- This is to facilitate testing new command line options which do not yet exist in starr. -->
- <property name="scalac.args.quickonly" value=""/>
- <property name="scalac.args.all" value="${scalac.args} ${scalac.args.optimise}"/>
- <property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
- <!-- Setting-up Ant contrib tasks -->
- <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant/ant-contrib.jar"/>
- <!-- This is the start time for the distribution -->
- <tstamp prefix="time">
- <format property="human" pattern="d MMMM yyyy, HH:mm:ss" locale="en,US"/>
- <format property="short" pattern="yyyyMMddHHmmss"/>
- </tstamp>
+ <target name="init.version.git" depends="init.build.suffix.done">
<!-- Find out whether we are running on Windows -->
<condition property="os.win">
<os family="windows"/>
@@ -292,15 +291,45 @@ INITIALISATION
name="maven.version.number"
value="${version.major}.${version.minor}.${version.patch}${version.suffix}${maven.version.suffix}"/>
<property
- name="version.number"
- value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
- <property
name="osgi.version.number"
value="${version.major}.${version.minor}.${version.patch}.v${git.commit.date}${version.suffix}-${git.commit.sha}"/>
+ </target>
+
+ <target name="init.version.snapshot" unless="build.release" depends="init.version.git">
+ <property
+ name="version.number"
+ value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
+ </target>
+
+ <target name="init.version.release" if="build.release" depends="init.version.git">
+ <property
+ name="version.number"
+ value="${maven.version.number}"/>
+ </target>
+
+ <target name="init.version.done" depends="init.version.release, init.version.snapshot"/>
+
+ <target name="init" depends="init.jars, init.maven.jars, init.version.done">
+ <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
+ <property name="scalac.args.optimise" value=""/>
+ <!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
+ This is to facilitate testing new command line options which do not yet exist in starr. -->
+ <property name="scalac.args.quickonly" value=""/>
+ <property name="scalac.args.all" value="${scalac.args} ${scalac.args.optimise}"/>
+ <property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
+ <!-- Setting-up Ant contrib tasks -->
+ <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant/ant-contrib.jar"/>
+ <!-- This is the start time for the distribution -->
+ <tstamp prefix="time">
+ <format property="human" pattern="d MMMM yyyy, HH:mm:ss" locale="en,US"/>
+ <format property="short" pattern="yyyyMMddHHmmss"/>
+ </tstamp>
+
<!-- some default in case something went wrong getting the revision -->
<property name="version.number" value="-unknown-"/>
<property name="init.avail" value="yes"/>
+
<!-- Local libs (developer use.) -->
<mkdir dir="${lib-extra.dir}"/>
@@ -321,6 +350,7 @@ INITIALISATION
</fileset>
<pathelement location="${ant.jar}"/>
<path refid="lib.extra"/>
+ <path refid="dependency.classpath"/>
</path>
<!-- And print-out what we are building -->
@@ -986,6 +1016,11 @@ PACKED QUICK BUILD (PACK)
<target name="pack.lib" depends="pack.pre-lib" unless="pack.lib.available">
<mkdir dir="${build-pack.dir}/lib"/>
+ <!-- First copy maven dependencies -->
+ <copy todir="${build-pack.dir}/lib">
+ <fileset refid="dependency.fileset" />
+ <mapper type="flatten" />
+ </copy>
<jar destfile="${build-pack.dir}/lib/scala-library.jar">
<fileset dir="${build-quick.dir}/classes/library">
<exclude name="scala/dbc/**"/>
diff --git a/classpath.SAMPLE b/classpath.SAMPLE
index 69c2baeba7..9e607a41d9 100644
--- a/classpath.SAMPLE
+++ b/classpath.SAMPLE
@@ -3,10 +3,9 @@
<classpathentry kind="src" path="src/compiler"/>
<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry exported="true" kind="lib" path="lib/msil.jar"/>
+ <classpathentry kind="lib" path="lib/msil.jar"/>
<classpathentry kind="lib" path="lib/jline.jar"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry exported="true" kind="lib" path="lib/fjbg.jar"/>
+ <classpathentry kind="lib" path="lib/fjbg.jar"/>
<classpathentry kind="lib" path="lib/forkjoin.jar"/>
<classpathentry kind="lib" path="lib/ant/ant.jar"/>
<classpathentry kind="output" path="build/quick/classes/compiler"/>
diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala
index aab533ae8d..bc9bbc6ef0 100644
--- a/src/actors/scala/actors/Actor.scala
+++ b/src/actors/scala/actors/Actor.scala
@@ -1,3 +1,5 @@
+
+
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2005-2011, LAMP/EPFL **
@@ -246,8 +248,8 @@ object Actor extends Combinators {
rawSelf.react(new RecursiveProxyHandler(rawSelf, f))
private class RecursiveProxyHandler(a: InternalReplyReactor, f: PartialFunction[Any, Unit])
- extends scala.runtime.AbstractPartialFunction[Any, Unit] {
- def _isDefinedAt(m: Any): Boolean =
+ extends PartialFunction[Any, Unit] {
+ def isDefinedAt(m: Any): Boolean =
true // events are immediately removed from the mailbox
def apply(m: Any) {
if (f.isDefinedAt(m)) f(m)
@@ -404,5 +406,5 @@ trait Actor extends InternalActor with ReplyReactor {
this
}
-}
+ }
diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala
index eec43013d3..735c13190b 100644
--- a/src/actors/scala/actors/Future.scala
+++ b/src/actors/scala/actors/Future.scala
@@ -200,8 +200,8 @@ object Futures {
Actor.timer.schedule(timerTask, timeout)
def awaitWith(partFuns: Seq[PartialFunction[Any, Pair[Int, Any]]]) {
- val reaction: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] {
- def _isDefinedAt(msg: Any) = msg match {
+ val reaction: PartialFunction[Any, Unit] = new PartialFunction[Any, Unit] {
+ def isDefinedAt(msg: Any) = msg match {
case TIMEOUT => true
case _ => partFuns exists (_ isDefinedAt msg)
}
diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala
index 8fc7578344..206a97d97c 100644
--- a/src/actors/scala/actors/Reactor.scala
+++ b/src/actors/scala/actors/Reactor.scala
@@ -38,8 +38,8 @@ private[actors] object Reactor {
}
}
- val waitingForNone: PartialFunction[Any, Unit] = new scala.runtime.AbstractPartialFunction[Any, Unit] {
- def _isDefinedAt(x: Any) = false
+ val waitingForNone: PartialFunction[Any, Unit] = new PartialFunction[Any, Unit] {
+ def isDefinedAt(x: Any) = false
def apply(x: Any) {}
}
}
diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml
index 673c3dfada..c3f8a4531c 100644
--- a/src/build/maven/scala-library-pom.xml
+++ b/src/build/maven/scala-library-pom.xml
@@ -30,17 +30,24 @@
<system>JIRA</system>
<url>https://issues.scala-lang.org/</url>
</issueManagement>
- <distributionManagement>
- <repository>
- <id>scala-tools.org</id>
- <url>@RELEASE_REPOSITORY@</url>
- </repository>
- <snapshotRepository>
- <id>scala-tools.org</id>
- <url>@SNAPSHOT_REPOSITORY@</url>
- <uniqueVersion>false</uniqueVersion>
- </snapshotRepository>
- </distributionManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.skife.com.typesafe.config</groupId>
+ <artifactId>typesafe-config</artifactId>
+ <version>0.3.0</version>
+ </dependency>
+ </dependencies>
+ <distributionManagement>
+ <repository>
+ <id>scala-tools.org</id>
+ <url>@RELEASE_REPOSITORY@</url>
+ </repository>
+ <snapshotRepository>
+ <id>scala-tools.org</id>
+ <url>@SNAPSHOT_REPOSITORY@</url>
+ <uniqueVersion>false</uniqueVersion>
+ </snapshotRepository>
+ </distributionManagement>
<developers>
<developer>
<id>lamp</id>
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index a2dd6fc4c3..8ea3cd511a 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -138,26 +138,47 @@ trait Definitions extends reflect.api.StandardDefinitions {
// symbols related to packages
var emptypackagescope: Scope = null //debug
- // This is the package _root_. The actual root cannot be referenced at
- // the source level, but _root_ is essentially a function () => <root>.
- lazy val RootPackage: Symbol = {
- val rp = (
- NoSymbol.newValue(nme.ROOTPKG, NoPosition, FINAL | MODULE | PACKAGE | JAVA)
- setInfo NullaryMethodType(RootClass.tpe)
- )
- RootClass.sourceModule = rp
- rp
+ sealed trait WellKnownSymbol extends Symbol {
+ this initFlags TopLevelCreationFlags
}
+ // Features common to RootClass and RootPackage, the roots of all
+ // type and term symbols respectively.
+ sealed trait RootSymbol extends WellKnownSymbol {
+ final override def isRootSymbol = true
+ }
+ // This is the package _root_. The actual root cannot be referenced at
+ // the source level, but _root_ is essentially a function => <root>.
+ final object RootPackage extends ModuleSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol {
+ this setInfo NullaryMethodType(RootClass.tpe)
+ RootClass.sourceModule = this
- // This is the actual root of everything, including the package _root_.
- lazy val RootClass: ModuleClassSymbol = (
- NoSymbol.newModuleClassSymbol(tpnme.ROOT, NoPosition, FINAL | MODULE | PACKAGE | JAVA)
- setInfo rootLoader
- )
+ override def isRootPackage = true
+ }
+ // This is <root>, the actual root of everything except the package _root_.
+ // <root> and _root_ (RootPackage and RootClass) should be the only "well known"
+ // symbols owned by NoSymbol. All owner chains should go through RootClass,
+ // although it is probable that some symbols are created as direct children
+ // of NoSymbol to ensure they will not be stumbled upon. (We should designate
+ // a better encapsulated place for that.)
+ final object RootClass extends ModuleClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol {
+ this setInfo rootLoader
+
+ override def isRoot = true
+ override def isEffectiveRoot = true
+ override def isStatic = true
+ override def isNestedClass = false
+ override def ownerOfNewSymbols = EmptyPackageClass
+ }
// The empty package, which holds all top level types without given packages.
- lazy val EmptyPackage = RootClass.newPackage(nme.EMPTY_PACKAGE_NAME, NoPosition, FINAL)
- lazy val EmptyPackageClass = EmptyPackage.moduleClass
-
+ final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
+ override def isEmptyPackage = true
+ }
+ final object EmptyPackageClass extends ModuleClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
+ override def isEffectiveRoot = true
+ override def isEmptyPackageClass = true
+ }
+ // It becomes tricky to create dedicated objects for other symbols because
+ // of initialization order issues.
lazy val JavaLangPackage = getModule(sn.JavaLang)
lazy val JavaLangPackageClass = JavaLangPackage.moduleClass
lazy val ScalaPackage = getModule(nme.scala_)
@@ -524,26 +545,54 @@ trait Definitions extends reflect.api.StandardDefinitions {
else nme.genericWrapArray
}
+ @deprecated("Use isTupleType", "2.10.0")
+ def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp)
+
def tupleField(n: Int, j: Int) = getMember(TupleClass(n), nme.productAccessorName(j))
- def isTupleType(tp: Type): Boolean = isTupleType(tp, false)
- def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp, true)
- private def isTupleType(tp: Type, subtypeOK: Boolean) = tp.normalize match {
- case TypeRef(_, sym, args) if args.nonEmpty =>
- val len = args.length
- len <= MaxTupleArity && {
- val tsym = TupleClass(len)
- (sym == tsym) || (subtypeOK && !tp.isHigherKinded && sym.isSubClass(tsym))
- }
- case _ => false
+ def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym)
+
+ def unspecializedSymbol(sym: Symbol): Symbol = {
+ if (sym hasFlag SPECIALIZED) {
+ // add initialization from its generic class constructor
+ val genericName = nme.unspecializedName(sym.name)
+ val member = sym.owner.info.decl(genericName.toTypeName)
+ member
}
+ else sym
+ }
- def tupleType(elems: List[Type]) = {
- val len = elems.length
- if (len <= MaxTupleArity) {
- val sym = TupleClass(len)
- typeRef(sym.typeConstructor.prefix, sym, elems)
- } else NoType
- }
+ // Checks whether the given type is true for the given condition,
+ // or if it is a specialized subtype of a type for which it is true.
+ //
+ // Origins notes:
+ // An issue was introduced with specialization in that the implementation
+ // of "isTupleType" in Definitions relied upon sym == TupleClass(elems.length).
+ // This test is untrue for specialized tuples, causing mysterious behavior
+ // because only some tuples are specialized.
+ def isPossiblySpecializedType(tp: Type)(cond: Type => Boolean) = {
+ cond(tp) || (tp match {
+ case TypeRef(pre, sym, args) if sym hasFlag SPECIALIZED =>
+ cond(tp baseType unspecializedSymbol(sym))
+ case _ =>
+ false
+ })
+ }
+ // No normalization.
+ def isTupleTypeDirect(tp: Type) = isPossiblySpecializedType(tp) {
+ case TypeRef(_, sym, args) if args.nonEmpty =>
+ val len = args.length
+ len <= MaxTupleArity && sym == TupleClass(len)
+ case _ => false
+ }
+ def isTupleType(tp: Type) = isTupleTypeDirect(tp.normalize)
+
+ def tupleType(elems: List[Type]) = {
+ val len = elems.length
+ if (len <= MaxTupleArity) {
+ val sym = TupleClass(len)
+ typeRef(sym.typeConstructor.prefix, sym, elems)
+ } else NoType
+ }
lazy val ProductRootClass: Symbol = getRequiredClass("scala.Product")
def Product_productArity = getMember(ProductRootClass, nme.productArity)
@@ -601,8 +650,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def isFunctionType(tp: Type): Boolean = tp.normalize match {
case TypeRef(_, sym, args) if args.nonEmpty =>
- val len = args.length
- len < MaxFunctionArity && sym == FunctionClass(len - 1)
+ val arity = args.length - 1 // -1 is the return type
+ arity <= MaxFunctionArity && sym == FunctionClass(arity)
case _ =>
false
}
@@ -1090,9 +1139,14 @@ trait Definitions extends reflect.api.StandardDefinitions {
def init() {
if (isInitialized) return
+ // Still fiddling with whether it's cleaner to do some of this setup here
+ // or from constructors. The latter approach tends to invite init order issues.
EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass)
EmptyPackage setInfo EmptyPackageClass.tpe
+ connectModuleToClass(EmptyPackage, EmptyPackageClass)
+ connectModuleToClass(RootPackage, RootClass)
+
RootClass.info.decls enter EmptyPackage
RootClass.info.decls enter RootPackage
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index 3110d73461..ce1c8d0908 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -84,7 +84,7 @@ import scala.collection.{ mutable, immutable }
*/
class ModifierFlags {
final val IMPLICIT = 0x00000200
- final val FINAL = 0x00000020
+ final val FINAL = 0x00000020 // May not be overridden. Note that java final implies much more than scala final.
final val PRIVATE = 0x00000004
final val PROTECTED = 0x00000001
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index 9fb7b5b747..e2c253628c 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -283,13 +283,13 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val TYPE_ : NameType = "TYPE"
val TypeTree: NameType = "TypeTree"
val UNIT : NameType = "UNIT"
- val _isDefinedAt: NameType = "_isDefinedAt"
val add_ : NameType = "add"
val annotation: NameType = "annotation"
val anyValClass: NameType = "anyValClass"
val append: NameType = "append"
val apply: NameType = "apply"
val applyDynamic: NameType = "applyDynamic"
+ val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
val argv : NameType = "argv"
val arrayValue: NameType = "arrayValue"
@@ -357,7 +357,6 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val main: NameType = "main"
val map: NameType = "map"
val mirror : NameType = "mirror"
- val missingCase: NameType = "missingCase"
val ne: NameType = "ne"
val newArray: NameType = "newArray"
val newScopeWith: NameType = "newScopeWith"
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index b58a0ef7d5..bb11ca634a 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -55,6 +55,12 @@ abstract class SymbolTable extends api.Universe
log(msg + ": " + result)
result
}
+ private[scala] def logResultIf[T](msg: String, cond: T => Boolean)(result: T): T = {
+ if (cond(result))
+ log(msg + ": " + result)
+
+ result
+ }
/** Are we compiling for Java SE? */
// def forJVM: Boolean
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index f4039cf6d3..4473d63f5f 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -451,12 +451,23 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isVarargsMethod = isMethod && hasFlag(VARARGS)
/** Package tests */
- final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME
- final def isEmptyPackageClass = isPackageClass && name == tpnme.EMPTY_PACKAGE_NAME
final def isPackage = isModule && hasFlag(PACKAGE)
final def isPackageClass = isClass && hasFlag(PACKAGE)
- final def isRoot = isPackageClass && owner == NoSymbol
- final def isRootPackage = isPackage && owner == NoSymbol
+
+ /** Overridden in custom objects in Definitions */
+ def isRoot = false
+ def isRootPackage = false
+ def isRootSymbol = false // RootPackage and RootClass. TODO: also NoSymbol.
+ def isEmptyPackage = false
+ def isEmptyPackageClass = false
+
+ /** Is this symbol an effective root for fullname string?
+ */
+ def isEffectiveRoot = false
+
+ /** For RootClass, EmptyPackageClass. For all other symbols, itself.
+ */
+ def ownerOfNewSymbols = this
/** Does this symbol denote a wrapper created by the repl? */
final def isInterpreterWrapper = (
@@ -464,9 +475,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
&& owner.isPackageClass
&& nme.isReplWrapperName(name)
)
- /** Is this symbol an effective root for fullname string?
- */
- def isEffectiveRoot = isRoot || isEmptyPackageClass
/** Term symbols with the exception of static parts of Java classes and packages.
*/
@@ -543,7 +551,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Conditions where we omit the prefix when printing a symbol, to avoid
* unpleasantries like Predef.String, $iw.$iw.Foo and <empty>.Bippy.
*/
- final def isOmittablePrefix = !settings.debug.value && (
+ final def isOmittablePrefix = /*!settings.debug.value &&*/ (
UnqualifiedOwners(skipPackageObject)
|| isEmptyPrefix
)
@@ -652,8 +660,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isModuleVar = hasFlag(MODULEVAR)
/** Is this symbol static (i.e. with no outer instance)? */
- final def isStatic: Boolean =
- hasFlag(STATIC) || isRoot || owner.isStaticOwner
+ def isStatic = (this hasFlag STATIC) || owner.isStaticOwner
/** Is this symbol a static constructor? */
final def isStaticConstructor: Boolean =
@@ -685,8 +692,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isConstant: Boolean = isStable && isConstantType(tpe.resultType)
/** Is this class nested in another class or module (not a package)? */
- final def isNestedClass: Boolean =
- isClass && !isRoot && !owner.isPackageClass
+ def isNestedClass = isClass && !owner.isPackageClass
/** Is this class locally defined?
* A class is local, if
@@ -1191,9 +1197,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
var ph = phase
while (ph.prev.keepsTypeParams)
ph = ph.prev
-
- if (ph ne phase)
- debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph)
+ //
+ // if (ph ne phase)
+ // debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph)
ph
}
@@ -2045,7 +2051,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def fullNameString: String = {
def recur(sym: Symbol): String = {
- if (sym.isRoot || sym.isRootPackage || sym == NoSymbol) sym.nameString
+ if (sym.isRootSymbol || sym == NoSymbol) sym.nameString
else if (sym.owner.isEffectiveRoot) sym.nameString
else recur(sym.effectiveOwner.enclClass) + "." + sym.nameString
}
@@ -2095,7 +2101,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case rt => " <: " + rt
}
)
- else if (isModule) moduleClass.infoString(tp)
+ else if (isModule) "" // avoid "object X of type X.type"
else tp match {
case PolyType(tparams, res) => typeParamsString(tp) + infoString(res)
case NullaryMethodType(res) => infoString(res)
@@ -2119,7 +2125,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else ""
def defaultFlagMask =
- if (settings.debug.value) -1L
+ if (isAbstractType) ExplicitFlags
+ else if (settings.debug.value) -1L
else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
else ExplicitFlags
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index bb9549deba..5afa5343ed 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -904,6 +904,12 @@ trait Types extends api.Types { self: SymbolTable =>
else str
}
+ /** The string representation of this type when the direct object in a sentence.
+ * Normally this is no different from the regular representation, but modules
+ * read better as "object Foo" here and "Foo.type" the rest of the time.
+ */
+ def directObjectString = safeToString
+
/** A test whether a type contains any unification type variables. */
def isGround: Boolean = this match {
case TypeVar(_, constr) =>
@@ -1224,8 +1230,7 @@ trait Types extends api.Types { self: SymbolTable =>
else if (sym.isModuleClass) sym.fullNameString + "."
else sym.nameString + ".this."
override def safeToString: String =
- if (sym.isRoot) "<root>"
- else if (sym.isEmptyPackageClass) "<empty>"
+ if (sym.isEffectiveRoot) "" + sym.name
else super.safeToString
override def narrow: Type = this
override def kind = "ThisType"
@@ -1851,6 +1856,35 @@ trait Types extends api.Types { self: SymbolTable =>
// advantage to call TypeRef directly.
override def typeConstructor = TypeRef(pre, sym, Nil)
}
+
+ class ModuleTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) with ClassTypeRef {
+ require(sym.isModuleClass, sym)
+ private[this] var narrowedCache: Type = _
+ override def isStable = true
+ override def narrow = {
+ if (narrowedCache eq null)
+ narrowedCache = singleType(pre, sym.sourceModule)
+
+ narrowedCache
+ }
+ final override def isNotNull = true
+ override protected def finishPrefix(rest: String) = objectPrefix + rest
+ override def directObjectString = super.safeToString
+ override def toLongString = toString
+ override def safeToString = narrow.toString
+ }
+ class PackageTypeRef(pre0: Type, sym0: Symbol) extends ModuleTypeRef(pre0, sym0) {
+ require(sym.isPackageClass, sym)
+ override protected def finishPrefix(rest: String) = packagePrefix + rest
+ }
+ class RefinementTypeRef(sym0: Symbol) extends NoArgsTypeRef(NoType, sym0) with ClassTypeRef {
+ require(sym.isRefinementClass, sym)
+
+ // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
+ override protected def normalizeImpl: Type = sym.info.normalize
+ override protected def finishPrefix(rest: String) = "" + thisInfo
+ }
+
class NoArgsTypeRef(pre0: Type, sym0: Symbol) extends TypeRef(pre0, sym0, Nil) with UniqueType {
// A reference (in a Scala program) to a type that has type parameters, but where the reference
// does not include type arguments. Note that it doesn't matter whether the symbol refers
@@ -1898,10 +1932,6 @@ trait Types extends api.Types { self: SymbolTable =>
// !!! There are scaladoc-created symbols arriving which violate this require.
// require(sym.isClass, sym)
- override protected def normalizeImpl: Type =
- if (sym.isRefinementClass) sym.info.normalize // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
- else super.normalizeImpl
-
override def baseType(clazz: Symbol): Type =
if (sym == clazz) this
else transform(sym.info.baseType(clazz))
@@ -2147,12 +2177,15 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
- private def preString = (
- // ensure that symbol is not a local copy with a name coincidence
- if (!settings.debug.value && shorthands(sym.fullName) && sym.ownerChain.forall(_.isClass)) ""
- else pre.prefixString
+ // ensure that symbol is not a local copy with a name coincidence
+ private def needsPreString = (
+ settings.debug.value
+ || !shorthands(sym.fullName)
+ || sym.ownerChain.exists(s => !s.isClass)
)
+ private def preString = if (needsPreString) pre.prefixString else ""
private def argsString = if (args.isEmpty) "" else args.mkString("[", ",", "]")
+
def refinementString = (
if (sym.isStructuralRefinement) (
decls filter (sym => sym.isPossibleInRefinement && sym.isPublic)
@@ -2162,25 +2195,23 @@ trait Types extends api.Types { self: SymbolTable =>
else ""
)
- private def finishPrefix(rest: String) = (
- if (sym.isPackageClass) packagePrefix + rest
- else if (sym.isModuleClass) objectPrefix + rest
- else if (!sym.isInitialized) rest
- else if (sym.isAnonymousClass && !phase.erasedTypes) parentsString(thisInfo.parents) + refinementString
- else if (sym.isRefinementClass) "" + thisInfo
+ protected def finishPrefix(rest: String) = (
+ if (sym.isInitialized && sym.isAnonymousClass && !phase.erasedTypes)
+ parentsString(thisInfo.parents) + refinementString
else rest
)
private def customToString = this match {
case TypeRef(_, RepeatedParamClass, arg :: _) => arg + "*"
case TypeRef(_, ByNameParamClass, arg :: _) => "=> " + arg
case _ =>
+ def targs = normalize.typeArgs
+
if (isFunctionType(this)) {
- val targs = normalize.typeArgs
// Aesthetics: printing Function1 as T => R rather than (T) => R
// ...but only if it's not a tuple, so ((T1, T2)) => R is distinguishable
// from (T1, T2) => R.
targs match {
- case in :: out :: Nil if !isTupleTypeOrSubtype(in) =>
+ case in :: out :: Nil if !isTupleType(in) =>
// A => B => C should be (A => B) => C or A => (B => C)
val in_s = if (isFunctionType(in)) "(" + in + ")" else "" + in
val out_s = if (isFunctionType(out)) "(" + out + ")" else "" + out
@@ -2189,9 +2220,9 @@ trait Types extends api.Types { self: SymbolTable =>
xs.init.mkString("(", ", ", ")") + " => " + xs.last
}
}
- else if (isTupleTypeOrSubtype(this))
- normalize.typeArgs.mkString("(", ", ", if (hasLength(normalize.typeArgs, 1)) ",)" else ")")
- else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (normalize ne this))
+ else if (isTupleType(this))
+ targs.mkString("(", ", ", if (hasLength(targs, 1)) ",)" else ")")
+ else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (this ne this.normalize))
"" + normalize
else
""
@@ -2226,6 +2257,9 @@ trait Types extends api.Types { self: SymbolTable =>
else {
if (sym.isAliasType) new NoArgsTypeRef(pre, sym) with AliasTypeRef
else if (sym.isAbstractType) new NoArgsTypeRef(pre, sym) with AbstractTypeRef
+ else if (sym.isRefinementClass) new RefinementTypeRef(sym)
+ else if (sym.isPackageClass) new PackageTypeRef(pre, sym)
+ else if (sym.isModuleClass) new ModuleTypeRef(pre, sym)
else new NoArgsTypeRef(pre, sym) with ClassTypeRef
}
})
@@ -3615,6 +3649,23 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ class TypeUnwrapper(poly: Boolean, existential: Boolean, annotated: Boolean, nullary: Boolean) extends (Type => Type) {
+ def apply(tp: Type): Type = tp match {
+ case AnnotatedType(_, underlying, _) if annotated => apply(underlying)
+ case ExistentialType(_, underlying) if existential => apply(underlying)
+ case PolyType(_, underlying) if poly => apply(underlying)
+ case NullaryMethodType(underlying) if nullary => apply(underlying)
+ case tp => tp
+ }
+ }
+ class ClassUnwrapper(existential: Boolean) extends TypeUnwrapper(poly = true, existential, annotated = true, nullary = false) {
+ override def apply(tp: Type) = super.apply(tp.normalize)
+ }
+
+ object unwrapToClass extends ClassUnwrapper(existential = true) { }
+ object unwrapToStableClass extends ClassUnwrapper(existential = false) { }
+ object unwrapWrapperTypes extends TypeUnwrapper(true, true, true, true) { }
+
trait AnnotationFilter extends TypeMap {
def keepAnnotation(annot: AnnotationInfo): Boolean
@@ -4585,31 +4636,22 @@ trait Types extends api.Types { self: SymbolTable =>
object adaptToNewRunMap extends TypeMap {
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
- if (phase.flatClasses) {
+ if (phase.flatClasses || sym.isRootSymbol || (pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass)
sym
- } else if (sym == definitions.RootClass) {
- definitions.RootClass
- } else if (sym == definitions.RootPackage) {
- definitions.RootPackage
- } else if (sym.isModuleClass) {
+ else if (sym.isModuleClass) {
val sourceModule1 = adaptToNewRun(pre, sym.sourceModule)
- var result = sourceModule1.moduleClass
- if (result == NoSymbol) result = sourceModule1.initialize.moduleClass
- if (result != NoSymbol) result
- else {
+
+ sourceModule1.moduleClass orElse sourceModule1.initialize.moduleClass orElse {
val msg = "Cannot adapt module class; sym = %s, sourceModule = %s, sourceModule.moduleClass = %s => sourceModule1 = %s, sourceModule1.moduleClass = %s"
debuglog(msg.format(sym, sym.sourceModule, sym.sourceModule.moduleClass, sourceModule1, sourceModule1.moduleClass))
sym
}
- } else if ((pre eq NoPrefix) || (pre eq NoType) || sym.isPackageClass) {
- sym
- } else {
- var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
- if (rebind0 == NoSymbol) {
+ }
+ else {
+ var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true) orElse {
if (sym.isAliasType) throw missingAliasException
debugwarn(pre+"."+sym+" does no longer exist, phase = "+phase)
throw new MissingTypeControl // For build manager and presentation compiler purposes
- //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
}
/** The two symbols have the same fully qualified name */
def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
@@ -4628,12 +4670,10 @@ trait Types extends api.Types { self: SymbolTable =>
", rebind = " + rebind0.fullLocationString
)
}
- val rebind = rebind0.suchThat(sym => sym.isType || sym.isStable)
- if (rebind == NoSymbol) {
+ rebind0.suchThat(sym => sym.isType || sym.isStable) orElse {
debuglog("" + phase + " " +phase.flatClasses+sym.owner+sym.name+" "+sym.isType)
throw new MalformedType(pre, sym.nameString)
}
- rebind
}
}
def apply(tp: Type): Type = tp match {
@@ -5454,9 +5494,14 @@ trait Types extends api.Types { self: SymbolTable =>
case _: ClassSymbol =>
if (isRaw(sym1, tr1.args))
isSubType(rawToExistential(tp1), tp2, depth)
- else
- sym1.name == tpnme.REFINE_CLASS_NAME &&
+ else if (sym1.isModuleClass) tp2 match {
+ case SingleType(_, sym2) => sym1 == sym2
+ case _ => false
+ }
+ else if (sym1.isRefinementClass)
isSubType(sym1.info, tp2, depth)
+ else false
+
case _: TypeSymbol =>
if (sym1 hasFlag DEFERRED) {
val tp1a = tp1.bounds.hi
diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala
index e4504702d4..3792c26c34 100644
--- a/src/compiler/scala/tools/cmd/FromString.scala
+++ b/src/compiler/scala/tools/cmd/FromString.scala
@@ -14,9 +14,9 @@ import scala.reflect.OptManifest
* example instances are in the companion object, but in general
* either IntFromString will suffice or you'll want custom transformers.
*/
-abstract class FromString[+T](implicit m: OptManifest[T]) extends scala.runtime.AbstractPartialFunction[String, T] {
+abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] {
def apply(s: String): T
- def _isDefinedAt(s: String): Boolean = true
+ def isDefinedAt(s: String): Boolean = true
def zero: T = apply("")
def targetString: String = m.toString
@@ -30,20 +30,20 @@ object FromString {
/** Path related stringifiers.
*/
val ExistingFile: FromString[File] = new FromString[File] {
- override def _isDefinedAt(s: String) = toFile(s).isFile
+ override def isDefinedAt(s: String) = toFile(s).isFile
def apply(s: String): File =
if (isDefinedAt(s)) toFile(s)
else cmd.runAndExit(println("'%s' is not an existing file." format s))
}
val ExistingDir: FromString[Directory] = new FromString[Directory] {
- override def _isDefinedAt(s: String) = toDir(s).isDirectory
+ override def isDefinedAt(s: String) = toDir(s).isDirectory
def apply(s: String): Directory =
if (isDefinedAt(s)) toDir(s)
else cmd.runAndExit(println("'%s' is not an existing directory." format s))
}
def ExistingDirRelativeTo(root: Directory) = new FromString[Directory] {
private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory
- override def _isDefinedAt(s: String) = resolve(s).isDirectory
+ override def isDefinedAt(s: String) = resolve(s).isDirectory
def apply(s: String): Directory =
if (isDefinedAt(s)) resolve(s)
else cmd.runAndExit(println("'%s' is not an existing directory." format resolve(s)))
@@ -65,7 +65,7 @@ object FromString {
/** Implicit as the most likely to be useful as-is.
*/
implicit val IntFromString: FromString[Int] = new FromString[Int] {
- override def _isDefinedAt(s: String) = safeToInt(s).isDefined
+ override def isDefinedAt(s: String) = safeToInt(s).isDefined
def apply(s: String) = safeToInt(s).get
def safeToInt(s: String): Option[Int] = try Some(java.lang.Integer.parseInt(s)) catch { case _: NumberFormatException => None }
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 8e326c202a..7b7135d180 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -121,6 +121,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (settings.debug.value)
inform("[running phase " + name + " on icode]")
+ if (settings.Xverify.value && !SigParser.isParserAvailable)
+ global.warning("signature verification requested by signature parser unavailable: signatures not checked")
+
if (settings.Xdce.value)
for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym))
icodes.classes -= sym
@@ -285,6 +288,15 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val emitLines = debugLevel >= 2
val emitVars = debugLevel >= 3
+ // bug had phase with wrong name; leaving enabled for brief pseudo deprecation
+ private val checkSignatures = (
+ (settings.check containsName phaseName)
+ || (settings.check.value contains "genjvm") && {
+ global.warning("This option will be removed: please use -Ycheck:%s, not -Ycheck:genjvm." format phaseName)
+ true
+ }
+ )
+
/** For given symbol return a symbol corresponding to a class that should be declared as inner class.
*
* For example:
@@ -726,10 +738,10 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
def addGenericSignature(jmember: JMember, sym: Symbol, owner: Symbol) {
if (needsGenericSignature(sym)) {
val memberTpe = beforeErasure(owner.thisType.memberInfo(sym))
- // println("addGenericSignature sym: " + sym.fullName + " : " + memberTpe + " sym.info: " + sym.info)
- // println("addGenericSignature: "+ (sym.ownerChain map (x => (x.name, x.isImplClass))))
+
erasure.javaSig(sym, memberTpe) foreach { sig =>
- debuglog("sig(" + jmember.getName + ", " + sym + ", " + owner + ") " + sig)
+ // This seems useful enough in the general case.
+ log(sig)
/** Since we're using a sun internal class for signature validation,
* we have to allow for it not existing or otherwise malfunctioning:
* in which case we treat every signature as valid. Medium term we
@@ -743,7 +755,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
""".trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
return
}
- if ((settings.check.value contains "genjvm")) {
+ if (checkSignatures) {
val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe))
val bytecodeTpe = owner.thisType.memberInfo(sym)
if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
@@ -871,7 +883,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
debuglog("Adding field: " + f.symbol.fullName)
val jfield = jclass.addNewField(
- javaFlags(f.symbol) | javaFieldFlags(f.symbol),
+ javaFieldFlags(f.symbol),
javaName(f.symbol),
javaType(f.symbol.tpe)
)
@@ -1915,16 +1927,30 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val privateFlag =
sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner))
- // This does not check .isFinal (which checks flags for the FINAL flag),
- // instead checking rawflags for that flag so as to exclude symbols which
- // received lateFINAL. These symbols are eligible for inlining, but to
- // avoid breaking proxy software which depends on subclassing, we avoid
- // insisting on their finality in the bytecode.
+ // Final: the only fields which can receive ACC_FINAL are eager vals.
+ // Neither vars nor lazy vals can, because:
+ //
+ // Source: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3
+ // "Another problem is that the specification allows aggressive
+ // optimization of final fields. Within a thread, it is permissible to
+ // reorder reads of a final field with those modifications of a final
+ // field that do not take place in the constructor."
+ //
+ // A var or lazy val which is marked final still has meaning to the
+ // scala compiler. The word final is heavily overloaded unfortunately;
+ // for us it means "not overridable". At present you can't override
+ // vars regardless; this may change.
+ //
+ // The logic does not check .isFinal (which checks flags for the FINAL flag,
+ // and includes symbols marked lateFINAL) instead inspecting rawflags so
+ // we can exclude lateFINAL. Such symbols are eligible for inlining, but to
+ // avoid breaking proxy software which depends on subclassing, we do not
+ // emit ACC_FINAL.
val finalFlag = (
((sym.rawflags & (Flags.FINAL | Flags.MODULE)) != 0)
&& !sym.enclClass.isInterface
&& !sym.isClassConstructor
- && !sym.isMutable // fix for SI-3569, it is too broad?
+ && !sym.isMutable // lazy vals and vars both
)
mkFlags(
@@ -1939,13 +1965,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (sym.hasFlag(Flags.SYNCHRONIZED)) JAVA_ACC_SYNCHRONIZED else 0
)
}
- def javaFieldFlags(sym: Symbol) = {
- mkFlags(
+ def javaFieldFlags(sym: Symbol) = (
+ javaFlags(sym) | mkFlags(
if (sym hasAnnotation TransientAttr) ACC_TRANSIENT else 0,
if (sym hasAnnotation VolatileAttr) ACC_VOLATILE else 0,
if (sym.isMutable) 0 else ACC_FINAL
)
- }
+ )
def isTopLevelModule(sym: Symbol): Boolean =
afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index dd1c75c322..702d643fb4 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -620,7 +620,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
case tp: TypeRef if definitions.isByNameParamType(tp) =>
nameBuffer append "⇒ "
appendType0(tp.args.head)
- case tp: TypeRef if definitions.isTupleTypeOrSubtype(tp) =>
+ case tp: TypeRef if definitions.isTupleType(tp) =>
val args = tp.normalize.typeArgs
nameBuffer append '('
appendTypes0(args, ", ")
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
index 33ef4a432d..2f47685757 100644
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
@@ -6,8 +6,8 @@
package scala.tools.nsc
package interpreter
-class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends scala.runtime.AbstractPartialFunction[Throwable, T] {
- def _isDefinedAt(t: Throwable) = t match {
+class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends PartialFunction[Throwable, T] {
+ def isDefinedAt(t: Throwable) = t match {
case _: AbstractMethodError => true
case _: NoSuchMethodError => true
case _: MissingRequirementError => true
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
index 015dc2a7f1..808f549304 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
@@ -15,7 +15,7 @@ trait CompletionOutput {
val global: Global
import global._
- import definitions.{ isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType }
+ import definitions.{ isTupleType, isFunctionType, isRepeatedParamType }
/** Reducing fully qualified noise for some common packages.
*/
@@ -48,11 +48,11 @@ trait CompletionOutput {
def typeToString(tp: Type): String = relativize(
tp match {
- case x if isFunctionType(x) => functionString(x)
- case x if isTupleTypeOrSubtype(x) => tupleString(x)
- case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*"
- case mt @ MethodType(_, _) => methodTypeToString(mt)
- case x => x.toString
+ case x if isFunctionType(x) => functionString(x)
+ case x if isTupleType(x) => tupleString(x)
+ case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*"
+ case mt @ MethodType(_, _) => methodTypeToString(mt)
+ case x => x.toString
}
)
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index be5a9907b8..43aad9f591 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -425,7 +425,7 @@ trait ParallelMatching extends ast.TreeDSL
// Should the given pattern join the expanded pivot in the success matrix? If so,
// this partial function will be defined for the pattern, and the result of the apply
// is the expanded sequence of new patterns.
- lazy val successMatrixFn = new scala.runtime.AbstractPartialFunction[Pattern, List[Pattern]] {
+ lazy val successMatrixFn = new PartialFunction[Pattern, List[Pattern]] {
private def seqIsDefinedAt(x: SequenceLikePattern) = (hasStar, x.hasStar) match {
case (true, true) => true
case (true, false) => pivotLen <= x.nonStarLength
@@ -433,7 +433,7 @@ trait ParallelMatching extends ast.TreeDSL
case (false, false) => pivotLen == x.nonStarLength
}
- def _isDefinedAt(pat: Pattern) = pat match {
+ def isDefinedAt(pat: Pattern) = pat match {
case x: SequenceLikePattern => seqIsDefinedAt(x)
case WildcardPattern() => true
case _ => false
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 8bdf83fda4..4f6a4c8dc0 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -343,10 +343,9 @@ trait Patterns extends ast.TreeDSL {
def apply(x: Apply): Pattern = {
val Apply(fn, args) = x
def isModule = x.symbol.isModule || x.tpe.termSymbol.isModule
- def isTuple = isTupleTypeOrSubtype(fn.tpe)
if (fn.isType) {
- if (isTuple) TuplePattern(x)
+ if (isTupleType(fn.tpe)) TuplePattern(x)
else ConstructorPattern(x)
}
else if (args.isEmpty) {
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index fdde8f9990..14b3bcc8ce 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -31,7 +31,7 @@ trait ScalaSettings extends AbsScalaSettings
protected def defaultClasspath = sys.env.getOrElse("CLASSPATH", ".")
/** Enabled under -Xexperimental. */
- protected def experimentalSettings = List[BooleanSetting](YmethodInfer, overrideObjects)
+ protected def experimentalSettings = List[BooleanSetting](YmethodInfer, overrideObjects, overrideVars)
/** Enabled under -Xfuture. */
protected def futureSettings = List[BooleanSetting]()
@@ -117,6 +117,7 @@ trait ScalaSettings extends AbsScalaSettings
* -Y "Private" settings
*/
val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.")
+ val overrideVars = BooleanSetting ("-Yoverride-vars", "Allow vars to be overridden.")
val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.")
val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
index 59342a36ef..5f7deb87bd 100644
--- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
@@ -105,7 +105,7 @@ abstract class BrowsingLoaders extends SymbolLoaders {
*/
override def enterToplevelsFromSource(root: Symbol, name: String, src: AbstractFile) {
try {
- if (root == definitions.RootClass || root == definitions.EmptyPackageClass)
+ if (root.isEffectiveRoot) // RootClass or EmptyPackageClass
super.enterToplevelsFromSource(root, name, src)
else
browseTopLevel(root, src)
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index f9ff147e82..7eb04eaf40 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -30,15 +30,11 @@ abstract class SymbolLoaders {
member
}
- private def realOwner(root: Symbol): Symbol = {
- if (root.isRoot) definitions.EmptyPackageClass else root
- }
-
/** Enter class with given `name` into scope of `root`
* and give them `completer` as type.
*/
def enterClass(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = realOwner(root)
+ val owner = root.ownerOfNewSymbols
val clazz = owner.newClass(newTypeName(name))
clazz setInfo completer
enterIfNew(owner, clazz, completer)
@@ -48,7 +44,7 @@ abstract class SymbolLoaders {
* and give them `completer` as type.
*/
def enterModule(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = realOwner(root)
+ val owner = root.ownerOfNewSymbols
val module = owner.newModule(newTermName(name))
module setInfo completer
module.moduleClass setInfo moduleClassLoader
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 61668b1a8a..9dee441527 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -433,10 +433,7 @@ abstract class ClassfileParser {
sym.info.decl(part.encode)
}//.suchThat(module == _.isModule)
- sym = (
- if (sym1 ne NoSymbol) sym1
- else sym.info.decl(part.encode.toTypeName)
- )
+ sym = sym1 orElse sym.info.decl(part.encode.toTypeName)
}
}
sym
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 7b0f5254b6..1afa1dbf58 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -134,16 +134,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case _ => false
}
- def unspecializedSymbol(sym: Symbol): Symbol = {
- if (sym hasFlag SPECIALIZED) {
- // add initialization from its generic class constructor
- val genericName = nme.unspecializedName(sym.name)
- val member = sym.owner.info.decl(genericName.toTypeName)
- member
- }
- else NoSymbol
- }
-
object TypeEnv {
/** Return a new type environment binding specialized type parameters of sym to
* the given args. Expects the lists to have the same length.
@@ -318,7 +308,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else specializedTypeVars(sym).intersect(env.keySet)
)
val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod)
- debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
+ // debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
specializedName(sym.name, methparams map env, others map env)
}
@@ -518,7 +508,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// better evaluate it before creating the new class symbol
val clazzName = specializedName(clazz, env0).toTypeName
val bytecodeClazz = clazz.owner.info.decl(clazzName)
- debuglog("Specializing " + clazz + " found " + bytecodeClazz + " already there")
+ // debuglog("Specializing " + clazz + ", but found " + bytecodeClazz + " already there")
bytecodeClazz.info
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
@@ -574,7 +564,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
parents = parents.head.parents.head :: parents
val extraSpecializedMixins = specializedParents(clazz.info.parents map applyContext)
if (extraSpecializedMixins.nonEmpty)
- debuglog("specializeClass on " + clazz + " founds extra specialized mixins: " + extraSpecializedMixins.mkString(", "))
+ debuglog("extra specialized mixins for %s: %s".format(clazz.name.decode, extraSpecializedMixins.mkString(", ")))
// If the class being specialized has a self-type, the self type may
// require specialization. First exclude classes whose self types have
// the same type constructor as the class itself, since they will
@@ -652,7 +642,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val NormalizedMember(original) = info(m)
if (nonConflicting(env ++ typeEnv(m))) {
if (info(m).degenerate) {
- debuglog("degenerate normalized member " + m + " info(m): " + info(m))
+ debuglog("degenerate normalized member " + m.defString)
val specMember = enterMember(cloneInSpecializedClass(m, _ & ~DEFERRED))
info(specMember) = Implementation(original)
@@ -660,7 +650,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
else debuglog({
val om = forwardToOverload(m)
- "normalizedMember " + m + " om: " + om + " typeEnv(om): " + typeEnv(om)
+ "normalizedMember " + m + " om: " + om + " " + pp(typeEnv(om))
})
}
else
@@ -668,7 +658,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
else if (m.isDeferred) { // abstract methods
val specMember = enterMember(cloneInSpecializedClass(m, _ | DEFERRED))
- debuglog("deferred " + specMember.fullName + " remains abstract")
+ // debuglog("deferred " + specMember.fullName + " remains abstract")
info(specMember) = new Abstract(specMember)
// was: new Forward(specMember) {
@@ -698,20 +688,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
enterMember(specVal)
// create accessors
- debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
+ // debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
+
if (nme.isLocalName(m.name)) {
val specGetter = mkAccessor(specVal, nme.localToGetter(specVal.name)) setInfo MethodType(Nil, specVal.info)
val origGetter = overrideIn(sClass, m.getter(clazz))
info(origGetter) = Forward(specGetter)
enterMember(specGetter)
enterMember(origGetter)
- debuglog("created accessors: " + specGetter + " orig: " + origGetter)
+ debuglog("specialize accessor in %s: %s -> %s".format(sClass.name.decode, origGetter.name.decode, specGetter.name.decode))
clazz.caseFieldAccessors.find(_.name.startsWith(m.name)) foreach { cfa =>
val cfaGetter = overrideIn(sClass, cfa)
info(cfaGetter) = SpecializedAccessor(specVal)
enterMember(cfaGetter)
- debuglog("found case field accessor for " + m + " added override " + cfaGetter);
+ debuglog("override case field accessor %s -> %s".format(m.name.decode, cfaGetter.name.decode))
}
if (specVal.isVariable && m.setter(clazz) != NoSymbol) {
@@ -724,11 +715,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
enterMember(specSetter)
enterMember(origSetter)
}
- } else { // if there are no accessors, specialized methods will need to access this field in specialized subclasses
+ }
+ else { // if there are no accessors, specialized methods will need to access this field in specialized subclasses
m.resetFlag(PRIVATE)
specVal.resetFlag(PRIVATE)
+ debuglog("no accessors for %s/%s, specialized methods must access field in subclass".format(
+ m.name.decode, specVal.name.decode))
}
- } else if (m.isClass) {
+ }
+ else if (m.isClass) {
val specClass: Symbol = cloneInSpecializedClass(m, x => x)
typeEnv(specClass) = fullEnv
specClass.name = specializedName(specClass, fullEnv).toTypeName
@@ -787,10 +782,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* // etc.
*/
private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = {
- debuglog("normalizeMember: " + sym.fullName)
sym :: (
if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil
else {
+ // debuglog("normalizeMember: " + sym.fullNameAsName('.').decode)
var specializingOn = specializedParams(sym)
val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info)
@@ -810,7 +805,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val (keys, vals) = env.toList.unzip
specMember.name = specializedName(sym, env)
- debuglog("normalizing: " + sym + " to " + specMember + " with params " + tps)
+ // debuglog("%s normalizes to %s%s".format(sym, specMember,
+ // if (tps.isEmpty) "" else " with params " + tps.mkString(", ")))
typeEnv(specMember) = outerEnv ++ env
val tps1 = produceTypeParameters(tps, specMember, env)
@@ -820,11 +816,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val methodType = sym.info.resultType.instantiateTypeParams(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember)
specMember setInfo GenPolyType(tps1, methodType)
- debuglog("expanded member: " + sym + ": " + sym.info +
- " -> " + specMember +
- ": " + specMember.info +
- " env: " + env
- )
+ debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
info(specMember) = NormalizedMember(sym)
overloads(sym) ::= Overload(specMember, env)
specMember
@@ -833,6 +825,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
)
}
+ // concise printing of type env
+ private def pp(env: TypeEnv): String = {
+ env.toList.sortBy(_._1.name.toString) map {
+ case (k, v) =>
+ val vsym = v.typeSymbol
+ if (k == vsym) "" + k.name
+ else k.name + ":" + vsym.name
+
+ } mkString ("env(", ", ", ")")
+ }
+
/** Specialize member `m` w.r.t. to the outer environment and the type
* parameters of the innermost enclosing class.
*
@@ -841,37 +844,38 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Return a list of symbols that are specializations of 'sym', owned by 'owner'.
*/
private def specializeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv, tps: List[Symbol]): List[Symbol] = {
- def specializeOn(tparams: List[Symbol]): List[Symbol] =
- for (spec0 <- specializations(tparams)) yield {
- val spec = mapAnyRefsInOrigCls(spec0, owner)
- if (sym.isPrivate/* || sym.isProtected*/) {
- //sym.privateWithin = sym.enclosingPackage
- sym.resetFlag(PRIVATE).setFlag(PROTECTED)
- debuglog("-->d SETTING PRIVATE WITHIN TO " + sym.enclosingPackage + " for " + sym)
- }
+ def specializeOn(tparams: List[Symbol]): List[Symbol] = specializations(tparams) map { spec0 =>
+ val spec = mapAnyRefsInOrigCls(spec0, owner)
+ if (sym.isPrivate) {
+ sym.resetFlag(PRIVATE).setFlag(PROTECTED)
+ debuglog("Set %s to private[%s]".format(sym, sym.enclosingPackage))
+ }
- val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
- typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
- wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
+ val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
+ typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
+ wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
- debuglog("sym " + specMember + " was specialized for type vars " + wasSpecializedForTypeVars(specMember))
- debuglog("added specialized overload: %s in env: %s".format(specMember, typeEnv(specMember)))
+ val wasSpec = wasSpecializedForTypeVars(specMember)
+ if (wasSpec.nonEmpty)
+ debuglog("specialized overload for %s in %s".format(specMember, pp(typeEnv(specMember))))
- overloads(sym) ::= Overload(specMember, spec)
- specMember
- }
+ overloads(sym) ::= Overload(specMember, spec)
+ info(specMember) = SpecialOverload(sym, typeEnv(specMember))
+
+ specMember
+ }
if (sym.isMethod) {
- debuglog("specializeMember %s with tps: %s stvars(sym): %s".format(sym, tps, specializedTypeVars(sym)))
+ val stvars = specializedTypeVars(sym)
+ if (stvars.nonEmpty)
+ debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", ")))
val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps
- val tps2 = tps1 intersect specializedTypeVars(sym).toList
+ val tps2 = tps1 filter stvars
if (!sym.isDeferred)
addConcreteSpecMethod(sym)
- val ms = specializeOn(tps2)
- ms foreach (m => info(m) = SpecialOverload(sym, typeEnv(m)))
- ms
+ specializeOn(tps2)
}
else Nil
}
@@ -894,7 +898,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*
* this method will return List('apply$mcII$sp')
*/
- private def specialOverrides(clazz: Symbol): List[Symbol] = {
+ private def specialOverrides(clazz: Symbol) = logResultIf[List[Symbol]]("specialOverrides(" + clazz + ")", _.nonEmpty) {
/** Return the overridden symbol in syms that needs a specialized overriding symbol,
* together with its specialization environment. The overridden symbol may not be
* the closest to 'overriding', in a given hierarchy.
@@ -917,24 +921,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
if (!overriding.isParamAccessor) {
for (overridden <- overriding.allOverriddenSymbols) {
- debuglog(
- "Overridden: " + overridden.fullName +
- ": " + overridden.info +
- "\n by " + overriding.fullName +
- ": " + overriding.info
- )
val stvars = specializedTypeVars(overridden.info)
if (stvars.nonEmpty) {
- debuglog("\t\tspecializedTVars: " + stvars)
+ debuglog("specialized override of %s by %s%s".format(overridden.fullLocationString, overriding.fullLocationString,
+ if (stvars.isEmpty) "" else stvars.map(_.name).mkString("(", ", ", ")")))
+
if (currentRun compiles overriding)
checkOverriddenTParams(overridden)
val env = unify(overridden.info, overriding.info, emptyEnv, false)
def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
- debuglog("\t\tenv: " + env + "isValid: " + TypeEnv.isValid(env, overridden) + "found: " + atNext)
- if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol)
+ if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) {
+ debuglog(" " + pp(env) + " found " + atNext)
return (overridden, env)
+ }
}
}
}
@@ -945,7 +946,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (NoSymbol, _) => None
case (overridden, env) =>
val om = specializedOverload(clazz, overridden, env)
- debuglog("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info))
+ debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info))
typeEnv(om) = env
addConcreteSpecMethod(overriding)
info(om) = (
@@ -993,7 +994,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) =>
- debuglog("Unify - basic case: " + tp1 + ", " + tp2)
+ debuglog("Unify " + tp1 + ", " + tp2)
if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
env + ((sym1, tp2))
else if (isSpecializedAnyRefSubtype(tp2, sym1))
@@ -1003,19 +1004,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else
env
case (TypeRef(_, sym1, args1), TypeRef(_, sym2, args2)) =>
- debuglog("Unify TypeRefs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - ")
+ if (args1.nonEmpty || args2.nonEmpty)
+ debuglog("Unify types " + tp1 + " and " + tp2)
+
if (strict && args1.length != args2.length) unifyError(tp1, tp2)
val e = unify(args1, args2, env, strict)
- debuglog("unified to: " + e)
+ if (e.nonEmpty) debuglog("unified to: " + e)
e
case (TypeRef(_, sym1, _), _) if sym1.isTypeParameterOrSkolem =>
env
case (MethodType(params1, res1), MethodType(params2, res2)) =>
if (strict && params1.length != params2.length) unifyError(tp1, tp2)
- debuglog("Unify MethodTypes: " + tp1 + " and " + tp2)
+ debuglog("Unify methods " + tp1 + " and " + tp2)
unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict)
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
- debuglog("Unify PolyTypes: " + tp1 + " and " + tp2)
+ debuglog("Unify polytypes " + tp1 + " and " + tp2)
if (strict && tparams1.length != tparams2.length)
unifyError(tp1, tp2)
else
@@ -1123,11 +1126,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (tparams.isEmpty)
afterSpecialize(parents map (_.typeSymbol.info))
- val parents1 = parents map specializedType
- debuglog("transformInfo %s %s with parents1 %s ph: %s".format(
- if (tparams.nonEmpty) " (poly)" else "",
- clazz, parents1, phase)
- )
+ val parents1 = parents mapConserve specializedType
+ if (parents ne parents1) {
+ debuglog("specialization transforms %s%s parents to %s".format(
+ if (tparams.nonEmpty) "(poly) " else "", clazz, parents1)
+ )
+ }
val newScope = newScopeWith(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz): _*)
// If tparams.isEmpty, this is just the ClassInfoType.
GenPolyType(tparams, ClassInfoType(parents1, newScope, clazz))
@@ -1253,7 +1257,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
override def traverse(tree: Tree) = tree match {
case DefDef(_, _, _, vparams :: Nil, _, rhs) =>
if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) {
- debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
+ // debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
body(tree.symbol) = rhs
// body(tree.symbol) = tree // whole method
parameters(tree.symbol) = vparams.map(_.symbol)
@@ -1559,7 +1563,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val env = typeEnv(symbol)
val boundTvars = env.keySet
val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam)))
- debuglog("substituting " + origtparams + " for " + symbol.typeParams)
+ if (origtparams.nonEmpty || symbol.typeParams.nonEmpty)
+ debuglog("substituting " + origtparams + " for " + symbol.typeParams)
// skolemize type parameters
val oldtparams = tparams map (_.symbol)
@@ -1656,7 +1661,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
buf +=
ClassDef(specCls, atPos(impl.pos)(Template(parents, emptyValDef, List()))
.setSymbol(specCls.newLocalDummy(sym1.pos))) setPos tree.pos
- debuglog("created synthetic class: " + specCls + " of " + sym1 + " in env: " + env)
+ debuglog("created synthetic class: " + specCls + " of " + sym1 + " in " + pp(env))
}
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index e54e0289bb..0efdd9ab9f 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -210,14 +210,15 @@ abstract class UnCurry extends InfoTransform
* body = expr match { case P_i if G_i => E_i }_i=1..n
* to:
*
+ //TODO: correct code template below
* class $anon() extends AbstractPartialFunction[T, R] with Serializable {
- * def apply(x: T): R = (expr: @unchecked) match {
+ * def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = (expr: @unchecked) match {
* case P_1 if G_1 => E_1
* ...
- * case P_n if G_n => true
- * case _ => this.missingCase(expr)
+ * case P_n if G_n => E_n
+ * case _ => default(expr)
* }
- * def _isDefinedAt(x: T): boolean = (x: @unchecked) match {
+ * def isDefinedAt(x: T): boolean = (x: @unchecked) match {
* case P_1 if G_1 => true
* ...
* case P_n if G_n => true
@@ -231,127 +232,107 @@ abstract class UnCurry extends InfoTransform
*
* def isDefinedAtCurrent(x: T): boolean = true
*/
- def transformFunction(fun: Function): Tree = {
- val fun1 = deEta(fun)
- def owner = fun.symbol.owner
- def targs = fun.tpe.typeArgs
- def isPartial = fun.tpe.typeSymbol == PartialFunctionClass
-
- // if the function was eta-expanded, it's not a match without a selector
- if (fun1 ne fun) fun1
- else {
- assert(!(opt.virtPatmat && isPartial)) // empty-selector matches have already been translated into instantiations of anonymous (partial) functions
- val (formals, restpe) = (targs.init, targs.last)
- val anonClass = owner.newAnonymousFunctionClass(fun.pos, inConstructorFlag)
- def parents =
- if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe)
- else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
- else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe)
-
- anonClass setInfo ClassInfoType(parents, newScope, anonClass)
- val applyMethod = anonClass.newMethod(nme.apply, fun.pos, FINAL)
- applyMethod setInfoAndEnter MethodType(applyMethod newSyntheticValueParams formals, restpe)
- anonClass addAnnotation serialVersionUIDAnnotation
-
- fun.vparams foreach (_.symbol.owner = applyMethod)
- fun.body.changeOwner(fun.symbol -> applyMethod)
-
- def missingCaseCall(scrutinee: Tree): Tree = Apply(Select(This(anonClass), nme.missingCase), List(scrutinee))
-
- def applyMethodDef() = {
- val body = localTyper.typedPos(fun.pos) {
- if (isPartial) gen.mkUncheckedMatch(gen.withDefaultCase(fun.body, missingCaseCall))
- else fun.body
- }
- // Have to repack the type to avoid mismatches when existentials
- // appear in the result - see SI-4869.
- val applyResultType = localTyper.packedType(body, applyMethod)
- DefDef(Modifiers(FINAL), nme.apply, Nil, List(fun.vparams), TypeTree(applyResultType), body) setSymbol applyMethod
- }
- def isDefinedAtMethodDef() = {
- val isDefinedAtName = {
- if (anonClass.info.member(nme._isDefinedAt) != NoSymbol) nme._isDefinedAt
- else nme.isDefinedAt
- }
- val m = anonClass.newMethod(isDefinedAtName, fun.pos, FINAL)
- val params = m newSyntheticValueParams formals
- m setInfoAndEnter MethodType(params, BooleanClass.tpe)
+ def transformFunction(fun: Function): Tree =
+ deEta(fun) match {
+ // nullary or parameterless
+ case fun1 if fun1 ne fun => fun1
+ case _ =>
+ def owner = fun.symbol.owner
+ def targs = fun.tpe.typeArgs
+ def isPartial = fun.tpe.typeSymbol == PartialFunctionClass
+ assert(!(opt.virtPatmat && isPartial)) // empty-selector matches have already been translated into instantiations of anonymous (partial) functions
- val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), params)
- def substTree[T <: Tree](t: T): T = substParam(resetLocalAttrs(t))
+ def parents =
+ if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe)
+ else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
+ else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe)
- object isDefinedAtTransformer extends gen.MatchMatcher {
- // TODO: optimize duplication, but make sure ValDef's introduced by wrap are treated correctly
- override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = {
- def transformCase(cdef: CaseDef): CaseDef =
- CaseDef(cdef.pat, cdef.guard, Literal(Constant(true)))
+ val anonClass = owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation serialVersionUIDAnnotation
+ anonClass setInfo ClassInfoType(parents, newScope, anonClass)
- def defaultCase = CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(false)))
+ val (formals, restpe) = (targs.init, targs.last)
-// val casesNoSynthCatchAll = dropSyntheticCatchAll(cases)
+ def applyMethodDef = {
+ val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
+ methSym setInfoAndEnter MethodType(methSym newSyntheticValueParams formals, restpe)
- gen.mkUncheckedMatch(
- if (cases exists treeInfo.isDefaultCase) Literal(Constant(true))
- else substTree(wrap(Match(selector, (cases map transformCase) :+ defaultCase)).duplicate)
- )
+ fun.vparams foreach (_.symbol.owner = methSym)
+ fun.body changeOwner (fun.symbol -> methSym)
+
+ val body = localTyper.typedPos(fun.pos)(fun.body)
+ val methDef = DefDef(methSym, List(fun.vparams), body)
+
+ // Have to repack the type to avoid mismatches when existentials
+ // appear in the result - see SI-4869.
+ methDef.tpt setType localTyper.packedType(body, methSym)
+ methDef
+ }
+
+ // def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ def applyOrElseMethodDef = {
+ val methSym = anonClass.newMethod(fun.pos, nme.applyOrElse) setFlag (FINAL | OVERRIDE)
+
+ val List(argtpe) = formals
+ val A1 = methSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argtpe)
+ val B1 = methSym newTypeParameter(newTypeName("B1")) setInfo TypeBounds.lower(restpe)
+ val methFormals = List(A1.tpe, functionType(List(A1.tpe), B1.tpe))
+ val params@List(x, default) = methSym newSyntheticValueParams methFormals
+ methSym setInfoAndEnter polyType(List(A1, B1), MethodType(params, B1.tpe))
+
+ val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), List(x))
+ val body = localTyper.typedPos(fun.pos) { import CODE._
+ gen.mkUncheckedMatch(gen.withDefaultCase(substParam(fun.body), scrut => REF(default) APPLY (REF(x))))
}
+ body.changeOwner(fun.symbol -> methSym)
+
+ val methDef = DefDef(methSym, body)
- override def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = {assert(false); orig}
- // {
- // object noOne extends Transformer {
- // override val treeCopy = newStrictTreeCopier // must duplicate everything
- // val one = _match.tpe member newTermName("one")
- // override def transform(tree: Tree): Tree = tree match {
- // case Apply(fun, List(a)) if fun.symbol == one =>
- // // blow one's argument away since all we want to know is whether the match succeeds or not
- // // (the alternative, making `one` CBN, would entail moving away from Option)
- // Apply(fun.duplicate, List(gen.mkZeroContravariantAfterTyper(a.tpe)))
- // case _ =>
- // super.transform(tree)
- // }
- // }
- // substTree(Apply(Apply(TypeApply(Select(_match.duplicate, _match.tpe.member(newTermName("isSuccess"))), targs map (_.duplicate)), List(scrut.duplicate)), List(noOne.transform(matcher))))
- // }
-
- override def caseVirtualizedMatchOpt(orig: Tree, zero: ValDef, x: ValDef, matchRes: ValDef, keepGoing: ValDef, stats: List[Tree], epilogue: Tree, wrap: Tree => Tree) = {assert(false); orig}
- // {
- // object dropMatchResAssign extends Transformer {
- // // override val treeCopy = newStrictTreeCopier // will duplicate below
- // override def transform(tree: Tree): Tree = tree match {
- // // don't compute the result of the match -- remove the block for the RHS (emitted by pmgen.one), except for the assignment to keepGoing
- // case gen.VirtualCaseDef(assignKeepGoing, matchRes, zero) if assignKeepGoing.lhs.symbol eq keepGoing.symbol =>
- // Block(List(assignKeepGoing), zero)
- // case _ =>
- // super.transform(tree)
- // }
- // }
- // val statsNoMatchRes: List[Tree] = stats map (dropMatchResAssign.transform) toList
- // val idaBlock = wrap(Block(
- // zero ::
- // x ::
- // /* drop matchRes def */
- // keepGoing ::
- // statsNoMatchRes,
- // NOT(REF(keepGoing.symbol)) // replace `if (keepGoing) throw new MatchError(...) else matchRes` epilogue by `!keepGoing`
- // ))
- // substTree(idaBlock.duplicate) // duplicate on block as a whole to ensure valdefs are properly cloned and substed
- // }
+ // Have to repack the type to avoid mismatches when existentials
+ // appear in the result - see SI-4869.
+ methDef.tpt setType localTyper.packedType(body, methSym)
+ methDef
}
- DefDef(m, isDefinedAtTransformer(fun.body))
- }
+ // duplicate before applyOrElseMethodDef is run so we start with the same symbols as applyOrElseMethodDef
+ // otherwise `TreeSymSubstituter(fun.vparams map (_.symbol), params)` won't work as the subst has been run already
+ val bodyForIDA = fun.body.duplicate
+ def isDefinedAtMethodDef = {
+ val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL)
+ val params = methSym newSyntheticValueParams formals
+ methSym setInfoAndEnter MethodType(params, BooleanClass.tpe)
+
+ val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), params)
+ def doSubst(x: Tree) = substParam(resetLocalAttrs(x)) // see pos/t1761 for why `resetLocalAttrs`
+ object isDefinedAtTransformer extends gen.MatchMatcher {
+ // TODO: optimize duplication, but make sure ValDef's introduced by wrap are treated correctly
+ override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = { import CODE._
+ gen.mkUncheckedMatch(
+ if (cases exists treeInfo.isDefaultCase) TRUE_typed
+ else
+ doSubst(wrap(
+ Match(selector,
+ (cases map (c => deriveCaseDef(c)(x => TRUE_typed))) :+ (
+ DEFAULT ==> FALSE_typed)
+ )))
+ )
+ }
+ }
+ val body = isDefinedAtTransformer(bodyForIDA)
+ body.changeOwner(fun.symbol -> methSym)
- val members =
- if (isPartial) List(applyMethodDef, isDefinedAtMethodDef)
- else List(applyMethodDef)
+ DefDef(methSym, body)
+ }
+
+ val members =
+ if (isPartial) List(applyOrElseMethodDef, isDefinedAtMethodDef)
+ else List(applyMethodDef)
- localTyper.typedPos(fun.pos) {
- Block(
- List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos)),
- Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
+ localTyper.typedPos(fun.pos) {
+ Block(
+ List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos)),
+ Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
+ }
}
- }
- }
def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]) = {
val isJava = fun.isJavaDefined
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 764823d786..49ddb985dc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -317,7 +317,7 @@ trait ContextErrors {
}
withAddendum(qual.pos)(
if (name == nme.CONSTRUCTOR) target + " does not have a constructor"
- else nameString + " is not a member of " + targetKindString + target + addendum
+ else nameString + " is not a member of " + targetKindString + target.directObjectString + addendum
)
}
issueNormalTypeError(sel, errMsg)
@@ -677,7 +677,7 @@ trait ContextErrors {
def AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String) = {
def errMsg = {
- val location = if (sym.isClassConstructor) owner0 else pre.widen
+ val location = if (sym.isClassConstructor) owner0 else pre.widen.directObjectString
underlyingSymbol(sym).fullLocationString + " cannot be accessed in " +
location + explanation
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index eb0d489901..f6d1e42c32 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -79,7 +79,17 @@ abstract class Duplicators extends Analyzer {
override def mapOver(tpe: Type): Type = tpe match {
case TypeRef(NoPrefix, sym, args) if sym.isTypeParameterOrSkolem =>
- val sym1 = context.scope.lookup(sym.name)
+ var sym1 = context.scope.lookup(sym.name)
+ if (sym1 eq NoSymbol) {
+ // try harder (look in outer scopes)
+ // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen)
+ BodyDuplicator.super.silent(_.typedType(Ident(sym.name))) match {
+ case SilentResultValue(t) =>
+ sym1 = t.symbol
+ debuglog("fixed by trying harder: "+(sym, sym1, context))
+ case _ =>
+ }
+ }
// assert(sym1 ne NoSymbol, tpe)
if ((sym1 ne NoSymbol) && (sym1 ne sym)) {
debuglog("fixing " + sym + " -> " + sym1)
@@ -255,7 +265,10 @@ abstract class Duplicators extends Analyzer {
case ldef @ LabelDef(name, params, rhs) =>
// log("label def: " + ldef)
+ // in case the rhs contains any definitions -- TODO: is this necessary?
+ invalidate(rhs)
ldef.tpe = null
+
// since typer does not create the symbols for a LabelDef's params,
// we do that manually here -- we should really refactor LabelDef to be a subclass of DefDef
def newParam(p: Tree): Ident = {
@@ -265,6 +278,7 @@ abstract class Duplicators extends Analyzer {
val params1 = params map newParam
val rhs1 = (new TreeSubstituter(params map (_.symbol), params1) transform rhs) // TODO: duplicate?
rhs1.tpe = null
+
super.typed(treeCopy.LabelDef(tree, name, params1, rhs1), mode, pt)
case Bind(name, _) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 6b27c27652..8604366bf2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -315,9 +315,10 @@ trait Namers extends MethodSynthesis {
case DefDef(_, _, _, _, _, _) => owner.newMethod(name.toTermName, pos, flags)
case ClassDef(_, _, _, _) => owner.newClassSymbol(name.toTypeName, pos, flags)
case ModuleDef(_, _, _) => owner.newModule(name, pos, flags)
- case ValDef(_, _, _, _) if isParameter => owner.newValueParameter(name, pos, flags)
case PackageDef(pid, _) => createPackageSymbol(pos, pid)
- case ValDef(_, _, _, _) => owner.newValue(name, pos, flags)
+ case ValDef(_, _, _, _) =>
+ if (isParameter) owner.newValueParameter(name, pos, flags)
+ else owner.newValue(name, pos, flags)
}
}
private def createFieldSymbol(tree: ValDef): TermSymbol =
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 013a74da7e..045614e773 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -267,6 +267,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
sym1.locationString +
(if (sym1.isAliasType) ", which equals "+self.memberInfo(sym1)
else if (sym1.isAbstractType) " with bounds"+self.memberInfo(sym1)
+ else if (sym1.isModule) ""
else if (sym1.isTerm) " of type "+self.memberInfo(sym1)
else "")
else "")
@@ -394,9 +395,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("needs `override' modifier")
} else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) {
overrideError("needs `abstract override' modifiers")
- } else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) {
- overrideError("cannot override a mutable variable")
- } else if (member.isAnyOverride &&
+ }
+ else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) {
+ // !?! this is not covered by the spec. We need to resolve this either by changing the spec or removing the test here.
+ // !!! is there a !?! convention? I'm !!!ing this to make sure it turns up on my searches.
+ if (!settings.overrideVars.value)
+ overrideError("cannot override a mutable variable")
+ }
+ else if (member.isAnyOverride &&
!(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) &&
!member.isDeferred && !other.isDeferred &&
intersectionIsEmpty(member.extendedOverriddenSymbols, other.extendedOverriddenSymbols)) {
@@ -1248,9 +1254,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
List(tree1)
}
- case Import(_, _) => Nil
+ case Import(_, _) => Nil
case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) => Nil
- case _ => List(transform(tree))
+ case _ => List(transform(tree))
}
/* Check whether argument types conform to bounds of type parameters */
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 4248b6f024..94733369a8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -259,7 +259,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case sel @ Select(Super(_, mix), name) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
- unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
+ 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")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 06a7311f79..2aff00f6a5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -235,32 +235,41 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
result
}
}
+ def isNonRefinementClassType(tpe: Type) = tpe match {
+ case SingleType(_, sym) => sym.isModuleClass
+ case TypeRef(_, sym, _) => sym.isClass && !sym.isRefinementClass
+ case ErrorType => true
+ case _ => false
+ }
+ private def errorNotClass(tpt: Tree, found: Type) = { ClassTypeRequiredError(tpt, found); false }
+ private def errorNotStable(tpt: Tree, found: Type) = { TypeNotAStablePrefixError(tpt, found); false }
/** Check that `tpt` refers to a non-refinement class type */
- def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean): Boolean = {
- def errorNotClass(found: AnyRef) = { ClassTypeRequiredError(tpt, found); false }
- def check(tpe: Type): Boolean = tpe.normalize match {
- case TypeRef(pre, sym, _) if sym.isClass && !sym.isRefinementClass =>
- if (stablePrefix && !isPastTyper)
- if (!pre.isStable) {
- TypeNotAStablePrefixError(tpt, pre)
- false
- } else
- // A type projection like X#Y can get by the stable check if the
- // prefix is singleton-bounded, so peek at the tree too.
- tpt match {
- case SelectFromTypeTree(qual, _) if !isSingleType(qual.tpe) => errorNotClass(tpt)
- case _ => true
- }
- else
- true
- case ErrorType => true
- case PolyType(_, restpe) => check(restpe)
- case ExistentialType(_, restpe) if existentialOK => check(restpe)
- case AnnotatedType(_, underlying, _) => check(underlying)
- case t => errorNotClass(t)
+ def checkClassType(tpt: Tree): Boolean = {
+ val tpe = unwrapToClass(tpt.tpe)
+ isNonRefinementClassType(tpe) || errorNotClass(tpt, tpe)
+ }
+
+ /** Check that `tpt` refers to a class type with a stable prefix. */
+ def checkStablePrefixClassType(tpt: Tree): Boolean = {
+ val tpe = unwrapToStableClass(tpt.tpe)
+ def prefixIsStable = {
+ def checkPre = tpe match {
+ case TypeRef(pre, _, _) => pre.isStable || errorNotStable(tpt, pre)
+ case _ => false
+ }
+ // A type projection like X#Y can get by the stable check if the
+ // prefix is singleton-bounded, so peek at the tree too.
+ def checkTree = tpt match {
+ case SelectFromTypeTree(qual, _) => isSingleType(qual.tpe) || errorNotClass(tpt, tpe)
+ case _ => true
+ }
+ checkPre && checkTree
}
- check(tpt.tpe)
+
+ ( (isNonRefinementClassType(tpe) || errorNotClass(tpt, tpe))
+ && (isPastTyper || prefixIsStable)
+ )
}
/** Check that type <code>tp</code> is not a subtype of itself.
@@ -643,13 +652,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- private def isNarrowable(tpe: Type): Boolean = tpe match {
+ private def isNarrowable(tpe: Type): Boolean = unwrapWrapperTypes(tpe) match {
case TypeRef(_, _, _) | RefinedType(_, _) => true
- case ExistentialType(_, tpe1) => isNarrowable(tpe1)
- case AnnotatedType(_, tpe1, _) => isNarrowable(tpe1)
- case PolyType(_, tpe1) => isNarrowable(tpe1)
- case NullaryMethodType(tpe1) => isNarrowable(tpe1)
- case _ => !phase.erasedTypes
+ case _ => !phase.erasedTypes
}
/**
@@ -1438,7 +1443,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def validateParentClass(parent: Tree, superclazz: Symbol) {
if (!parent.isErrorTyped) {
val psym = parent.tpe.typeSymbol.initialize
- checkClassType(parent, false, true)
+ checkStablePrefixClassType(parent)
if (psym != superclazz) {
if (psym.isTrait) {
val ps = psym.info.parents
@@ -2186,17 +2191,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
anonClass addAnnotation serialVersionUIDAnnotation
- def mkParams(methodSym: Symbol) = {
+ def deriveFormals =
+ selOverride match {
+ case None if targs.isEmpty => Nil
+ case None => targs.init // is there anything we can do if targs.isEmpty??
+ case Some((vparams, _)) =>
+ vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe}
+ }
+
+ def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = {
selOverride match {
case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree)
case None =>
- val ps = methodSym newSyntheticValueParams targs.init // is there anything we can do if targs.isEmpty??
+ val ps = methodSym newSyntheticValueParams formals // is there anything we can do if targs.isEmpty??
val ids = ps map (p => Ident(p.name))
val sel = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
(ps, sel)
case Some((vparams, sel)) =>
- val newParamSyms = vparams map {p =>
- val tp = if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe
+ val newParamSyms = (vparams, formals).zipped map {(p, tp) =>
methodSym.newValueParameter(p.name, focusPos(p.pos), SYNTHETIC) setInfo tp
}
@@ -2209,7 +2221,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up
val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => TRUE_typed).duplicate) else Nil
- val applyMethod = {
+ def applyMethod = {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL)
@@ -2224,25 +2236,59 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes)
- val formalTypes = paramSyms map (_.tpe)
- val parents =
- if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, List(formalTypes.head, resTp)), SerializableClass.tpe)
- else List(appliedType(AbstractFunctionClass(arity).typeConstructor, formalTypes :+ resTp), SerializableClass.tpe)
+ val methFormals = paramSyms map (_.tpe)
+ val parents = List(appliedType(AbstractFunctionClass(arity).typeConstructor, methFormals :+ resTp), SerializableClass.tpe)
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
methodSym setInfoAndEnter MethodType(paramSyms, resTp)
- // use apply's parameter since the scrut's type has been widened
- def missingCase(scrut_ignored: Tree) = (funThis DOT nme.missingCase) (REF(paramSyms.head))
+ DefDef(methodSym, methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation))
+ }
+ }
+
+ // def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ def applyOrElseMethodDef = {
+ // rig the show so we can get started typing the method body -- later we'll correct the infos...
+ // targs were type arguments for PartialFunction, so we know they will work for AbstractPartialFunction as well
+ def parents(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
+
+ anonClass setInfo ClassInfoType(parents(targs), newScope, anonClass)
+ val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE)
+
+ // create the parameter that corresponds to the function's parameter
+ val List(argTp) = deriveFormals
+ val A1 = methodSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argTp)
+ val (List(x), selector) = mkParams(methodSym, List(A1.tpe))
+
+ if (selector eq EmptyTree) EmptyTree
+ else {
+ // applyOrElse's default parameter:
+ val B1 = methodSym newTypeParameter(newTypeName("B1")) setInfo TypeBounds.empty //lower(resTp)
+ val default = methodSym newValueParameter(newTermName("default"), focusPos(tree.pos), SYNTHETIC) setInfo functionType(List(A1.tpe), B1.tpe)
+
+ val paramSyms = List(x, default)
+ methodSym setInfoAndEnter polyType(List(A1, B1), MethodType(paramSyms, B1.tpe))
+
+ val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
+ paramSyms foreach (methodBodyTyper.context.scope enter _)
+
+ val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes)
+
+ anonClass setInfo ClassInfoType(parents(List(argTp, resTp)), newScope, anonClass)
+ B1 setInfo TypeBounds.lower(resTp)
+ anonClass.info.decls enter methodSym // methodSym's info need not change (B1's bound has been updated instead)
+
+ // use applyOrElse's first parameter since the scrut's type has been widened
+ def doDefault(scrut_ignored: Tree) = REF(default) APPLY (REF(x))
- val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation, if (isPartial) Some(missingCase) else None)
+ val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, B1.tpe, doTranslation, Some(doDefault))
DefDef(methodSym, body)
}
}
def isDefinedAtMethod = {
- val methodSym = anonClass.newMethod(nme._isDefinedAt, tree.pos, FINAL)
+ val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL)
val (paramSyms, selector) = mkParams(methodSym)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2257,7 +2303,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- val members = if (!isPartial) List(applyMethod) else List(applyMethod, isDefinedAtMethod)
+ val members = if (!isPartial) List(applyMethod) else List(applyOrElseMethodDef, isDefinedAtMethod)
if (members.head eq EmptyTree) setError(tree)
else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
}
@@ -3312,7 +3358,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
- if (!checkClassType(tpt, true, false) && noGen) tpt
+ if (!checkClassType(tpt) && noGen) tpt
else atPos(tree.pos)(gen.mkClassOf(tpt.tpe))
protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = {
@@ -3624,7 +3670,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedNew(tpt: Tree) = {
val tpt1 = {
val tpt0 = typedTypeConstructor(tpt)
- if (checkClassType(tpt0, false, true))
+ if (checkStablePrefixClassType(tpt0))
if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
TypeTree().setOriginal(tpt0)
@@ -4142,7 +4188,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
var cx = startingIdentContext
- while (defSym == NoSymbol && cx != NoContext) {
+ while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
// !!! Shouldn't the argument to compileSourceFor be cx, not context?
// I can't tell because those methods do nothing in the standard compiler,
// presumably they are overridden in the IDE.
diff --git a/src/library/scala/Function.scala b/src/library/scala/Function.scala
index 4a10b65735..9fa56a332f 100644
--- a/src/library/scala/Function.scala
+++ b/src/library/scala/Function.scala
@@ -29,6 +29,7 @@ object Function {
/** Turns a function `A => Option[B]` into a `PartialFunction[A, B]`.
*
+ * TODO: check if the paragraph below is still correct
* '''Important note''': this transformation implies the original function
* will be called 2 or more times on each logical invocation, because the
* only way to supply an implementation of `isDefinedAt` is to call the
@@ -39,11 +40,7 @@ object Function {
* f returns `Some(_)` and undefined where `f` returns `None`.
* @see [[scala.PartialFunction#lift]]
*/
- def unlift[T, R](f: T => Option[R]): PartialFunction[T, R] = new runtime.AbstractPartialFunction[T, R] {
- def apply(x: T): R = f(x).get
- def _isDefinedAt(x: T): Boolean = f(x).isDefined
- override def lift: T => Option[R] = f
- }
+ def unlift[T, R](f: T => Option[R]): PartialFunction[T, R] = PartialFunction.unlifted(f)
/** Uncurrying for functions of arity 2. This transforms a unary function
* returning another unary function into a function of arity 2.
diff --git a/src/library/scala/PartialFunction.scala b/src/library/scala/PartialFunction.scala
index 3c5d6d0d23..7154b8da34 100644
--- a/src/library/scala/PartialFunction.scala
+++ b/src/library/scala/PartialFunction.scala
@@ -8,6 +8,7 @@
package scala
+
/** A partial function of type `PartialFunction[A, B]` is a unary function
* where the domain does not necessarily include all values of type `A`.
* The function `isDefinedAt` allows to test dynamically if a value is in
@@ -43,10 +44,11 @@ package scala
* }}}
*
*
- * @author Martin Odersky
+ * @author Martin Odersky, Pavel Pavlov, Adriaan Moors
* @version 1.0, 16/07/2003
*/
-trait PartialFunction[-A, +B] extends (A => B) {
+trait PartialFunction[-A, +B] extends (A => B) { self =>
+ import PartialFunction._
/** Checks if a value is contained in the function's domain.
*
@@ -55,10 +57,6 @@ trait PartialFunction[-A, +B] extends (A => B) {
*/
def isDefinedAt(x: A): Boolean
- //protected def missingCase[A1 <: A, B1 >: B]: PartialFunction[A1, B1] = PartialFunction.empty
-
- protected def missingCase(x: A): B = throw new MatchError(x)
-
/** Composes this partial function with a fallback partial function which
* gets applied where this partial function is not defined.
*
@@ -70,16 +68,8 @@ trait PartialFunction[-A, +B] extends (A => B) {
* takes `x` to `this(x)` where `this` is defined, and to `that(x)` where it is not.
*/
def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] =
- new runtime.AbstractPartialFunction[A1, B1] {
- def _isDefinedAt(x: A1): Boolean =
- PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x)
- def apply(x: A1): B1 =
- if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x)
- else that.apply(x)
- }
-
- def orElseFast[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] =
- orElse(that)
+ new OrElse[A1, B1] (this, that)
+ //TODO: why not overload it with orElse(that: F1): F1?
/** Composes this partial function with a transformation function that
* gets applied to results of this partial function.
@@ -88,9 +78,9 @@ trait PartialFunction[-A, +B] extends (A => B) {
* @return a partial function with the same domain as this partial function, which maps
* arguments `x` to `k(this(x))`.
*/
- override def andThen[C](k: B => C) : PartialFunction[A, C] = new runtime.AbstractPartialFunction[A, C] {
- def _isDefinedAt(x: A): Boolean = PartialFunction.this.isDefinedAt(x)
- def apply(x: A): C = k(PartialFunction.this.apply(x))
+ override def andThen[C](k: B => C) : PartialFunction[A, C] = new PartialFunction[A, C] {
+ def isDefinedAt(x: A): Boolean = self isDefinedAt x
+ def apply(x: A): C = k(self(x))
}
/** Turns this partial function into an plain function returning an `Option` result.
@@ -98,9 +88,30 @@ trait PartialFunction[-A, +B] extends (A => B) {
* @return a function that takes an argument `x` to `Some(this(x))` if `this`
* is defined for `x`, and to `None` otherwise.
*/
- def lift: A => Option[B] = new (A => Option[B]) {
- def apply(x: A): Option[B] = if (isDefinedAt(x)) Some(PartialFunction.this.apply(x)) else None
- }
+ def lift: A => Option[B] = new Lifted(this)
+
+ /**
+ * TODO: comment
+ * @since 2.10
+ */
+ def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ if (isDefinedAt(x)) apply(x) else default(x)
+
+ /**
+ * TODO: comment
+ * @since 2.10
+ */
+ def run[U](x: A)(action: B => U): Boolean =
+ applyOrElse(x, fallbackToken) match {
+ case FallbackToken => false
+ case z => action(z); true
+ }
+
+ /**
+ * TODO: comment
+ * @since 2.10
+ */
+ def runWith[U](action: B => U): A => Boolean = { x => run(x)(action) }
}
/** A few handy operations which leverage the extra bit of information
@@ -119,14 +130,73 @@ trait PartialFunction[-A, +B] extends (A => B) {
* @since 2.8
*/
object PartialFunction {
- private[this] final val empty_pf: PartialFunction[Any, Nothing] = new runtime.AbstractPartialFunction[Any, Nothing] {
- def _isDefinedAt(x: Any) = false
- override def isDefinedAt(x: Any) = false
- def apply(x: Any): Nothing = throw new MatchError(x)
- override def orElse[A1, B1](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = that
- override def orElseFast[A1, B1](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = that
- override def lift = (x: Any) => None
+ /** Composite function produced by `PartialFunction#orElse` method
+ */
+ private final class OrElse[-A, +B] (f1: PartialFunction[A, B], f2: PartialFunction[A, B]) extends PartialFunction[A, B] {
+ def isDefinedAt(x: A) = f1.isDefinedAt(x) || f2.isDefinedAt(x)
+
+ def apply(x: A): B = f1.applyOrElse(x, f2)
+
+ override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ f1.applyOrElse(x, fallbackToken) match {
+ case FallbackToken => f2.applyOrElse(x, default)
+ case z => z
+ }
+
+ override def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]) =
+ new OrElse[A1, B1] (f1, f2 orElse that)
+
+ override def andThen[C](k: B => C) =
+ new OrElse[A, C] (f1 andThen k, f2 andThen k)
}
+
+ private[scala] lazy val FallbackToken: PartialFunction[Any, PartialFunction[Any, Nothing]] = { case _ => FallbackToken.asInstanceOf[PartialFunction[Any, Nothing]] }
+ private[scala] final def fallbackToken[B] = FallbackToken.asInstanceOf[PartialFunction[Any, B]]
+ //TODO: check generated code for PF literal here
+
+ private[scala] final class Lifted[-A, +B] (val pf: PartialFunction[A, B])
+ extends runtime.AbstractFunction1[A, Option[B]] {
+
+ def apply(x: A): Option[B] = pf.applyOrElse(x, fallbackToken) match {
+ case FallbackToken => None
+ case z => Some(z)
+ }
+ }
+
+ private final class Unlifted[A, B] (f: A => Option[B]) extends runtime.AbstractPartialFunction[A, B] {
+ def isDefinedAt(x: A): Boolean = f(x).isDefined
+ override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ f(x) getOrElse default(x) //TODO: check generated code and inline getOrElse if needed
+ override def lift = f
+ }
+
+ private[scala] def unlifted[A, B](f: A => Option[B]): PartialFunction[A, B] = f match {
+ case lf: Lifted[A, B] => lf.pf
+ case ff => new Unlifted(ff)
+ }
+
+ /** Converts ordinary function to partial one
+ * @since 2.10
+ */
+ //TODO: check generated code for PF literal here
+ def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) }
+
+ private[this] final val constFalse: Any => Boolean = { _ => false}
+
+ private[this] final val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] {
+ def isDefinedAt(x: Any) = false
+ def apply(x: Any) = throw new MatchError(x)
+ override def orElse[A1, B1](that: PartialFunction[A1, B1]) = that
+ override def andThen[C](k: Nothing => C) = this
+ override val lift = (x: Any) => None
+ override def run[U](x: Any)(action: Nothing => U) = false
+ override def runWith[U](action: Nothing => U) = constFalse
+ }
+
+ /**
+ * TODO: comment
+ * @since 2.10
+ */
def empty[A, B] : PartialFunction[A, B] = empty_pf
/** Creates a Boolean test based on a value and a partial function.
@@ -137,8 +207,7 @@ object PartialFunction {
* @param pf the partial function
* @return true, iff `x` is in the domain of `pf` and `pf(x) == true`.
*/
- def cond[T](x: T)(pf: PartialFunction[T, Boolean]): Boolean =
- (pf isDefinedAt x) && pf(x)
+ def cond[T](x: T)(pf: PartialFunction[T, Boolean]): Boolean = pf.applyOrElse(x, constFalse)
/** Transforms a PartialFunction[T, U] `pf` into Function1[T, Option[U]] `f`
* whose result is `Some(x)` if the argument is in `pf`'s domain and `None`
@@ -150,6 +219,5 @@ object PartialFunction {
* @param pf the PartialFunction[T, U]
* @return `Some(pf(x))` if `pf isDefinedAt x`, `None` otherwise.
*/
- def condOpt[T,U](x: T)(pf: PartialFunction[T, U]): Option[U] =
- if (pf isDefinedAt x) Some(pf(x)) else None
+ def condOpt[T,U](x: T)(pf: PartialFunction[T, U]): Option[U] = pf.lift(x)
}
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 75ab3f28f5..a978a9a783 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -127,3 +127,5 @@ object JavaConversions extends WrapAsScala with WrapAsJava {
@deprecated("use propertiesAsScalaMap instead", "2.9.0")
def asScalaMap(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p)
}
+
+
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
index 13f1f19f81..f8a9466caf 100755
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -100,4 +100,4 @@ object JavaConverters extends DecorateAsJava with DecorateAsScala {
@deprecated("Use propertiesAsScalaMapConverter instead", "2.9.0")
def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] = propertiesAsScalaMapConverter(p)
-} \ No newline at end of file
+}
diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala
index 76837d937c..e05bfc41cd 100644
--- a/src/library/scala/collection/convert/DecorateAsJava.scala
+++ b/src/library/scala/collection/convert/DecorateAsJava.scala
@@ -291,6 +291,26 @@ trait DecorateAsJava {
* @return An object with an `asJava` method that returns a Java
* `ConcurrentMap` view of the argument.
*/
+ @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
implicit def asJavaConcurrentMapConverter[A, B](m: mutable.ConcurrentMap[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
new AsJava(asJavaConcurrentMap(m))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable
+ * `concurrent.Map` to a Java `ConcurrentMap`.
+ *
+ * The returned Java `ConcurrentMap` is backed by the provided Scala
+ * `concurrent.Map` and any side-effects of using it via the Java interface
+ * will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `concurrent.Map` was previously obtained from an implicit or
+ * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * then the original Java `ConcurrentMap` will be returned.
+ *
+ * @param m The Scala `concurrent.Map` to be converted.
+ * @return An object with an `asJava` method that returns a Java
+ * `ConcurrentMap` view of the argument.
+ */
+ implicit def asJavaConcurrentMapConverter[A, B](m: concurrent.Map[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
+ new AsJava(asJavaConcurrentMap(m))
}
diff --git a/src/library/scala/collection/convert/DecorateAsScala.scala b/src/library/scala/collection/convert/DecorateAsScala.scala
index bb14228e67..722f0b9af9 100644
--- a/src/library/scala/collection/convert/DecorateAsScala.scala
+++ b/src/library/scala/collection/convert/DecorateAsScala.scala
@@ -156,10 +156,29 @@ trait DecorateAsScala {
* @return An object with an `asScala` method that returns a Scala mutable
* `ConcurrentMap` view of the argument.
*/
- implicit def asScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[mutable.ConcurrentMap[A, B]] =
+ @deprecated("Use `mapAsScalaConcurrentMapConverter` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
+ def asScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[mutable.ConcurrentMap[A, B]] =
new AsScala(asScalaConcurrentMap(m))
/**
+ * Adds an `asScala` method that implicitly converts a Java `ConcurrentMap`
+ * to a Scala mutable `concurrent.Map`. The returned Scala `concurrent.Map` is
+ * backed by the provided Java `ConcurrentMap` and any side-effects of using
+ * it via the Scala interface will be visible via the Java interface and
+ * vice versa.
+ *
+ * If the Java `ConcurrentMap` was previously obtained from an implicit or
+ * explicit call of `mapAsScalaConcurrentMap(scala.collection.mutable.ConcurrentMap)`
+ * then the original Scala `concurrent.Map` will be returned.
+ *
+ * @param m The `ConcurrentMap` to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable
+ * `concurrent.Map` view of the argument.
+ */
+ implicit def mapAsScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[concurrent.Map[A, B]] =
+ new AsScala(mapAsScalaConcurrentMap(m))
+
+ /**
* Adds an `asScala` method that implicitly converts a Java `Dictionary`
* to a Scala mutable `Map[String, String]`. The returned Scala
* `Map[String, String]` is backed by the provided Java `Dictionary` and
diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala
index 6274518d1a..cdec72b9fe 100644
--- a/src/library/scala/collection/convert/WrapAsJava.scala
+++ b/src/library/scala/collection/convert/WrapAsJava.scala
@@ -241,16 +241,45 @@ trait WrapAsJava {
* will be visible via the Scala interface and vice versa.
*
* If the Scala `ConcurrentMap` was previously obtained from an implicit or
- * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * explicit call of `asScalaConcurrentMap(java.util.concurrect.ConcurrentMap)`
* then the original Java ConcurrentMap will be returned.
*
* @param m The `ConcurrentMap` to be converted.
* @return A Java `ConcurrentMap` view of the argument.
*/
+ @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
implicit def asJavaConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = m match {
+ case JConcurrentMapDeprecatedWrapper(wrapped) => wrapped
+ case _ => new ConcurrentMapDeprecatedWrapper(m)
+ }
+
+ /**
+ * Implicitly converts a Scala mutable `concurrent.Map` to a Java
+ * `ConcurrentMap`.
+ *
+ * The returned Java `ConcurrentMap` is backed by the provided Scala
+ * `concurrent.Map` and any side-effects of using it via the Java interface
+ * will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `concurrent.Map` was previously obtained from an implicit or
+ * explicit call of `mapAsScalaConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * then the original Java ConcurrentMap will be returned.
+ *
+ * @param m The Scala `concurrent.Map` to be converted.
+ * @return A Java `ConcurrentMap` view of the argument.
+ */
+ implicit def asJavaConcurrentMap[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = m match {
case JConcurrentMapWrapper(wrapped) => wrapped
case _ => new ConcurrentMapWrapper(m)
}
}
object WrapAsJava extends WrapAsJava { }
+
+
+
+
+
+
+
+
diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala
index 02b58f55a4..56e13b2105 100644
--- a/src/library/scala/collection/convert/WrapAsScala.scala
+++ b/src/library/scala/collection/convert/WrapAsScala.scala
@@ -154,9 +154,28 @@ trait WrapAsScala {
* @param m The ConcurrentMap to be converted.
* @return A Scala mutable ConcurrentMap view of the argument.
*/
- implicit def asScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match {
- case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying
- case _ => new JConcurrentMapWrapper(m)
+ @deprecated("Use `mapAsScalaConcurrentMap` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
+ def asScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match {
+ case cmw: ConcurrentMapDeprecatedWrapper[a, b] => cmw.underlying
+ case _ => new JConcurrentMapDeprecatedWrapper(m)
+ }
+
+ /**
+ * Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap.
+ * The returned Scala ConcurrentMap is backed by the provided Java
+ * ConcurrentMap and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ *
+ * If the Java ConcurrentMap was previously obtained from an implicit or
+ * explicit call of `asConcurrentMap(scala.collection.mutable.ConcurrentMap)`
+ * then the original Scala ConcurrentMap will be returned.
+ *
+ * @param m The ConcurrentMap to be converted.
+ * @return A Scala mutable ConcurrentMap view of the argument.
+ */
+ implicit def mapAsScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = m match {
+ case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying
+ case _ => new JConcurrentMapWrapper(m)
}
/**
diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala
index 8136e462cb..b1b48b760f 100644
--- a/src/library/scala/collection/convert/Wrappers.scala
+++ b/src/library/scala/collection/convert/Wrappers.scala
@@ -268,7 +268,7 @@ private[collection] trait Wrappers {
override def empty = JMapWrapper(new ju.HashMap[A, B])
}
- class ConcurrentMapWrapper[A, B](override val underlying: mutable.ConcurrentMap[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
+ class ConcurrentMapDeprecatedWrapper[A, B](override val underlying: mutable.ConcurrentMap[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
case Some(v) => v
@@ -290,7 +290,54 @@ private[collection] trait Wrappers {
def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
}
- case class JConcurrentMapWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with mutable.ConcurrentMap[A, B] {
+ class ConcurrentMapWrapper[A, B](override val underlying: concurrent.Map[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
+
+ def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def remove(k: AnyRef, v: AnyRef) = try {
+ underlying.remove(k.asInstanceOf[A], v.asInstanceOf[B])
+ } catch {
+ case ex: ClassCastException =>
+ false
+ }
+
+ def replace(k: A, v: B): B = underlying.replace(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
+ }
+
+ case class JConcurrentMapDeprecatedWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapDeprecatedWrapper[A, B]] with mutable.ConcurrentMap[A, B] {
+ override def get(k: A) = {
+ val v = underlying get k
+ if (v != null) Some(v)
+ else None
+ }
+
+ override def empty = new JConcurrentMapDeprecatedWrapper(new juc.ConcurrentHashMap[A, B])
+
+ def putIfAbsent(k: A, v: B): Option[B] = {
+ val r = underlying.putIfAbsent(k, v)
+ if (r != null) Some(r) else None
+ }
+
+ def remove(k: A, v: B): Boolean = underlying.remove(k, v)
+
+ def replace(k: A, v: B): Option[B] = {
+ val prev = underlying.replace(k, v)
+ if (prev != null) Some(prev) else None
+ }
+
+ def replace(k: A, oldvalue: B, newvalue: B): Boolean =
+ underlying.replace(k, oldvalue, newvalue)
+ }
+
+ case class JConcurrentMapWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with concurrent.Map[A, B] {
override def get(k: A) = {
val v = underlying get k
if (v != null) Some(v)
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 870c179b2d..1b75c10113 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -58,7 +58,7 @@ import java.io._
* @author Martin Odersky and others
* @version 2.8
* @since 1.0
- * @see [["http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists" "Scala's Collection Library overview"]]
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#lists "Scala's Collection Library overview"]]
* section on `Lists` for more information.
*
* @define coll list
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index cc0aed6963..06b7d40bfc 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -366,7 +366,7 @@ private[collection] object HashTable {
private[collection] final def newThreshold(_loadFactor: Int, size: Int) = ((size.toLong * _loadFactor) / loadFactorDenum).toInt
- private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = thr * loadFactorDenum / _loadFactor
+ private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = ((thr.toLong * loadFactorDenum) / _loadFactor).toInt
private[collection] final def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala
index 8fad131009..b70df05c55 100644
--- a/src/library/scala/collection/mutable/Stack.scala
+++ b/src/library/scala/collection/mutable/Stack.scala
@@ -44,7 +44,7 @@ object Stack extends SeqFactory[Stack] {
* @author Martin Odersky
* @version 2.8
* @since 1
- * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks"Scala's Collection Library overview"]]
+ * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks "Scala's Collection Library overview"]]
* section on `Stacks` for more information.
* @define Coll Stack
* @define coll stack
diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
index 49b00bebdb..e630a9dbed 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
@@ -36,7 +36,9 @@ import collection.parallel.Task
*
* @author Aleksandar Prokopec
* @since 2.9
- *
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tries for more information.
+ *
* @define Coll immutable.ParHashMap
* @define coll immutable parallel hash map
*/
diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
index 11d92a27c9..084637c5dc 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
@@ -35,6 +35,8 @@ import collection.parallel.Task
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tries for more information.
*
* @define Coll immutable.ParHashSet
* @define coll immutable parallel hash set
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index 9cac433460..277fd5fdd3 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -25,6 +25,8 @@ import scala.collection.Iterator
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_range Scala's Parallel Collections Library overview]]
+ * section on `ParRange` for more information.
*
* @define Coll immutable.ParRange
* @define coll immutable parallel range
diff --git a/src/library/scala/collection/parallel/immutable/ParVector.scala b/src/library/scala/collection/parallel/immutable/ParVector.scala
index 5d9c431bc1..8baa84b77c 100644
--- a/src/library/scala/collection/parallel/immutable/ParVector.scala
+++ b/src/library/scala/collection/parallel/immutable/ParVector.scala
@@ -34,6 +34,8 @@ import immutable.VectorIterator
*
* @author Aleksandar Prokopec
* @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_vector Scala's Parallel Collections Library overview]]
+ * section on `ParVector` for more information.
*
* @define Coll immutable.ParVector
* @define coll immutable parallel vector
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index c33495bd39..8cc0b95997 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -44,10 +44,14 @@ import scala.collection.GenTraversableOnce
*
* @tparam T type of the elements in the array
*
+ * @author Aleksandar Prokopec
+ * @since 2.9
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_array Scala's Parallel Collections Library overview]]
+ * section on `ParArray` for more information.
+ *
* @define Coll ParArray
* @define coll parallel array
*
- * @author Aleksandar Prokopec
*/
@SerialVersionUID(1L)
class ParArray[T] private[mutable] (val arrayseq: ArraySeq[T])
diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
index 6ce6c45460..23b23d55a1 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
@@ -32,6 +32,8 @@ import collection.parallel.Task
* @define coll parallel hash map
*
* @author Aleksandar Prokopec
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tables Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tables for more information.
*/
@SerialVersionUID(1L)
class ParHashMap[K, V] private[collection] (contents: HashTable.Contents[K, DefaultEntry[K, V]])
diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
index e0a2ab03df..4e9a38c13f 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
@@ -29,6 +29,8 @@ import collection.parallel.Task
* @define coll parallel hash set
*
* @author Aleksandar Prokopec
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tables Scala's Parallel Collections Library overview]]
+ * section on Parallel Hash Tables for more information.
*/
@SerialVersionUID(1L)
class ParHashSet[T] private[collection] (contents: FlatHashTable.Contents[T])
diff --git a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
index fa19990b91..359c35f1dd 100644
--- a/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParTrieMap.scala
@@ -33,6 +33,8 @@ import scala.collection.concurrent.TrieMapIterator
*
* @author Aleksandar Prokopec
* @since 2.10
+ * @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_concurrent_tries Scala's Parallel Collections Library overview]]
+ * section on `ParTrieMap` for more information.
*/
final class ParTrieMap[K, V] private[collection] (private val ctrie: TrieMap[K, V])
extends ParMap[K, V]
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index c1f45eccfb..cb42b76b51 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -183,7 +183,8 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
override def equals (that: Any): Boolean = that match {
case that: BigDecimal => this equals that
case that: BigInt => this.toBigIntExact exists (that equals _)
- case _: Float | _: Double => unifiedPrimitiveEquals(that)
+ case that: Double => isValidDouble && toDouble == that
+ case that: Float => isValidFloat && toFloat == that
case _ => isValidLong && unifiedPrimitiveEquals(that)
}
override def isValidByte = noArithmeticException(toByteExact)
@@ -191,6 +192,18 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
override def isValidChar = isValidInt && toIntExact >= Char.MinValue && toIntExact <= Char.MaxValue
override def isValidInt = noArithmeticException(toIntExact)
def isValidLong = noArithmeticException(toLongExact)
+ /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`.
+ */
+ def isValidFloat = {
+ val f = toFloat
+ !f.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(f)) == 0
+ }
+ /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`.
+ */
+ def isValidDouble = {
+ val d = toDouble
+ !d.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(d)) == 0
+ }
private def noArithmeticException(body: => Unit): Boolean = {
try { body ; true }
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 8a53afaa62..dbec30b2fe 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -20,6 +20,7 @@ object BigInt {
private val minCached = -1024
private val maxCached = 1024
private val cache = new Array[BigInt](maxCached - minCached + 1)
+ private val minusOne = BigInteger.valueOf(-1)
@deprecated("Use Long.MinValue", "2.9.0")
val MinLong = BigInt(Long.MinValue)
@@ -122,6 +123,8 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
override def equals(that: Any): Boolean = that match {
case that: BigInt => this equals that
case that: BigDecimal => that.toBigIntExact exists (this equals _)
+ case that: Double => isValidDouble && toDouble == that
+ case that: Float => isValidFloat && toFloat == that
case x => isValidLong && unifiedPrimitiveEquals(x)
}
override def isValidByte = this >= Byte.MinValue && this <= Byte.MaxValue
@@ -129,6 +132,41 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
override def isValidChar = this >= Char.MinValue && this <= Char.MaxValue
override def isValidInt = this >= Int.MinValue && this <= Int.MaxValue
def isValidLong = this >= Long.MinValue && this <= Long.MaxValue
+ /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`.
+ */
+ def isValidFloat = {
+ val bitLen = bitLength
+ (bitLen <= 24 ||
+ {
+ val lowest = lowestSetBit
+ bitLen <= java.lang.Float.MAX_EXPONENT + 1 && // exclude this < -2^128 && this >= 2^128
+ lowest >= bitLen - 24 &&
+ lowest < java.lang.Float.MAX_EXPONENT + 1 // exclude this == -2^128
+ }
+ ) && !bitLengthOverflow
+ }
+ /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`.
+ */
+ def isValidDouble = {
+ val bitLen = bitLength
+ (bitLen <= 53 ||
+ {
+ val lowest = lowestSetBit
+ bitLen <= java.lang.Double.MAX_EXPONENT + 1 && // exclude this < -2^1024 && this >= 2^1024
+ lowest >= bitLen - 53 &&
+ lowest < java.lang.Double.MAX_EXPONENT + 1 // exclude this == -2^1024
+ }
+ ) && !bitLengthOverflow
+ }
+ /** Some implementations of java.math.BigInteger allow huge values with bit length greater than Int.MaxValue .
+ * The BigInteger.bitLength method returns truncated bit length in this case .
+ * This method tests if result of bitLength is valid.
+ * This method will become unnecessary if BigInt constructors reject huge BigIntegers.
+ */
+ private def bitLengthOverflow = {
+ val shifted = bigInteger.shiftRight(Int.MaxValue)
+ (shifted.signum != 0) && !(shifted equals BigInt.minusOne)
+ }
protected[math] def isWhole = true
def underlying = bigInteger
diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala
index cbe778f09b..2e435d8a7e 100644
--- a/src/library/scala/runtime/AbstractPartialFunction.scala
+++ b/src/library/scala/runtime/AbstractPartialFunction.scala
@@ -8,45 +8,61 @@
package scala.runtime
-import scala.annotation.unchecked.uncheckedVariance
-
-/** This class provides a default implementation of partial functions
- * that is used for all partial function literals.
- * It contains an optimized `orElse` method which supports
- * chained `orElse` in linear time, and with no slow-down
- * if the `orElse` part is not needed.
- * The implementation of `orElse` works by cloning the abstract function object
- * and modifying a private `fallBack` variable that encodes the `getorElse` part.
+/** `AbstractPartialFunction` reformulates all operations of its supertrait `PartialFunction` in terms of `isDefinedAt` and `applyOrElse`.
+ *
+ * This allows more efficient implementations in many cases:
+ * - optimized `orElse` method supports chained `orElse` in linear time,
+ * and with no slow-down if the `orElse` part is not needed.
+ * - optimized `lift` method helps to avoid double evaluation of pattern matchers & guards
+ * of partial function literals.
+ *
+ * This trait is used as a basis for implementation of all partial function literals
+ * with non-exhaustive matchers.
+ *
+ * Use of `AbstractPartialFunction` instead of `PartialFunction` as a base trait for
+ * user-defined partial functions may result in better performance
+ * and more predictable behavior w.r.t. side effects.
+ *
+ * @author Pavel Pavlov
+ * @since 2.10
*/
-abstract class AbstractPartialFunction[-T1, +R]
- extends AbstractFunction1[T1, R]
- with PartialFunction[T1, R]
- with Cloneable {
-
- private var fallBackField: PartialFunction[T1 @uncheckedVariance, R @uncheckedVariance] = _
+abstract class AbstractPartialFunction[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends Function1[T1, R] with PartialFunction[T1, R] { self =>
+ // this method must be overridden for better performance,
+ // for backwards compatibility, fall back to the one inherited from PartialFunction
+ // this assumes the old-school partial functions override the apply method, though
+ // override def applyOrElse[A1 <: T1, B1 >: R](x: A1, default: A1 => B1): B1 = ???
- def fallBack: PartialFunction[T1, R] = synchronized {
- if (fallBackField eq null) fallBackField = PartialFunction.empty
- fallBackField
- }
+ // probably okay to make final since classes compiled before have overridden against the old version of AbstractPartialFunction
+ // let's not make it final so as not to confuse anyone
+ /*final*/ def apply(x: T1): R = applyOrElse(x, PartialFunction.empty)
- override protected def missingCase(x: T1): R = fallBack(x)
-
- // Question: Need to ensure that fallBack is overwritten before any access
- // Is the `synchronized` here the right thing to achieve this?
- // Is there a cheaper way?
- override def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = {
- val result = this.clone.asInstanceOf[AbstractPartialFunction[A1, B1]]
- result.synchronized {
- result.fallBackField = if (this.fallBackField eq null) that else this.fallBackField orElse that
- result
+ override final def andThen[C](k: R => C) : PartialFunction[T1, C] =
+ new AbstractPartialFunction[T1, C] {
+ def isDefinedAt(x: T1): Boolean = self.isDefinedAt(x)
+ override def applyOrElse[A1 <: T1, C1 >: C](x: A1, default: A1 => C1): C1 =
+ self.applyOrElse(x, PartialFunction.fallbackToken) match {
+ case PartialFunction.FallbackToken => default(x)
+ case z => k(z)
+ }
}
- }
-
- def isDefinedAt(x: T1): scala.Boolean = _isDefinedAt(x) || fallBack.isDefinedAt(x)
- def _isDefinedAt(x: T1): scala.Boolean
+ // TODO: remove
+ protected def missingCase(x: T1): R = throw new MatchError(x)
}
-
+/** `AbstractTotalFunction` is a partial function whose `isDefinedAt` method always returns `true`.
+ *
+ * This class is used as base class for partial function literals with
+ * certainly exhaustive pattern matchers.
+ *
+ * @author Pavel Pavlov
+ * @since 2.10
+ */
+abstract class AbstractTotalFunction[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends Function1[T1, R] with PartialFunction[T1, R] {
+ final def isDefinedAt(x: T1): Boolean = true
+ override final def applyOrElse[A1 <: T1, B1 >: R](x: A1, default: A1 => B1): B1 = apply(x)
+ override final def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = this
+ //TODO: check generated code for PF literal here
+ override final def andThen[C](k: R => C): PartialFunction[T1, C] = { case x => k(apply(x)) }
+}
diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala
index 5e3f8b6451..20a179a884 100644
--- a/src/library/scala/util/control/Exception.scala
+++ b/src/library/scala/util/control/Exception.scala
@@ -230,8 +230,5 @@ object Exception {
classes exists (_ isAssignableFrom x.getClass)
private def pfFromExceptions(exceptions: Class[_]*): PartialFunction[Throwable, Nothing] =
- new scala.runtime.AbstractPartialFunction[Throwable, Nothing] {
- def apply(x: Throwable) = throw x
- def _isDefinedAt(x: Throwable) = wouldMatch(x, exceptions)
- }
+ { case x if wouldMatch(x, exceptions) => throw x }
}
diff --git a/test/files/neg/override-object-flag.check b/test/files/neg/override-object-flag.check
index 152d31ff8a..344165138d 100644
--- a/test/files/neg/override-object-flag.check
+++ b/test/files/neg/override-object-flag.check
@@ -1,4 +1,4 @@
-override-object-flag.scala:3: error: overriding object Foo in trait A of type object B.this.Foo;
+override-object-flag.scala:3: error: overriding object Foo in trait A;
object Foo cannot override final member
trait B extends A { override object Foo }
^
diff --git a/test/files/neg/override-object-no.check b/test/files/neg/override-object-no.check
index f9fb37381b..52bad2b937 100644
--- a/test/files/neg/override-object-no.check
+++ b/test/files/neg/override-object-no.check
@@ -10,7 +10,7 @@ an overriding object must conform to the overridden object's class bound;
required: Object{def g: Int}
trait Quux2 extends Quux1 { override object Bar { def g = "abc" } } // err
^
-override-object-no.scala:25: error: overriding object Bar in trait Quux3 of type object Quux4.this.Bar;
+override-object-no.scala:25: error: overriding object Bar in trait Quux3;
object Bar cannot override final member
trait Quux4 extends Quux3 { override object Bar } // err
^
diff --git a/test/files/neg/t961.check b/test/files/neg/t961.check
index 48273f764d..14d39b0f42 100644
--- a/test/files/neg/t961.check
+++ b/test/files/neg/t961.check
@@ -1,4 +1,4 @@
-t961.scala:11: error: object Temp.B does not take parameters
+t961.scala:11: error: Temp.B.type does not take parameters
B() match {
^
one error found
diff --git a/test/files/pos/t4545.scala b/test/files/pos/t4545.scala
new file mode 100644
index 0000000000..8c7a3236c4
--- /dev/null
+++ b/test/files/pos/t4545.scala
@@ -0,0 +1,14 @@
+object Test {
+ def f[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](table: Tuple20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Unit) {
+ }
+ def g[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](table: Tuple21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Unit) {
+ }
+
+ def g20 = f(
+ ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
+ ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t)) => () }
+
+ def g21 = g(
+ (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
+ ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u)) => () }
+}
diff --git a/test/files/presentation/callcc-interpreter.check b/test/files/presentation/callcc-interpreter.check
index 3385ef12b7..c50e171b4e 100644
--- a/test/files/presentation/callcc-interpreter.check
+++ b/test/files/presentation/callcc-interpreter.check
@@ -52,7 +52,7 @@ retrieved 64 members
`method wait(x$1: Long, x$2: Int)Unit`
`method x=> callccInterpreter.type`
`method →[B](y: B)(callccInterpreter.type, B)`
-`object Wrongobject callccInterpreter.Wrong`
+`object WrongcallccInterpreter.Wrong.type`
`trait TermcallccInterpreter.Term`
`trait ValuecallccInterpreter.Value`
`type AnswercallccInterpreter.Answer`
diff --git a/test/files/run/concurrent-map-conversions.scala b/test/files/run/concurrent-map-conversions.scala
new file mode 100644
index 0000000000..0350b69642
--- /dev/null
+++ b/test/files/run/concurrent-map-conversions.scala
@@ -0,0 +1,36 @@
+
+
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ testConversions()
+ testConverters()
+ }
+
+ def needPackageConcurrentMap(map: collection.concurrent.Map[Int, Int]) {
+ }
+ def needJavaConcurrent(map: java.util.concurrent.ConcurrentMap[Int, Int]) {
+ }
+
+ def testConversions() {
+ import collection.JavaConversions._
+ val skiplist = new java.util.concurrent.ConcurrentSkipListMap[Int, Int]
+ val ctrie = new collection.concurrent.TrieMap[Int, Int]
+
+ needPackageConcurrentMap(skiplist)
+ needJavaConcurrent(ctrie)
+ }
+
+ def testConverters() {
+ import collection.JavaConverters._
+ val skiplist = new java.util.concurrent.ConcurrentSkipListMap[Int, Int]
+ val ctrie = new collection.concurrent.TrieMap[Int, Int]
+
+ needPackageConcurrentMap(skiplist.asScala)
+ needJavaConcurrent(ctrie.asJava)
+ }
+
+}
diff --git a/test/files/run/finalvar.check b/test/files/run/finalvar.check
new file mode 100644
index 0000000000..2496293972
--- /dev/null
+++ b/test/files/run/finalvar.check
@@ -0,0 +1,6 @@
+(2,2,2,2,1)
+(2,2,2,2)
+(2,2,2,2,1001)
+(2,2,2,2)
+2
+10
diff --git a/test/files/run/finalvar.flags b/test/files/run/finalvar.flags
new file mode 100644
index 0000000000..aee3039bec
--- /dev/null
+++ b/test/files/run/finalvar.flags
@@ -0,0 +1 @@
+-Yoverride-vars -Yinline \ No newline at end of file
diff --git a/test/files/run/finalvar.scala b/test/files/run/finalvar.scala
new file mode 100644
index 0000000000..010813e520
--- /dev/null
+++ b/test/files/run/finalvar.scala
@@ -0,0 +1,37 @@
+object Final {
+ class X(final var x: Int) { }
+ def f = new X(0).x += 1
+}
+
+class A {
+ var x = 1
+ def y0 = x
+ def y1 = this.x
+ def y2 = (this: A).x
+}
+
+class B extends A {
+ override def x = 2
+ def z = super.x
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ Final.f
+ val a = new B
+ println((a.x, a.y0, a.y1, a.y2, a.z))
+ val a0: A = a
+ println((a0.x, a0.y0, a0.y1, a0.y2))
+ a.x = 1001
+ println((a.x, a.y0, a.y1, a.y2, a.z))
+ println((a0.x, a0.y0, a0.y1, a0.y2))
+
+ val d = new D
+ println(d.w)
+ d.ten
+ println(d.w)
+ }
+}
+
+class C { var w = 1 ; def ten = this.w = 10 }
+class D extends C { override var w = 2 } \ No newline at end of file
diff --git a/test/files/run/is-valid-num.scala b/test/files/run/is-valid-num.scala
index f919a21dee..9c43e98911 100644
--- a/test/files/run/is-valid-num.scala
+++ b/test/files/run/is-valid-num.scala
@@ -1,11 +1,15 @@
object Test {
def x = BigInt("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
def y = BigDecimal("" + (Short.MaxValue + 1) + ".0")
+ def y1 = BigDecimal("0.1")
+ def y2 = BigDecimal("0.5")
def l1 = Int.MaxValue.toLong + 1
def l2 = Int.MinValue.toLong - 1
def main(args: Array[String]): Unit = {
+ assert(!x.isValidDouble, x)
+ assert(!x.isValidFloat, x)
assert(!x.isValidLong, x)
assert(!x.isValidInt, x)
assert(!x.isValidChar, x)
@@ -13,8 +17,81 @@ object Test {
assert(!y.isValidShort, y)
assert(y.isValidChar, y)
assert(y.isValidInt, y)
+ assert(y.isValidFloat, y)
+ assert(y.isValidDouble, y)
+ assert(!y1.isValidLong, y1)
+ assert(!y1.isValidFloat, y1)
+ assert(!y1.isValidDouble, y1)
+ assert(!y2.isValidLong, y2)
+ assert(y2.isValidFloat, y2)
+ assert(y2.isValidDouble, y2)
+
+ testBigIntIsFloat()
+ testBigIntIsDouble()
assert(!l1.isValidInt && (l1 - 1).isValidInt, l1)
assert(!l2.isValidInt && (l2 + 1).isValidInt, l2)
}
+
+ def biExp2(e: Int) = BigInt(1) << e
+
+ def testBigIntIsFloat() {
+ val prec = 24
+ def checkFloatT(x: BigInt) = {
+ assert(x.isValidFloat, x)
+ assert((-x).isValidFloat, -x)
+ }
+ def checkFloatF(x: BigInt) = {
+ assert(!x.isValidFloat, x)
+ assert(!(-x).isValidFloat, -x)
+ }
+ checkFloatT(biExp2(prec) - 1)
+ checkFloatT(biExp2(prec))
+ checkFloatF(biExp2(prec) + 1)
+ checkFloatT(biExp2(prec) + 2)
+ checkFloatT(biExp2(prec) - 2)
+ checkFloatF(biExp2(prec + 1) - 1)
+ checkFloatT(biExp2(prec + 1))
+ checkFloatF(biExp2(prec + 1) + 1)
+ checkFloatF(biExp2(prec + 1) + 2)
+ checkFloatF(biExp2(prec + 1) + 3)
+ checkFloatT(biExp2(prec + 1) + 4)
+ checkFloatT(biExp2(64))
+ checkFloatF(biExp2(64) + biExp2(64 - prec))
+ checkFloatT(biExp2(64) + biExp2(64 - prec + 1))
+ checkFloatT(biExp2(127))
+ checkFloatT(biExp2(128) - biExp2(128 - prec))
+ checkFloatF(biExp2(128) - biExp2(128 - prec - 1))
+ checkFloatF(biExp2(128))
+ }
+
+ def testBigIntIsDouble() {
+ val prec = 53
+ def checkDoubleT(x: BigInt) = {
+ assert(x.isValidDouble, x)
+ assert((-x).isValidDouble, -x)
+ }
+ def checkDoubleF(x: BigInt) = {
+ assert(!x.isValidDouble, x)
+ assert(!(-x).isValidDouble, -x)
+ }
+ checkDoubleT(biExp2(prec) - 1)
+ checkDoubleT(biExp2(prec))
+ checkDoubleF(biExp2(prec) + 1)
+ checkDoubleT(biExp2(prec) + 2)
+ checkDoubleT(biExp2(prec + 1) - 2)
+ checkDoubleF(biExp2(prec + 1) - 1)
+ checkDoubleT(biExp2(prec + 1))
+ checkDoubleF(biExp2(prec + 1) + 1)
+ checkDoubleF(biExp2(prec + 1) + 2)
+ checkDoubleF(biExp2(prec + 1) + 3)
+ checkDoubleT(biExp2(prec + 1) + 4)
+ checkDoubleT(biExp2(64))
+ checkDoubleF(biExp2(64) + biExp2(64 - prec))
+ checkDoubleT(biExp2(64) + biExp2(64 - prec + 1))
+ checkDoubleT(biExp2(1023))
+ checkDoubleT(biExp2(1024) - biExp2(1024 - prec))
+ checkDoubleF(biExp2(1024) - biExp2(1024 - prec - 1))
+ checkDoubleF(biExp2(1024))
+ }
}
diff --git a/test/files/run/lift-and-unlift.scala b/test/files/run/lift-and-unlift.scala
index b944c70155..a4a5d9502e 100644
--- a/test/files/run/lift-and-unlift.scala
+++ b/test/files/run/lift-and-unlift.scala
@@ -2,7 +2,7 @@ import Function.unlift
object Test {
def evens1(x: Int) = if (x % 2 == 0) Some(x) else None
- def evens2: PartialFunction[Int, Int] = {
+ val evens2: PartialFunction[Int, Int] = {
case x if x % 2 == 0 => x
}
@@ -21,7 +21,7 @@ object Test {
})
assert(f1 eq f3.lift)
- // Hmm, why is this not true:
- // assert(f2 eq f4.lift)
+ assert(f4 eq unlift(f2))
+ assert(f4 eq evens2)
}
}
diff --git a/test/files/run/numbereq.scala b/test/files/run/numbereq.scala
index 77a217df36..a1f11da205 100644
--- a/test/files/run/numbereq.scala
+++ b/test/files/run/numbereq.scala
@@ -16,7 +16,20 @@ object Test {
base ::: extras
}
-
+
+ def mkNumbers(x: BigInt): List[AnyRef] = {
+ List(
+ List(BigDecimal(x, java.math.MathContext.UNLIMITED)),
+ List(x),
+ if (x.isValidDouble) List(new java.lang.Double(x.toDouble)) else Nil,
+ if (x.isValidFloat) List(new java.lang.Float(x.toFloat)) else Nil,
+ if (x.isValidLong) List(new java.lang.Long(x.toLong)) else Nil,
+ if (x.isValidInt) List(new java.lang.Integer(x.toInt)) else Nil,
+ if (x.isValidShort) List(new java.lang.Short(x.toShort)) else Nil,
+ if (x.isValidByte) List(new java.lang.Byte(x.toByte)) else Nil,
+ if (x.isValidChar) List(new java.lang.Character(x.toChar)) else Nil
+ ).flatten
+ }
def main(args: Array[String]): Unit = {
val ints = (0 to 15).toList map (Short.MinValue >> _)
@@ -37,5 +50,23 @@ object Test {
assert(x == y, "%s/%s != %s/%s".format(x, x.getClass, y, y.getClass))
assert(x.## == y.##, "%s != %s".format(x.getClass, y.getClass))
}
+
+ val bigInts = (0 to 1024).toList map (BigInt(-1) << _)
+ val bigInts2 = bigInts map (x => -x)
+ val bigInts3 = bigInts map (_ + 1)
+ val bigInts4 = bigInts2 map (_ - 1)
+
+ val setneg1b = bigInts map mkNumbers
+ val setneg2b = bigInts3 map mkNumbers
+ val setpos1b = bigInts2 map mkNumbers
+ val setpos2b = bigInts4 map mkNumbers
+
+ val sets2 = setneg1 ++ setneg1b ++ setneg2 ++ setneg2b ++ List(zero) ++ setpos1 ++ setpos1b ++ setpos2 ++ setpos2b
+
+ for (set <- sets2 ; x <- set ; y <- set) {
+// println("'%s' == '%s' (%s == %s) (%s == %s)".format(x, y, x.hashCode, y.hashCode, x.##, y.##))
+ assert(x == y, "%s/%s != %s/%s".format(x, x.getClass, y, y.getClass))
+// assert(x.## == y.##, "%s != %s".format(x.getClass, y.getClass)) Disable until Double.## is fixed (SI-5640)
+ }
}
-} \ No newline at end of file
+}
diff --git a/test/pending/pos/t1476.scala b/test/pending/pos/t1476.scala
new file mode 100644
index 0000000000..1f8e95c28f
--- /dev/null
+++ b/test/pending/pos/t1476.scala
@@ -0,0 +1,23 @@
+abstract class Module {
+ def moduleDemands(): List[Module]
+}
+
+object Test {
+ new Module { owner: Module =>
+ def moduleDemands() = Nil
+
+ val a = new Module { def moduleDemands(): List[Module] = Nil }
+ val b = new Module { def moduleDemands(): List[Module] = owner :: c :: Nil }
+ val c = new Module { def moduleDemands(): List[Module] = owner :: a :: Nil }
+ }
+}
+
+object Test2 {
+ new Module { owner =>
+ def moduleDemands() = Nil
+
+ val a = new Module { def moduleDemands(): List[Module] = Nil }
+ val b = new Module { def moduleDemands(): List[Module] = owner :: c :: Nil }
+ val c = new Module { def moduleDemands(): List[Module] = owner :: a :: Nil }
+ }
+}
diff --git a/test/pending/pos/t5626.scala b/test/pending/pos/t5626.scala
new file mode 100644
index 0000000000..7ab3881827
--- /dev/null
+++ b/test/pending/pos/t5626.scala
@@ -0,0 +1,12 @@
+object Test {
+ val blob0 = new {
+ case class Foo(i : Int)
+ }
+ val foo0 = blob0.Foo(22)
+
+ val blob1 = new {
+ class Foo(i: Int)
+ object Foo { def apply(i: Int): Foo = new Foo(i) }
+ }
+ val foo1 = blob1.Foo(22)
+}
diff --git a/test/pending/run/t5629.check b/test/pending/run/t5629.check
new file mode 100644
index 0000000000..6a2d630f4e
--- /dev/null
+++ b/test/pending/run/t5629.check
@@ -0,0 +1,2 @@
+int child got: 33
+any child got: 33
diff --git a/test/pending/run/t5629.scala b/test/pending/run/t5629.scala
new file mode 100644
index 0000000000..28e74a1c94
--- /dev/null
+++ b/test/pending/run/t5629.scala
@@ -0,0 +1,25 @@
+import scala.{specialized => spec}
+
+trait GrandParent[@spec(Int) -A] {
+ def foo(a:A): Unit
+ def bar[B <: A](b:B): Unit = println("grandparent got: %s" format b)
+}
+
+trait Parent[@spec(Int) -A] extends GrandParent[A] {
+ def foo(a:A) = bar(a)
+}
+
+class IntChild extends Parent[Int] {
+ override def bar[B <: Int](b:B): Unit = println("int child got: %s" format b)
+}
+
+class AnyChild extends Parent[Any] {
+ override def bar[B <: Any](b:B): Unit = println("any child got: %s" format b)
+}
+
+object Test {
+ def main(args:Array[String]) {
+ new IntChild().foo(33)
+ new AnyChild().foo(33)
+ }
+}