summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/reify/Phases.scala2
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala2
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala6
-rw-r--r--src/compiler/scala/reflect/reify/phases/Metalevels.scala2
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala3
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala6
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala245
-rw-r--r--src/compiler/scala/tools/nsc/SubComponent.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala17
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala12
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala62
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala36
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala23
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala25
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala10
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala8
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala93
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala70
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala134
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala23
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ISettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Imports.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala19
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Phased.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala6
-rw-r--r--src/compiler/scala/tools/nsc/settings/AestheticSettings.scala39
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala36
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala36
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala80
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala182
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/InfoTransform.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala40
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/PostErasure.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala296
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala46
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala501
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala78
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala86
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala81
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Tags.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala343
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Variances.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/FreshNameCreator.scala5
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala1
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala2
-rw-r--r--src/continuations/library/scala/util/continuations/package.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala4
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala8
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala6
-rw-r--r--src/detach/plugin/scala/tools/detach/Detach.scala24
-rw-r--r--src/library/scala/Application.scala79
-rw-r--r--src/library/scala/Option.scala9
-rw-r--r--src/library/scala/StringContext.scala2
-rw-r--r--src/library/scala/UninitializedFieldError.scala6
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala5
-rw-r--r--src/library/scala/collection/IndexedSeq.scala13
-rw-r--r--src/library/scala/collection/JavaConversions.scala36
-rwxr-xr-xsrc/library/scala/collection/JavaConverters.scala33
-rwxr-xr-xsrc/library/scala/collection/LinearSeqOptimized.scala2
-rw-r--r--src/library/scala/collection/Searching.scala116
-rw-r--r--src/library/scala/collection/SeqLike.scala2
-rw-r--r--src/library/scala/collection/SeqProxyLike.scala2
-rw-r--r--src/library/scala/collection/Sequentializable.scala.disabled10
-rw-r--r--src/library/scala/collection/TraversableOnce.scala2
-rw-r--r--src/library/scala/collection/generic/GenTraversableFactory.scala8
-rw-r--r--src/library/scala/collection/generic/IndexedSeqFactory.scala21
-rw-r--r--src/library/scala/collection/generic/IsSeqLike.scala57
-rw-r--r--src/library/scala/collection/generic/SeqForwarder.scala2
-rw-r--r--src/library/scala/collection/immutable/GenIterable.scala.disabled37
-rw-r--r--src/library/scala/collection/immutable/GenMap.scala.disabled36
-rw-r--r--src/library/scala/collection/immutable/GenSeq.scala.disabled49
-rw-r--r--src/library/scala/collection/immutable/GenSet.scala.disabled43
-rw-r--r--src/library/scala/collection/immutable/GenTraversable.scala.disabled41
-rw-r--r--src/library/scala/collection/immutable/IndexedSeq.scala6
-rw-r--r--src/library/scala/collection/immutable/List.scala272
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala2
-rw-r--r--src/library/scala/collection/immutable/Range.scala1
-rw-r--r--src/library/scala/collection/immutable/RedBlackTree.scala22
-rw-r--r--src/library/scala/collection/immutable/Vector.scala33
-rw-r--r--src/library/scala/collection/mutable/GenIterable.scala.disabled37
-rw-r--r--src/library/scala/collection/mutable/GenMap.scala.disabled40
-rw-r--r--src/library/scala/collection/mutable/GenSeq.scala.disabled44
-rw-r--r--src/library/scala/collection/mutable/GenSet.scala.disabled46
-rw-r--r--src/library/scala/collection/mutable/GenTraversable.scala.disabled38
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala44
-rw-r--r--src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala8
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala47
-rw-r--r--src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled128
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala2
-rw-r--r--src/library/scala/io/Position.scala8
-rw-r--r--src/library/scala/math/BigDecimal.scala6
-rw-r--r--src/library/scala/math/BigInt.scala6
-rw-r--r--src/library/scala/package.scala6
-rw-r--r--src/library/scala/parallel/package.scala.disabled178
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala3
-rw-r--r--src/library/scala/util/matching/Regex.scala98
-rw-r--r--src/library/scala/util/parsing/combinator/JavaTokenParsers.scala7
-rw-r--r--src/library/scala/util/parsing/combinator/lexical/StdLexical.scala2
-rw-r--r--src/library/scala/xml/dtd/DocType.scala8
-rw-r--r--src/library/scala/xml/dtd/ExternalID.scala11
-rw-r--r--src/partest/scala/tools/partest/javaagent/ASMTransformer.java30
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala7
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala30
-rw-r--r--src/partest/scala/tools/partest/package.scala3
-rw-r--r--src/reflect/scala/reflect/internal/BaseTypeSeqs.scala2
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala27
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala19
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala6
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala26
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala269
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala27
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala60
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala19
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala845
-rw-r--r--src/reflect/scala/reflect/internal/pickling/PickleFormat.scala4
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala4
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/Set.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/StringOps.scala8
-rw-r--r--src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/package.scala34
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala3
-rw-r--r--src/scalap/scala/tools/scalap/scalax/rules/Rule.scala2
-rw-r--r--src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala52
-rw-r--r--src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala1
-rw-r--r--src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala1
-rw-r--r--src/swing/scala/swing/ComboBox.scala2
-rw-r--r--src/swing/scala/swing/Font.scala.disabled70
-rw-r--r--src/swing/scala/swing/ListView.scala2
-rw-r--r--src/swing/scala/swing/TabbedPane.scala3
178 files changed, 2702 insertions, 3540 deletions
diff --git a/src/compiler/scala/reflect/reify/Phases.scala b/src/compiler/scala/reflect/reify/Phases.scala
index 1710cae2a5..5a10ad9282 100644
--- a/src/compiler/scala/reflect/reify/Phases.scala
+++ b/src/compiler/scala/reflect/reify/Phases.scala
@@ -26,7 +26,7 @@ trait Phases extends Reshape
if (reifyDebug) println("[reshape phase]")
tree = reshape.transform(tree)
if (reifyDebug) println("[interlude]")
- if (reifyDebug) println("reifee = " + (if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString))
+ if (reifyDebug) println("reifee = " + (if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString))
if (reifyDebug) println("[calculate phase]")
calculate.traverse(tree)
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index 47669f57b0..b3224b1aa6 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -57,7 +57,7 @@ abstract class Reifier extends States
val result = reifee match {
case tree: Tree =>
- reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
+ reifyTrace("reifying = ")(if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
reifyTrace("reifee is located at: ")(tree.pos)
reifyTrace("universe = ")(universe)
reifyTrace("mirror = ")(mirror)
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index bdcc7383b0..86ad23cd15 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -64,7 +64,7 @@ trait GenTrees {
// usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
// however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why.
- if (reifyTreeSymbols && tree.hasSymbol) {
+ if (reifyTreeSymbols && tree.hasSymbolField) {
if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree))
rtree = mirrorBuildCall(nme.setSymbol, rtree, reify(tree.symbol))
}
@@ -86,8 +86,8 @@ trait GenTrees {
// see ``Metalevels'' for more info about metalevel breaches
// and about how we deal with splices that contain them
- val isMetalevelBreach = splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
- val isRuntimeEval = splicee exists (sub => sub.hasSymbol && sub.symbol == ExprSplice)
+ val isMetalevelBreach = splicee exists (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
+ val isRuntimeEval = splicee exists (sub => sub.hasSymbolField && sub.symbol == ExprSplice)
if (isMetalevelBreach || isRuntimeEval) {
// we used to convert dynamic splices into runtime evals transparently, but we no longer do that
// why? see comments in ``Metalevels''
diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
index fbbd12a42f..4c6ebbb288 100644
--- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala
+++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
@@ -124,7 +124,7 @@ trait Metalevels {
withinSplice { super.transform(TreeSplice(ReifiedTree(universe, mirror, symtab1, rtree, tpe, rtpe, concrete))) }
case TreeSplice(splicee) =>
if (reifyDebug) println("entering splice: " + splicee)
- val breaches = splicee filter (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
+ val breaches = splicee filter (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)
if (!insideSplice && breaches.nonEmpty) {
// we used to convert dynamic splices into runtime evals transparently, but we no longer do that
// why? see comments above
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index 1b7509fdbe..9a1732a872 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -326,7 +326,8 @@ trait Reshape {
case Some(ddef) =>
toPreTyperLazyVal(ddef)
case None =>
- CannotReifyInvalidLazyVal(vdef)
+ if (reifyDebug) println("couldn't find corresponding lazy val accessor")
+ vdef
}
if (reifyDebug) println(s"reconstructed lazy val is $vdef1")
vdef1::Nil
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index c6809fb48e..bcb7d494b6 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -19,6 +19,7 @@ import org.apache.tools.ant.util.facade.{FacadeTaskHelper,
ImplementationSpecificArgument}
import scala.tools.nsc.{Global, Settings, CompilerCommand}
+import scala.tools.nsc.interactive.RangePositions
import scala.tools.nsc.io.{Path => SPath}
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
@@ -518,7 +519,10 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
new Settings(error)
protected def newGlobal(settings: Settings, reporter: Reporter) =
- new Global(settings, reporter)
+ if (settings.Yrangepos.value)
+ new Global(settings, reporter) with RangePositions
+ else
+ new Global(settings, reporter)
/*============================================================================*\
** The big execute method **
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
index b2f27d1925..00e374db62 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
@@ -39,7 +39,4 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) {
val nc = BooleanSetting(
"-nc",
"do not use the fsc compilation daemon") withAbbreviation "-nocompdaemon"
-
- @deprecated("Use `nc` instead", "2.9.0") def nocompdaemon = nc
- @deprecated("Use `save` instead", "2.9.0") def savecompiled = save
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 12c3338e0d..40a14aec6f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -12,10 +12,9 @@ import scala.tools.util.PathResolver
import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
import reporters.{ Reporter, ConsoleReporter }
-import util.{ Exceptional, ClassPath, MergedClassPath, StatisticsInfo, ScalaClassLoader, returning }
+import util.{ Exceptional, ClassPath, MergedClassPath, StatisticsInfo, ScalaClassLoader, returning, stackTraceString }
import scala.reflect.internal.util.{ NoPosition, OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile }
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
-import settings.{ AestheticSettings }
import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers }
import symtab.classfile.Pickler
import dependencies.DependencyAnalysis
@@ -172,7 +171,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (lastPrintedSource == source)
println(": tree is unchanged since " + lastPrintedPhase)
else {
- lastPrintedPhase = phase.prev // since we're running inside "afterPhase"
+ lastPrintedPhase = phase.prev // since we're running inside "exitingPhase"
lastPrintedSource = source
println("")
println(source)
@@ -268,7 +267,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
msg + " in " + (currentTime - start) + "ms"
def informComplete(msg: String): Unit = reporter.withoutTruncating(inform(msg))
- def informProgress(msg: String) = if (opt.verbose) inform("[" + msg + "]")
+ def informProgress(msg: String) = if (settings.verbose.value) inform("[" + msg + "]")
def inform[T](msg: String, value: T): T = returning(value)(x => inform(msg + x))
def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start))
@@ -312,7 +311,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
None
}
- val charset = opt.encoding flatMap loadCharset getOrElse {
+ val charset = ( if (settings.encoding.isSetByUser) Some(settings.encoding.value) else None ) flatMap loadCharset getOrElse {
settings.encoding.value = defaultEncoding // A mandatory charset
Charset.forName(defaultEncoding)
}
@@ -327,7 +326,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
}
- opt.sourceReader flatMap loadReader getOrElse {
+ ( if (settings.sourceReader.isSetByUser) Some(settings.sourceReader.value) else None ) flatMap loadReader getOrElse {
new SourceReader(charset.newDecoder(), reporter)
}
}
@@ -335,54 +334,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (!dependencyAnalysis.off)
dependencyAnalysis.loadDependencyAnalysis()
- if (opt.verbose || opt.logClasspath) {
+ if (settings.verbose.value || settings.Ylogcp.value) {
// Uses the "do not truncate" inform
informComplete("[search path for source files: " + classPath.sourcepaths.mkString(",") + "]")
informComplete("[search path for class files: " + classPath.asClasspathString + "]")
}
- object opt extends AestheticSettings {
- def settings = Global.this.settings
-
- // protected implicit lazy val globalPhaseOrdering: Ordering[Phase] = Ordering[Int] on (_.id)
- def isActive(ph: Settings#PhasesSetting) = ph containsPhase globalPhase
- def wasActive(ph: Settings#PhasesSetting) = ph containsPhase globalPhase.prev
-
- // Allows for syntax like scalac -Xshow-class Random@erasure,typer
- private def splitClassAndPhase(str: String, term: Boolean): Name = {
- def mkName(s: String) = if (term) newTermName(s) else newTypeName(s)
- (str indexOf '@') match {
- case -1 => mkName(str)
- case idx =>
- val phasePart = str drop (idx + 1)
- settings.Yshow.tryToSetColon(phasePart split ',' toList)
- mkName(str take idx)
- }
- }
-
- // behavior
-
- // debugging
- def checkPhase = wasActive(settings.check)
- def logPhase = isActive(settings.log)
-
- // Write *.icode files right after GenICode when -Xprint-icode was given.
- def writeICodeAtICode = settings.writeICode.isSetByUser && isActive(settings.writeICode)
-
- // showing/printing things
- def browsePhase = isActive(settings.browse)
- def echoFilenames = opt.debug && (opt.verbose || currentRun.size < 5)
- def noShow = settings.Yshow.isDefault
- def printLate = settings.printLate.value
- def printPhase = isActive(settings.Xprint)
- def showNames = List(showClass, showObject).flatten
- def showPhase = isActive(settings.Yshow)
- def showSymbols = settings.Yshowsyms.value
- def showTrees = settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value
- val showClass = optSetting[String](settings.Xshowcls) map (x => splitClassAndPhase(x, false))
- val showObject = optSetting[String](settings.Xshowobj) map (x => splitClassAndPhase(x, true))
- }
-
// The current division between scala.reflect.* and scala.tools.nsc.* is pretty
// clunky. It is often difficult to have a setting influence something without having
// to create it on that side. For this one my strategy is a constant def at the file
@@ -391,11 +348,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// Here comes another one...
override protected val enableTypeVarExperimentals = settings.Xexperimental.value
- // True if -Xscript has been set, indicating a script run.
- def isScriptRun = opt.script.isDefined
-
def getSourceFile(f: AbstractFile): BatchSourceFile =
- if (isScriptRun) ScriptSourceFile(f, reader read f)
+ if (settings.script.isSetByUser) ScriptSourceFile(f, reader read f)
else new BatchSourceFile(f, reader read f)
def getSourceFile(name: String): SourceFile = {
@@ -450,7 +404,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if ((unit ne null) && unit.exists)
lastSeenSourceFile = unit.source
- if (opt.echoFilenames)
+ if (settings.debug.value && (settings.verbose.value || currentRun.size < 5))
inform("[running phase " + name + " on " + unit + "]")
val unit0 = currentUnit
@@ -830,7 +784,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
*/
def afterEachPhase[T](op: => T): List[(Phase, T)] = {
phaseDescriptors.map(_.ownPhase).filterNot(_ eq NoPhase).foldLeft(List[(Phase, T)]()) { (res, ph) =>
- val value = afterPhase(ph)(op)
+ val value = exitingPhase(ph)(op)
if (res.nonEmpty && res.head._2 == value) res
else ((ph, value)) :: res
} reverse
@@ -1092,28 +1046,34 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit
def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile
+ override def isPastTyper = (
+ (curRun ne null)
+ && (currentRun.typerPhase ne null)
+ && (globalPhase.id > currentRun.typerPhase.id)
+ )
+
// TODO - trim these to the absolute minimum.
- @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op)
- @inline final def afterPostErasure[T](op: => T): T = afterPhase(currentRun.posterasurePhase)(op)
- @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op)
- @inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op)
- @inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op)
- @inline final def afterMixin[T](op: => T): T = afterPhase(currentRun.mixinPhase)(op)
- @inline final def afterPickler[T](op: => T): T = afterPhase(currentRun.picklerPhase)(op)
- @inline final def afterRefchecks[T](op: => T): T = afterPhase(currentRun.refchecksPhase)(op)
- @inline final def afterSpecialize[T](op: => T): T = afterPhase(currentRun.specializePhase)(op)
- @inline final def afterTyper[T](op: => T): T = afterPhase(currentRun.typerPhase)(op)
- @inline final def afterUncurry[T](op: => T): T = afterPhase(currentRun.uncurryPhase)(op)
- @inline final def beforeErasure[T](op: => T): T = beforePhase(currentRun.erasurePhase)(op)
- @inline final def beforeExplicitOuter[T](op: => T): T = beforePhase(currentRun.explicitouterPhase)(op)
- @inline final def beforeFlatten[T](op: => T): T = beforePhase(currentRun.flattenPhase)(op)
- @inline final def beforeIcode[T](op: => T): T = beforePhase(currentRun.icodePhase)(op)
- @inline final def beforeMixin[T](op: => T): T = beforePhase(currentRun.mixinPhase)(op)
- @inline final def beforePickler[T](op: => T): T = beforePhase(currentRun.picklerPhase)(op)
- @inline final def beforeRefchecks[T](op: => T): T = beforePhase(currentRun.refchecksPhase)(op)
- @inline final def beforeSpecialize[T](op: => T): T = beforePhase(currentRun.specializePhase)(op)
- @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op)
- @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op)
+ @inline final def exitingErasure[T](op: => T): T = exitingPhase(currentRun.erasurePhase)(op)
+ @inline final def exitingPostErasure[T](op: => T): T = exitingPhase(currentRun.posterasurePhase)(op)
+ @inline final def exitingExplicitOuter[T](op: => T): T = exitingPhase(currentRun.explicitouterPhase)(op)
+ @inline final def exitingFlatten[T](op: => T): T = exitingPhase(currentRun.flattenPhase)(op)
+ @inline final def exitingIcode[T](op: => T): T = exitingPhase(currentRun.icodePhase)(op)
+ @inline final def exitingMixin[T](op: => T): T = exitingPhase(currentRun.mixinPhase)(op)
+ @inline final def exitingPickler[T](op: => T): T = exitingPhase(currentRun.picklerPhase)(op)
+ @inline final def exitingRefchecks[T](op: => T): T = exitingPhase(currentRun.refchecksPhase)(op)
+ @inline final def exitingSpecialize[T](op: => T): T = exitingPhase(currentRun.specializePhase)(op)
+ @inline final def exitingTyper[T](op: => T): T = exitingPhase(currentRun.typerPhase)(op)
+ @inline final def exitingUncurry[T](op: => T): T = exitingPhase(currentRun.uncurryPhase)(op)
+ @inline final def enteringErasure[T](op: => T): T = enteringPhase(currentRun.erasurePhase)(op)
+ @inline final def enteringExplicitOuter[T](op: => T): T = enteringPhase(currentRun.explicitouterPhase)(op)
+ @inline final def enteringFlatten[T](op: => T): T = enteringPhase(currentRun.flattenPhase)(op)
+ @inline final def enteringIcode[T](op: => T): T = enteringPhase(currentRun.icodePhase)(op)
+ @inline final def enteringMixin[T](op: => T): T = enteringPhase(currentRun.mixinPhase)(op)
+ @inline final def enteringPickler[T](op: => T): T = enteringPhase(currentRun.picklerPhase)(op)
+ @inline final def enteringRefchecks[T](op: => T): T = enteringPhase(currentRun.refchecksPhase)(op)
+ @inline final def enteringSpecialize[T](op: => T): T = enteringPhase(currentRun.specializePhase)(op)
+ @inline final def enteringTyper[T](op: => T): T = enteringPhase(currentRun.typerPhase)(op)
+ @inline final def enteringUncurry[T](op: => T): T = enteringPhase(currentRun.uncurryPhase)(op)
def explainContext(c: analyzer.Context): String = (
if (c == null) "" else (
@@ -1152,7 +1112,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val info1 = formatExplain(
"while compiling" -> currentSource.path,
- "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ),
+ "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, enteringPhase=%s".format(globalPhase, phase) ),
"library version" -> scala.util.Properties.versionString,
"compiler version" -> Properties.versionString,
"reconstructed args" -> settings.recreateArgs.mkString(" ")
@@ -1168,7 +1128,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val info3: List[String] = (
( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
- ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
+ ++ ( if (!settings.debug.value) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
++ ( List(errorMessage) )
)
@@ -1182,7 +1142,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def echoPhaseSummary(ph: Phase) = {
/** Only output a summary message under debug if we aren't echoing each file. */
- if (opt.debug && !opt.echoFilenames)
+ if (settings.debug.value && !(settings.verbose.value || currentRun.size < 5))
inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]")
}
@@ -1490,8 +1450,24 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
}
- private def showMembers() =
- opt.showNames foreach (x => showDef(x, opt.declsOnly, globalPhase))
+ private def showMembers() = {
+ // Allows for syntax like scalac -Xshow-class Random@erasure,typer
+ def splitClassAndPhase(str: String, term: Boolean): Name = {
+ def mkName(s: String) = if (term) newTermName(s) else newTypeName(s)
+ (str indexOf '@') match {
+ case -1 => mkName(str)
+ case idx =>
+ val phasePart = str drop (idx + 1)
+ settings.Yshow.tryToSetColon(phasePart split ',' toList)
+ mkName(str take idx)
+ }
+ }
+ if (settings.Xshowcls.isSetByUser)
+ showDef(splitClassAndPhase(settings.Xshowcls.value, false), false, globalPhase)
+
+ if (settings.Xshowobj.isSetByUser)
+ showDef(splitClassAndPhase(settings.Xshowobj.value, true), false, globalPhase)
+ }
// Similarly, this will only be created under -Yshow-syms.
object trackerFactory extends SymbolTrackers {
@@ -1499,7 +1475,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
lazy val trackers = currentRun.units.toList map (x => SymbolTracker(x))
def snapshot() = {
inform("\n[[symbol layout at end of " + phase + "]]")
- afterPhase(phase) {
+ exitingPhase(phase) {
trackers foreach { t =>
t.snapshot()
inform(t.show("Heading from " + phase.prev.name + " to " + phase.name))
@@ -1509,6 +1485,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
def reportCompileErrors() {
+ if (!reporter.hasErrors && reporter.hasWarnings && settings.fatalWarnings.value)
+ globalError("No warnings can be incurred under -Xfatal-warnings.")
+
if (reporter.hasErrors) {
for ((sym, file) <- symSource.iterator) {
sym.reset(new loaders.SourcefileLoader(file))
@@ -1528,8 +1507,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Compile list of source files */
def compileSources(_sources: List[SourceFile]) {
- val depSources = dependencyAnalysis calculateFiles _sources.distinct
- val sources = coreClassesFirst(depSources)
+ val sources = dependencyAnalysis calculateFiles _sources.distinct
// there is a problem already, e.g. a plugin was passed a bad option
if (reporter.hasErrors)
return
@@ -1547,11 +1525,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def compileUnits(units: List[CompilationUnit], fromPhase: Phase) {
try compileUnitsInternal(units, fromPhase)
catch { case ex: Throwable =>
- val shown = if (settings.verbose.value) {
- val pw = new java.io.PrintWriter(new java.io.StringWriter)
- ex.printStackTrace(pw)
- pw.toString
- } else ex.getClass.getName
+ val shown = if (settings.verbose.value)
+ stackTraceString(ex)
+ else
+ ex.getClass.getName
// ex.printStackTrace(Console.out) // DEBUG for fsc, note that error stacktraces do not print in fsc
globalError(supplementErrorMessage("uncaught exception during compilation: " + shown))
throw ex
@@ -1576,37 +1553,40 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// progress update
informTime(globalPhase.description, startTime)
phaseTimings(globalPhase) = currentTime - startTime
-
- if (opt.writeICodeAtICode || (opt.printPhase && runIsAtOptimiz)) {
+ val shouldWriteIcode = (
+ (settings.writeICode.isSetByUser && (settings.writeICode containsPhase globalPhase))
+ || (!settings.Xprint.doAllPhases && (settings.Xprint containsPhase globalPhase) && runIsAtOptimiz)
+ )
+ if (shouldWriteIcode) {
// Write *.icode files when -Xprint-icode or -Xprint:<some-optimiz-phase> was given.
writeICode()
- } else if (opt.printPhase || opt.printLate && runIsAt(cleanupPhase)) {
+ } else if ((settings.Xprint containsPhase globalPhase) || settings.printLate.value && runIsAt(cleanupPhase)) {
// print trees
- if (opt.showTrees) nodePrinters.printAll()
+ if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) nodePrinters.printAll()
else printAllUnits()
}
// print the symbols presently attached to AST nodes
- if (opt.showSymbols)
+ if (settings.Yshowsyms.value)
trackerFactory.snapshot()
// print members
- if (opt.showPhase)
+ if (settings.Yshow containsPhase globalPhase)
showMembers()
// browse trees with swing tree viewer
- if (opt.browsePhase)
+ if (settings.browse containsPhase globalPhase)
treeBrowser browse (phase.name, units)
// move the pointer
globalPhase = globalPhase.next
// run tree/icode checkers
- if (opt.checkPhase)
+ if (settings.check containsPhase globalPhase.prev)
runCheckers()
// output collected statistics
- if (opt.printStats)
+ if (settings.Ystatistics.value)
statistics.print(phase)
advancePhase
@@ -1616,7 +1596,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
units map (_.body) foreach (traceSymbols recordSymbolsInTree _)
// In case no phase was specified for -Xshow-class/object, show it now for sure.
- if (opt.noShow)
+ if (settings.Yshow.isDefault)
showMembers()
reportCompileErrors()
@@ -1632,7 +1612,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// Reset project
if (!stopPhase("namer")) {
- atPhase(namerPhase) {
+ enteringPhase(namerPhase) {
resetProjectClasses(RootClass)
}
}
@@ -1648,7 +1628,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def compile(filenames: List[String]) {
try {
val sources: List[SourceFile] =
- if (isScriptRun && filenames.size > 1) returning(Nil)(_ => globalError("can only compile one script at a time"))
+ if (settings.script.isSetByUser && filenames.size > 1) returning(Nil)(_ => globalError("can only compile one script at a time"))
else filenames map getSourceFile
compileSources(sources)
@@ -1672,7 +1652,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (firstPhase ne null) { // we might get here during initialization, is a source is newer than the binary
val maxId = math.max(globalPhase.id, typerPhase.id)
firstPhase.iterator takeWhile (_.id < maxId) foreach (ph =>
- atPhase(ph)(ph.asInstanceOf[GlobalPhase] applyPhase unit))
+ enteringPhase(ph)(ph.asInstanceOf[GlobalPhase] applyPhase unit))
refreshProgress
}
}
@@ -1681,56 +1661,16 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
* is needed for?)
*/
private def resetPackageClass(pclazz: Symbol) {
- atPhase(firstPhase) {
- pclazz.setInfo(atPhase(typerPhase)(pclazz.info))
+ enteringPhase(firstPhase) {
+ pclazz.setInfo(enteringPhase(typerPhase)(pclazz.info))
}
if (!pclazz.isRoot) resetPackageClass(pclazz.owner)
}
-
- /**
- * Re-orders the source files to
- * 1. This Space Intentionally Left Blank
- * 2. LowPriorityImplicits / EmbeddedControls (i.e. parents of Predef)
- * 3. the rest
- *
- * 1 is to avoid cyclic reference errors.
- * 2 is due to the following. When completing "Predef" (*), typedIdent is called
- * for its parents (e.g. "LowPriorityImplicits"). typedIdent checks whether
- * the symbol reallyExists, which tests if the type of the symbol after running
- * its completer is != NoType.
- * If the "namer" phase has not yet run for "LowPriorityImplicits", the symbol
- * has a SourcefileLoader as type. Calling "doComplete" on it does nothing at
- * all, because the source file is part of the files to be compiled anyway.
- * So the "reallyExists" test will return "false".
- * Only after the namer, the symbol has a lazy type which actually computes
- * the info, and "reallyExists" behaves as expected.
- * So we need to make sure that the "namer" phase is run on predef's parents
- * before running it on predef.
- *
- * (*) Predef is completed early when calling "mkAttributedRef" during the
- * addition of "import Predef._" to sourcefiles. So this situation can't
- * happen for user classes.
- *
- */
- private def coreClassesFirst(files: List[SourceFile]) = {
- val goLast = 4
- def rank(f: SourceFile) = {
- if (f.file.container.name != "scala") goLast
- else f.file.name match {
- case "LowPriorityImplicits.scala" => 2
- case "StandardEmbeddings.scala" => 2
- case "EmbeddedControls.scala" => 2
- case "Predef.scala" => 3 /* Predef.scala before Any.scala, etc. */
- case _ => goLast
- }
- }
- files sortBy rank
- }
} // class Run
def printAllUnits() {
print("[[syntax trees at end of %25s]]".format(phase))
- afterPhase(phase)(currentRun.units foreach { unit =>
+ exitingPhase(phase)(currentRun.units foreach { unit =>
nodePrinters showUnit unit
})
}
@@ -1739,7 +1679,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
*/
def showDef(fullName: Name, declsOnly: Boolean, ph: Phase) = {
val boringOwners = Set[Symbol](definitions.AnyClass, definitions.AnyRefClass, definitions.ObjectClass)
- def phased[T](body: => T): T = afterPhase(ph)(body)
+ def phased[T](body: => T): T = exitingPhase(ph)(body)
def boringMember(sym: Symbol) = boringOwners(sym.owner)
def symString(sym: Symbol) = if (sym.isTerm) sym.defString else sym.toString
@@ -1795,7 +1735,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
informProgress("wrote " + file)
} catch {
case ex: IOException =>
- if (opt.debug) ex.printStackTrace()
+ if (settings.debug.value) ex.printStackTrace()
globalError("could not write file " + file)
}
})
@@ -1806,14 +1746,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// and forScaladoc default to onlyPresentation, which is the same as defaulting
// to false except in old code. The downside is that this leaves us calling a
// deprecated method: but I see no simple way out, so I leave it for now.
- def forJVM = opt.jvm
- override def forMSIL = opt.msil
- def forInteractive = onlyPresentation
- def forScaladoc = onlyPresentation
+ def forJVM = settings.target.value startsWith "jvm"
+ override def forMSIL = settings.target.value startsWith "msil"
+ def forInteractive = false
+ def forScaladoc = false
def createJavadoc = false
-
- @deprecated("Use forInteractive or forScaladoc, depending on what you're after", "2.9.0")
- def onlyPresentation = false
}
object Global {
diff --git a/src/compiler/scala/tools/nsc/SubComponent.scala b/src/compiler/scala/tools/nsc/SubComponent.scala
index fc3316fb7f..2f23a780f4 100644
--- a/src/compiler/scala/tools/nsc/SubComponent.scala
+++ b/src/compiler/scala/tools/nsc/SubComponent.scala
@@ -47,8 +47,8 @@ abstract class SubComponent {
private var ownPhaseCache: WeakReference[Phase] = new WeakReference(null)
private var ownPhaseRunId = global.NoRunId
- @inline final def beforeOwnPhase[T](op: => T) = global.beforePhase(ownPhase)(op)
- @inline final def afterOwnPhase[T](op: => T) = global.afterPhase(ownPhase)(op)
+ @inline final def beforeOwnPhase[T](op: => T) = global.enteringPhase(ownPhase)(op)
+ @inline final def afterOwnPhase[T](op: => T) = global.exitingPhase(ownPhase)(op)
/** The phase corresponding to this subcomponent in the current compiler run */
def ownPhase: Phase = {
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 267a5dcefd..be7a6295b4 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -509,7 +509,7 @@ abstract class TreeBrowsers {
/** Return a textual representation of this t's symbol */
def symbolText(t: Tree): String = {
val prefix =
- if (t.hasSymbol) "[has] "
+ if (t.hasSymbolField) "[has] "
else if (t.isDef) "[defines] "
else ""
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index fc8228f644..a74b62bf8d 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -22,7 +22,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
def mkCheckInit(tree: Tree): Tree = {
val tpe =
- if (tree.tpe != null || !tree.hasSymbol) tree.tpe
+ if (tree.tpe != null || !tree.hasSymbolField) tree.tpe
else tree.symbol.tpe
if (!global.phase.erasedTypes && settings.warnSelectNullable.value &&
@@ -52,7 +52,10 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
}
// wrap the given expression in a SoftReference so it can be gc-ed
- def mkSoftRef(expr: Tree): Tree = atPos(expr.pos)(New(SoftReferenceClass.tpe, expr))
+ def mkSoftRef(expr: Tree): Tree = atPos(expr.pos) {
+ val constructor = SoftReferenceClass.info.nonPrivateMember(nme.CONSTRUCTOR).suchThat(_.paramss.flatten.size == 1)
+ NewFromConstructor(constructor, expr)
+ }
// annotate the expression with @unchecked
def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) {
@@ -89,16 +92,16 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
case Block((vd: ValDef) :: Nil, orig@Match(selector, cases)) => // println("block match: "+ (selector, cases, vd) + "for:\n"+ matchExpr )
caseMatch(matchExpr, selector, cases, m => copyBlock(matchExpr, List(vd), m))
// virtpatmat
- case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
+ case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if !settings.XoldPatmat.value => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher)
// optimized version of virtpatmat
- case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
+ case Block(stats, matchEndDef) if !settings.XoldPatmat.value && (stats forall treeInfo.hasSynthCaseSymbol) =>
// the assumption is once we encounter a case, the remainder of the block will consist of cases
// the prologue may be empty, usually it is the valdef that stores the scrut
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity)
// optimized version of virtpatmat
- case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) =>
+ case Block(outerStats, orig@Block(stats, matchEndDef)) if !settings.XoldPatmat.value && (stats forall treeInfo.hasSynthCaseSymbol) =>
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m))
case other =>
@@ -109,7 +112,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
def copyBlock(orig: Tree, stats: List[Tree], expr: Tree): Block = Block(stats, expr)
def dropSyntheticCatchAll(cases: List[CaseDef]): List[CaseDef] =
- if (!opt.virtPatmat) cases
+ if (settings.XoldPatmat.value) cases
else cases filter {
case CaseDef(pat, EmptyTree, Throw(Apply(Select(New(exTpt), nme.CONSTRUCTOR), _))) if (treeInfo.isWildcardArg(pat) && (exTpt.tpe.typeSymbol eq MatchErrorClass)) => false
case CaseDef(pat, guard, body) => true
@@ -206,7 +209,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
else AppliedTypeTree(Ident(clazz), targs map TypeTree)
))
}
- def mkSuperSelect = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
+ def mkSuperInitCall: Select = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR)
def wildcardStar(tree: Tree) =
atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) }
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index dec7b648ee..f6073cf185 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -116,7 +116,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
// convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
vparamss1 = List() :: vparamss1;
- val superRef: Tree = atPos(superPos)(gen.mkSuperSelect)
+ val superRef: Tree = atPos(superPos)(gen.mkSuperInitCall)
val superCall = (superRef /: argss) (Apply.apply)
List(
atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) (
@@ -341,7 +341,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
tree
case _ =>
val dupl = tree.duplicate
- if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
+ if (tree.hasSymbolField && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
dupl.symbol = NoSymbol
dupl.tpe = null
dupl
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index a7da857429..072f4b9ef2 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -389,7 +389,7 @@ self =>
Nil,
ListOfNil,
TypeTree(),
- Block(List(Apply(gen.mkSuperSelect, Nil)), Literal(Constant(())))
+ Block(List(Apply(gen.mkSuperInitCall, Nil)), Literal(Constant(())))
)
// def main
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 69091e4880..5b828ded79 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -283,10 +283,16 @@ trait Scanners extends ScannersCommon {
prev copyFrom this
val nextLastOffset = charOffset - 1
fetchToken()
+ def resetOffset() {
+ offset = prev.offset
+ lastOffset = prev.lastOffset
+ }
if (token == CLASS) {
token = CASECLASS
+ resetOffset()
} else if (token == OBJECT) {
token = CASEOBJECT
+ resetOffset()
} else {
lastOffset = nextLastOffset
next copyFrom this
@@ -402,7 +408,7 @@ trait Scanners extends ScannersCommon {
* there a realistic situation where one would need it?
*/
if (isDigit(ch)) {
- if (opt.future) syntaxError("Non-zero numbers may not have a leading zero.")
+ if (settings.future.value) syntaxError("Non-zero numbers may not have a leading zero.")
else deprecationWarning("Treating numbers with a leading zero as octal is deprecated.")
}
base = 8
@@ -998,9 +1004,9 @@ trait Scanners extends ScannersCommon {
val c = lookahead.getc()
/** As of scala 2.11, it isn't a number unless c here is a digit, so
- * opt.future excludes the rest of the logic.
+ * settings.future.value excludes the rest of the logic.
*/
- if (opt.future && !isDigit(c))
+ if (settings.future.value && !isDigit(c))
return setStrVal()
val isDefinitelyNumber = (c: @switch) match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index afafff4a64..c6a38f5be6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -191,7 +191,7 @@ abstract class TreeBuilder {
} else {
val x = freshTermName()
Block(
- List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))),
+ List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))),
Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x))))
}
} else {
@@ -497,7 +497,7 @@ abstract class TreeBuilder {
def makeCatchFromExpr(catchExpr: Tree): CaseDef = {
val binder = freshTermName("x")
val pat = Bind(binder, Typed(Ident(nme.WILDCARD), Ident(tpnme.Throwable)))
- val catchDef = ValDef(NoMods, freshTermName("catchExpr"), TypeTree(), catchExpr)
+ val catchDef = ValDef(Modifiers(ARTIFACT), freshTermName("catchExpr"), TypeTree(), catchExpr)
val catchFn = Ident(catchDef.name)
val body = atPos(catchExpr.pos.makeTransparent)(Block(
List(catchDef),
@@ -568,7 +568,7 @@ abstract class TreeBuilder {
val tmp = freshTermName()
val firstDef =
atPos(matchExpr.pos) {
- ValDef(Modifiers(PrivateLocal | SYNTHETIC | (mods.flags & LAZY)),
+ ValDef(Modifiers(PrivateLocal | SYNTHETIC | ARTIFACT | (mods.flags & LAZY)),
tmp, TypeTree(), matchExpr)
}
var cnt = 0
diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
index 5e3ba5d355..1ab9f5c280 100644
--- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
@@ -565,7 +565,7 @@ abstract class ScalaPrimitives {
import definitions._
val code = getPrimitive(fun)
- def elementType = beforeTyper {
+ def elementType = enteringTyper {
val arrayParent = tpe :: tpe.parents collectFirst {
case TypeRef(_, ArrayClass, elem :: Nil) => elem
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 2fa9c076dd..d4126f2786 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1163,34 +1163,30 @@ abstract class GenICode extends SubComponent {
resCtx
}
- private def adapt(from: TypeKind, to: TypeKind, ctx: Context, pos: Position): Unit = {
- if (!(from <:< to) && !(from == NullReference && to == NothingReference)) {
- to match {
- case UNIT =>
- ctx.bb.emit(DROP(from), pos)
- debuglog("Dropped an " + from);
-
- case _ =>
- debugassert(from != UNIT, "Can't convert from UNIT to " + to + " at: " + pos)
- assert(!from.isReferenceType && !to.isReferenceType,
- "type error: can't convert from " + from + " to " + to +" in unit " + unit.source + " at " + pos)
-
- ctx.bb.emit(CALL_PRIMITIVE(Conversion(from, to)), pos)
- }
- } else if (from == NothingReference) {
- ctx.bb.emit(THROW(ThrowableClass))
- ctx.bb.enterIgnoreMode
- } else if (from == NullReference) {
- ctx.bb.emit(DROP(from))
- ctx.bb.emit(CONSTANT(Constant(null)))
+ private def adapt(from: TypeKind, to: TypeKind, ctx: Context, pos: Position) {
+ // An awful lot of bugs explode here - let's leave ourselves more clues.
+ // A typical example is an overloaded type assigned after typer.
+ log(s"GenICode#adapt($from, $to, $ctx, $pos)")
+
+ val conforms = (from <:< to) || (from == NullReference && to == NothingReference)
+ def coerce(from: TypeKind, to: TypeKind) = ctx.bb.emit(CALL_PRIMITIVE(Conversion(from, to)), pos)
+ def checkAssertions() {
+ def msg = s"Can't convert from $from to $to in unit ${unit.source} at $pos"
+ debugassert(from != UNIT, msg)
+ assert(!from.isReferenceType && !to.isReferenceType, msg)
}
- else if (from == ThrowableReference && !(ThrowableClass.tpe <:< to.toType)) {
- log("Inserted check-cast on throwable to " + to + " at " + pos)
- ctx.bb.emit(CHECK_CAST(to))
+ if (conforms) from match {
+ case NothingReference => ctx.bb.emit(THROW(ThrowableClass)) ; ctx.bb.enterIgnoreMode
+ case NullReference => ctx.bb.emit(Seq(DROP(from), CONSTANT(Constant(null))))
+ case ThrowableReference if !(ThrowableClass.tpe <:< to.toType) => ctx.bb.emit(CHECK_CAST(to)) // downcast throwables
+ case _ =>
+ // widen subrange types
+ if (from.isIntSizedType && to == LONG)
+ coerce(INT, LONG)
}
- else (from, to) match {
- case (BYTE, LONG) | (SHORT, LONG) | (CHAR, LONG) | (INT, LONG) => ctx.bb.emit(CALL_PRIMITIVE(Conversion(INT, LONG)))
- case _ => ()
+ else to match {
+ case UNIT => ctx.bb.emit(DROP(from), pos) // value discarding
+ case _ => checkAssertions() ; coerce(from, to) // other primitive coercions
}
}
@@ -1906,18 +1902,8 @@ abstract class GenICode extends SubComponent {
var handlerCount = 0
- override def toString(): String = {
- val buf = new StringBuilder()
- buf.append("\tpackage: ").append(packg).append('\n')
- buf.append("\tclazz: ").append(clazz).append('\n')
- buf.append("\tmethod: ").append(method).append('\n')
- buf.append("\tbb: ").append(bb).append('\n')
- buf.append("\tlabels: ").append(labels).append('\n')
- buf.append("\texception handlers: ").append(handlers).append('\n')
- buf.append("\tcleanups: ").append(cleanups).append('\n')
- buf.append("\tscope: ").append(scope).append('\n')
- buf.toString()
- }
+ override def toString =
+ s"package $packg { class $clazz { def $method { bb=$bb } } }"
def loadException(ctx: Context, exh: ExceptionHandler, pos: Position) = {
debuglog("Emitting LOAD_EXCEPTION for class: " + exh.loadExceptionClass)
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
index 0d688d51f2..aa3f4dcb7e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
@@ -381,10 +381,9 @@ abstract class ICodeCheckers {
for (instr <- b) {
this.instruction = instr
- def checkLocal(local: Local): Unit = {
- method lookupLocal local.sym.name getOrElse {
- icodeError(" " + local + " is not defined in method " + method)
- }
+ def checkLocal(local: Local) {
+ if ((method lookupLocal local.sym.name).isEmpty)
+ icodeError(s" $local is not defined in method $method")
}
def checkField(obj: TypeKind, field: Symbol): Unit = obj match {
case REFERENCE(sym) =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index d43013c644..ffe8c8afe3 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -37,7 +37,7 @@ abstract class ICodes extends AnyRef
/** Debugging flag */
def shouldCheckIcode = settings.check contains global.genicode.phaseName
- def checkerDebug(msg: String) = if (shouldCheckIcode && global.opt.debug) println(msg)
+ def checkerDebug(msg: String) = if (shouldCheckIcode && global.settings.debug.value) println(msg)
/** The ICode linearizer. */
val linearizer: Linearizer = settings.Xlinearizer.value match {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 0cacce10f9..dc948a3d08 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -55,7 +55,7 @@ trait TypeKinds { self: ICodes =>
def toType: Type = reversePrimitiveMap get this map (_.tpe) getOrElse {
this match {
- case REFERENCE(cls) => cls.tpe
+ case REFERENCE(cls) => cls.tpe_*
case ARRAY(elem) => arrayType(elem.toType)
case _ => abort("Unknown type kind.")
}
@@ -139,7 +139,7 @@ trait TypeKinds { self: ICodes =>
* Here we make the adjustment by rewinding to a pre-erasure state and
* sifting through the parents for a class type.
*/
- def lub0(tk1: TypeKind, tk2: TypeKind): Type = beforeUncurry {
+ def lub0(tk1: TypeKind, tk2: TypeKind): Type = enteringUncurry {
import definitions._
val tp = global.lub(List(tk1.toType, tk2.toType))
val (front, rest) = tp.parents span (_.typeSymbol.isTrait)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index ef3e82a75a..086327934b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -23,7 +23,7 @@ trait BytecodeWriters {
import global._
private def outputDirectory(sym: Symbol): AbstractFile = (
- settings.outputDirs.outputDirFor(beforeFlatten(sym.sourceFile))
+ settings.outputDirs.outputDirFor(enteringFlatten(sym.sourceFile))
)
private def getFile(base: AbstractFile, /*cls.getName()*/ clsName: String, suffix: String): AbstractFile = {
var dir = base
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index f9eeb41e6d..34d46e27fe 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -33,7 +33,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
override def newPhase(p: Phase): Phase = new AsmPhase(p)
private def outputDirectory(sym: Symbol): AbstractFile =
- settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
+ settings.outputDirs outputDirFor enteringFlatten(sym.sourceFile)
private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
var dir = base
@@ -81,9 +81,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
hasApproximate && {
// Before erasure so we can identify generic mains.
- beforeErasure {
+ enteringErasure {
val companion = sym.linkedClassOfClass
- val companionMain = companion.tpe.member(nme.main)
+ val companionMain = companion.tpe_*.member(nme.main)
if (hasJavaMainMethod(companion))
failNoForwarder("companion contains its own main method")
@@ -311,7 +311,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
}
def isTopLevelModule(sym: Symbol): Boolean =
- afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
+ exitingPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
def isStaticModule(sym: Symbol): Boolean = {
sym.isModuleClass && !sym.isImplClass && !sym.isLifted
@@ -579,7 +579,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
* of inner class all until root class.
*/
def collectInnerClass(s: Symbol): Unit = {
- // TODO: some beforeFlatten { ... } which accounts for
+ // TODO: some enteringFlatten { ... } which accounts for
// being nested in parameterized classes (if we're going to selectively flatten.)
val x = innerClassSymbolFor(s)
if(x ne NoSymbol) {
@@ -604,11 +604,18 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
val internalName = cachedJN.toString()
val trackedSym = jsymbol(sym)
reverseJavaName.get(internalName) match {
- case None =>
+ case Some(oldsym) if oldsym.exists && trackedSym.exists =>
+ assert(
+ // In contrast, neither NothingClass nor NullClass show up bytecode-level.
+ (oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass),
+ s"""|Different class symbols have the same bytecode-level internal name:
+ | name: $internalName
+ | oldsym: ${oldsym.fullNameString}
+ | tracked: ${trackedSym.fullNameString}
+ """.stripMargin
+ )
+ case _ =>
reverseJavaName.put(internalName, trackedSym)
- case Some(oldsym) =>
- assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass), // In contrast, neither NothingClass nor NullClass show up bytecode-level.
- "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: " + internalName)
}
}
@@ -681,7 +688,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
innerSym.rawname + innerSym.moduleSuffix
// add inner classes which might not have been referenced yet
- afterErasure {
+ exitingErasure {
for (sym <- List(csym, csym.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass)
innerClassBuffer += m
}
@@ -872,7 +879,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
if (!needsGenericSignature(sym)) { return null }
- val memberTpe = beforeErasure(owner.thisType.memberInfo(sym))
+ val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
if (jsOpt.isEmpty) { return null }
@@ -906,7 +913,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
}
if ((settings.check containsName phaseName)) {
- val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe))
+ val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
val bytecodeTpe = owner.thisType.memberInfo(sym)
if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
getCurrentCUnit().warning(sym.pos,
@@ -1335,7 +1342,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// Additional interface parents based on annotations and other cues
def newParentForAttr(attr: Symbol): Option[Symbol] = attr match {
- case SerializableAttr => Some(SerializableClass)
case CloneableAttr => Some(CloneableClass)
case RemoteAttr => Some(RemoteInterfaceClass)
case _ => None
@@ -1439,7 +1445,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
if (lmoc != NoSymbol) {
// it must be a top level class (name contains no $s)
val isCandidateForForwarders = {
- afterPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass }
+ exitingPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass }
}
if (isCandidateForForwarders) {
log("Adding static forwarders from '%s' to implementations in '%s'".format(c.symbol, lmoc))
@@ -2401,6 +2407,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
import asm.Opcodes
(instr.category: @scala.annotation.switch) match {
+
case icodes.localsCat =>
def genLocalInstr() = (instr: @unchecked) match {
case THIS(_) => jmethod.visitVarInsn(Opcodes.ALOAD, 0)
@@ -2494,7 +2501,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
case icodes.objsCat =>
def genObjsInstr() = (instr: @unchecked) match {
-
case BOX(kind) =>
val MethodNameAndType(mname, mdesc) = jBoxTo(kind)
jcode.invokestatic(BoxesRunTime, mname, mdesc)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index cb6156c59c..617c641fa9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -38,7 +38,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
override def newPhase(p: Phase): Phase = new JvmPhase(p)
private def outputDirectory(sym: Symbol): AbstractFile =
- settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
+ settings.outputDirs outputDirFor enteringFlatten(sym.sourceFile)
private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
var dir = base
@@ -85,7 +85,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// succeed or warn that it isn't.
hasApproximate && {
// Before erasure so we can identify generic mains.
- beforeErasure {
+ enteringErasure {
val companion = sym.linkedClassOfClass
val companionMain = companion.tpe.member(nme.main)
@@ -218,7 +218,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// Additional interface parents based on annotations and other cues
def newParentForAttr(attr: Symbol): Option[Symbol] = attr match {
- case SerializableAttr => Some(SerializableClass)
case CloneableAttr => Some(JavaCloneableClass)
case RemoteAttr => Some(RemoteInterfaceClass)
case _ => None
@@ -318,7 +317,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* of inner class all until root class.
*/
def collectInnerClass(s: Symbol): Unit = {
- // TODO: some beforeFlatten { ... } which accounts for
+ // TODO: some enteringFlatten { ... } which accounts for
// being nested in parameterized classes (if we're going to selectively flatten.)
val x = innerClassSymbolFor(s)
if(x ne NoSymbol) {
@@ -448,7 +447,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// it must be a top level class (name contains no $s)
def isCandidateForForwarders(sym: Symbol): Boolean =
- afterPickler {
+ exitingPickler {
!(sym.name.toString contains '$') && sym.hasModuleFlag && !sym.isImplClass && !sym.isNestedClass
}
@@ -736,13 +735,13 @@ 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))
+ val memberTpe = enteringErasure(owner.thisType.memberInfo(sym))
erasure.javaSig(sym, memberTpe) foreach { sig =>
// This seems useful enough in the general case.
log(sig)
if (checkSignatures) {
- val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe))
+ val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe))
val bytecodeTpe = owner.thisType.memberInfo(sym)
if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
clasz.cunit.warning(sym.pos,
@@ -757,8 +756,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
}
val index = jmember.getConstantPool.addUtf8(sig).toShort
- if (opt.verboseDebug)
- beforeErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index))
+ if (settings.verbose.value && settings.debug.value)
+ enteringErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index))
val buf = ByteBuffer.allocate(2)
buf putShort index
@@ -834,7 +833,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
innerSym.rawname + innerSym.moduleSuffix
// add inner classes which might not have been referenced yet
- afterErasure {
+ exitingErasure {
for (sym <- List(clasz.symbol, clasz.symbol.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass)
innerClassBuffer += m
}
@@ -1812,7 +1811,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* Synthetic locals are skipped. All variables are method-scoped.
*/
private def genLocalVariableTable(m: IMethod, jcode: JCode) {
- val vars = m.locals filterNot (_.sym.isSynthetic)
+ val vars = m.locals filterNot (_.sym.isArtifact)
if (vars.isEmpty) return
val pool = jclass.getConstantPool
@@ -1989,7 +1988,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
)
def isTopLevelModule(sym: Symbol): Boolean =
- afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
+ exitingPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
def isStaticModule(sym: Symbol): Boolean = {
sym.isModuleClass && !sym.isImplClass && !sym.isLifted
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index f56aa74d53..39ea074dc0 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -45,8 +45,8 @@ abstract class GenMSIL extends SubComponent {
//classes is ICodes.classes, a HashMap[Symbol, IClass]
classes.values foreach codeGenerator.findEntryPoint
- if( opt.showClass.isDefined && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead
- val entryclass = opt.showClass.get.toString
+ if( settings.Xshowcls.isSetByUser && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead
+ val entryclass = settings.Xshowcls.value.toString
warning("Couldn't find entry class " + entryclass)
}
@@ -124,7 +124,6 @@ abstract class GenMSIL extends SubComponent {
// Scala attributes
// symtab.Definitions -> object (singleton..)
- val SerializableAttr = definitions.SerializableAttr.tpe
val CloneableAttr = definitions.CloneableAttr.tpe
val TransientAtt = definitions.TransientAttr.tpe
// remoting: the architectures are too different, no mapping (no portable code
@@ -1126,7 +1125,7 @@ abstract class GenMSIL extends SubComponent {
}
// method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType
- val (isDelegateView, paramType, resType) = beforeTyper {
+ val (isDelegateView, paramType, resType) = enteringTyper {
msym.tpe match {
case MethodType(params, resultType)
if (params.length == 1 && msym.name == nme.view_) =>
@@ -1633,18 +1632,6 @@ abstract class GenMSIL extends SubComponent {
mf = mf | (if (sym hasFlag Flags.ABSTRACT) TypeAttributes.Abstract else 0)
mf = mf | (if (sym.isTrait && !sym.isImplClass) TypeAttributes.Interface else TypeAttributes.Class)
mf = mf | (if (sym isFinal) TypeAttributes.Sealed else 0)
-
- sym.annotations foreach { a => a match {
- case AnnotationInfo(SerializableAttr, _, _) =>
- // TODO: add the Serializable TypeAttribute also if the annotation
- // System.SerializableAttribute is present (.net annotation, not scala)
- // Best way to do it: compare with
- // definitions.getClass("System.SerializableAttribute").tpe
- // when frontend available
- mf = mf | TypeAttributes.Serializable
- case _ => ()
- }}
-
mf
// static: not possible (or?)
}
@@ -1731,8 +1718,8 @@ abstract class GenMSIL extends SubComponent {
false
}
- if((entryPoint == null) && opt.showClass.isDefined) { // TODO introduce dedicated setting instead
- val entryclass = opt.showClass.get.toString
+ if((entryPoint == null) && settings.Xshowcls.isSetByUser) { // TODO introduce dedicated setting instead
+ val entryclass = settings.Xshowcls.value.toString
val cfn = cls.symbol.fullName
if(cfn == entryclass) {
for (m <- cls.methods; if isEntryPoint(m.symbol)) { entryPoint = m.symbol }
@@ -1955,7 +1942,7 @@ abstract class GenMSIL extends SubComponent {
} // createClassMembers0
private def isTopLevelModule(sym: Symbol): Boolean =
- beforeRefchecks {
+ enteringRefchecks {
sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index e9fb060dda..5c2c2a37e6 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -193,7 +193,7 @@ abstract class Inliners extends SubComponent {
private var currentIClazz: IClass = _
private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg)
- private def ownedName(sym: Symbol): String = afterUncurry {
+ private def ownedName(sym: Symbol): String = exitingUncurry {
val count = (
if (!sym.isMethod) 1
else if (sym.owner.isAnonymousFunction) 3
@@ -279,7 +279,7 @@ abstract class Inliners extends SubComponent {
}
val tfa = new analysis.MTFAGrowable()
- tfa.stat = global.opt.printStats
+ tfa.stat = global.settings.Ystatistics.value
val staleOut = new mutable.ListBuffer[BasicBlock]
val splicedBlocks = mutable.Set.empty[BasicBlock]
val staleIn = mutable.Set.empty[BasicBlock]
@@ -584,7 +584,7 @@ abstract class Inliners extends SubComponent {
private def isHigherOrderMethod(sym: Symbol) = (
sym.isMethod
- && beforeExplicitOuter(sym.info.paramTypes exists isFunctionType) // was "at erasurePhase.prev"
+ && enteringExplicitOuter(sym.info.paramTypes exists isFunctionType) // was "at erasurePhase.prev"
)
/** Should method 'sym' being called in 'receiver' be loaded from disk? */
@@ -1058,8 +1058,8 @@ abstract class Inliners extends SubComponent {
if (inc.isMonadic) score += 3
else if (inc.isHigherOrder) score += 1
- if (inc.isInClosure) score += 2
- if (inlinedMethodCount(inc.sym) > 2) score -= 2
+ if (inc.isInClosure) score += 2;
+ if (inlinedMethodCount(inc.sym) > 2) score -= 2;
score
}
}
diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
index cdde768274..ad6ca68fec 100644
--- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala
@@ -145,7 +145,7 @@ trait DependencyAnalysis extends SubComponent with Files {
val name = d.toString
d.symbol match {
case s : ModuleClassSymbol =>
- val isTopLevelModule = afterPickler { !s.isImplClass && !s.isNestedClass }
+ val isTopLevelModule = exitingPickler { !s.isImplClass && !s.isNestedClass }
if (isTopLevelModule && (s.companionModule != NoSymbol)) {
dependencies.emits(source, nameToFile(unit.source.file, name))
@@ -183,7 +183,7 @@ trait DependencyAnalysis extends SubComponent with Files {
// was "at uncurryPhase.prev", which is actually non-deterministic
// because the continuations plugin may or may not supply uncurry's
// immediately preceding phase.
- beforeRefchecks(checkType(tree.symbol.tpe))
+ enteringRefchecks(checkType(tree.symbol.tpe))
}
tree match {
@@ -191,7 +191,7 @@ trait DependencyAnalysis extends SubComponent with Files {
!cdef.symbol.isAnonymousFunction =>
if (cdef.symbol != NoSymbol) buf += cdef.symbol
// was "at erasurePhase.prev"
- beforeExplicitOuter {
+ enteringExplicitOuter {
for (s <- cdef.symbol.info.decls)
s match {
case ts: TypeSymbol if !ts.isClass =>
@@ -203,7 +203,7 @@ trait DependencyAnalysis extends SubComponent with Files {
case ddef: DefDef =>
// was "at typer.prev"
- beforeTyper { checkType(ddef.symbol.tpe) }
+ enteringTyper { checkType(ddef.symbol.tpe) }
super.traverse(tree)
case a @ Select(q, n) if ((a.symbol != NoSymbol) && (q.symbol != null)) => // #2556
if (!a.symbol.isConstructor &&
diff --git a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
index e21ee07963..01c0b78efe 100644
--- a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
@@ -40,7 +40,7 @@ private[html] object SyntaxHigh {
/** Standard library classes/objects, sorted alphabetically */
val standards = Array (
- "WeakTypeTag", "Any", "AnyRef", "AnyVal", "App", "Application", "Array",
+ "WeakTypeTag", "Any", "AnyRef", "AnyVal", "App", "Array",
"Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest",
"Console", "Double", "Enumeration", "Float", "Function", "Int",
"List", "Long", "Manifest", "Map",
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index a63849e3f6..fb3b7a7dc6 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -149,9 +149,6 @@ trait MemberEntity extends Entity {
/** Some migration warning if this member has a migration annotation, or none otherwise. */
def migration: Option[Body]
- @deprecated("Use `inDefinitionTemplates` instead", "2.9.0")
- def inheritedFrom: List[TemplateEntity]
-
/** For members representing values: the type of the value returned by this member; for members
* representing types: the type itself. */
def resultType: TypeEntity
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 496aeb4aa1..6690eee1ea 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -127,18 +127,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
if (inTpl != null) thisFactory.comment(sym, thisTpl, inTpl) else None
}
- def group = if (comment.isDefined) comment.get.group.getOrElse(defaultGroup) else defaultGroup
+ def group = comment flatMap (_.group) getOrElse defaultGroup
override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
- def inDefinitionTemplates = this match {
- case mb: NonTemplateMemberEntity if (mb.useCaseOf.isDefined) =>
- mb.useCaseOf.get.inDefinitionTemplates
- case _ =>
- if (inTpl == null)
- List(makeRootPackage)
- else
- makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
- }
+ def inDefinitionTemplates =
+ if (inTpl == null)
+ List(makeRootPackage)
+ else
+ makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
def visibility = {
if (sym.isPrivateLocal) PrivateInInstance()
else if (sym.isProtectedLocal) ProtectedInInstance()
@@ -149,8 +145,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
else None
if (sym.isPrivate) PrivateInTemplate(inTpl)
else if (sym.isProtected) ProtectedInTemplate(qual getOrElse inTpl)
- else if (qual.isDefined) PrivateInTemplate(qual.get)
- else Public()
+ else qual match {
+ case Some(q) => PrivateInTemplate(q)
+ case None => Public()
+ }
}
}
def flags = {
@@ -199,7 +197,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
case NullaryMethodType(res) => resultTpe(res)
case _ => tpe
}
- val tpe = if (!isImplicitlyInherited) sym.tpe else byConversion.get.toType memberInfo sym
+ val tpe = byConversion.fold(sym.tpe) (_.toType memberInfo sym)
makeTypeInTemplateContext(resultTpe(tpe), inTemplate, sym)
}
def isDef = false
@@ -439,12 +437,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
conversions flatMap (conv =>
if (!implicitExcluded(conv.conversionQualifiedName))
conv.targetTypeComponents map {
- case pair@(template, tpe) =>
+ case (template, tpe) =>
template match {
case d: DocTemplateImpl if (d != this) => d.registerImplicitlyConvertibleClass(this, conv)
case _ => // nothing
}
- (pair._1, pair._2, conv)
+ (template, tpe, conv)
}
else List()
)
@@ -536,29 +534,25 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity {
override lazy val comment = {
val inRealTpl =
- /* Variable precendence order for implicitly added members: Take the variable defifinitions from ...
- * 1. the target of the implicit conversion
- * 2. the definition template (owner)
- * 3. the current template
- */
- if (conversion.isDefined) findTemplateMaybe(conversion.get.toType.typeSymbol) match {
- case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package
- case _ => findTemplateMaybe(sym.owner) match {
- case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package
- case _ => inTpl
- }
- } else inTpl
- if (inRealTpl != null) thisFactory.comment(sym, None, inRealTpl) else None
+ conversion.fold(Option(inTpl)) { conv =>
+ /* Variable precendence order for implicitly added members: Take the variable defifinitions from ...
+ * 1. the target of the implicit conversion
+ * 2. the definition template (owner)
+ * 3. the current template
+ */
+ findTemplateMaybe(conv.toType.typeSymbol) filterNot (_ == makeRootPackage) orElse (
+ findTemplateMaybe(sym.owner) filterNot (_ == makeRootPackage) orElse Option(inTpl)
+ )
+ }
+ inRealTpl flatMap (thisFactory.comment(sym, None, _))
}
+ override def inDefinitionTemplates = useCaseOf.fold(super.inDefinitionTemplates)(_.inDefinitionTemplates)
+
override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name)
lazy val definitionName = {
- // this contrived name is here just to satisfy some older tests -- if you decide to remove it, be my guest, and
- // also remove property("package object") from test/scaladoc/scalacheck/HtmlFactoryTest.scala so you don't break
- // the test suite...
- val packageObject = if (inPackageObject) ".package" else ""
- if (!conversion.isDefined) optimize(inDefinitionTemplates.head.qualifiedName + packageObject + "#" + name)
- else optimize(conversion.get.conversionQualifiedName + packageObject + "#" + name)
+ val qualifiedName = conversion.fold(inDefinitionTemplates.head.qualifiedName)(_.conversionQualifiedName)
+ optimize(qualifiedName + "#" + name)
}
def isBridge = sym.isBridge
def isUseCase = useCaseOf.isDefined
@@ -573,7 +567,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl)
extends NonTemplateMemberImpl(sym, conversion, useCaseOf, inTpl) {
def valueParams = {
- val info = if (!isImplicitlyInherited) sym.info else conversion.get.toType memberInfo sym
+ val info = conversion.fold(sym.info)(_.toType memberInfo sym)
info.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl)
}}
@@ -792,7 +786,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
}
- /** Get the root package */
def makeRootPackage: PackageImpl = docTemplatesCache(RootPackage).asInstanceOf[PackageImpl]
// TODO: Should be able to override the type
@@ -889,20 +882,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def makeTemplate(aSym: Symbol, inTpl: Option[TemplateImpl]): TemplateImpl = {
assert(modelFinished)
- def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl = {
- val bSym = normalizeTemplate(aSym)
- noDocTemplatesCache.get(bSym) match {
- case Some(noDocTpl) => noDocTpl
- case None => new NoDocTemplateImpl(bSym, inTpl)
- }
- }
+ def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl =
+ noDocTemplatesCache getOrElse (aSym, new NoDocTemplateImpl(aSym, inTpl))
- findTemplateMaybe(aSym) match {
- case Some(dtpl) =>
- dtpl
- case None =>
- val bSym = normalizeTemplate(aSym)
- makeNoDocTemplate(bSym, if (inTpl.isDefined) inTpl.get else makeTemplate(bSym.owner))
+ findTemplateMaybe(aSym) getOrElse {
+ val bSym = normalizeTemplate(aSym)
+ makeNoDocTemplate(bSym, inTpl getOrElse makeTemplate(bSym.owner))
}
}
@@ -995,10 +980,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
val ignoreParents = Set[Symbol](AnyClass, AnyRefClass, ObjectClass)
val filtParents =
// we don't want to expose too many links to AnyRef, that will just be redundant information
- if (tpl.isDefined && { val sym = tpl.get.sym; (!sym.isModule && parents.length < 2) || (sym == AnyValClass) || (sym == AnyRefClass) || (sym == AnyClass) })
- parents
- else
- parents.filterNot((p: Type) => ignoreParents(p.typeSymbol))
+ tpl match {
+ case Some(tpl) if (!tpl.sym.isModule && parents.length < 2) || (tpl.sym == AnyValClass) || (tpl.sym == AnyRefClass) || (tpl.sym == AnyClass) => parents
+ case _ => parents.filterNot((p: Type) => ignoreParents(p.typeSymbol))
+ }
/** Returns:
* - a DocTemplate if the type's symbol is documented
@@ -1029,7 +1014,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
def makeQualifiedName(sym: Symbol, relativeTo: Option[Symbol] = None): String = {
- val stop = if (relativeTo.isDefined) relativeTo.get.ownerChain.toSet else Set[Symbol]()
+ val stop = relativeTo map (_.ownerChain.toSet) getOrElse Set[Symbol]()
var sym1 = sym
var path = new StringBuilder()
// var path = List[Symbol]()
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 89195020c4..af89978be1 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -98,7 +98,7 @@ trait ModelFactoryImplicitSupport {
else {
var context: global.analyzer.Context = global.analyzer.rootContext(NoCompilationUnit)
- val results = global.analyzer.allViewsFrom(sym.tpe, context, sym.typeParams)
+ val results = global.analyzer.allViewsFrom(sym.tpe_*, context, sym.typeParams)
var conversions = results.flatMap(result => makeImplicitConversion(sym, result._1, result._2, context, inTpl))
// also keep empty conversions, so they appear in diagrams
// conversions = conversions.filter(!_.members.isEmpty)
@@ -109,7 +109,7 @@ trait ModelFactoryImplicitSupport {
hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName))
// Filter out non-sensical conversions from value types
- if (isPrimitiveValueType(sym.tpe))
+ if (isPrimitiveValueType(sym.tpe_*))
conversions = conversions.filter((ic: ImplicitConversionImpl) =>
hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName))
@@ -424,66 +424,52 @@ trait ModelFactoryImplicitSupport {
/* ========================= HELPER METHODS ========================== */
/**
* Computes the shadowing table for all the members in the implicit conversions
- * @param mbrs All template's members, including usecases and full signature members
+ * @param members All template's members, including usecases and full signature members
* @param convs All the conversions the template takes part in
- * @param inTpl the ususal :)
+ * @param inTpl the usual :)
*/
- def makeShadowingTable(mbrs: List[MemberImpl],
+ def makeShadowingTable(members: List[MemberImpl],
convs: List[ImplicitConversionImpl],
inTpl: DocTemplateImpl): Map[MemberEntity, ImplicitMemberShadowing] = {
assert(modelFinished)
- var shadowingTable = Map[MemberEntity, ImplicitMemberShadowing]()
+ val shadowingTable = mutable.Map[MemberEntity, ImplicitMemberShadowing]()
+ val membersByName: Map[Name, List[MemberImpl]] = members.groupBy(_.sym.name)
+ val convsByMember = (Map.empty[MemberImpl, ImplicitConversionImpl] /: convs) {
+ case (map, conv) => map ++ conv.memberImpls.map (_ -> conv)
+ }
for (conv <- convs) {
- val otherConvs = convs.filterNot(_ == conv)
+ val otherConvMembers: Map[Name, List[MemberImpl]] = convs filterNot (_ == conv) flatMap (_.memberImpls) groupBy (_.sym.name)
for (member <- conv.memberImpls) {
- // for each member in our list
val sym1 = member.sym
val tpe1 = conv.toType.memberInfo(sym1)
- // check if it's shadowed by a member in the original class
- var shadowedBySyms: List[Symbol] = List()
- for (mbr <- mbrs) {
- val sym2 = mbr.sym
- if (sym1.name == sym2.name) {
- val shadowed = !settings.docImplicitsSoundShadowing.value || {
- val tpe2 = inTpl.sym.info.memberInfo(sym2)
- !isDistinguishableFrom(tpe1, tpe2)
- }
- if (shadowed)
- shadowedBySyms ::= sym2
- }
+ // check if it's shadowed by a member in the original class.
+ val shadowed = membersByName.get(sym1.name).toList.flatten filter { other =>
+ !settings.docImplicitsSoundShadowing.value || !isDistinguishableFrom(tpe1, inTpl.sym.info.memberInfo(other.sym))
}
- val shadowedByMembers = mbrs.filter((mb: MemberImpl) => shadowedBySyms.contains(mb.sym))
-
- // check if it's shadowed by another member
- var ambiguousByMembers: List[MemberEntity] = List()
- for (conv <- otherConvs)
- for (member2 <- conv.memberImpls) {
- val sym2 = member2.sym
- if (sym1.name == sym2.name) {
- val tpe2 = conv.toType.memberInfo(sym2)
- // Ambiguity should be an equivalence relation
- val ambiguated = !isDistinguishableFrom(tpe1, tpe2) || !isDistinguishableFrom(tpe2, tpe1)
- if (ambiguated)
- ambiguousByMembers ::= member2
- }
- }
+ // check if it's shadowed by another conversion.
+ val ambiguous = otherConvMembers.get(sym1.name).toList.flatten filter { other =>
+ val tpe2 = convsByMember(other).toType.memberInfo(other.sym)
+ !isDistinguishableFrom(tpe1, tpe2) || !isDistinguishableFrom(tpe2, tpe1)
+ }
// we finally have the shadowing info
- val shadowing = new ImplicitMemberShadowing {
- def shadowingMembers: List[MemberEntity] = shadowedByMembers
- def ambiguatingMembers: List[MemberEntity] = ambiguousByMembers
- }
+ if (!shadowed.isEmpty || !ambiguous.isEmpty) {
+ val shadowing = new ImplicitMemberShadowing {
+ def shadowingMembers: List[MemberEntity] = shadowed
+ def ambiguatingMembers: List[MemberEntity] = ambiguous
+ }
- shadowingTable += (member -> shadowing)
+ shadowingTable += (member -> shadowing)
+ }
}
}
- shadowingTable
+ shadowingTable.toMap
}
@@ -608,4 +594,4 @@ trait ModelFactoryImplicitSupport {
false
} else true // the member structure is different foo(3, 5) vs foo(3)(5)
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index 924ebb8a3b..822c11307c 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -477,7 +477,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
var summaryParsed = false
def document(): Body = {
- nextChar()
val blocks = new mutable.ListBuffer[Block]
while (char != endOfText)
blocks += block()
@@ -559,21 +558,21 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def code(): Block = {
jumpWhitespace()
jump("{{{")
- readUntil("}}}")
+ val str = readUntil("}}}")
if (char == endOfText)
reportError(pos, "unclosed code block")
else
jump("}}}")
blockEnded("code block")
- Code(normalizeIndentation(getRead))
+ Code(normalizeIndentation(str))
}
/** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */
def title(): Block = {
jumpWhitespace()
- val inLevel = repeatJump("=")
+ val inLevel = repeatJump('=')
val text = inline(check("=" * inLevel))
- val outLevel = repeatJump("=", inLevel)
+ val outLevel = repeatJump('=', inLevel)
if (inLevel != outLevel)
reportError(pos, "unbalanced or unclosed heading")
blockEnded("heading")
@@ -583,7 +582,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
/** {{{ hrule ::= "----" { '-' } '\n' }}} */
def hrule(): Block = {
jumpWhitespace()
- repeatJump("-")
+ repeatJump('-')
blockEnded("horizontal rule")
HorizontalRule()
}
@@ -621,8 +620,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
}
do {
- readUntil { char == safeTagMarker || char == endOfText }
- val str = getRead()
+ val str = readUntil { char == safeTagMarker || char == endOfText }
nextChar()
list += str
@@ -660,8 +658,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
else if (check(",,")) subscript()
else if (check("[[")) link()
else {
- readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
- Text(getRead())
+ val str = readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
+ Text(str)
}
}
@@ -698,9 +696,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def htmlTag(): HtmlTag = {
jump(safeTagMarker)
- readUntil(safeTagMarker)
+ val read = readUntil(safeTagMarker)
if (char != endOfText) jump(safeTagMarker)
- var read = getRead
HtmlTag(read)
}
@@ -762,14 +759,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def link(): Inline = {
val SchemeUri = """([a-z]+:.*)""".r
jump("[[")
- var parens = 1
- readUntil { parens += 1; !check("[") }
- getRead // clear the buffer
+ var parens = 2 + repeatJump('[')
val start = "[" * parens
val stop = "]" * parens
//println("link with " + parens + " matching parens")
- readUntil { check(stop) || check(" ") }
- val target = getRead()
+ val target = readUntil { check(stop) || check(" ") }
val title =
if (!check(stop)) Some({
jump(" ")
@@ -860,7 +854,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
(char == endOfText) ||
((char == endOfLine) && {
val poff = offset
- val pc = char
nextChar() // read EOL
val ok = {
checkSkipInitWhitespace(endOfLine) ||
@@ -870,7 +863,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
checkSkipInitWhitespace('\u003D')
}
offset = poff
- char = pc
ok
})
}
@@ -882,40 +874,31 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
protected sealed class CharReader(buffer: String) { reader =>
- var char: Char = _
var offset: Int = 0
+ def char: Char =
+ if (offset >= buffer.length) endOfText else buffer charAt offset
final def nextChar() {
- if (offset >= buffer.length)
- char = endOfText
- else {
- char = buffer charAt offset
- offset += 1
- }
+ offset += 1
}
final def check(chars: String): Boolean = {
val poff = offset
- val pc = char
val ok = jump(chars)
offset = poff
- char = pc
ok
}
def checkSkipInitWhitespace(c: Char): Boolean = {
val poff = offset
- val pc = char
jumpWhitespace()
val ok = jump(c)
offset = poff
- char = pc
ok
}
def checkSkipInitWhitespace(chars: String): Boolean = {
val poff = offset
- val pc = char
jumpWhitespace()
val (ok0, chars0) =
if (chars.charAt(0) == ' ')
@@ -924,20 +907,17 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
(true, chars)
val ok = ok0 && jump(chars0)
offset = poff
- char = pc
ok
}
def countWhitespace: Int = {
var count = 0
val poff = offset
- val pc = char
while (isWhitespace(char) && char != endOfText) {
nextChar()
count += 1
}
offset = poff
- char = pc
count
}
@@ -964,38 +944,10 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
index == chars.length
}
- final def checkedJump(chars: String): Boolean = {
- val poff = offset
- val pc = char
- val ok = jump(chars)
- if (!ok) {
- offset = poff
- char = pc
- }
- ok
- }
-
- final def repeatJump(chars: String, max: Int): Int = {
+ final def repeatJump(c: Char, max: Int = Int.MaxValue): Int = {
var count = 0
- var more = true
- while (more && count < max) {
- if (!checkedJump(chars))
- more = false
- else
- count += 1
- }
- count
- }
-
- final def repeatJump(chars: String): Int = {
- var count = 0
- var more = true
- while (more) {
- if (!checkedJump(chars))
- more = false
- else
- count += 1
- }
+ while (jump(c) && count < max)
+ count += 1
count
}
@@ -1035,47 +987,41 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
/* READERS */
- private val readBuilder = new mutable.StringBuilder
-
- final def getRead(): String = {
- val bld = readBuilder.toString
- readBuilder.clear()
- if (bld.length < 6) bld.intern else bld
- }
-
- final def readUntil(ch: Char): Int = {
- var count = 0
- while (char != ch && char != endOfText) {
- readBuilder += char
- nextChar()
+ final def readUntil(c: Char): String = {
+ withRead {
+ while (char != c && char != endOfText) {
+ nextChar()
+ }
}
- count
}
- final def readUntil(chars: String): Int = {
+ final def readUntil(chars: String): String = {
assert(chars.length > 0)
- var count = 0
- val c = chars.charAt(0)
- while (!check(chars) && char != endOfText) {
- readBuilder += char
- nextChar()
- while (char != c && char != endOfText) {
- readBuilder += char
+ withRead {
+ val c = chars.charAt(0)
+ while (!check(chars) && char != endOfText) {
nextChar()
+ while (char != c && char != endOfText)
+ nextChar()
}
}
- count
}
- final def readUntil(pred: => Boolean): Int = {
- var count = 0
- while (!pred && char != endOfText) {
- readBuilder += char
- nextChar()
+ final def readUntil(pred: => Boolean): String = {
+ withRead {
+ while (char != endOfText && !pred) {
+ nextChar()
+ }
}
- count
}
+ private def withRead(read: => Unit): String = {
+ val start = offset
+ read
+ buffer.substring(start, offset)
+ }
+
+
/* CHARS CLASSES */
def isWhitespace(c: Char) = c == ' ' || c == '\t'
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 01889f4f98..2e2c772a38 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -1042,7 +1042,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
- def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) =
+ def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) {
try {
interruptsEnabled = false
respond(response) {
@@ -1051,6 +1051,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
} finally {
interruptsEnabled = true
}
+ }
// ---------------- Helper classes ---------------------------
@@ -1082,7 +1083,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
* @return true iff typechecked correctly
*/
private def applyPhase(phase: Phase, unit: CompilationUnit) {
- atPhase(phase) { phase.asInstanceOf[GlobalPhase] applyPhase unit }
+ enteringPhase(phase) { phase.asInstanceOf[GlobalPhase] applyPhase unit }
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
index 40982c62f0..f3d454ad3e 100644
--- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
@@ -49,7 +49,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
protected def newCompiler(settings: Settings) = new BuilderGlobal(settings)
val compiler = newCompiler(settings)
- import compiler.{ Symbol, Type, beforeErasure }
+ import compiler.{ Symbol, Type, enteringErasure }
import compiler.dependencyAnalysis.Inherited
private case class SymWithHistory(sym: Symbol, befErasure: Type)
@@ -161,7 +161,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
isCorrespondingSym(s.sym, sym)) match {
case Some(SymWithHistory(oldSym, info)) =>
val changes = changeSet(oldSym.info, sym)
- val changesErasure = beforeErasure(changeSet(info, sym))
+ val changesErasure = enteringErasure(changeSet(info, sym))
changesOf(oldSym) = (changes ++ changesErasure).distinct
case _ =>
@@ -332,7 +332,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
for (src <- files; localDefs = compiler.dependencyAnalysis.definitions(src)) {
definitions(src) = (localDefs map (s => {
this.classes += s.fullName -> src
- SymWithHistory(s.cloneSymbol, beforeErasure(s.info.cloneInfo(s)))
+ SymWithHistory(s.cloneSymbol, enteringErasure(s.info.cloneInfo(s)))
}))
}
this.references = compiler.dependencyAnalysis.references
diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
index 0f5777d260..4a8ee6549f 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
@@ -63,7 +63,7 @@ trait ExprTyper {
case IR.Success =>
val sym0 = symbolOfTerm(name)
// drop NullaryMethodType
- val sym = sym0.cloneSymbol setInfo afterTyper(sym0.info.finalResultType)
+ val sym = sym0.cloneSymbol setInfo exitingTyper(sym0.info.finalResultType)
if (sym.info.typeSymbol eq UnitClass) NoSymbol
else sym
case _ => NoSymbol
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 864f9bd073..1d6ec77ef2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -65,7 +65,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
import global._
def printAfterTyper(msg: => String) =
- intp.reporter printUntruncatedMessage afterTyper(msg)
+ intp.reporter printUntruncatedMessage exitingTyper(msg)
/** Strip NullaryMethodType artifacts. */
private def replInfo(sym: Symbol) = {
@@ -342,7 +342,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
// This groups the members by where the symbol is defined
val byOwner = syms groupBy (_.owner)
- val sortedOwners = byOwner.toList sortBy { case (owner, _) => afterTyper(source.info.baseClasses indexOf owner) }
+ val sortedOwners = byOwner.toList sortBy { case (owner, _) => exitingTyper(source.info.baseClasses indexOf owner) }
sortedOwners foreach {
case (owner, members) =>
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index e7c56718f7..92c2fc9768 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -187,8 +187,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
else null
}
}
- @deprecated("Use `global` for access to the compiler instance.", "2.9.0")
- lazy val compiler: global.type = global
import global._
import definitions.{ScalaPackage, JavaLangPackage, termMember, typeMember}
@@ -262,7 +260,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = {
settings.outputDirs setSingleOutput virtualDirectory
settings.exposeEmptyPackage.value = true
- new Global(settings, reporter) with ReplGlobal
+ if (settings.Yrangepos.value)
+ new Global(settings, reporter) with ReplGlobal with interactive.RangePositions
+ else
+ new Global(settings, reporter) with ReplGlobal
}
/** Parent classloader. Overridable. */
@@ -387,7 +388,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
newSym <- req.definedSymbols get name
oldSym <- oldReq.definedSymbols get name.companionName
} {
- afterTyper(replwarn(s"warning: previously defined $oldSym is not a companion to $newSym."))
+ exitingTyper(replwarn(s"warning: previously defined $oldSym is not a companion to $newSym."))
replwarn("Companions must be defined together; you may wish to use :paste mode for this.")
}
@@ -764,7 +765,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
val readRoot = getRequiredModule(readPath) // the outermost wrapper
(accessPath split '.').foldLeft(readRoot: Symbol) {
case (sym, "") => sym
- case (sym, name) => afterTyper(termMember(sym, name))
+ case (sym, name) => exitingTyper(termMember(sym, name))
}
}
/** We get a bunch of repeated warnings for reasons I haven't
@@ -951,7 +952,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath)
- def applyToResultMember[T](name: Name, f: Symbol => T) = afterTyper(f(resultSymbol.info.nonPrivateDecl(name)))
+ def applyToResultMember[T](name: Name, f: Symbol => T) = exitingTyper(f(resultSymbol.info.nonPrivateDecl(name)))
/* typeOf lookup with encoding */
def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString)))
@@ -963,10 +964,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** Types of variables defined by this request. */
lazy val compilerTypeOf = typeMap[Type](x => x) withDefaultValue NoType
/** String representations of same. */
- lazy val typeOf = typeMap[String](tp => afterTyper(tp.toString))
+ lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString))
// lazy val definedTypes: Map[Name, Type] = {
- // typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
+ // typeNames map (x => x -> exitingTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
// }
lazy val definedSymbols = (
termNames.map(x => x -> applyToResultMember(x, x => x)) ++
@@ -1059,9 +1060,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
else NoType
}
}
- def cleanMemberDecl(owner: Symbol, member: Name): Type = afterTyper {
+ def cleanMemberDecl(owner: Symbol, member: Name): Type = exitingTyper {
normalizeNonPublic {
- owner.info.nonPrivateDecl(member).tpe match {
+ owner.info.nonPrivateDecl(member).tpe_* match {
case NullaryMethodType(tp) => tp
case tp => tp
}
@@ -1148,7 +1149,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def symbolDefString(sym: Symbol) = {
TypeStrings.quieter(
- afterTyper(sym.defString),
+ exitingTyper(sym.defString),
sym.owner.name + ".this.",
sym.owner.fullName + "."
)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
index b65a1ac889..762092c08a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
@@ -44,7 +44,7 @@ class ISettings(intp: IMain) {
}
def deprecation: Boolean = intp.settings.deprecation.value
- def allSettings = Map(
+ def allSettings = Map[String, Any](
"maxPrintString" -> maxPrintString,
"maxAutoprintCompletion" -> maxAutoprintCompletion,
"unwrapStrings" -> unwrapStrings,
diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala
index 14d43bc6d5..91b70726c2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala
@@ -191,5 +191,5 @@ trait Imports {
prevRequestList flatMap (req => req.handlers map (req -> _))
private def membersAtPickler(sym: Symbol): List[Symbol] =
- beforePickler(sym.info.nonPrivateMembers.toList)
+ enteringPickler(sym.info.nonPrivateMembers.toList)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
index bab3a1e506..9a4be27c76 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -10,6 +10,7 @@ import scala.tools.jline._
import scala.tools.jline.console.completer._
import Completion._
import scala.collection.mutable.ListBuffer
+import scala.reflect.internal.util.StringOps.longestCommonPrefix
// REPL completor - queries supplied interpreter for valid
// completions based on current contents of buffer.
@@ -47,12 +48,12 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
def anyRefMethodsToShow = Set("isInstanceOf", "asInstanceOf", "toString")
def tos(sym: Symbol): String = sym.decodedName
- def memberNamed(s: String) = afterTyper(effectiveTp member newTermName(s))
+ def memberNamed(s: String) = exitingTyper(effectiveTp member newTermName(s))
def hasMethod(s: String) = memberNamed(s).isMethod
// XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the
// compiler to crash for reasons not yet known.
- def members = afterTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic))
+ def members = exitingTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic))
def methods = members.toList filter (_.isMethod)
def packages = members.toList filter (_.isPackage)
def aliases = members.toList filter (_.isAliasType)
@@ -111,7 +112,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
def excludeNames: List[String] = (anyref.methodNames filterNot anyRefMethodsToShow) :+ "_root_"
def methodSignatureString(sym: Symbol) = {
- IMain stripString afterTyper(new MethodSymbolOutput(sym).methodString())
+ IMain stripString exitingTyper(new MethodSymbolOutput(sym).methodString())
}
def exclude(name: String): Boolean = (
@@ -301,16 +302,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
def isConsecutiveTabs(buf: String, cursor: Int) =
cursor == lastCursor && buf == lastBuf
- // Longest common prefix
- def commonPrefix(xs: List[String]): String = {
- if (xs.isEmpty || xs.contains("")) ""
- else xs.head.head match {
- case ch =>
- if (xs.tail forall (_.head == ch)) "" + ch + commonPrefix(xs map (_.tail))
- else ""
- }
- }
-
// This is jline's entry point for completion.
override def complete(buf: String, cursor: Int): Candidates = {
verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
@@ -324,7 +315,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
val newCursor =
if (winners contains "") p.cursor
else {
- val advance = commonPrefix(winners)
+ val advance = longestCommonPrefix(winners)
lastCursor = p.position + advance.length
lastBuf = (buf take p.position) + advance
repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format(
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
index bf7204c754..df96a27291 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -209,10 +209,10 @@ trait MemberHandlers {
def importedSymbols = individualSymbols ++ wildcardSymbols
lazy val individualSymbols: List[Symbol] =
- beforePickler(individualNames map (targetType nonPrivateMember _))
+ enteringPickler(individualNames map (targetType nonPrivateMember _))
lazy val wildcardSymbols: List[Symbol] =
- if (importsWildcard) beforePickler(targetType.nonPrivateMembers.toList)
+ if (importsWildcard) enteringPickler(targetType.nonPrivateMembers.toList)
else Nil
/** Complete list of names imported by a wildcard */
diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/compiler/scala/tools/nsc/interpreter/Phased.scala
index 66d748a9f1..83d7012bb1 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Phased.scala
@@ -68,7 +68,7 @@ trait Phased {
def apply[T](body: => T) = immutable.SortedMap[PhaseName, T](atMap(PhaseName.all)(body): _*)
- def atCurrent[T](body: => T): T = atPhase(get)(body)
+ def atCurrent[T](body: => T): T = enteringPhase(get)(body)
def multi[T](body: => T): Seq[T] = multi map (ph => at(ph)(body))
def all[T](body: => T): Seq[T] = atMulti(PhaseName.all)(body)
def show[T](body: => T): Seq[T] = {
@@ -121,7 +121,7 @@ trait Phased {
def isEmpty = this eq NoPhaseName
// Execute some code during this phase.
- def apply[T](body: => T): T = atPhase(phase)(body)
+ def apply[T](body: => T): T = enteringPhase(phase)(body)
}
case object Parser extends PhaseName
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 244c04bdf4..4aef54bce5 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -73,7 +73,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
pass += 1
val (repeats, unseen) = todo partition seen
unseenHistory += unseen.size
- if (opt.verbose) {
+ if (settings.verbose.value) {
println("%3d %s accumulated, %s discarded. This pass: %s unseen, %s repeats".format(
pass, keep.size, discarded, unseen.size, repeats.size))
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index 5642566cf7..0bf4999fd6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -57,7 +57,7 @@ trait StructuredTypeStrings extends DestructureTypes {
else block(level, grouping)(name, nodes)
}
private def shortClass(x: Any) = {
- if (opt.debug) {
+ if (settings.debug.value) {
val name = (x.getClass.getName split '.').last
val isAnon = name.reverse takeWhile (_ != '$') forall (_.isDigit)
val str = if (isAnon) name else (name split '$').last
@@ -212,6 +212,7 @@ trait TypeStrings {
}
private def tparamString[T: ru.TypeTag] : String = {
+ import ru._
def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil }
// [Eugene to Paul] need to use not the `rootMirror`, but a mirror with the REPL's classloader
// how do I get to it? acquiring context classloader seems unreliable because of multithreading
diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
index 491718bc0d..fdf82ece71 100644
--- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
@@ -29,11 +29,7 @@ abstract class AbstractReporter extends Reporter {
private def noWarnings = settings.nowarnings.value
private def isPromptSet = settings.prompt.value
- protected def info0(pos: Position, msg: String, _severity: Severity, force: Boolean) {
- val severity =
- if (settings.fatalWarnings.value && _severity == WARNING) ERROR
- else _severity
-
+ protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean) {
if (severity == INFO) {
if (isVerbose || force) {
severity.count += 1
diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
deleted file mode 100644
index 5d324903e9..0000000000
--- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2012 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package settings
-
-/** Taking flag checking to a somewhat higher level. */
-trait AestheticSettings {
- def settings: Settings
-
- // Some(value) if setting has been set by user, None otherwise.
- def optSetting[T](s: Settings#Setting): Option[T] =
- if (s.isDefault) None else Some(s.value.asInstanceOf[T])
-
- def script = optSetting[String](settings.script)
- def encoding = optSetting[String](settings.encoding)
- def sourceReader = optSetting[String](settings.sourceReader)
-
- def debug = settings.debug.value
- def declsOnly = false
- def deprecation = settings.deprecation.value
- def experimental = settings.Xexperimental.value
- def fatalWarnings = settings.fatalWarnings.value
- def feature = settings.feature.value
- def future = settings.future.value
- def logClasspath = settings.Ylogcp.value
- def printStats = settings.Ystatistics.value
- def target = settings.target.value
- def unchecked = settings.unchecked.value
- def verbose = settings.verbose.value
- def virtPatmat = !settings.XoldPatmat.value
-
- /** Derived values */
- def jvm = target startsWith "jvm"
- def msil = target == "msil"
- def verboseDebug = debug && verbose
-}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 3ff7af791b..404f5e6b6e 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -127,6 +127,7 @@ trait ScalaSettings extends AbsScalaSettings
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 breakCycles = BooleanSetting ("-Ybreak-cycles", "Attempt to break cycles encountered during typing")
val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
val Yshow = PhasesSetting ("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index 72284cc940..0792a2b95f 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -30,7 +30,8 @@ trait Warnings {
warnInaccessible,
warnNullaryOverride,
warnNullaryUnit,
- warnAdaptedArgs
+ warnAdaptedArgs,
+ warnInferAny
)
// Warning groups.
@@ -53,6 +54,7 @@ trait Warnings {
val warnInaccessible = BooleanSetting ("-Ywarn-inaccessible", "Warn about inaccessible types in method signatures.")
val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override",
"Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.")
+ val warnInferAny = BooleanSetting ("-Ywarn-infer-any", "Warn when a type argument is inferred to be `Any`.")
// Backward compatibility.
def Xwarnfatal = fatalWarnings
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 8fd8dfaf83..42589874fe 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -358,7 +358,7 @@ abstract class ClassfileParser {
}
value match {
case ct: Constant => ct
- case cls: Symbol => Constant(cls.tpe)
+ case cls: Symbol => Constant(cls.tpe_*)
case arr: Type => Constant(arr)
}
}
@@ -420,9 +420,9 @@ abstract class ClassfileParser {
var sym: Symbol = rootMirror.RootClass
// was "at flatten.prev"
- beforeFlatten {
+ enteringFlatten {
for (part0 <- parts; if !(part0 == ""); part = newTermName(part0)) {
- val sym1 = beforeIcode {
+ val sym1 = enteringIcode {
sym.linkedClassOfClass.info
sym.info.decl(part.encode)
}//.suchThat(module == _.isModule)
@@ -512,9 +512,9 @@ abstract class ClassfileParser {
}
else raiseLoaderLevel {
val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
- else pool.getSuperClass(in.nextChar).tpe
+ else pool.getSuperClass(in.nextChar).tpe_*
val ifaceCount = in.nextChar
- var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe
+ var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe_*
if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
superType :: ifaces
}
@@ -732,17 +732,19 @@ abstract class ClassfileParser {
}
accept('>')
assert(xs.length > 0, tp)
- newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList))
- } else if (classSym.isMonomorphicType) {
+ logResult("new existential")(newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList)))
+ }
+ // isMonomorphicType is false if the info is incomplete, as it usually is here
+ // so have to check unsafeTypeParams.isEmpty before worrying about raw type case below,
+ // or we'll create a boatload of needless existentials.
+ else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) {
tp
- } else {
+ }
+ else {
// raw type - existentially quantify all type parameters
val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)
- val t = typeRef(pre, classSym, eparams.map(_.tpeHK))
- val res = newExistentialType(eparams, t)
- if (settings.debug.value && settings.verbose.value)
- println("raw type " + classSym + " -> " + res)
- res
+ val t = typeRef(pre, classSym, eparams.map(_.tpeHK))
+ logResult(s"raw type from $classSym")(newExistentialType(eparams, t))
}
case tp =>
assert(sig.charAt(index) != '<', tp)
@@ -751,7 +753,7 @@ abstract class ClassfileParser {
val classSym = classNameToSymbol(subName(c => c == ';' || c == '<'))
assert(!classSym.isOverloaded, classSym.alternatives)
- var tpe = processClassType(processInner(classSym.tpe))
+ var tpe = processClassType(processInner(classSym.tpe_*))
while (sig.charAt(index) == '.') {
accept('.')
val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName
@@ -784,7 +786,7 @@ abstract class ClassfileParser {
index += 1
val restype = if (sym != null && sym.isClassConstructor) {
accept('V')
- clazz.tpe
+ clazz.tpe_*
} else
sig2type(tparams, skiptvs)
JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype)
@@ -872,7 +874,7 @@ abstract class ClassfileParser {
sym.setFlag(SYNTHETIC | ARTIFACT)
in.skip(attrLen)
case tpnme.BridgeATTR =>
- sym.setFlag(BRIDGE)
+ sym.setFlag(BRIDGE | ARTIFACT)
in.skip(attrLen)
case tpnme.DeprecatedATTR =>
val arg = Literal(Constant("see corresponding Javadoc for more information."))
@@ -1203,7 +1205,7 @@ abstract class ClassfileParser {
// if loading during initialization of `definitions` typerPhase is not yet set.
// in that case we simply load the member at the current phase
if (currentRun.typerPhase != null)
- beforeTyper(getMember(sym, innerName.toTypeName))
+ enteringTyper(getMember(sym, innerName.toTypeName))
else
getMember(sym, innerName.toTypeName)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 175c322786..c02503902e 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -174,7 +174,7 @@ abstract class ICodeReader extends ClassfileParser {
}
else {
forceMangledName(name, false)
- afterFlatten(rootMirror.getClassByName(name.toTypeName))
+ exitingFlatten(rootMirror.getClassByName(name.toTypeName))
}
if (sym.isModule)
sym.moduleClass
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 29b238c4cb..933c689378 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -68,11 +68,11 @@ abstract class Pickler extends SubComponent {
return
}
- if (!t.isDef && t.hasSymbol && t.symbol.isTermMacro) {
+ if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) {
unit.error(t.pos, t.symbol.typeParams.length match {
case 0 => "macro has not been expanded"
- case 1 => "type parameter not specified"
- case _ => "type parameters not specified"
+ case 1 => "this type parameter must be specified"
+ case _ => "these type parameters must be specified"
})
return
}
@@ -177,7 +177,7 @@ abstract class Pickler extends SubComponent {
*/
private def putType(tp: Type): Unit = if (putEntry(tp)) {
tp match {
- case NoType | NoPrefix /*| DeBruijnIndex(_, _) */ =>
+ case NoType | NoPrefix =>
;
case ThisType(sym) =>
putSymbol(sym)
@@ -235,7 +235,7 @@ abstract class Pickler extends SubComponent {
private def putTree(tree: Tree): Unit = if (putEntry(tree)) {
if (tree != EmptyTree)
putType(tree.tpe)
- if (tree.hasSymbol)
+ if (tree.hasSymbolField)
putSymbol(tree.symbol)
tree match {
@@ -568,7 +568,7 @@ abstract class Pickler extends SubComponent {
tag
case sym: ClassSymbol =>
writeSymInfo(sym)
- if (sym.thisSym.tpe != sym.tpe) writeRef(sym.typeOfThis)
+ if (sym.thisSym.tpe_* != sym.tpe_*) writeRef(sym.typeOfThis)
CLASSsym
case sym: TypeSymbol =>
writeSymInfo(sym)
@@ -609,8 +609,6 @@ abstract class Pickler extends SubComponent {
writeRef(restpe); writeRefs(tparams); POLYtpe
case ExistentialType(tparams, restpe) =>
writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe
- // case DeBruijnIndex(l, i) =>
- // writeNat(l); writeNat(i); DEBRUIJNINDEXtpe
case c @ Constant(_) =>
if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0)
else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue)
@@ -1057,8 +1055,6 @@ abstract class Pickler extends SubComponent {
case ExistentialType(tparams, restpe) =>
print("EXISTENTIALtpe "); printRef(restpe); printRefs(tparams);
print("||| "+entry)
- // case DeBruijnIndex(l, i) =>
- // print("DEBRUIJNINDEXtpe "); print(l+" "+i)
case c @ Constant(_) =>
print("LITERAL ")
if (c.tag == BooleanTag) print("Boolean "+(if (c.booleanValue) 1 else 0))
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 143dcaa8be..328e4ce71f 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -111,7 +111,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
def implClass(iface: Symbol): Symbol = {
iface.info
- implClassMap.getOrElse(iface, atPhase(implClassPhase) {
+ implClassMap.getOrElse(iface, enteringPhase(implClassPhase) {
if (iface.implClass eq NoSymbol)
debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.")
else
@@ -196,7 +196,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
case PolyType(_, restpe) =>
implType(restpe)
}
- implSym setInfo implType(beforeErasure(iface.info))
+ implSym setInfo implType(enteringErasure(iface.info))
}
override def load(clazz: Symbol) { complete(clazz) }
@@ -317,10 +317,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
// body until now, because the typer knows that Any has no
// constructor and won't accept a call to super.init.
assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz)
- Block(List(Apply(gen.mkSuperSelect, Nil)), expr)
+ Block(List(Apply(gen.mkSuperInitCall, Nil)), expr)
case Block(stats, expr) =>
- // needs `hasSymbol` check because `supercall` could be a block (named / default args)
+ // needs `hasSymbolField` check because `supercall` could be a block (named / default args)
val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER))
treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr)
}
@@ -352,7 +352,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
val mix1 = mix
if (mix == tpnme.EMPTY) mix
else {
- val ps = beforeErasure {
+ val ps = enteringErasure {
sym.info.parents dropWhile (p => p.symbol.name != mix)
}
assert(!ps.isEmpty, tree);
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index fa7a53f888..1f353bb31c 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -437,19 +437,31 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
* is a value type (int et al.) in which case it must cast to the boxed version
* because invoke only returns object and erasure made sure the result is
* expected to be an AnyRef. */
- val t: Tree = ad.symbol.tpe match {
- case MethodType(mparams, resType) =>
- assert(params.length == mparams.length, mparams)
-
- typedPos {
- val sym = currentOwner.newValue(mkTerm("qual"), ad.pos) setInfo qual0.tpe
- qual = REF(sym)
+ val t: Tree = {
+ val (mparams, resType) = ad.symbol.tpe match {
+ case MethodType(mparams, resType) =>
+ assert(params.length == mparams.length, ((params, mparams)))
+ (mparams, resType)
+ case tpe @ OverloadedType(pre, alts) =>
+ unit.warning(ad.pos, s"Overloaded type reached the backend! This is a bug in scalac.\n Symbol: ${ad.symbol}\n Overloads: $tpe\n Arguments: " + ad.args.map(_.tpe))
+ alts filter (_.paramss.flatten.size == params.length) map (_.tpe) match {
+ case mt @ MethodType(mparams, resType) :: Nil =>
+ unit.warning(NoPosition, "Only one overload has the right arity, proceeding with overload " + mt)
+ (mparams, resType)
+ case _ =>
+ unit.error(ad.pos, "Cannot resolve overload.")
+ (Nil, NoType)
+ }
+ }
+ typedPos {
+ val sym = currentOwner.newValue(mkTerm("qual"), ad.pos) setInfo qual0.tpe
+ qual = REF(sym)
- BLOCK(
- VAL(sym) === qual0,
- callAsReflective(mparams map (_.tpe), resType)
- )
- }
+ BLOCK(
+ VAL(sym) === qual0,
+ callAsReflective(mparams map (_.tpe), resType)
+ )
+ }
}
/* For testing purposes, the dynamic application's condition
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 4b9585bb93..1db3db9376 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -130,7 +130,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
if (from.name != nme.OUTER ||
from.tpe.typeSymbol.isPrimitiveValueClass) result
else localTyper.typedPos(to.pos) {
- IF (from OBJ_EQ NULL) THEN Throw(NullPointerExceptionClass.tpe) ELSE result
+ IF (from OBJ_EQ NULL) THEN Throw(NewFromConstructor(NPEConstructor)) ELSE result
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 3ac7dd2a8f..45be0901c3 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -172,7 +172,7 @@ abstract class Erasure extends AddInterfaces
/** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return
* type for constructors.
*/
- def javaSig(sym0: Symbol, info: Type): Option[String] = beforeErasure {
+ def javaSig(sym0: Symbol, info: Type): Option[String] = enteringErasure {
val isTraitSignature = sym0.enclClass.isTrait
def superSig(parents: List[Type]) = {
@@ -206,7 +206,7 @@ abstract class Erasure extends AddInterfaces
// Anything which could conceivably be a module (i.e. isn't known to be
// a type parameter or similar) must go through here or the signature is
// likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$.
- def fullNameInSig(sym: Symbol) = "L" + beforeIcode(sym.javaBinaryName)
+ def fullNameInSig(sym: Symbol) = "L" + enteringIcode(sym.javaBinaryName)
def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = {
val tp = tp0.dealias
@@ -398,7 +398,7 @@ abstract class Erasure extends AddInterfaces
val bridgeTarget = mutable.HashMap[Symbol, Symbol]()
var bridges = List[Tree]()
- val opc = beforeExplicitOuter {
+ val opc = enteringExplicitOuter {
new overridingPairs.Cursor(root) {
override def parents = List(root.info.firstParent)
override def exclude(sym: Symbol) = !sym.isMethod || sym.isPrivate || super.exclude(sym)
@@ -410,7 +410,7 @@ abstract class Erasure extends AddInterfaces
val member = opc.overriding
val other = opc.overridden
//println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG
- if (beforeExplicitOuter(!member.isDeferred))
+ if (enteringExplicitOuter(!member.isDeferred))
checkPair(member, other)
opc.next
@@ -440,11 +440,11 @@ abstract class Erasure extends AddInterfaces
s"""bridge generated for member ${fulldef(member)}
|which overrides ${fulldef(other)}
|clashes with definition of $what;
- |both have erased type ${afterPostErasure(bridge.tpe)}""".stripMargin)
+ |both have erased type ${exitingPostErasure(bridge.tpe)}""".stripMargin)
}
for (bc <- root.baseClasses) {
if (settings.debug.value)
- afterPostErasure(println(
+ exitingPostErasure(println(
s"""check bridge overrides in $bc
${bc.info.nonPrivateDecl(bridge.name)}
${site.memberType(bridge)}
@@ -453,13 +453,13 @@ abstract class Erasure extends AddInterfaces
def overriddenBy(sym: Symbol) =
sym.matchingSymbol(bc, site).alternatives filter (sym => !sym.isBridge)
- for (overBridge <- afterPostErasure(overriddenBy(bridge))) {
+ for (overBridge <- exitingPostErasure(overriddenBy(bridge))) {
if (overBridge == member) {
clashError("the member itself")
} else {
val overMembers = overriddenBy(member)
if (!overMembers.exists(overMember =>
- afterPostErasure(overMember.tpe =:= overBridge.tpe))) {
+ exitingPostErasure(overMember.tpe =:= overBridge.tpe))) {
clashError(fulldef(overBridge))
}
}
@@ -470,7 +470,7 @@ abstract class Erasure extends AddInterfaces
def checkPair(member: Symbol, other: Symbol) {
val otpe = erasure(root)(other.tpe)
- val bridgeNeeded = afterErasure (
+ val bridgeNeeded = exitingErasure (
!(other.tpe =:= member.tpe) &&
!(deconstMap(other.tpe) =:= deconstMap(member.tpe)) &&
{ var e = bridgesScope.lookupEntry(member.name)
@@ -482,7 +482,7 @@ abstract class Erasure extends AddInterfaces
if (!bridgeNeeded)
return
- val newFlags = (member.flags | BRIDGE) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
+ val newFlags = (member.flags | BRIDGE | ARTIFACT) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
val bridge = other.cloneSymbolImpl(root, newFlags) setPos root.pos
debuglog("generating bridge from %s (%s): %s to %s: %s".format(
@@ -497,9 +497,9 @@ abstract class Erasure extends AddInterfaces
if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) ||
checkBridgeOverrides(member, other, bridge)) {
- afterErasure(root.info.decls enter bridge)
+ exitingErasure(root.info.decls enter bridge)
if (other.owner == root) {
- afterErasure(root.info.decls.unlink(other))
+ exitingErasure(root.info.decls.unlink(other))
toBeRemoved += other
}
@@ -508,7 +508,7 @@ abstract class Erasure extends AddInterfaces
}
}
- def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = afterErasure {
+ def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = exitingErasure {
// type checking ensures we can safely call `other`, but unless `member.tpe <:< other.tpe`,
// calling `member` is not guaranteed to succeed in general, there's
// nothing we can do about this, except for an unapply: when this subtype test fails,
@@ -519,7 +519,7 @@ abstract class Erasure extends AddInterfaces
def maybeWrap(bridgingCall: Tree): Tree = {
val guardExtractor = ( // can't statically know which member is going to be selected, so don't let this depend on member.isSynthetic
(member.name == nme.unapply || member.name == nme.unapplySeq)
- && !afterErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?)
+ && !exitingErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?)
import CODE._
val _false = FALSE_typed
@@ -736,7 +736,7 @@ abstract class Erasure extends AddInterfaces
if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) {
val noNullCheckNeeded = targ.tpe match {
case ErasedValueType(tref) =>
- atPhase(currentRun.erasurePhase) {
+ enteringPhase(currentRun.erasurePhase) {
isPrimitiveValueClass(erasedValueClassArg(tref).typeSymbol)
}
case _ =>
@@ -817,7 +817,7 @@ abstract class Erasure extends AddInterfaces
(tree.attachments.get[TypeRefAttachment]: @unchecked) match {
case Some(itype) =>
val tref = itype.tpe
- val argPt = atPhase(currentRun.erasurePhase)(erasedValueClassArg(tref))
+ val argPt = enteringPhase(currentRun.erasurePhase)(erasedValueClassArg(tref))
log(s"transforming inject $arg -> $tref/$argPt")
val result = typed(arg, mode, argPt)
log(s"transformed inject $arg -> $tref/$argPt = $result:${result.tpe}")
@@ -885,20 +885,20 @@ abstract class Erasure extends AddInterfaces
private def checkNoDoubleDefs(root: Symbol) {
def doubleDefError(sym1: Symbol, sym2: Symbol) {
// the .toString must also be computed at the earlier phase
- val tpe1 = afterRefchecks(root.thisType.memberType(sym1))
- val tpe2 = afterRefchecks(root.thisType.memberType(sym2))
+ val tpe1 = exitingRefchecks(root.thisType.memberType(sym1))
+ val tpe2 = exitingRefchecks(root.thisType.memberType(sym2))
if (!tpe1.isErroneous && !tpe2.isErroneous)
unit.error(
if (sym1.owner == root) sym1.pos else root.pos,
(if (sym1.owner == sym2.owner) "double definition:\n"
else if (sym1.owner == root) "name clash between defined and inherited member:\n"
else "name clash between inherited members:\n") +
- sym1 + ":" + afterRefchecks(tpe1.toString) +
+ sym1 + ":" + exitingRefchecks(tpe1.toString) +
(if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
- sym2 + ":" + afterRefchecks(tpe2.toString) +
+ sym2 + ":" + exitingRefchecks(tpe2.toString) +
(if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) +
"\nhave same type" +
- (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterPostErasure(sym1.tpe)))
+ (if (exitingRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + exitingPostErasure(sym1.tpe)))
sym1.setInfo(ErrorType)
}
@@ -908,7 +908,7 @@ abstract class Erasure extends AddInterfaces
if (e.sym.isTerm) {
var e1 = decls.lookupNextEntry(e)
while (e1 ne null) {
- if (afterPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
+ if (exitingPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
e1 = decls.lookupNextEntry(e1)
}
}
@@ -916,16 +916,17 @@ abstract class Erasure extends AddInterfaces
}
val opc = new overridingPairs.Cursor(root) {
- override def exclude(sym: Symbol): Boolean =
- (!sym.isTerm || sym.isPrivate || super.exclude(sym)
- // specialized members have no type history before 'specialize', causing double def errors for curried defs
- || !sym.hasTypeAt(currentRun.refchecksPhase.id))
+ override def exclude(sym: Symbol): Boolean = (
+ !sym.isTerm || sym.isPrivate || super.exclude(sym)
+ // specialized members have no type history before 'specialize', causing double def errors for curried defs
+ || !sym.hasTypeAt(currentRun.refchecksPhase.id)
+ )
override def matches(sym1: Symbol, sym2: Symbol): Boolean =
- afterPostErasure(sym1.tpe =:= sym2.tpe)
+ exitingPostErasure(sym1.tpe =:= sym2.tpe)
}
while (opc.hasNext) {
- if (!afterRefchecks(
+ if (!exitingRefchecks(
root.thisType.memberType(opc.overriding) matches
root.thisType.memberType(opc.overridden))) {
debuglog("" + opc.overriding.locationString + " " +
@@ -944,8 +945,8 @@ abstract class Erasure extends AddInterfaces
for (member <- root.info.nonPrivateMember(other.name).alternatives) {
if (member != other &&
!(member hasFlag BRIDGE) &&
- afterErasure(member.tpe =:= other.tpe) &&
- !afterRefchecks(
+ exitingErasure(member.tpe =:= other.tpe) &&
+ !exitingRefchecks(
root.thisType.memberType(member) matches root.thisType.memberType(other))) {
debuglog("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString);
doubleDefError(member, other)
@@ -1067,6 +1068,7 @@ abstract class Erasure extends AddInterfaces
} else if (fn.symbol == Any_isInstanceOf) {
preEraseIsInstanceOf
} else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) {
+ // !!! Another spot where we produce overloaded types (see test run/t6301)
ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos
} else if (fn.symbol.isMethodWithExtension && !fn.symbol.tpe.isErroneous) {
Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args)
@@ -1123,7 +1125,8 @@ abstract class Erasure extends AddInterfaces
SelectFromArray(qual, name, erasure(tree.symbol)(qual.tpe)).copyAttrs(fn),
args)
}
- } else if (args.isEmpty && interceptedMethods(fn.symbol)) {
+ }
+ else if (args.isEmpty && interceptedMethods(fn.symbol)) {
if (fn.symbol == Any_## || fn.symbol == Object_##) {
// This is unattractive, but without it we crash here on ().## because after
// erasure the ScalaRunTime.hash overload goes from Unit => Int to BoxedUnit => Int.
@@ -1135,7 +1138,18 @@ abstract class Erasure extends AddInterfaces
case s @ (ShortClass | ByteClass | CharClass) => numericConversion(qual, s)
case BooleanClass => If(qual, LIT(true.##), LIT(false.##))
case _ =>
- global.typer.typed(gen.mkRuntimeCall(nme.hash_, List(qual)))
+ // Since we are past typer, we need to avoid creating trees carrying
+ // overloaded types. This logic is custom (and technically incomplete,
+ // although serviceable) for def hash. What is really needed is for
+ // the overloading logic presently hidden away in a few different
+ // places to be properly exposed so we can just call "resolveOverload"
+ // after typer. Until then:
+ val alts = ScalaRunTimeModule.info.member(nme.hash_).alternatives
+ def alt1 = alts find (_.info.paramTypes.head =:= qual.tpe)
+ def alt2 = ScalaRunTimeModule.info.member(nme.hash_) suchThat (_.info.paramTypes.head.typeSymbol == AnyClass)
+ val newTree = gen.mkRuntimeCall(nme.hash_, qual :: Nil) setSymbol (alt1 getOrElse alt2)
+
+ global.typer.typed(newTree)
}
} else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
@@ -1261,7 +1275,7 @@ abstract class Erasure extends AddInterfaces
override def transform(tree: Tree): Tree = {
val tree1 = preTransformer.transform(tree)
// log("tree after pretransform: "+tree1)
- afterErasure {
+ exitingErasure {
val tree2 = mixinTransformer.transform(tree1)
// debuglog("tree after addinterfaces: \n" + tree2)
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 77ad65957d..4a0d25fd09 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -83,12 +83,6 @@ abstract class ExplicitOuter extends InfoTransform
}
}
- /** Issue a migration warning for instance checks which might be on an Array and
- * for which the type parameter conforms to Seq, because these answers changed in 2.8.
- */
- def isArraySeqTest(lhs: Type, rhs: Type) =
- (ArrayClass.tpe <:< lhs.widen) && (rhs.widen matchesPattern SeqClass.tpe)
-
def outerAccessor(clazz: Symbol): Symbol = {
val firstTry = clazz.info.decl(nme.expandedName(nme.OUTER, clazz))
if (firstTry != NoSymbol && firstTry.outerSource == clazz) firstTry
@@ -97,7 +91,7 @@ abstract class ExplicitOuter extends InfoTransform
def newOuterAccessor(clazz: Symbol) = {
val accFlags = SYNTHETIC | ARTIFACT | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 )
val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags)
- val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType
+ val restpe = if (clazz.isTrait) clazz.outerClass.tpe_* else clazz.outerClass.thisType
sym expandName clazz
sym.referenced = clazz
@@ -173,7 +167,7 @@ abstract class ExplicitOuter extends InfoTransform
}
if (!clazz.isTrait && !parents.isEmpty) {
for (mc <- clazz.mixinClasses) {
- val mixinOuterAcc: Symbol = afterExplicitOuter(outerAccessor(mc))
+ val mixinOuterAcc: Symbol = exitingExplicitOuter(outerAccessor(mc))
if (mixinOuterAcc != NoSymbol) {
if (decls1 eq decls) decls1 = decls.cloneScope
val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
@@ -550,13 +544,6 @@ abstract class ExplicitOuter extends InfoTransform
}
case _ =>
- if (settings.Xmigration28.value) tree match {
- case TypeApply(fn @ Select(qual, _), args) if fn.symbol == Object_isInstanceOf || fn.symbol == Any_isInstanceOf =>
- if (isArraySeqTest(qual.tpe, args.head.tpe))
- unit.warning(tree.pos, "An Array will no longer match as Seq[_].")
- case _ => ()
- }
-
val x = super.transform(tree)
if (x.tpe eq null) x
else x setType transformInfo(currentOwner, x.tpe)
@@ -565,7 +552,7 @@ abstract class ExplicitOuter extends InfoTransform
/** The transformation method for whole compilation units */
override def transformUnit(unit: CompilationUnit) {
- afterExplicitOuter(super.transformUnit(unit))
+ exitingExplicitOuter(super.transformUnit(unit))
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 6dd937c0ad..5aa7a804fd 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -66,7 +66,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
/** Return the extension method that corresponds to given instance method `meth`.
*/
- def extensionMethod(imeth: Symbol): Symbol = atPhase(currentRun.refchecksPhase) {
+ def extensionMethod(imeth: Symbol): Symbol = enteringPhase(currentRun.refchecksPhase) {
val companionInfo = imeth.owner.companionModule.info
val candidates = extensionNames(imeth) map (companionInfo.decl(_)) filter (_.exists)
val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe)
@@ -75,32 +75,41 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
matching.head
}
+ /** Recognize a MethodType which represents an extension method.
+ *
+ * It may have a curried parameter list with the `$this` alone in the first
+ * parameter list, in which case that parameter list is dropped. Or, since
+ * the curried lists disappear during uncurry, it may have a single parameter
+ * list with `$this` as the first parameter, in which case that parameter is
+ * removed from the list.
+ */
+ object ExtensionMethodType {
+ def unapply(tp: Type) = tp match {
+ case MethodType(thiz :: rest, restpe) if thiz.name == nme.SELF =>
+ Some( if (rest.isEmpty) restpe else MethodType(rest, restpe) )
+ case _ =>
+ None
+ }
+ }
+
/** This method removes the `$this` argument from the parameter list a method.
*
* A method may be a `PolyType`, in which case we tear out the `$this` and the class
- * type params from its nested `MethodType`.
- * It may be a `MethodType`, either with a curried parameter list in which the first argument
- * is a `$this` - we just return the rest of the list.
- * This means that the corresponding symbol was generated during `extmethods`.
- *
- * It may also be a `MethodType` in which the `$this` does not appear in a curried parameter list.
- * The curried lists disappear during `uncurry`, and the methods may be duplicated afterwards,
- * for instance, during `specialize`.
- * In this case, the first argument is `$this` and we just get rid of it.
+ * type params from its nested `MethodType`. Or it may be a MethodType, as
+ * described at the ExtensionMethodType extractor.
*/
private def normalize(stpe: Type, clazz: Symbol): Type = stpe match {
case PolyType(tparams, restpe) =>
- GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe.substSym(tparams takeRight clazz.typeParams.length, clazz.typeParams), clazz))
- case MethodType(List(thiz), restpe) if thiz.name == nme.SELF =>
- restpe
- case MethodType(tparams, restpe) =>
- MethodType(tparams.drop(1), restpe)
+ // method type parameters, class type parameters
+ val (mtparams, ctparams) = tparams splitAt (tparams.length - clazz.typeParams.length)
+ GenPolyType(mtparams, normalize(restpe.substSym(ctparams, clazz.typeParams), clazz))
+ case ExtensionMethodType(etpe) =>
+ etpe
case _ =>
stpe
}
class Extender(unit: CompilationUnit) extends TypingTransformer(unit) {
-
private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]()
def checkNonCyclic(pos: Position, seen: Set[Symbol], clazz: Symbol): Unit =
@@ -111,27 +120,51 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
if (unboxed.isDerivedValueClass) checkNonCyclic(pos, seen + clazz, unboxed)
}
+ /** We will need to clone the info of the original method (which obtains clones
+ * of the method type parameters), clone the type parameters of the value class,
+ * and create a new polymethod with the union of all those type parameters, with
+ * their infos adjusted to be consistent with their new home. Example:
+ *
+ * class Foo[+A <: AnyRef](val xs: List[A]) extends AnyVal {
+ * def baz[B >: A](x: B): List[B] = x :: xs
+ * // baz has to be transformed into this extension method, where
+ * // A is cloned from class Foo and B is cloned from method baz:
+ * // def extension$baz[B >: A <: Any, A >: Nothing <: AnyRef]($this: Foo[A])(x: B): List[B]
+ * }
+ *
+ * TODO: factor out the logic for consolidating type parameters from a class
+ * and a method for re-use elsewhere, because nobody will get this right without
+ * some higher level facilities.
+ */
def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = {
- // No variance for method type parameters
- var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) map (_ resetFlag COVARIANT | CONTRAVARIANT)
- val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpeHK))
- val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType
- def transform(clonedType: Type): Type = clonedType match {
- case MethodType(params, restpe) =>
- // I assume it was a bug that this was dropping params... [Martin]: No, it wasn't; it's curried.
- MethodType(List(thisParam), clonedType)
- case NullaryMethodType(restpe) =>
- MethodType(List(thisParam), restpe)
- }
- val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth
- GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams))
- }
+ val GenPolyType(tparamsFromMethod, methodResult) = origInfo cloneInfo extensionMeth
+ // Start with the class type parameters - clones will be method type parameters
+ // so must drop their variance.
+ val tparamsFromClass = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) map (_ resetFlag COVARIANT | CONTRAVARIANT)
+ def fix(tp: Type) = tp.substSym(clazz.typeParams, tparamsFromClass)
- private def allParams(tpe: Type): List[Symbol] = tpe match {
- case MethodType(params, res) => params ::: allParams(res)
- case _ => List()
+ val thisParamType = appliedType(clazz, tparamsFromClass map (_.tpeHK): _*)
+ val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType
+ val resultType = MethodType(List(thisParam), dropNullaryMethod(methodResult))
+
+ // We can't substitute symbols on the entire polytype because we
+ // need to modify the bounds of the cloned type parameters, but we
+ // don't want to substitute for the cloned type parameters themselves.
+ val tparams = tparamsFromMethod ::: tparamsFromClass
+ GenPolyType(tparams map (_ modifyInfo fix), fix(resultType))
+
+ // For reference, calling fix on the GenPolyType plays out like this:
+ // error: scala.reflect.internal.Types$TypeError: type arguments [B#7344,A#6966]
+ // do not conform to method extension$baz#16148's type parameter bounds
+ //
+ // And the difference is visible here. See how B is bounded from below by A#16149
+ // in both cases, but in the failing case, the other type parameter has turned into
+ // a different A. (What is that A? It is a clone of the original A created in
+ // SubstMap during the call to substSym, but I am not clear on all the particulars.)
+ //
+ // bad: [B#16154 >: A#16149, A#16155 <: AnyRef#2189]($this#16156: Foo#6965[A#16155])(x#16157: B#16154)List#2457[B#16154]
+ // good: [B#16151 >: A#16149, A#16149 <: AnyRef#2189]($this#16150: Foo#6965[A#16149])(x#16153: B#16151)List#2457[B#16151]
}
-
override def transform(tree: Tree): Tree = {
tree match {
case Template(_, _, _) =>
@@ -146,39 +179,58 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
super.transform(tree)
} else tree
case DefDef(_, _, tparams, vparamss, _, rhs) if tree.symbol.isMethodWithExtension =>
- val companion = currentOwner.companionModule
- val origMeth = tree.symbol
- val extensionName = extensionNames(origMeth).head
- val extensionMeth = companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL)
- .setAnnotations(origMeth.annotations)
- companion.info.decls.enter(extensionMeth)
- val newInfo = extensionMethInfo(extensionMeth, origMeth.info, currentOwner)
+ val origMeth = tree.symbol
+ val origThis = currentOwner
+ val origTpeParams = tparams.map(_.symbol) ::: origThis.typeParams // method type params ++ class type params
+ val origParams = vparamss.flatten map (_.symbol)
+ val companion = origThis.companionModule
+
+ def makeExtensionMethodSymbol = {
+ val extensionName = extensionNames(origMeth).head
+ val extensionMeth = (
+ companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL)
+ setAnnotations origMeth.annotations
+ )
+ companion.info.decls.enter(extensionMeth)
+ }
+
+ val extensionMeth = makeExtensionMethodSymbol
+ val newInfo = extensionMethInfo(extensionMeth, origMeth.info, origThis)
extensionMeth setInfo newInfo
- log("Value class %s spawns extension method.\n Old: %s\n New: %s".format(
- currentOwner,
- origMeth.defString,
- extensionMeth.defString)) // extensionMeth.defStringSeenAs(origInfo
-
- def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos)
- val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info
- val origTpeParams = (tparams map (_.symbol)) ::: currentOwner.typeParams
- val extensionBody = rhs
+
+ log(s"Value class $origThis spawns extension method.\n Old: ${origMeth.defString}\n New: ${extensionMeth.defString}")
+
+ val GenPolyType(extensionTpeParams, MethodType(thiz :: Nil, extensionMono)) = newInfo
+ val extensionParams = allParameters(extensionMono)
+ val extensionThis = gen.mkAttributedIdent(thiz setPos extensionMeth.pos)
+
+ val extensionBody = (
+ rhs
.substituteSymbols(origTpeParams, extensionTpeParams)
- .substituteSymbols(vparamss.flatten map (_.symbol), allParams(extensionMono).tail)
- .substituteThis(currentOwner, thisParamRef)
- .changeOwner((origMeth, extensionMeth))
- extensionDefs(companion) += atPos(tree.pos) { DefDef(extensionMeth, extensionBody) }
- val extensionCallPrefix = Apply(
- gen.mkTypeApply(gen.mkAttributedRef(companion), extensionMeth, origTpeParams map (_.tpeHK)),
- List(This(currentOwner)))
- val extensionCall = atOwner(origMeth) {
- localTyper.typedPos(rhs.pos) {
- (extensionCallPrefix /: vparamss) {
- case (fn, params) => Apply(fn, params map (param => Ident(param.symbol)))
- }
- }
- }
- deriveDefDef(tree)(_ => extensionCall)
+ .substituteSymbols(origParams, extensionParams)
+ .substituteThis(origThis, extensionThis)
+ .changeOwner(origMeth -> extensionMeth)
+ )
+
+ // Record the extension method ( FIXME: because... ? )
+ extensionDefs(companion) += atPos(tree.pos)(DefDef(extensionMeth, extensionBody))
+
+ // These three lines are assembling Foo.bar$extension[T1, T2, ...]($this)
+ // which leaves the actual argument application for extensionCall.
+ val sel = Select(gen.mkAttributedRef(companion), extensionMeth)
+ val targs = origTpeParams map (_.tpeHK)
+ val callPrefix = gen.mkMethodCall(sel, targs, This(origThis) :: Nil)
+
+ // Apply all the argument lists.
+ deriveDefDef(tree)(_ =>
+ atOwner(origMeth)(
+ localTyper.typedPos(rhs.pos)(
+ (callPrefix /: vparamss) {
+ case (fn, params) => Apply(fn, params map (param => Ident(param.symbol)))
+ }
+ )
+ )
+ )
case _ =>
super.transform(tree)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 3bbf429fc2..e2913bea0d 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -20,7 +20,7 @@ abstract class Flatten extends InfoTransform {
/** Updates the owning scope with the given symbol; returns the old symbol.
*/
- private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = afterFlatten {
+ private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = exitingFlatten {
val scope = sym.owner.info.decls
val old = scope lookup sym.name andAlso scope.unlink
scope enter sym
@@ -53,7 +53,7 @@ abstract class Flatten extends InfoTransform {
clazz.isClass && !clazz.isPackageClass && {
// Cannot flatten here: class A[T] { object B }
// was "at erasurePhase.prev"
- beforeErasure(clazz.typeParams.isEmpty)
+ enteringErasure(clazz.typeParams.isEmpty)
}
}
@@ -67,11 +67,11 @@ abstract class Flatten extends InfoTransform {
val decls1 = scopeTransform(clazz) {
val decls1 = newScope
if (clazz.isPackageClass) {
- afterFlatten { decls foreach (decls1 enter _) }
+ exitingFlatten { decls foreach (decls1 enter _) }
}
else {
val oldowner = clazz.owner
- afterFlatten { oldowner.info }
+ exitingFlatten { oldowner.info }
parents1 = parents mapConserve (this)
for (sym <- decls) {
@@ -123,7 +123,7 @@ abstract class Flatten extends InfoTransform {
liftedDefs(sym.enclosingTopLevelClass.owner) += tree
EmptyTree
case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) =>
- afterFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym)))
+ exitingFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym)))
case _ =>
tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala
index ab078421b0..897809a063 100644
--- a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala
+++ b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala
@@ -10,11 +10,11 @@ package transform
* An InfoTransform contains a compiler phase that transforms trees and symbol infos -- making sure they stay consistent.
* The symbol info is transformed assuming it is consistent right before this phase.
* The info transformation is triggered by Symbol::rawInfo, which caches the results in the symbol's type history.
- * This way sym.info (during an atPhase(p)) can look up what the symbol's info should look like at the beginning of phase p.
+ * This way sym.info (during an enteringPhase(p)) can look up what the symbol's info should look like at the beginning of phase p.
* (If the transformed info had not been stored yet, rawInfo will compute the info by composing the info-transformers
* of the most recent phase before p, up to the transformer of the phase right before p.)
*
- * Concretely, atPhase(p) { sym.info } yields the info *before* phase p has transformed it. Imagine you're a phase and it all makes sense.
+ * Concretely, enteringPhase(p) { sym.info } yields the info *before* phase p has transformed it. Imagine you're a phase and it all makes sense.
*/
trait InfoTransform extends Transform {
import global.{Symbol, Type, InfoTransformer, infoTransformers}
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index 21213cf9d9..481228fb3d 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -278,7 +278,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
bmps(n)
else {
val sym = meth.newVariable(nme.newBitmapName(nme.BITMAP_NORMAL, n), meth.pos).setInfo(ByteClass.tpe)
- beforeTyper {
+ enteringTyper {
sym addAnnotation VolatileAttr
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 80900a1a0a..6e0d2bb08a 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -68,7 +68,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* maps all other types to themselves.
*/
private def toInterface(tp: Type): Type =
- beforeMixin(tp.typeSymbol.toInterface).tpe
+ enteringMixin(tp.typeSymbol.toInterface).tpe
private def isFieldWithBitmap(field: Symbol) = {
field.info // ensure that nested objects are transformed
@@ -102,7 +102,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
private val toInterfaceMap = new TypeMap {
def apply(tp: Type): Type = mapOver( tp match {
case TypeRef(pre, sym, args) if sym.isImplClass =>
- typeRef(pre, beforeMixin(sym.toInterface), args)
+ typeRef(pre, enteringMixin(sym.toInterface), args)
case _ => tp
})
}
@@ -119,7 +119,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* @param mixinClass The mixin class that produced the superaccessor
*/
private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol =
- afterPickler {
+ exitingPickler {
var bcs = base.info.baseClasses.dropWhile(mixinClass != _).tail
var sym: Symbol = NoSymbol
debuglog("starting rebindsuper " + base + " " + member + ":" + member.tpe +
@@ -165,7 +165,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
addMember(clazz, cloneBeforeErasure(mixinClass, mixinMember, clazz))
def cloneBeforeErasure(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = {
- val newSym = beforeErasure {
+ val newSym = enteringErasure {
// since we used `mixinMember` from the interface that represents the trait that's
// being mixed in, have to instantiate the interface type params (that may occur in mixinMember's
// info) as they are seen from the class. We can't use the member that we get from the
@@ -311,12 +311,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// mixinMember is a value of type unit. No field needed
;
case _ => // otherwise mixin a field as well
- // atPhase: the private field is moved to the implementation class by erasure,
+ // enteringPhase: the private field is moved to the implementation class by erasure,
// so it can no longer be found in the mixinMember's owner (the trait)
- val accessed = beforePickler(mixinMember.accessed)
+ val accessed = enteringPickler(mixinMember.accessed)
// #3857, need to retain info before erasure when cloning (since cloning only
// carries over the current entry in the type history)
- val sym = beforeErasure {
+ val sym = enteringErasure {
// so we have a type history entry before erasure
clazz.newValue(nme.getterToLocal(mixinMember.name), mixinMember.pos).setInfo(mixinMember.tpe.resultType)
}
@@ -380,7 +380,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
var parents1 = parents
var decls1 = decls
if (!clazz.isPackageClass) {
- afterMixin(clazz.owner.info)
+ exitingMixin(clazz.owner.info)
if (clazz.isImplClass) {
clazz setFlag lateMODULE
var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName)
@@ -408,7 +408,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
parents1 = parents.head :: (parents.tail map toInterface)
}
}
- //decls1 = atPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug
+ //decls1 = enteringPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug
if ((parents1 eq parents) && (decls1 eq decls)) tp
else ClassInfoType(parents1, decls1, clazz)
@@ -438,7 +438,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
tree match {
case Assign(lhs, rhs) => traverse(rhs) // assignments don't count
case _ =>
- if (tree.hasSymbol && tree.symbol != NoSymbol) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol) {
val sym = tree.symbol
if ((sym.hasAccessorFlag || (sym.isTerm && !sym.isMethod))
&& sym.isPrivate
@@ -525,7 +525,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
tree match {
case Template(parents, self, body) =>
localTyper = erasure.newTyper(rootContext.make(tree, currentOwner))
- afterMixin(currentOwner.owner.info)//todo: needed?
+ exitingMixin(currentOwner.owner.info)//todo: needed?
if (!currentOwner.isTrait && !isPrimitiveValueClass(currentOwner))
addMixedinMembers(currentOwner, unit)
@@ -544,7 +544,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else EmptyTree
}
else {
- if (currentOwner.isTrait && sym.isSetter && !beforePickler(sym.isDeferred)) {
+ if (currentOwner.isTrait && sym.isSetter && !enteringPickler(sym.isDeferred)) {
sym.addAnnotation(TraitSetterAnnotationClass)
}
tree
@@ -703,7 +703,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val rhs0 = (Super(clazz, tpnme.EMPTY) DOT stat.symbol.alias)(vparams map (v => Ident(v.symbol)): _*)
val rhs1 = localTyped(stat.pos, rhs0, stat.symbol.tpe.resultType)
- deriveDefDef(stat)(_ => beforeMixin(transform(rhs1)))
+ deriveDefDef(stat)(_ => enteringMixin(transform(rhs1)))
case _ =>
stat
}
@@ -722,7 +722,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
def createBitmap: Symbol = {
val bitmapKind = bitmapKindForCategory(category)
val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo bitmapKind.tpe
- beforeTyper(sym addAnnotation VolatileAttr)
+ enteringTyper(sym addAnnotation VolatileAttr)
category match {
case nme.BITMAP_TRANSIENT | nme.BITMAP_CHECKINIT_TRANSIENT => sym addAnnotation TransientAttr
@@ -804,7 +804,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
class TreeSymSubstituterWithCopying(from: List[Symbol], to: List[Symbol]) extends TreeSymSubstituter(from, to) {
override def transform(tree: Tree): Tree =
- if (tree.hasSymbol && from.contains(tree.symbol))
+ if (tree.hasSymbolField && from.contains(tree.symbol))
super.transform(tree.duplicate)
else super.transform(tree.duplicate)
@@ -868,7 +868,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
rhs match {
case Block(List(assign), returnTree) =>
val Assign(moduleVarRef, _) = assign
- val cond = Apply(Select(moduleVarRef, nme.eq), List(NULL))
+ val cond = Apply(Select(moduleVarRef, Object_eq), List(NULL))
mkFastPathBody(clazz, moduleSym, cond, List(assign), List(NULL), returnTree, attrThis, args)
case _ =>
assert(false, "Invalid getter " + rhs + " for module in class " + clazz)
@@ -884,7 +884,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val result =
IF (mkTest(clazz, mask, bitmapSym, false, kind)) .
THEN (retVal) .
- ELSE (THROW(UninitializedErrorClass, LIT(msg)))
+ ELSE (Throw(NewFromConstructor(UninitializedFieldConstructor, LIT(msg))))
typedPos(pos)(BLOCK(result, retVal))
}
@@ -1166,7 +1166,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
def implSym = implClass(sym.owner).info.member(sym.name)
assert(target ne NoSymbol,
List(sym + ":", sym.tpe, sym.owner, implClass(sym.owner), implSym,
- beforePrevPhase(implSym.tpe), phase) mkString " "
+ enteringPrevPhase(implSym.tpe), phase) mkString " "
)
typedPos(tree.pos)(Apply(staticRef(target), transformSuper(qual) :: args))
}
@@ -1195,7 +1195,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
typedPos(tree.pos)((transformSuper(qual) DOT sym1)())
}
else {
- staticCall(beforePrevPhase(sym.overridingSymbol(implClass(sym.owner))))
+ staticCall(enteringPrevPhase(sym.overridingSymbol(implClass(sym.owner))))
}
}
else {
@@ -1245,7 +1245,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val tree1 = super.transform(preTransform(tree))
// localTyper needed when not flattening inner classes. parts after an
// inner class will otherwise be typechecked with a wrong scope
- try afterMixin(postTransform(tree1))
+ try exitingMixin(postTransform(tree1))
finally localTyper = saved
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 0b58292f28..eef8bb31e6 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -31,11 +31,11 @@ abstract class OverridingPairs {
private val self = base.thisType
/** Symbols to exclude: Here these are constructors, private locals,
- * and bridges. But it may be refined in subclasses.
+ * and hidden symbols, including bridges. But it may be refined in subclasses.
*
*/
protected def exclude(sym: Symbol): Boolean =
- sym.isConstructor || sym.isPrivateLocal || sym.hasFlag(BRIDGE)
+ sym.isConstructor || sym.isPrivateLocal || sym.isArtifact
/** The parents of base (may also be refined).
*/
diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
index 479bc2292e..4815eacd40 100644
--- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
@@ -24,7 +24,7 @@ trait PostErasure extends InfoTransform with TypingTransformers {
case ConstantType(Constant(tp: Type)) =>
ConstantType(Constant(apply(tp)))
case ErasedValueType(tref) =>
- atPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref))
+ enteringPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref))
case _ => mapOver(tp)
}
}
@@ -39,7 +39,7 @@ trait PostErasure extends InfoTransform with TypingTransformers {
Apply(sel @ Select(
Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)),
acc), List())
- if atPhase(currentRun.erasurePhase) {
+ if enteringPhase(currentRun.erasurePhase) {
tpt.tpe.typeSymbol.isDerivedValueClass &&
sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox
} =>
@@ -50,7 +50,7 @@ trait PostErasure extends InfoTransform with TypingTransformers {
Apply(Select(New(tpt1), nme.CONSTRUCTOR), List(arg1)),
cmp),
List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2))))
- if atPhase(currentRun.erasurePhase) {
+ if enteringPhase(currentRun.erasurePhase) {
tpt1.tpe.typeSymbol.isDerivedValueClass &&
(sel.symbol == Object_== || sel.symbol == Object_!=) &&
tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 0fa50a255b..88c6f8d823 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -119,6 +119,22 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
+ @annotation.tailrec private def findSymbol[T](candidates: List[T], f: T => Symbol): Symbol = {
+ if (candidates.isEmpty) NoSymbol
+ else f(candidates.head) match {
+ case NoSymbol => findSymbol(candidates.tail, f)
+ case sym => sym
+ }
+ }
+ private def hasNewParents(tree: Tree) = {
+ val parents = tree.symbol.info.parents
+ val prev = enteringPrevPhase(tree.symbol.info.parents)
+ (parents != prev) && {
+ debuglog(s"$tree parents changed from: $prev to: $parents")
+ true
+ }
+ }
+
// If we replace `isBoundedGeneric` with (tp <:< AnyRefClass.tpe),
// then pos/spec-List.scala fails - why? Does this kind of check fail
// for similar reasons? Does `sym.isAbstractType` make a difference?
@@ -178,6 +194,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case class Overload(sym: Symbol, env: TypeEnv) {
override def toString = "specialized overload " + sym + " in " + env
+ def matchesSym(sym1: Symbol) = sym.info =:= sym1.info
+ def matchesEnv(env1: TypeEnv) = TypeEnv.includes(env, env1)
+ }
+ private def newOverload(method: Symbol, specializedMethod: Symbol, env: TypeEnv) = {
+ assert(!specializedMethod.isOverloaded, specializedMethod.defString)
+ val om = Overload(specializedMethod, env)
+ overloads(method) ::= om
+ om
}
/** Just to mark uncheckable */
@@ -218,6 +242,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def target = t
}
+ /** Symbol is a special overload of the super accessor. */
+ case class SpecialSuperAccessor(t: Symbol) extends SpecializedInfo {
+ def target = t
+ }
+
/** Symbol is a specialized accessor for the `target` field. */
case class SpecializedAccessor(target: Symbol) extends SpecializedInfo {
override def isAccessor = true
@@ -289,10 +318,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
- /** Return the specialized overload of sym in the given env, if any. */
- def overload(sym: Symbol, env: TypeEnv) =
- overloads(sym).find(ov => TypeEnv.includes(ov.env, env))
-
/** Return the specialized name of 'sym' in the given environment. It
* guarantees the same result regardless of the map order by sorting
* type variables alphabetically.
@@ -397,7 +422,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
tpes foreach (tp => buf ++= specializedTypeVars(tp))
buf.result
}
- def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = beforeTyper(specializedTypeVars(sym.info))
+ def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = enteringTyper(specializedTypeVars(sym.info))
/** Return the set of @specialized type variables mentioned by the given type.
* It only counts type variables that appear:
@@ -533,7 +558,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
var newClassTParams: List[Symbol] = Nil // unspecialized type parameters of 'specializedClass' (cloned)
// has to be a val in order to be computed early. It is later called
- // within 'atPhase(next)', which would lead to an infinite cycle otherwise
+ // within 'enteringPhase(next)', which would lead to an infinite cycle otherwise
val specializedInfoType: Type = {
oldClassTParams = survivingParams(clazz.info.typeParams, env)
newClassTParams = produceTypeParameters(oldClassTParams, sClass, env) map subst(env)
@@ -553,7 +578,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
var res: List[Type] = Nil
// log(specializedClass + ": seeking specialized parents of class with parents: " + parents.map(_.typeSymbol))
for (p <- parents) {
- val stp = afterSpecialize(specializedType(p))
+ val stp = exitingSpecialize(specializedType(p))
if (stp != p)
if (p.typeSymbol.isTrait) res ::= stp
else if (currentRun.compiles(clazz))
@@ -563,7 +588,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
res
}
- var parents = List(applyContext(beforeTyper(clazz.tpe)))
+ var parents = List(applyContext(enteringTyper(clazz.tpe_*)))
// log("!!! Parents: " + parents + ", sym: " + parents.map(_.typeSymbol))
if (parents.head.typeSymbol.isTrait)
parents = parents.head.parents.head :: parents
@@ -585,7 +610,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
GenPolyType(newClassTParams, ClassInfoType(parents ::: extraSpecializedMixins, decls1, sClass))
}
- afterSpecialize(sClass setInfo specializedInfoType)
+ exitingSpecialize(sClass setInfo specializedInfoType)
val fullEnv = outerEnv ++ env
/** Enter 'sym' in the scope of the current specialized class. It's type is
@@ -628,7 +653,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
info(om) = if (original.isDeferred) Forward(original) else Implementation(original)
typeEnv(om) = env ++ typeEnv(m) // add the environment for any method tparams
- overloads(specMember) ::= Overload(om, typeEnv(om))
+ newOverload(specMember, om, typeEnv(om))
enterMember(om)
}
@@ -773,7 +798,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (existing != NoSymbol)
clazz.owner.info.decls.unlink(existing)
- afterSpecialize(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes
+ exitingSpecialize(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes
}
if (subclasses.nonEmpty) clazz.resetFlag(FINAL)
cleanAnyRefSpecCache(clazz, decls1)
@@ -791,7 +816,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = {
sym :: (
- if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil
+ if (!sym.isMethod || enteringTyper(sym.typeParams.isEmpty)) Nil
else {
// debuglog("normalizeMember: " + sym.fullNameAsName('.').decode)
var specializingOn = specializedParams(sym)
@@ -835,7 +860,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
info(specMember) = NormalizedMember(sym)
- overloads(sym) ::= Overload(specMember, env)
+ newOverload(sym, specMember, env)
owner.info.decls.enter(specMember)
specMember
}
@@ -870,6 +895,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
+ owner.info.decls.enter(specMember)
typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
@@ -877,9 +903,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (wasSpec.nonEmpty)
debuglog("specialized overload for %s in %s".format(specMember, pp(typeEnv(specMember))))
- overloads(sym) ::= Overload(specMember, spec)
+ newOverload(sym, specMember, spec)
info(specMember) = SpecialOverload(sym, typeEnv(specMember))
-
specMember
}
@@ -899,10 +924,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
/** Return the specialized overload of `m`, in the given environment. */
- private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = {
+ private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv, nameSymbol: Symbol = NoSymbol): Symbol = {
val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR)
// this method properly duplicates the symbol's info
- ( sym.cloneSymbol(owner, newFlags, newName = specializedName(sym, env))
+ val specname = specializedName(nameSymbol orElse sym, env)
+ ( sym.cloneSymbol(owner, newFlags, newName = specname)
modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner)))
)
}
@@ -949,7 +975,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
checkOverriddenTParams(overridden)
val env = unify(overridden.info, overriding.info, emptyEnv, false, true)
- def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
+ def atNext = exitingSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) {
debuglog(" " + pp(env) + " found " + atNext)
@@ -962,14 +988,32 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
(clazz.info.decls flatMap { overriding =>
needsSpecialOverride(overriding) match {
- case (NoSymbol, _) => None
+ case (NoSymbol, _) =>
+ if (overriding.isSuperAccessor) {
+ val alias = overriding.alias
+ debuglog("checking special overload for super accessor: %s, alias for %s".format(overriding.fullName, alias.fullName))
+ needsSpecialOverride(alias) match {
+ case nope @ (NoSymbol, _) => None
+ case (overridden, env) =>
+ val om = specializedOverload(clazz, overriding, env, overridden)
+ om.setName(nme.superName(om.name))
+ om.asInstanceOf[TermSymbol].setAlias(info(alias).target)
+ om.owner.info.decls.enter(om)
+ info(om) = SpecialSuperAccessor(om)
+ om.makeNotPrivate(om.owner)
+ newOverload(overriding, om, env)
+ Some(om)
+ }
+ } else None
case (overridden, env) =>
val om = specializedOverload(clazz, overridden, env)
+ clazz.info.decls.enter(om)
debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info))
+ if (overriding.isAbstractOverride) om.setFlag(ABSOVERRIDE)
typeEnv(om) = env
addConcreteSpecMethod(overriding)
info(om) = (
- if (overriding.isDeferred) { // abstract override
+ if (overriding.isDeferred) { // abstract override
debuglog("abstract override " + overriding.fullName + " with specialized " + om.fullName)
Forward(overriding)
}
@@ -989,8 +1033,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
SpecialOverride(impl)
}
)
- overloads(overriding) ::= Overload(om, env)
- ifDebug(afterSpecialize(assert(
+ newOverload(overriding, om, env)
+ ifDebug(exitingSpecialize(assert(
overridden.owner.info.decl(om.name) != NoSymbol,
"Could not find " + om.name + " in " + overridden.owner.info.decls))
)
@@ -1106,7 +1150,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
private def subst(env: TypeEnv)(decl: Symbol): Symbol =
decl modifyInfo (info =>
- if (decl.isConstructor) MethodType(subst(env, info).params, decl.owner.tpe)
+ if (decl.isConstructor) MethodType(subst(env, info).params, decl.owner.tpe_*)
else subst(env, info)
)
@@ -1148,7 +1192,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case cinfo @ ClassInfoType(parents, decls, clazz) if !unspecializableClass(cinfo) =>
val tparams = tpe.typeParams
if (tparams.isEmpty)
- afterSpecialize(parents map (_.typeSymbol.info))
+ exitingSpecialize(parents map (_.typeSymbol.info))
val parents1 = parents mapConserve specializedType
if (parents ne parents1) {
@@ -1292,7 +1336,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (sym.isPrivate) debuglog(
"seeing private member %s, currentClass: %s, owner: %s, isAccessible: %b, isLocalName: %b".format(
sym, currentClass, sym.owner.enclClass, isAccessible(sym), nme.isLocalName(sym.name))
- )
+ )
if (shouldMakePublic(sym) && !isAccessible(sym)) {
debuglog("changing private flag of " + sym)
sym.makeNotPrivate(sym.owner)
@@ -1377,59 +1421,72 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def transform1(tree: Tree) = {
val symbol = tree.symbol
-
/** The specialized symbol of 'tree.symbol' for tree.tpe, if there is one */
- def specSym(qual: Tree): Option[Symbol] = {
+ def specSym(qual: Tree): Symbol = {
val env = unify(symbol.tpe, tree.tpe, emptyEnv, false)
- debuglog("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s"
- .format(tree, symbol.tpe, tree.tpe, env, specializedName(symbol, env)))
- if (!env.isEmpty) { // a method?
- val specCandidates = qual.tpe.member(specializedName(symbol, env))
- val specMember = specCandidates suchThat { s =>
- doesConform(symbol, tree.tpe, qual.tpe.memberType(s), env)
- }
+ def isMatch(member: Symbol) = (
+ doesConform(symbol, tree.tpe, qual.tpe memberType member, env)
+ && TypeEnv.includes(typeEnv(member), env)
+ )
+ if (env.isEmpty) NoSymbol
+ else qual.tpe member specializedName(symbol, env) suchThat isMatch
+ }
- debuglog("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe)
- debuglog("[specSym] found specMember: " + specMember)
- if (specMember ne NoSymbol)
- if (TypeEnv.includes(typeEnv(specMember), env)) Some(specMember)
- else {
- debuglog("wrong environments for specialized member: \n\ttypeEnv(%s) = %s\n\tenv = %s".format(specMember, typeEnv(specMember), env))
- None
- }
- else None
- } else None
+ def matchingSymbolInPrefix(pre: Type, member: Symbol, env: TypeEnv): Symbol = {
+ pre member specializedName(member, env) suchThat (_.tpe matches subst(env, member.tpe))
+ }
+
+ def transformSelect(sel: Select) = {
+ val Select(qual, name) = sel
+ debuglog(s"specializing Select(sym=${symbol.defString}, tree.tpe=${tree.tpe})")
+
+ val qual1 = transform(qual)
+ def copySelect = treeCopy.Select(tree, qual1, name)
+ def newSelect(member: Symbol) = atPos(tree.pos)(Select(qual1, member))
+ def typedOp(member: Symbol) = localTyper typedOperator newSelect(member)
+ def typedTree(member: Symbol) = localTyper typed newSelect(member)
+
+ val ignoreEnv = specializedTypeVars(symbol.info).isEmpty || name == nme.CONSTRUCTOR
+ if (ignoreEnv) overloads(symbol) find (_ matchesSym symbol) match {
+ case Some(Overload(member, _)) => typedOp(member)
+ case _ => copySelect
+ }
+ else {
+ val env = unify(symbol.tpe, tree.tpe, emptyEnv, false)
+ overloads(symbol) find (_ matchesEnv env) match {
+ case Some(Overload(member, _)) => typedOp(member)
+ case _ =>
+ matchingSymbolInPrefix(qual1.tpe, symbol, env) match {
+ case NoSymbol => copySelect
+ case member if member.isMethod => typedOp(member)
+ case member => typedTree(member)
+ }
+ }
+ }
}
curTree = tree
tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
def transformNew = {
- debuglog("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", ")))
- val found = findSpec(tpt.tpe)
- if (found.typeSymbol ne tpt.tpe.typeSymbol) {
- // the ctor can be specialized
- debuglog("** instantiated specialized type: " + found)
- reportError {
- localTyper.typedPos(tree.pos)(New(found, transformTrees(args): _*))
- } {
- _ => super.transform(tree)
+ debuglog("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", ")))
+ val found = specializedType(tpt.tpe)
+ if (found.typeSymbol ne tpt.tpe.typeSymbol) { // the ctor can be specialized
+ val inst = New(found, transformTrees(args): _*)
+ reportError(localTyper.typedPos(tree.pos)(inst))(_ => super.transform(tree))
}
- } else super.transform(tree)
+ else
+ super.transform(tree)
}
transformNew
- case Apply(sel @ Select(sup @ Super(qual, name), name1), args)
- if (sup.symbol.info.parents != beforePrevPhase(sup.symbol.info.parents)) =>
+ case Apply(sel @ Select(sup @ Super(qual, name), name1), args) if hasNewParents(sup) =>
def transformSuperApply = {
-
- def parents = sup.symbol.info.parents
- debuglog(tree + " parents changed from: " + beforePrevPhase(parents) + " to: " + parents)
-
- val res = localTyper.typed(
- Apply(Select(Super(qual, name) setPos sup.pos, name1) setPos sel.pos, transformTrees(args)) setPos tree.pos)
- debuglog("retyping call to super, from: " + symbol + " to " + res.symbol)
- res
+ val sup1 = Super(qual, name) setPos sup.pos
+ val tree1 = Apply(Select(sup1, name1) setPos sel.pos, transformTrees(args))
+ val res = localTyper.typedPos(tree.pos)(tree1)
+ debuglog(s"retyping call to super, from: $symbol to ${res.symbol}")
+ res
}
transformSuperApply
@@ -1440,7 +1497,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val qual1 = transform(qual)
// log(">>> TypeApply: " + tree + ", qual1: " + qual1)
specSym(qual1) match {
- case Some(specMember) =>
+ case NoSymbol =>
+ // See pos/exponential-spec.scala - can't call transform on the whole tree again.
+ treeCopy.TypeApply(tree, treeCopy.Select(sel, qual1, name), transformTrees(targs))
+ case specMember =>
debuglog("found " + specMember.fullName)
ifDebug(assert(symbol.info.typeParams.length == targs.length, symbol.info.typeParams + " / " + targs))
@@ -1462,63 +1522,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("rewrote " + tree + " to " + tree1)
localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
}
-
- case None =>
- treeCopy.TypeApply(tree, treeCopy.Select(sel, qual1, name), super.transformTrees(targs))
- // See pos/exponential-spec.scala - can't call transform on the whole tree again.
- // super.transform(tree)
}
}
transformTypeApply
- case Select(qual, name) =>
- def transformSelect = {
- qual match {
- case _: Super if illegalSpecializedInheritance(currentClass) =>
- val pos = tree.pos
- debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.")
- debuglog(pos.lineContent)
- tree
- case _ =>
+ case Select(Super(_, _), _) if illegalSpecializedInheritance(currentClass) =>
+ val pos = tree.pos
+ debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.\n" + pos.lineContent)
+ tree
- debuglog("specializing Select %s [tree.tpe: %s]".format(symbol.defString, tree.tpe))
-
- //log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info))
- if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) {
- // log("!!! unifying " + (symbol, symbol.tpe) + " and " + (tree, tree.tpe))
- val env = unify(symbol.tpe, tree.tpe, emptyEnv, false)
- // log("!!! found env: " + env + "; overloads: " + overloads(symbol))
- if (!env.isEmpty) {
- // debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env)
- val specMember = overload(symbol, env)
- if (specMember.isDefined) {
- localTyper.typedOperator(atPos(tree.pos)(Select(transform(qual), specMember.get.sym.name)))
- }
- else {
- val qual1 = transform(qual)
- val specMember = qual1.tpe.member(specializedName(symbol, env)).suchThat(_.tpe matches subst(env, symbol.tpe))
- if (specMember ne NoSymbol) {
- val tree1 = atPos(tree.pos)(Select(qual1, specMember))
- if (specMember.isMethod)
- localTyper.typedOperator(tree1)
- else
- localTyper.typed(tree1)
- } else
- treeCopy.Select(tree, qual1, name)
- }
- } else
- super.transform(tree)
- } else overloads(symbol).find(_.sym.info =:= symbol.info) match {
- case Some(specMember) =>
- val qual1 = transform(qual)
- debuglog("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym))
- localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym)))
- case None =>
- super.transform(tree)
- }
- }
- }
- transformSelect
+ case sel @ Select(_, _) =>
+ transformSelect(sel)
case PackageDef(pid, stats) =>
tree.symbol.info // make sure specializations have been performed
@@ -1543,47 +1557,37 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
transformTemplate
case ddef @ DefDef(_, _, _, vparamss, _, _) if info.isDefinedAt(symbol) =>
- def transformDefDef = {
- // log("--> method: " + ddef + " in " + ddef.symbol.owner + ", " + info(symbol))
- def reportTypeError(body: =>Tree) = reportError(body)(_ => ddef)
-
+ def transformDefDef = {
if (symbol.isConstructor) {
-
- val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperSelect, vparamss, symbol.owner))
-
+ val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperInitCall, vparamss, symbol.owner))
if (symbol.isPrimaryConstructor)
localTyper.typedPos(symbol.pos)(deriveDefDef(tree)(_ => Block(List(t), Literal(Constant()))))
else // duplicate the original constructor
- reportTypeError(duplicateBody(ddef, info(symbol).target))
+ reportError(duplicateBody(ddef, info(symbol).target))(_ => ddef)
}
else info(symbol) match {
case Implementation(target) =>
assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName)
// we have an rhs, specialize it
- val tree1 = reportTypeError {
- duplicateBody(ddef, target)
- }
+ val tree1 = reportError(duplicateBody(ddef, target))(_ => ddef)
debuglog("implementation: " + tree1)
deriveDefDef(tree1)(transform)
case NormalizedMember(target) =>
- val constraints = satisfiabilityConstraints(typeEnv(symbol))
- log("constraints: " + constraints)
- if (target.isDeferred || constraints == None) {
- deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called."))
- } else {
- // we have an rhs, specialize it
- val tree1 = reportTypeError {
- duplicateBody(ddef, target, constraints.get)
- }
- debuglog("implementation: " + tree1)
- deriveDefDef(tree1)(transform)
+ logResult("constraints")(satisfiabilityConstraints(typeEnv(symbol))) match {
+ case Some(constraint) if !target.isDeferred =>
+ // we have an rhs, specialize it
+ val tree1 = reportError(duplicateBody(ddef, target, constraint))(_ => ddef)
+ debuglog("implementation: " + tree1)
+ deriveDefDef(tree1)(transform)
+ case _ =>
+ deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called."))
}
case SpecialOverride(target) =>
assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName)
//debuglog("moving implementation, body of target " + target + ": " + body(target))
- debuglog("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor))
+ log("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor))
// we have an rhs, specialize it
val tree1 = addBody(ddef, target)
(new ChangeOwnerTraverser(target, tree1.symbol))(tree1.rhs)
@@ -1631,6 +1635,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case Abstract(targ) =>
debuglog("abstract: " + targ)
localTyper.typed(deriveDefDef(tree)(rhs => rhs))
+
+ case SpecialSuperAccessor(targ) =>
+ debuglog("special super accessor: " + targ + " for " + tree)
+ localTyper.typed(deriveDefDef(tree)(rhs => rhs))
}
}
transformDefDef
@@ -1652,7 +1660,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
deriveValDef(newValDef)(transform)
}
transformValDef
-
case _ =>
super.transform(tree)
}
@@ -1824,6 +1831,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* }}
*/
private def forwardCtorCall(pos: scala.reflect.internal.util.Position, receiver: Tree, paramss: List[List[ValDef]], clazz: Symbol): Tree = {
+ log(s"forwardCtorCall($pos, $receiver, $paramss, $clazz)")
/** A constructor parameter `f` initializes a specialized field
* iff:
@@ -1860,16 +1868,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
//! TODO: make sure the param types are seen from the right prefix
map2(fun.info.paramTypes, vparams)((tp, arg) => gen.maybeMkAsInstanceOf(Ident(arg), tp, arg.tpe))
)
- private def findSpec(tp: Type): Type = tp match {
- case TypeRef(pre, sym, _ :: _) => specializedType(tp)
- case _ => tp
- }
class SpecializationTransformer(unit: CompilationUnit) extends Transformer {
informProgress("specializing " + unit)
override def transform(tree: Tree) = {
val resultTree = if (settings.nospecialization.value) tree
- else afterSpecialize(specializeCalls(unit).transform(tree))
+ else exitingSpecialize(specializeCalls(unit).transform(tree))
// Remove the final modifier and @inline annotation from anything in the
// original class (since it's being overridden in at least onesubclass).
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index d3a5cebea0..5fc5d2127b 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -134,7 +134,7 @@ abstract class UnCurry extends InfoTransform
def isByNameRef(tree: Tree) = (
tree.isTerm
&& !byNameArgs(tree)
- && tree.hasSymbolWhich(s => isByNameParamType(s.tpe))
+ && tree.hasSymbolWhich(isByName)
)
/** Uncurry a type of a tree node.
@@ -205,6 +205,9 @@ abstract class UnCurry extends InfoTransform
val keyDef = ValDef(key, New(ObjectClass.tpe))
val tryCatch = Try(body, pat -> rhs)
+ for (Try(t, catches, _) <- body ; cdef <- catches ; if treeInfo catchesThrowable cdef)
+ unit.warning(body.pos, "catch block may intercept non-local return from " + meth)
+
Block(List(keyDef), tryCatch)
}
}
@@ -405,7 +408,7 @@ abstract class UnCurry extends InfoTransform
// when calling into scala varargs, make sure it's a sequence.
def arrayToSequence(tree: Tree, elemtp: Type) = {
- afterUncurry {
+ exitingUncurry {
localTyper.typedPos(pos) {
val pt = arrayType(elemtp)
val adaptedTree = // might need to cast to Array[elemtp], as arrays are not covariant
@@ -435,7 +438,7 @@ abstract class UnCurry extends InfoTransform
case _ => EmptyTree
}
}
- afterUncurry {
+ exitingUncurry {
localTyper.typedPos(pos) {
gen.mkMethodCall(tree, toArraySym, Nil, List(traversableClassTag(tree.tpe)))
}
@@ -459,7 +462,7 @@ abstract class UnCurry extends InfoTransform
else arrayToSequence(mkArray, varargsElemType)
}
- afterUncurry {
+ exitingUncurry {
if (isJava && !isReferenceArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) {
// The array isn't statically known to be a reference array, so call ScalaRuntime.toObjectArray.
suffix = localTyper.typedPos(pos) {
@@ -624,7 +627,7 @@ abstract class UnCurry extends InfoTransform
treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals)))
}
- case Assign(Select(_, _), _) =>
+ case Assign(_: RefTree, _) =>
withNeedLift(true) { super.transform(tree) }
case Assign(lhs, _) if lhs.symbol.owner != currentMethod || lhs.symbol.hasFlag(LAZY | ACCESSOR) =>
@@ -670,7 +673,7 @@ abstract class UnCurry extends InfoTransform
result setType uncurryTreeType(result.tpe)
}
- def postTransform(tree: Tree): Tree = afterUncurry {
+ def postTransform(tree: Tree): Tree = exitingUncurry {
def applyUnary(): Tree = {
// TODO_NMT: verify that the inner tree of a type-apply also gets parens if the
// whole tree is a polymorphic nullary method application
@@ -701,7 +704,7 @@ abstract class UnCurry extends InfoTransform
val body = tree.block
val catches = tree.catches
val finalizer = tree.finalizer
- if (opt.virtPatmat) {
+ if (!settings.XoldPatmat.value) {
if (catches exists (cd => !treeInfo.isCatchCase(cd)))
debugwarn("VPM BUG! illegal try/catch " + catches)
tree
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 399f9a1eac..3526d932d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -87,10 +87,10 @@ trait Analyzer extends AnyRef
override def run() {
val start = if (Statistics.canEnable) Statistics.startTimer(typerNanos) else null
global.echoPhaseSummary(this)
- currentRun.units foreach applyPhase
- undoLog.clear()
- // need to clear it after as well or 10K+ accumulated entries are
- // uncollectable the rest of the way.
+ for (unit <- currentRun.units) {
+ applyPhase(unit)
+ undoLog.clear()
+ }
if (Statistics.canEnable) Statistics.stopTimer(typerNanos, start)
}
def apply(unit: CompilationUnit) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index ec097a9b08..bd7e1a45c0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -154,6 +154,7 @@ trait Checkable {
def neverSubClass = isNeverSubClass(Xsym, Psym)
def neverMatches = result == StaticallyFalse
def isUncheckable = result == Uncheckable
+ def isCheckable = !isUncheckable
def uncheckableMessage = uncheckableType match {
case NoType => "something"
case tp @ RefinedType(_, _) => "refinement " + tp
@@ -232,6 +233,17 @@ trait Checkable {
trait InferCheckable {
self: Inferencer =>
+ def isUncheckable(P0: Type) = !isCheckable(P0)
+
+ def isCheckable(P0: Type): Boolean = (
+ uncheckedOk(P0) || (P0.widen match {
+ case TypeRef(_, NothingClass | NullClass | AnyValClass, _) => false
+ case RefinedType(_, decls) if !decls.isEmpty => false
+ case p =>
+ new CheckabilityChecker(AnyClass.tpe, p) isCheckable
+ })
+ )
+
/** TODO: much better error positions.
* Kind of stuck right now because they just pass us the one tree.
* TODO: Eliminate inPattern, canRemedy, which have no place here.
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index d78efd8280..7c02f094ed 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -269,9 +269,6 @@ trait ContextErrors {
def VolatileValueError(vdef: Tree) =
issueNormalTypeError(vdef, "values cannot be volatile")
- def FinalVolatileVarError(vdef: Tree) =
- issueNormalTypeError(vdef, "final vars cannot be volatile")
-
def LocalVarUninitializedError(vdef: Tree) =
issueNormalTypeError(vdef, "local variables must be initialized")
@@ -660,8 +657,8 @@ trait ContextErrors {
def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) =
issueTypeError(PosAndMsgTypeError(errPos, "cyclic aliasing or subtyping involving "+sym0))
- def CyclicReferenceError(errPos: Position, lockedSym: Symbol) =
- issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym))
+ def CyclicReferenceError(errPos: Position, tp: Type, lockedSym: Symbol) =
+ issueTypeError(PosAndMsgTypeError(errPos, s"illegal cyclic reference involving $tp and $lockedSym"))
// macro-related errors (also see MacroErrors below)
@@ -838,7 +835,7 @@ trait ContextErrors {
// side-effect on the tree, break the overloaded type cycle in infer
private def setErrorOnLastTry(lastTry: Boolean, tree: Tree) = if (lastTry) setError(tree)
-
+
def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type, lastTry: Boolean) = {
issueNormalTypeError(tree,
applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
@@ -851,7 +848,7 @@ trait ContextErrors {
def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol,
firstCompeting: Symbol, argtpes: List[Type], pt: Type, lastTry: Boolean) = {
-
+
if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous) {
val msg0 =
"argument types " + argtpes.mkString("(", ",", ")") +
@@ -861,7 +858,7 @@ trait ContextErrors {
setErrorOnLastTry(lastTry, tree)
} else setError(tree) // do not even try further attempts because they should all fail
// even if this is not the last attempt (because of the SO's possibility on the horizon)
-
+
}
def NoBestExprAlternativeError(tree: Tree, pt: Type, lastTry: Boolean) = {
@@ -1194,7 +1191,7 @@ trait ContextErrors {
setError(arg)
} else arg
}
-
+
def WarnAfterNonSilentRecursiveInference(param: Symbol, arg: Tree)(implicit context: Context) = {
val note = "type-checking the invocation of "+ param.owner +" checks if the named argument expression '"+ param.name + " = ...' is a valid assignment\n"+
"in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for "+ param.name +"."
diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
index e8865964b0..2555d199d5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
@@ -188,7 +188,6 @@ trait DestructureTypes {
case AntiPolyType(pre, targs) => product(tp, prefix(pre), typeArgs(targs))
case ClassInfoType(parents, decls, clazz) => product(tp, parentList(parents), scope(decls), wrapAtom(clazz))
case ConstantType(const) => product(tp, constant("value", const))
- case DeBruijnIndex(level, index, args) => product(tp, const("level" -> level), const("index" -> index), typeArgs(args))
case OverloadedType(pre, alts) => product(tp, prefix(pre), node("alts", typeList(alts map pre.memberType)))
case RefinedType(parents, decls) => product(tp, parentList(parents), scope(decls))
case SingleType(pre, sym) => product(tp, prefix(pre), wrapAtom(sym))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index aa507efe5a..0a07a598d9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -233,7 +233,7 @@ abstract class Duplicators extends Analyzer {
override def typed(tree: Tree, mode: Int, pt: Type): Tree = {
debuglog("typing " + tree + ": " + tree.tpe + ", " + tree.getClass)
val origtreesym = tree.symbol
- if (tree.hasSymbol && tree.symbol != NoSymbol
+ if (tree.hasSymbolField && tree.symbol != NoSymbol
&& !tree.symbol.isLabel // labels cannot be retyped by the type checker as LabelDef has no ValDef/return type trees
&& invalidSyms.isDefinedAt(tree.symbol)) {
debuglog("removed symbol " + tree.symbol)
@@ -317,15 +317,39 @@ abstract class Duplicators extends Analyzer {
super.typed(tree, mode, pt)
case Select(th @ This(_), sel) if (oldClassOwner ne null) && (th.symbol == oldClassOwner) =>
- // log("selection on this, no type ascription required")
- // we use the symbol name instead of the tree name because the symbol may have been
- // name mangled, rendering the tree name obsolete
- // log(tree)
- val t = super.typedPos(tree.pos, mode, pt) {
- Select(This(newClassOwner), tree.symbol.name)
- }
- // log("typed to: " + t + "; tpe = " + t.tpe + "; " + inspectTpe(t.tpe))
- t
+ // We use the symbol name instead of the tree name because the symbol
+ // may have been name mangled, rendering the tree name obsolete.
+ // ...but you can't just do a Select on a name because if the symbol is
+ // overloaded, you will crash in the backend.
+ val memberByName = newClassOwner.thisType.member(tree.symbol.name)
+ def nameSelection = Select(This(newClassOwner), tree.symbol.name)
+ val newTree = (
+ if (memberByName.isOverloaded) {
+ // Find the types of the overload alternatives as seen in the new class,
+ // and filter the list down to those which match the old type (after
+ // fixing the old type so it is seen as if from the new class.)
+ val typeInNewClass = fixType(oldClassOwner.info memberType tree.symbol)
+ val alts = memberByName.alternatives
+ val memberTypes = alts map (newClassOwner.info memberType _)
+ val memberString = memberByName.defString
+ alts zip memberTypes filter (_._2 =:= typeInNewClass) match {
+ case ((alt, tpe)) :: Nil =>
+ log(s"Arrested overloaded type in Duplicators, narrowing to ${alt.defStringSeenAs(tpe)}\n Overload was: $memberString")
+ Select(This(newClassOwner), alt)
+ case xs =>
+ alts filter (alt => (alt.paramss corresponds tree.symbol.paramss)(_.size == _.size)) match {
+ case alt :: Nil =>
+ log(s"Resorted to parameter list arity to disambiguate to $alt\n Overload was: $memberString")
+ Select(This(newClassOwner), alt)
+ case _ =>
+ log(s"Could not disambiguate $memberTypes. Attempting name-based selection, but we may crash later.")
+ nameSelection
+ }
+ }
+ }
+ else nameSelection
+ )
+ super.typed(atPos(tree.pos)(newTree), mode, pt)
case This(_) if (oldClassOwner ne null) && (tree.symbol == oldClassOwner) =>
// val tree1 = Typed(This(newClassOwner), TypeTree(fixType(tree.tpe.widen)))
@@ -379,7 +403,7 @@ abstract class Duplicators extends Analyzer {
case _ =>
debuglog("Duplicators default case: " + tree.summaryString)
debuglog(" ---> " + tree)
- if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) {
tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==)
}
val ntree = castType(tree, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index b04a736fd3..059d32fcb5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -118,7 +118,7 @@ trait EtaExpansion { self: Analyzer =>
val origTpe = sym.tpe
val isRepeated = definitions.isRepeatedParamType(origTpe)
// SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala
- val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropRepeatedParamType(origTpe)
+ val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropIllegalStarTypes(origTpe)
val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree)
(valDef, isRepeated)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 99301cebcf..5a9a4caea1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -132,7 +132,7 @@ trait Implicits {
}
/* Map a polytype to one in which all type parameters and argument-dependent types are replaced by wildcards.
- * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate DebruijnIndex types
+ * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate debruijn index types
* when checking whether `b` is a valid implicit, as we haven't even searched a value for the implicit arg `x`,
* so we have to approximate (otherwise it is excluded a priori).
*/
@@ -997,7 +997,7 @@ trait Implicits {
case Some(imap) => imap
case None =>
val result = new InfoMap
- getClassParts(sym.tpe)(result, new mutable.HashSet(), pending + sym)
+ getClassParts(sym.tpeHK)(result, new mutable.HashSet(), pending + sym)
infoMapCache(sym) = result
result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index cb5fc8df5a..61e4fb86a2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -30,8 +30,8 @@ trait Infer extends Checkable {
private def assertNonCyclic(tvar: TypeVar) =
assert(tvar.constr.inst != tvar, tvar.origin)
- /** The formal parameter types corresponding to <code>formals</code>.
- * If <code>formals</code> has a repeated last parameter, a list of
+ /** The formal parameter types corresponding to `formals`.
+ * If `formals` has a repeated last parameter, a list of
* (nargs - params.length + 1) copies of its type is returned.
* By-name types are replaced with their underlying type.
*
@@ -49,6 +49,24 @@ trait Infer extends Checkable {
} else formals1
}
+ /** Sorts the alternatives according to the given comparison function.
+ * Returns a list containing the best alternative as well as any which
+ * the best fails to improve upon.
+ */
+ private def bestAlternatives(alternatives: List[Symbol])(isBetter: (Symbol, Symbol) => Boolean): List[Symbol] = {
+ def improves(sym1: Symbol, sym2: Symbol) = (
+ sym2 == NoSymbol
+ || sym2.isError
+ || sym2.hasAnnotation(BridgeClass)
+ || isBetter(sym1, sym2)
+ )
+
+ alternatives sortWith improves match {
+ case best :: rest if rest.nonEmpty => best :: rest.filterNot(alt => improves(best, alt))
+ case bests => bests
+ }
+ }
+
/** Returns `(formals, formalsExpanded)` where `formalsExpanded` are the expected types
* for the `nbSubPats` sub-patterns of an extractor pattern, of which the corresponding
* unapply[Seq] call is assumed to have result type `resTp`.
@@ -112,17 +130,6 @@ trait Infer extends Checkable {
else (formals, formalsExpanded)
}
- def actualTypes(actuals: List[Type], nformals: Int): List[Type] =
- if (nformals == 1 && !hasLength(actuals, 1))
- List(if (actuals.isEmpty) UnitClass.tpe else tupleType(actuals))
- else actuals
-
- def actualArgs(pos: Position, actuals: List[Tree], nformals: Int): List[Tree] = {
- val inRange = nformals == 1 && !hasLength(actuals, 1) && actuals.lengthCompare(MaxTupleArity) <= 0
- if (inRange && !phase.erasedTypes) List(atPos(pos)(gen.mkTuple(actuals)))
- else actuals
- }
-
/** A fresh type variable with given type parameter as origin.
*
* @param tparam ...
@@ -149,14 +156,13 @@ trait Infer extends Checkable {
case tv @ TypeVar(origin, constr) if !tv.untouchable =>
if (constr.inst == NoType) {
throw new DeferredNoInstance(() =>
- "no unique instantiation of type variable " + origin + " could be found")
+ s"no unique instantiation of type variable $origin could be found")
} else if (excludedVars(tv)) {
throw new NoInstance("cyclic instantiation")
} else {
excludedVars += tv
- val res = apply(constr.inst)
- excludedVars -= tv
- res
+ try apply(constr.inst)
+ finally excludedVars -= tv
}
case _ =>
mapOver(tp)
@@ -270,7 +276,7 @@ trait Infer extends Checkable {
def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue
def errorSym = if (tree.isType) errorClass else errorValue
- if (tree.hasSymbol)
+ if (tree.hasSymbolField)
tree setSymbol errorSym
tree setType ErrorType
@@ -296,8 +302,8 @@ trait Infer extends Checkable {
/* -- Tests & Checks---------------------------------------------------- */
- /** Check that <code>sym</code> is defined and accessible as a member of
- * tree <code>site</code> with type <code>pre</code> in current context.
+ /** Check that `sym` is defined and accessible as a member of
+ * tree `site` with type `pre` in current context.
*
* Note: pre is not refchecked -- moreover, refchecking the resulting tree may not refcheck pre,
* since pre may not occur in its type (callers should wrap the result in a TypeTreeWithDeferredRefCheck)
@@ -404,8 +410,19 @@ trait Infer extends Checkable {
/** Like weakly compatible but don't apply any implicit conversions yet.
* Used when comparing the result type of a method with its prototype.
+ *
* [Martin] I think Infer is also created by Erasure, with the default
* implementation of isCoercible
+ * [Paulp] (Assuming the above must refer to my comment on isCoercible)
+ * Nope, I examined every occurrence of Inferencer in trunk. It
+ * appears twice as a self-type, once at its definition, and once
+ * where it is instantiated in Typers. There are no others.
+ *
+ % ack -A0 -B0 --no-filename '\bInferencer\b' src
+ self: Inferencer =>
+ self: Inferencer =>
+ class Inferencer(context: Context) extends InferencerContextErrors with InferCheckable {
+ val infer = new Inferencer(context0) {
*/
def isConservativelyCompatible(tp: Type, pt: Type): Boolean =
context.withImplicitsDisabled(isWeaklyCompatible(tp, pt))
@@ -439,9 +456,9 @@ trait Infer extends Checkable {
}
/** Return inferred type arguments of polymorphic expression, given
- * its type parameters and result type and a prototype <code>pt</code>.
+ * its type parameters and result type and a prototype `pt`.
* If no minimal type variables exist that make the
- * instantiated type a subtype of <code>pt</code>, return null.
+ * instantiated type a subtype of `pt`, return null.
*
* @param tparams ...
* @param restpe ...
@@ -473,7 +490,7 @@ trait Infer extends Checkable {
/** Return inferred proto-type arguments of function, given
* its type and value parameters and result type, and a
- * prototype <code>pt</code> for the function result.
+ * prototype `pt` for the function result.
* Type arguments need to be either determined precisely by
* the prototype, or they are maximized, if they occur only covariantly
* in the value parameter list.
@@ -566,7 +583,7 @@ trait Infer extends Checkable {
*
* Rewrite for repeated param types: Map T* entries to Seq[T].
* @return map from tparams to inferred arg, if inference was successful, tparams that map to None are considered left undetermined
- * type parameters that are inferred as `scala.Nothing` and that are not covariant in <code>restpe</code> are taken to be undetermined
+ * type parameters that are inferred as `scala.Nothing` and that are not covariant in `restpe` are taken to be undetermined
*/
def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result = {
val buf = AdjustedTypeArgs.Result.newBuilder[Symbol, Option[Type]]
@@ -577,14 +594,14 @@ trait Infer extends Checkable {
&& (restpe.isWildcard || (varianceInType(restpe)(tparam) & COVARIANT) == 0) // don't retract covariant occurrences
)
- // checks opt.virtPatmat directly so one need not run under -Xexperimental to use virtpatmat
+ // checks !settings.XoldPatmat.value directly so one need not run under -Xexperimental to use virtpatmat
buf += ((tparam,
if (retract) None
else Some(
if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass)
else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass)
// this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
- else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ
+ else if (targ.typeSymbol.isModuleClass || ((settings.Xexperimental.value || !settings.XoldPatmat.value) && tvar.constr.avoidWiden)) targ
else targ.widen
)
))
@@ -594,7 +611,7 @@ trait Infer extends Checkable {
/** Return inferred type arguments, given type parameters, formal parameters,
* argument types, result type and expected result type.
- * If this is not possible, throw a <code>NoInstance</code> exception.
+ * If this is not possible, throw a `NoInstance` exception.
* Undetermined type arguments are represented by `definitions.NothingClass.tpe`.
* No check that inferred parameters conform to their bounds is made here.
*
@@ -651,9 +668,57 @@ trait Infer extends Checkable {
tvars, tparams, tparams map varianceInTypes(formals),
false, lubDepth(formals) max lubDepth(argtpes)
)
+ // Can warn about inferring Any/AnyVal as long as they don't appear
+ // explicitly anywhere amongst the formal, argument, result, or expected type.
+ def canWarnAboutAny = !(pt :: restpe :: formals ::: argtpes exists (t => (t contains AnyClass) || (t contains AnyValClass)))
+ def argumentPosition(idx: Int): Position = context.tree match {
+ case x: ValOrDefDef => x.rhs match {
+ case Apply(fn, args) if idx < args.size => args(idx).pos
+ case _ => context.tree.pos
+ }
+ case _ => context.tree.pos
+ }
+ if (settings.warnInferAny.value && context.reportErrors && canWarnAboutAny) {
+ foreachWithIndex(targs) ((targ, idx) =>
+ targ.typeSymbol match {
+ case sym @ (AnyClass | AnyValClass) =>
+ context.unit.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.")
+ case _ =>
+ }
+ )
+ }
adjustTypeArgs(tparams, tvars, targs, restpe)
}
+ /** One must step carefully when assessing applicability due to
+ * complications from varargs, tuple-conversion, named arguments.
+ * This method is used to filter out inapplicable methods,
+ * its behavior slightly configurable based on what stage of
+ * overloading resolution we're at.
+ *
+ * This method has boolean parameters, which is usually suboptimal
+ * but I didn't work out a better way. They don't have defaults,
+ * and the method's scope is limited.
+ */
+ private[typechecker] def isApplicableBasedOnArity(tpe: Type, argsCount: Int, varargsStar: Boolean, tuplingAllowed: Boolean): Boolean = followApply(tpe) match {
+ case OverloadedType(pre, alts) =>
+ alts exists (alt => isApplicableBasedOnArity(pre memberType alt, argsCount, varargsStar, tuplingAllowed))
+ case _ =>
+ val paramsCount = tpe.params.length
+ val simpleMatch = paramsCount == argsCount
+ val varargsTarget = isVarArgsList(tpe.params)
+ def varargsMatch = varargsTarget && (paramsCount - 1) <= argsCount
+ def tuplingMatch = tuplingAllowed && eligibleForTupleConversion(paramsCount, argsCount, varargsTarget)
+
+ // A varargs star call, e.g. (x, y:_*) can only match a varargs method
+ // with the same number of parameters. See SI-5859 for an example of what
+ // would fail were this not enforced before we arrived at isApplicable.
+ if (varargsStar)
+ varargsTarget && simpleMatch
+ else
+ simpleMatch || varargsMatch || tuplingMatch
+ }
+
private[typechecker] def followApply(tp: Type): Type = tp match {
case NullaryMethodType(restp) =>
val restp1 = followApply(restp)
@@ -670,14 +735,6 @@ trait Infer extends Checkable {
else OverloadedType(tp, appmeth.alternatives)
}
- def hasExactlyNumParams(tp: Type, n: Int): Boolean = tp match {
- case OverloadedType(pre, alts) =>
- alts exists (alt => hasExactlyNumParams(pre.memberType(alt), n))
- case _ =>
- val len = tp.params.length
- len == n || isVarArgsList(tp.params) && len <= n + 1
- }
-
/**
* Verifies whether the named application is valid. The logic is very
* similar to the one in NamesDefaults.removeNames.
@@ -723,17 +780,54 @@ trait Infer extends Checkable {
(argtpes1, argPos, namesOK)
}
- /** don't do a () to (()) conversion for methods whose second parameter
- * is a varargs. This is a fairly kludgey way to address #3224.
- * We'll probably find a better way to do this by identifying
- * tupled and n-ary methods, but thiws is something for a future major revision.
+ /** True if the given parameter list can accept a tupled argument list,
+ * and the argument list can be tupled (based on its length.)
+ */
+ def eligibleForTupleConversion(paramsCount: Int, argsCount: Int, varargsTarget: Boolean): Boolean = {
+ def canSendTuple = argsCount match {
+ case 0 => !varargsTarget // avoid () to (()) conversion - SI-3224
+ case 1 => false // can't tuple a single argument
+ case n => n <= MaxTupleArity // <= 22 arguments
+ }
+ def canReceiveTuple = paramsCount match {
+ case 1 => true
+ case 2 => varargsTarget
+ case _ => false
+ }
+ canSendTuple && canReceiveTuple
+ }
+ def eligibleForTupleConversion(formals: List[Type], argsCount: Int): Boolean = formals match {
+ case p :: Nil => eligibleForTupleConversion(1, argsCount, varargsTarget = isScalaRepeatedParamType(p))
+ case _ :: p :: Nil if isScalaRepeatedParamType(p) => eligibleForTupleConversion(2, argsCount, varargsTarget = true)
+ case _ => false
+ }
+
+ /** The type of an argument list after being coerced to a tuple.
+ * @pre: the argument list is eligible for tuple conversion.
+ */
+ private def typeAfterTupleConversion(argtpes: List[Type]): Type = (
+ if (argtpes.isEmpty) UnitClass.tpe // aka "Tuple0"
+ else tupleType(argtpes map {
+ case NamedType(name, tp) => UnitClass.tpe // not a named arg - only assignments here
+ case RepeatedType(tp) => tp // but probably shouldn't be tupling a call containing :_*
+ case tp => tp
+ })
+ )
+
+ /** If the argument list needs to be tupled for the parameter list,
+ * a list containing the type of the tuple. Otherwise, the original
+ * argument list.
*/
- def isUnitForVarArgs(args: List[AnyRef], params: List[Symbol]): Boolean =
- args.isEmpty && hasLength(params, 2) && isVarArgsList(params)
+ def tupleIfNecessary(formals: List[Type], argtpes: List[Type]): List[Type] = {
+ if (eligibleForTupleConversion(formals, argtpes.size))
+ typeAfterTupleConversion(argtpes) :: Nil
+ else
+ argtpes
+ }
- /** Is there an instantiation of free type variables <code>undetparams</code>
- * such that function type <code>ftpe</code> is applicable to
- * <code>argtpes</code> and its result conform to <code>pt</code>?
+ /** Is there an instantiation of free type variables `undetparams`
+ * such that function type `ftpe` is applicable to
+ * `argtpes` and its result conform to `pt`?
*
* @param undetparams ...
* @param ftpe the type of the function (often a MethodType)
@@ -748,23 +842,16 @@ trait Infer extends Checkable {
argtpes0: List[Type], pt: Type): Boolean =
ftpe match {
case OverloadedType(pre, alts) =>
- alts exists (alt => isApplicable(undetparams, pre.memberType(alt), argtpes0, pt))
+ alts exists (alt => isApplicable(undetparams, pre memberType alt, argtpes0, pt))
case ExistentialType(tparams, qtpe) =>
isApplicable(undetparams, qtpe, argtpes0, pt)
case mt @ MethodType(params, _) =>
- val formals = formalTypes(mt.paramTypes, argtpes0.length, removeByName = false)
-
- def tryTupleApply: Boolean = {
- // if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0
- val tupleArgTpes = actualTypes(argtpes0 map {
- // no assignment is treated as named argument here
- case NamedType(name, tp) => UnitClass.tpe
- case tp => tp
- }, formals.length)
-
- !sameLength(argtpes0, tupleArgTpes) &&
- !isUnitForVarArgs(argtpes0, params) &&
- isApplicable(undetparams, ftpe, tupleArgTpes, pt)
+ val argslen = argtpes0.length
+ val formals = formalTypes(mt.paramTypes, argslen, removeByName = false)
+
+ def tryTupleApply = {
+ val tupled = tupleIfNecessary(mt.paramTypes, argtpes0)
+ (tupled ne argtpes0) && isApplicable(undetparams, ftpe, tupled, pt)
}
def typesCompatible(argtpes: List[Type]) = {
val restpe = ftpe.resultType(argtpes)
@@ -786,17 +873,16 @@ trait Infer extends Checkable {
val lencmp = compareLengths(argtpes0, formals)
if (lencmp > 0) tryTupleApply
else if (lencmp == 0) {
- if (!argtpes0.exists(_.isInstanceOf[NamedType])) {
- // fast track if no named arguments are used
+ // fast track if no named arguments are used
+ if (!containsNamedType(argtpes0))
typesCompatible(argtpes0)
- }
else {
// named arguments are used
val (argtpes1, argPos, namesOK) = checkNames(argtpes0, params)
// when using named application, the vararg param has to be specified exactly once
- ( namesOK && (isIdentity(argPos) || sameLength(formals, params)) &&
- // nb. arguments and names are OK, check if types are compatible
- typesCompatible(reorderArgs(argtpes1, argPos))
+ ( namesOK
+ && (isIdentity(argPos) || sameLength(formals, params))
+ && typesCompatible(reorderArgs(argtpes1, argPos)) // nb. arguments and names are OK, check if types are compatible
)
}
}
@@ -840,7 +926,7 @@ trait Infer extends Checkable {
} else res1
}
- /** Is type <code>ftpe1</code> strictly more specific than type <code>ftpe2</code>
+ /** Is type `ftpe1` strictly more specific than type `ftpe2`
* when both are alternatives in an overloaded function?
* @see SLS (sec:overloading-resolution)
*
@@ -850,7 +936,7 @@ trait Infer extends Checkable {
*/
def isAsSpecific(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match {
case OverloadedType(pre, alts) =>
- alts exists (alt => isAsSpecific(pre.memberType(alt), ftpe2))
+ alts exists (alt => isAsSpecific(pre memberType alt, ftpe2))
case et: ExistentialType =>
isAsSpecific(ftpe1.skolemizeExistential, ftpe2)
//et.withTypeVars(isAsSpecific(_, ftpe2))
@@ -877,7 +963,7 @@ trait Infer extends Checkable {
case _ =>
ftpe2 match {
case OverloadedType(pre, alts) =>
- alts forall (alt => isAsSpecific(ftpe1, pre.memberType(alt)))
+ alts forall (alt => isAsSpecific(ftpe1, pre memberType alt))
case et: ExistentialType =>
et.withTypeVars(isAsSpecific(ftpe1, _))
case mt: MethodType =>
@@ -1095,19 +1181,19 @@ trait Infer extends Checkable {
* @param targs ...
* @param pt ...
*/
- private def substExpr(tree: Tree, undetparams: List[Symbol],
- targs: List[Type], pt: Type) {
+ private def substExpr(tree: Tree, undetparams: List[Symbol], targs: List[Type], pt: Type) {
if (targs eq null) {
if (!tree.tpe.isErroneous && !pt.isErroneous)
PolymorphicExpressionInstantiationError(tree, undetparams, pt)
- } else {
+ }
+ else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
notifyUndetparamsInferred(undetparams, targs)
}
}
- /** Substitute free type variables <code>undetparams</code> of application
- * <code>fn(args)</code>, given prototype <code>pt</code>.
+ /** Substitute free type variables `undetparams` of application
+ * `fn(args)`, given prototype `pt`.
*
* @param fn fn: the function that needs to be instantiated.
* @param undetparams the parameters that need to be determined
@@ -1120,10 +1206,10 @@ trait Infer extends Checkable {
args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
case mt @ MethodType(params0, _) =>
try {
- val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
- val formals = formalTypes(mt.paramTypes, args.length)
- val argtpes = actualTypes(args map (x => elimAnonymousClass(x.tpe.deconst)), formals.length)
- val restpe = fn.tpe.resultType(argtpes)
+ val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
+ val formals = formalTypes(mt.paramTypes, args.length)
+ val argtpes = tupleIfNecessary(formals, args map (x => elimAnonymousClass(x.tpe.deconst)))
+ val restpe = fn.tpe.resultType(argtpes)
val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
methTypeArgs(undetparams, formals, restpe, argtpes, pt)
@@ -1160,8 +1246,8 @@ trait Infer extends Checkable {
def widen(tp: Type): Type = abstractTypesToBounds(tp)
- /** Substitute free type variables <code>undetparams</code> of type constructor
- * <code>tree</code> in pattern, given prototype <code>pt</code>.
+ /** Substitute free type variables `undetparams` of type constructor
+ * `tree` in pattern, given prototype `pt`.
*
* @param tree the constuctor that needs to be instantiated
* @param undetparams the undetermined type parameters
@@ -1228,17 +1314,19 @@ trait Infer extends Checkable {
}
} else None
- (inferFor(pt) orElse inferForApproxPt) map { targs =>
- new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- notifyUndetparamsInferred(undetparams, targs)
- } getOrElse {
- debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)"))
- // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
- ConstrInstantiationError(tree, resTp, pt)
+ val inferred = inferFor(pt) orElse inferForApproxPt
+
+ inferred match {
+ case Some(targs) =>
+ new TreeTypeSubstituter(undetparams, targs).traverse(tree)
+ notifyUndetparamsInferred(undetparams, targs)
+ case _ =>
+ debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)"))
+ // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
+ ConstrInstantiationError(tree, resTp, pt)
}
}
-
def instBounds(tvar: TypeVar): (Type, Type) = {
val tparam = tvar.origin.typeSymbol
val instType = toOrigin(tvar.constr.inst)
@@ -1286,51 +1374,6 @@ trait Infer extends Checkable {
}
}
- /** Does `tp` contain any types that cannot be checked at run-time (i.e., after erasure, will isInstanceOf[erased(tp)] imply conceptualIsInstanceOf[tp]?)
- * we should find a way to ask erasure: hey, is `tp` going to make it through you with all of its isInstanceOf resolving powers intact?
- * TODO: at the very least, reduce duplication wrt checkCheckable
- */
- def containsUnchecked(tp: Type): Boolean = {
- def check(tp: Type, bound: List[Symbol]): Boolean = {
- def isSurroundingTypeParam(sym: Symbol) = {
- val e = context.scope.lookupEntry(sym.name)
- ( (e ne null)
- && (e.sym == sym )
- && !e.sym.isTypeParameterOrSkolem
- && (e.owner == context.scope)
- )
- }
- def isLocalBinding(sym: Symbol) = (
- sym.isAbstractType && (
- (bound contains sym)
- || (sym.name == tpnme.WILDCARD)
- || isSurroundingTypeParam(sym)
- )
- )
- tp.normalize match {
- case SingleType(pre, _) =>
- check(pre, bound)
- case TypeRef(_, ArrayClass, arg :: _) =>
- check(arg, bound)
- case tp @ TypeRef(pre, sym, args) =>
- ( (sym.isAbstractType && !isLocalBinding(sym))
- || (args exists (x => !isLocalBinding(x.typeSymbol)))
- || check(pre, bound)
- )
- // case RefinedType(_, decls) if decls.nonEmpty =>
- // patternWarning(tp, "refinement ")
- case RefinedType(parents, _) =>
- parents exists (p => check(p, bound))
- case ExistentialType(quantified, tp1) =>
- check(tp1, bound ::: quantified)
- case _ =>
- false
- }
- }
- check(tp, Nil)
- }
-
-
/** Type intersection of simple type tp1 with general type tp2.
* The result eliminates some redundancies.
*/
@@ -1469,52 +1512,30 @@ trait Infer extends Checkable {
}
*/
- /** Assign <code>tree</code> the symbol and type of the alternative which
- * matches prototype <code>pt</code>, if it exists.
+ /** Assign `tree` the symbol and type of the alternative which
+ * matches prototype `pt`, if it exists.
* If several alternatives match `pt`, take parameterless one.
* If no alternative matches `pt`, take the parameterless one anyway.
*/
def inferExprAlternative(tree: Tree, pt: Type) = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice { isSecondTry =>
- val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
- val noAlternatives = alts0.isEmpty
- val alts1 = if (noAlternatives) alts else alts0
+ val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
+ val alts1 = if (alts0.isEmpty) alts else alts0
- //println("trying "+alts1+(alts1 map (_.tpe))+(alts1 map (_.locationString))+" for "+pt)
- def improves(sym1: Symbol, sym2: Symbol): Boolean =
- sym2 == NoSymbol || sym2.hasAnnotation(BridgeClass) ||
- { val tp1 = pre.memberType(sym1)
- val tp2 = pre.memberType(sym2)
- (tp2 == ErrorType ||
- !global.typer.infer.isWeaklyCompatible(tp2, pt) && global.typer.infer.isWeaklyCompatible(tp1, pt) ||
- isStrictlyMoreSpecific(tp1, tp2, sym1, sym2)) }
+ val bests = bestAlternatives(alts1) { (sym1, sym2) =>
+ val tp1 = pre.memberType(sym1)
+ val tp2 = pre.memberType(sym2)
- val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) =>
- if (improves(alt, best)) alt else best)
-
- val competing = alts1 dropWhile (alt => best == alt || improves(best, alt))
-
- if (best == NoSymbol) {
- if (settings.debug.value) {
- tree match {
- case Select(qual, _) =>
- Console.println("qual: " + qual + ":" + qual.tpe +
- " with decls " + qual.tpe.decls +
- " with members " + qual.tpe.members +
- " with members " + qual.tpe.member(newTermName("$minus")))
- case _ =>
- }
- }
- // todo: missing test case
- NoBestExprAlternativeError(tree, pt, isSecondTry)
- } else if (!competing.isEmpty) {
- if (noAlternatives) NoBestExprAlternativeError(tree, pt, isSecondTry)
- else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt, isSecondTry)
- } else {
-// val applicable = alts1 filter (alt =>
-// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
-// checkNotShadowed(tree.pos, pre, best, applicable)
- tree.setSymbol(best).setType(pre.memberType(best))
+ ( tp2 == ErrorType
+ || (!isWeaklyCompatible(tp2, pt) && isWeaklyCompatible(tp1, pt))
+ || isStrictlyMoreSpecific(tp1, tp2, sym1, sym2)
+ )
+ }
+ // todo: missing test case for bests.isEmpty
+ bests match {
+ case best :: Nil => tree setSymbol best setType (pre memberType best)
+ case best :: competing :: _ if alts0.nonEmpty => if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing, pt, isSecondTry)
+ case _ => if (bests.isEmpty || alts0.isEmpty) NoBestExprAlternativeError(tree, pt, isSecondTry)
}
}
}
@@ -1533,48 +1554,47 @@ trait Infer extends Checkable {
private def paramMatchesName(param: Symbol, name: Name) =
param.name == name || param.deprecatedParamName.exists(_ == name)
- // Check the first parameter list the same way.
- private def methodMatchesName(method: Symbol, name: Name) = method.paramss match {
- case ps :: _ => ps exists (p => paramMatchesName(p, name))
- case _ => false
+ private def containsNamedType(argtpes: List[Type]): Boolean = argtpes match {
+ case Nil => false
+ case NamedType(_, _) :: _ => true
+ case _ :: rest => containsNamedType(rest)
}
-
- private def resolveOverloadedMethod(argtpes: List[Type], eligible: List[Symbol]) = {
+ private def namesOfNamedArguments(argtpes: List[Type]) =
+ argtpes collect { case NamedType(name, _) => name }
+
+ /** Given a list of argument types and eligible method overloads, whittle the
+ * list down to the methods which should be considered for specificity
+ * testing, taking into account here:
+ * - named arguments at the call site (keep only methods with name-matching parameters)
+ * - if multiple methods are eligible, drop any methods which take default arguments
+ * - drop any where arity cannot match under any conditions (allowing for
+ * overloaded applies, varargs, and tupling conversions)
+ * This method is conservative; it can tolerate some varieties of false positive,
+ * but no false negatives.
+ *
+ * @param eligible the overloaded method symbols
+ * @param argtpes the argument types at the call site
+ * @param varargsStar true if the call site has a `: _*` attached to the last argument
+ */
+ private def overloadsToConsiderBySpecificity(eligible: List[Symbol], argtpes: List[Type], varargsStar: Boolean): List[Symbol] = {
// If there are any foo=bar style arguments, and any of the overloaded
// methods has a parameter named `foo`, then only those methods are considered.
- val namesOfArgs = argtpes collect { case NamedType(name, _) => name }
- val namesMatch = (
- if (namesOfArgs.isEmpty) Nil
- else eligible filter { m =>
- namesOfArgs forall { name =>
- methodMatchesName(m, name)
- }
- }
- )
-
- if (namesMatch.nonEmpty) namesMatch
- else if (eligible.isEmpty || eligible.tail.isEmpty) eligible
- else eligible filter { alt =>
- // for functional values, the `apply` method might be overloaded
- val mtypes = followApply(alt.tpe) match {
- case OverloadedType(_, alts) => alts map (_.tpe)
- case t => t :: Nil
- }
- // Drop those that use a default; keep those that use vararg/tupling conversion.
- mtypes exists (t =>
- !t.typeSymbol.hasDefaultFlag && {
- compareLengths(t.params, argtpes) < 0 || // tupling (*)
- hasExactlyNumParams(t, argtpes.length) // same nb or vararg
- }
- )
- // (*) more arguments than parameters, but still applicable: tupling conversion works.
- // todo: should not return "false" when paramTypes = (Unit) no argument is given
- // (tupling would work)
+ val namesMatch = namesOfNamedArguments(argtpes) match {
+ case Nil => Nil
+ case names => eligible filter (m => names forall (name => m.info.params exists (p => paramMatchesName(p, name))))
}
+ if (namesMatch.nonEmpty)
+ namesMatch
+ else if (eligible.isEmpty || eligible.tail.isEmpty)
+ eligible
+ else
+ eligible filter (alt =>
+ !alt.hasDefault && isApplicableBasedOnArity(alt.tpe, argtpes.length, varargsStar, tuplingAllowed = true)
+ )
}
- /** Assign <code>tree</code> the type of an alternative which is applicable
- * to <code>argtpes</code>, and whose result type is compatible with `pt`.
+ /** Assign `tree` the type of an alternative which is applicable
+ * to `argtpes`, and whose result type is compatible with `pt`.
* If several applicable alternatives exist, drop the alternatives which use
* default arguments, then select the most specialized one.
* If no applicable alternative exists, and pt != WildcardType, try again
@@ -1586,43 +1606,38 @@ trait Infer extends Checkable {
* of some NamedType does not exist in an alternative's parameter names,
* the type is replaces by `Unit`, i.e. the argument is treated as an
* assignment expression.
+ *
+ * @pre tree.tpe is an OverloadedType.
*/
- def inferMethodAlternative(tree: Tree, undetparams: List[Symbol],
- argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false, lastInferAttempt: Boolean = true): Unit = tree.tpe match {
- case OverloadedType(pre, alts) =>
- val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
- tryTwice { isSecondTry =>
- debuglog("infer method alt "+ tree.symbol +" with alternatives "+
- (alts map pre.memberType) +", argtpes = "+ argtpes +", pt = "+ pt)
-
- val applicable = resolveOverloadedMethod(argtpes, {
- alts filter { alt =>
- inSilentMode(context)(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) &&
- (!varArgsOnly || isVarArgsList(alt.tpe.params))
- }
- })
-
- def improves(sym1: Symbol, sym2: Symbol) = {
- // util.trace("improve "+sym1+sym1.locationString+" on "+sym2+sym2.locationString)
- sym2 == NoSymbol || sym2.isError || sym2.hasAnnotation(BridgeClass) ||
- isStrictlyMoreSpecific(followApply(pre.memberType(sym1)),
- followApply(pre.memberType(sym2)), sym1, sym2)
- }
-
- val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) =>
- if (improves(alt, best)) alt else best)
- val competing = applicable.dropWhile(alt => best == alt || improves(best, alt))
- if (best == NoSymbol) {
- if (pt == WildcardType) NoBestMethodAlternativeError(tree, argtpes, pt, isSecondTry && lastInferAttempt)
- else inferMethodAlternative(tree, undetparams, argtpes, WildcardType, lastInferAttempt = isSecondTry)
- } else if (!competing.isEmpty) {
- AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt, isSecondTry && lastInferAttempt)
- } else {
-// checkNotShadowed(tree.pos, pre, best, applicable)
- tree.setSymbol(best).setType(pre.memberType(best))
- }
+ def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes0: List[Type], pt0: Type): Unit = {
+ val OverloadedType(pre, alts) = tree.tpe
+ var varargsStar = false
+ val argtpes = argtpes0 mapConserve {
+ case RepeatedType(tp) => varargsStar = true ; tp
+ case tp => tp
+ }
+ def followType(sym: Symbol) = followApply(pre memberType sym)
+ def bestForExpectedType(pt: Type, isLastTry: Boolean): Unit = {
+ val applicable0 = alts filter (alt => inSilentMode(context)(isApplicable(undetparams, followType(alt), argtpes, pt)))
+ val applicable = overloadsToConsiderBySpecificity(applicable0, argtpes, varargsStar)
+ val ranked = bestAlternatives(applicable)((sym1, sym2) =>
+ isStrictlyMoreSpecific(followType(sym1), followType(sym2), sym1, sym2)
+ )
+ ranked match {
+ case best :: competing :: _ => AmbiguousMethodAlternativeError(tree, pre, best, competing, argtpes, pt, isLastTry) // ambiguous
+ case best :: Nil => tree setSymbol best setType (pre memberType best) // success
+ case Nil if pt eq WildcardType => NoBestMethodAlternativeError(tree, argtpes, pt, isLastTry) // failed
+ case Nil => bestForExpectedType(WildcardType, isLastTry) // failed, but retry with WildcardType
}
- case _ =>
+ }
+ // This potentially makes up to four attempts: tryTwice may execute
+ // with and without views enabled, and bestForExpectedType will try again
+ // with pt = WildcardType if it fails with pt != WildcardType.
+ tryTwice { isLastTry =>
+ val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
+ debuglog(s"infer method alt ${tree.symbol} with alternatives ${alts map pre.memberType} argtpes=$argtpes pt=$pt")
+ bestForExpectedType(pt, isLastTry)
+ }
}
/** Try inference twice, once without views and once with views,
@@ -1663,8 +1678,8 @@ trait Infer extends Checkable {
else infer(true)
}
- /** Assign <code>tree</code> the type of all polymorphic alternatives
- * with <code>nparams</code> as the number of type parameters, if it exists.
+ /** Assign `tree` the type of all polymorphic alternatives
+ * with `nparams` as the number of type parameters, if it exists.
* If no such polymorphic alternative exist, error.
*
* @param tree ...
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index bcc37e8b37..2b78b37439 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -300,53 +300,51 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
private def macroImplSig(macroDef: Symbol, tparams: List[TypeDef], vparamss: List[List[ValDef]], retTpe: Type): (List[List[Symbol]], Type) = {
// had to move method's body to an object because of the recursive dependencies between sigma and param
object SigGenerator {
- def sigma(tpe: Type): Type = {
- class SigmaTypeMap extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- val pre1 = pre match {
- case ThisType(sym) if sym == macroDef.owner =>
- SingleType(SingleType(SingleType(NoPrefix, ctxParam), MacroContextPrefix), ExprValue)
- case SingleType(NoPrefix, sym) =>
- mfind(vparamss)(_.symbol == sym) match {
- case Some(macroDefParam) => SingleType(SingleType(NoPrefix, param(macroDefParam)), ExprValue)
- case _ => pre
- }
- case _ =>
- pre
- }
- TypeRef(pre1, sym, args map mapOver)
- case _ =>
- mapOver(tp)
- }
+ def WeakTagClass = getMember(MacroContextClass, tpnme.WeakTypeTag)
+ def ExprClass = getMember(MacroContextClass, tpnme.Expr)
+ val cache = scala.collection.mutable.Map[Symbol, Symbol]()
+ val ctxParam = makeParam(nme.macroContext, macroDef.pos, MacroContextClass.tpe, SYNTHETIC)
+ val paramss = List(ctxParam) :: mmap(vparamss)(param)
+ val implReturnType = typeRef(singleType(NoPrefix, ctxParam), ExprClass, List(sigma(retTpe)))
+
+ object SigmaTypeMap extends TypeMap {
+ def mapPrefix(pre: Type) = pre match {
+ case ThisType(sym) if sym == macroDef.owner =>
+ singleType(singleType(singleType(NoPrefix, ctxParam), MacroContextPrefix), ExprValue)
+ case SingleType(NoPrefix, sym) =>
+ mfind(vparamss)(_.symbol == sym).fold(pre)(p => singleType(singleType(NoPrefix, param(p)), ExprValue))
+ case _ =>
+ mapOver(pre)
+ }
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = mapPrefix(pre)
+ val args1 = mapOverArgs(args, sym.typeParams)
+ if ((pre eq pre1) && (args eq args1)) tp
+ else typeRef(pre1, sym, args1)
+ case _ =>
+ mapOver(tp)
}
-
- new SigmaTypeMap() apply tpe
}
+ def sigma(tpe: Type): Type = SigmaTypeMap(tpe)
- def makeParam(name: Name, pos: Position, tpe: Type, flags: Long = 0L) =
+ def makeParam(name: Name, pos: Position, tpe: Type, flags: Long) =
macroDef.newValueParameter(name, pos, flags) setInfo tpe
- val ctxParam = makeParam(nme.macroContext, macroDef.pos, MacroContextClass.tpe, SYNTHETIC)
- def implType(isType: Boolean, origTpe: Type): Type =
+ def implType(isType: Boolean, origTpe: Type): Type = {
+ def tsym = if (isType) WeakTagClass else ExprClass
+ def targ = origTpe.typeArgs.headOption getOrElse NoType
+
if (isRepeatedParamType(origTpe))
- appliedType(
- RepeatedParamClass.typeConstructor,
- List(implType(isType, sigma(origTpe.typeArgs.head))))
- else {
- val tsym = getMember(MacroContextClass, if (isType) tpnme.WeakTypeTag else tpnme.Expr)
+ scalaRepeatedType(implType(isType, sigma(targ)))
+ else
typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(origTpe)))
- }
- val paramCache = scala.collection.mutable.Map[Symbol, Symbol]()
- def param(tree: Tree): Symbol =
- paramCache.getOrElseUpdate(tree.symbol, {
+ }
+ def param(tree: Tree): Symbol = (
+ cache.getOrElseUpdate(tree.symbol, {
val sym = tree.symbol
- val sigParam = makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe))
- if (sym.isSynthetic) sigParam.flags |= SYNTHETIC
- sigParam
+ makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym getFlag SYNTHETIC)
})
-
- val paramss = List(ctxParam) :: mmap(vparamss)(param)
- val implRetTpe = typeRef(singleType(NoPrefix, ctxParam), getMember(MacroContextClass, tpnme.Expr), List(sigma(retTpe)))
+ )
}
import SigGenerator._
@@ -354,7 +352,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroTraceVerbose("tparams are: ")(tparams)
macroTraceVerbose("vparamss are: ")(vparamss)
macroTraceVerbose("retTpe is: ")(retTpe)
- macroTraceVerbose("macroImplSig is: ")((paramss, implRetTpe))
+ macroTraceVerbose("macroImplSig is: ")((paramss, implReturnType))
}
/** Verifies that the body of a macro def typechecks to a reference to a static public non-overloaded method,
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9e9a22d4d1..2c4034db84 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -159,6 +159,9 @@ trait Namers extends MethodSynthesis {
else innerNamer
}
+ // FIXME - this logic needs to be thoroughly explained
+ // and justified. I know it's wrong with repect to package
+ // objects, but I think it's also wrong in other ways.
protected def conflict(newS: Symbol, oldS: Symbol) = (
( !oldS.isSourceMethod
|| nme.isSetterName(newS.name)
@@ -186,6 +189,19 @@ trait Namers extends MethodSynthesis {
/** Enter symbol into given scope and return symbol itself */
def enterInScope(sym: Symbol, scope: Scope): Symbol = {
+ // FIXME - this is broken in a number of ways.
+ //
+ // 1) If "sym" allows overloading, that is not itself sufficient to skip
+ // the check, because "prev.sym" also must allow overloading.
+ //
+ // 2) There is nothing which reconciles a package's scope with
+ // the package object's scope. This is the source of many bugs
+ // with e.g. defining a case class in a package object. When
+ // compiling against classes, the class symbol is created in the
+ // package and in the package object, and the conflict is undetected.
+ // There is also a non-deterministic outcome for situations like
+ // an object with the same name as a method in the package object.
+
// allow for overloaded methods
if (!allowsOverload(sym)) {
val prev = scope.lookupEntry(sym.name)
@@ -596,7 +612,7 @@ trait Namers extends MethodSynthesis {
// via "x$lzy" as can be seen in test #3927.
val sym = (
if (owner.isClass) createFieldSymbol(tree)
- else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, tree.mods.flags & ~IMPLICIT)
+ else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, (tree.mods.flags | ARTIFACT) & ~IMPLICIT)
)
enterValSymbol(tree, sym setFlag MUTABLE setLazyAccessor lazyAccessor)
}
@@ -617,7 +633,7 @@ trait Namers extends MethodSynthesis {
case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) =>
assignAndEnterFinishedSymbol(tree)
case DefDef(mods, name, tparams, _, _, _) =>
- val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE else 0
+ val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0
val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag
if (name == nme.copy && sym.isSynthetic)
@@ -691,41 +707,55 @@ trait Namers extends MethodSynthesis {
// --- Lazy Type Assignment --------------------------------------------------
- def initializeLowerBounds(tp: Type): Type = {
+ def findCyclicalLowerBound(tp: Type): Symbol = {
tp match {
case TypeBounds(lo, _) =>
// check that lower bound is not an F-bound
- for (TypeRef(_, sym, _) <- lo)
- sym.initialize
+ // but carefully: class Foo[T <: Bar[_ >: T]] should be allowed
+ for (tp1 @ TypeRef(_, sym, _) <- lo) {
+ if (settings.breakCycles.value) {
+ if (!sym.maybeInitialize) {
+ log(s"Cycle inspecting $lo for possible f-bounds: ${sym.fullLocationString}")
+ return sym
+ }
+ }
+ else sym.initialize
+ }
case _ =>
}
- tp
+ NoSymbol
}
def monoTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym =>
+ // this early test is there to avoid infinite baseTypes when
+ // adding setters and getters --> bug798
+ // It is a def in an attempt to provide some insulation against
+ // uninitialized symbols misleading us. It is not a certainty
+ // this accomplishes anything, but performance is a non-consideration
+ // on these flag checks so it can't hurt.
+ def needsCycleCheck = sym.isNonClassType && !sym.isParameter && !sym.isExistential
logAndValidate(sym) {
- val tp = initializeLowerBounds(typeSig(tree))
+ val tp = typeSig(tree)
+
+ findCyclicalLowerBound(tp) andAlso { sym =>
+ if (needsCycleCheck) {
+ // neg/t1224: trait C[T] ; trait A { type T >: C[T] <: C[C[T]] }
+ // To avoid an infinite loop on the above, we cannot break all cycles
+ log(s"Reinitializing info of $sym to catch any genuine cycles")
+ sym reset sym.info
+ sym.initialize
+ }
+ }
sym setInfo {
if (sym.isJavaDefined) RestrictJavaArraysMap(tp)
else tp
}
- // this early test is there to avoid infinite baseTypes when
- // adding setters and getters --> bug798
- val needsCycleCheck = (sym.isAliasType || sym.isAbstractType) && !sym.isParameter
- if (needsCycleCheck && !typer.checkNonCyclic(tree.pos, tp))
- sym setInfo ErrorType
+ if (needsCycleCheck) {
+ log(s"Needs cycle check: ${sym.debugLocationString}")
+ if (!typer.checkNonCyclic(tree.pos, tp))
+ sym setInfo ErrorType
+ }
}
- // tree match {
- // case ClassDef(_, _, _, impl) =>
- // val parentsOK = (
- // treeInfo.isInterface(sym, impl.body)
- // || (sym eq ArrayClass)
- // || (sym isSubClass AnyValClass)
- // )
- // if (!parentsOK)
- // ensureParent(sym, AnyRefClass)
- // case _ => ()
- // }
}
def moduleClassTypeCompleter(tree: ModuleDef) = {
@@ -784,7 +814,7 @@ trait Namers extends MethodSynthesis {
false
}
- val tpe1 = dropRepeatedParamType(tpe.deconst)
+ val tpe1 = dropIllegalStarTypes(tpe.deconst)
val tpe2 = tpe1.widen
// This infers Foo.type instead of "object Foo"
@@ -832,7 +862,7 @@ trait Namers extends MethodSynthesis {
val sym = (
if (hasType || hasName) {
- owner.typeOfThis = if (hasType) selfTypeCompleter(tpt) else owner.tpe
+ owner.typeOfThis = if (hasType) selfTypeCompleter(tpt) else owner.tpe_*
val selfSym = owner.thisSym setPos self.pos
if (hasName) selfSym setName name else selfSym
}
@@ -918,7 +948,7 @@ trait Namers extends MethodSynthesis {
// DEPMETTODO: do we need to skolemize value parameter symbols?
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) {
- tpt defineType context.enclClass.owner.tpe
+ tpt defineType context.enclClass.owner.tpe_*
tpt setPos meth.pos.focus
}
var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe
@@ -1259,8 +1289,8 @@ trait Namers extends MethodSynthesis {
if (!annotated.isInitialized) tree match {
case defn: MemberDef =>
val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann =>
- // need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892.
- AnnotationInfo lazily beforeTyper(typer typedAnnotation ann)
+ // need to be lazy, #1782. enteringTyper to allow inferView in annotation args, SI-5892.
+ AnnotationInfo lazily enteringTyper(typer typedAnnotation ann)
}
if (ainfos.nonEmpty) {
annotated setAnnotations ainfos
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 7ba198a9f2..74acaba74a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -164,7 +164,7 @@ trait NamesDefaults { self: Analyzer =>
// never used for constructor calls, they always have a stable qualifier
def blockWithQualifier(qual: Tree, selected: Name) = {
- val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe
+ val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo qual.tpe
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
// it stays in Vegas: SI-5720, SI-5727
@@ -281,7 +281,7 @@ trait NamesDefaults { self: Analyzer =>
}
else arg.tpe
).widen // have to widen or types inferred from literal defaults will be singletons
- val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos) setInfo (
+ val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo (
if (byName) functionType(Nil, argTpe) else argTpe
)
(context.scope.enter(s), byName, repeated)
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index de8685ab78..21e2b7ceec 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -70,7 +70,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
def newTransformer(unit: CompilationUnit): Transformer =
- if (opt.virtPatmat) new MatchTransformer(unit)
+ if (!settings.XoldPatmat.value) new MatchTransformer(unit)
else noopTransformer
// duplicated from CPSUtils (avoid dependency from compiler -> cps plugin...)
@@ -192,7 +192,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
trait MatchTranslation extends MatchMonadInterface { self: TreeMakers with CodegenCore =>
import typer.{typed, context, silent, reallyExists}
- // import typer.infer.containsUnchecked
// Why is it so difficult to say "here's a name and a context, give me any
// matching symbol in scope" ? I am sure this code is wrong, but attempts to
@@ -2543,7 +2542,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
val toString =
- if (p.hasSymbol && p.symbol.isStable) p.symbol.name.toString // tp.toString
+ if (p.hasSymbolField && p.symbol.isStable) p.symbol.name.toString // tp.toString
else p.toString //+"#"+ id
Const.unique(narrowTp, new ValueConst(narrowTp, checkableType(wideTp), toString)) // must make wide type checkable so that it is comparable to types from TypeConst
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index e3f694f724..dacb68ea86 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -60,23 +60,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
super.transformInfo(sym, tp)
}
- val toJavaRepeatedParam = new TypeMap {
- def apply(tp: Type) = tp match {
- case TypeRef(pre, RepeatedParamClass, args) =>
- typeRef(pre, JavaRepeatedParamClass, args)
- case _ =>
- mapOver(tp)
- }
- }
-
- val toScalaRepeatedParam = new TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, JavaRepeatedParamClass, args) =>
- typeRef(pre, RepeatedParamClass, args)
- case _ =>
- mapOver(tp)
- }
- }
+ val toJavaRepeatedParam = new SubstSymMap(RepeatedParamClass -> JavaRepeatedParamClass)
+ val toScalaRepeatedParam = new SubstSymMap(JavaRepeatedParamClass -> RepeatedParamClass)
def accessFlagsToString(sym: Symbol) = flagsToString(
sym getFlag (PRIVATE | PROTECTED),
@@ -156,27 +141,22 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// Override checking ------------------------------------------------------------
- def isJavaVarargsAncestor(clazz: Symbol) = (
- clazz.isClass
- && clazz.isJavaDefined
- && (clazz.info.nonPrivateDecls exists isJavaVarArgsMethod)
- )
-
/** Add bridges for vararg methods that extend Java vararg methods
*/
def addVarargBridges(clazz: Symbol): List[Tree] = {
// This is quite expensive, so attempt to skip it completely.
// Insist there at least be a java-defined ancestor which
// defines a varargs method. TODO: Find a cheaper way to exclude.
- if (clazz.thisType.baseClasses exists isJavaVarargsAncestor) {
+ if (inheritsJavaVarArgsMethod(clazz)) {
log("Found java varargs ancestor in " + clazz.fullLocationString + ".")
val self = clazz.thisType
val bridges = new ListBuffer[Tree]
def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
- log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe)
+ log(s"Generating varargs bridge for ${member.fullLocationString} of type $bridgetpe")
- val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE) setPos clazz.pos
+ val newFlags = (member.flags | VBRIDGE | ARTIFACT) & ~PRIVATE
+ val bridge = member.cloneSymbolImpl(clazz, newFlags) setPos clazz.pos
bridge.setInfo(bridgetpe.cloneInfo(bridge))
clazz.info.decls enter bridge
@@ -189,26 +169,35 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
localTyper typed DefDef(bridge, body)
}
- // For all concrete non-private members that have a (Scala) repeated parameter:
- // compute the corresponding method type `jtpe` with a Java repeated parameter
+ // For all concrete non-private members (but: see below) that have a (Scala) repeated
+ // parameter: compute the corresponding method type `jtpe` with a Java repeated parameter
// if a method with type `jtpe` exists and that method is not a varargs bridge
// then create a varargs bridge of type `jtpe` that forwards to the
// member method with the Scala vararg type.
- for (member <- clazz.info.nonPrivateMembers) {
+ //
+ // @PP: Can't call nonPrivateMembers because we will miss refinement members,
+ // which have been marked private. See SI-4729.
+ for (member <- nonTrivialMembers(clazz)) {
+ log(s"Considering $member for java varargs bridge in $clazz")
if (!member.isDeferred && member.isMethod && hasRepeatedParam(member.info)) {
val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE)
+
// Delaying calling memberType as long as possible
if (inherited ne NoSymbol) {
- val jtpe = toJavaRepeatedParam(self.memberType(member))
+ val jtpe = toJavaRepeatedParam(self memberType member)
// this is a bit tortuous: we look for non-private members or bridges
// if we find a bridge everything is OK. If we find another member,
// we need to create a bridge
- if (inherited filter (sym => (self.memberType(sym) matches jtpe) && !(sym hasFlag VBRIDGE)) exists)
+ val inherited1 = inherited filter (sym => !(sym hasFlag VBRIDGE) && (self memberType sym matches jtpe))
+ if (inherited1.exists)
bridges += varargBridge(member, jtpe)
}
}
}
+ if (bridges.size > 0)
+ log(s"Adding ${bridges.size} bridges for methods extending java varargs.")
+
bridges.toList
}
else Nil
@@ -556,13 +545,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp))
val tp1 = uncurryAndErase(clazz.thisType.memberType(sym))
val tp2 = uncurryAndErase(clazz.thisType.memberType(other))
- afterErasure(tp1 matches tp2)
+ exitingErasure(tp1 matches tp2)
})
def ignoreDeferred(member: Symbol) = (
(member.isAbstractType && !member.isFBounded) || (
member.isJavaDefined &&
- // the test requires afterErasure so shouldn't be
+ // the test requires exitingErasure so shouldn't be
// done if the compiler has no erasure phase available
(currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol)
)
@@ -905,13 +894,14 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
* the type occurs itself at variance position given by `variance`
*/
def validateVariance(tp: Type, variance: Int): Unit = tp match {
- case ErrorType => ;
- case WildcardType => ;
- case NoType => ;
- case NoPrefix => ;
- case ThisType(_) => ;
- case ConstantType(_) => ;
- // case DeBruijnIndex(_, _) => ;
+ case ErrorType =>
+ case WildcardType =>
+ case BoundedWildcardType(bounds) =>
+ validateVariance(bounds, variance)
+ case NoType =>
+ case NoPrefix =>
+ case ThisType(_) =>
+ case ConstantType(_) =>
case SingleType(pre, sym) =>
validateVariance(pre, variance)
case TypeRef(pre, sym, args) =>
@@ -1272,7 +1262,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case vsym => ValDef(vsym)
}
}
- def createStaticModuleAccessor() = afterRefchecks {
+ def createStaticModuleAccessor() = exitingRefchecks {
val method = (
sym.owner.newMethod(sym.name.toTermName, sym.pos, (sym.flags | STABLE) & ~MODULE)
setInfoAndEnter NullaryMethodType(sym.moduleClass.tpe)
@@ -1283,7 +1273,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
vdef,
localTyper.typedPos(tree.pos) {
val vsym = vdef.symbol
- afterRefchecks {
+ exitingRefchecks {
val rhs = gen.newModule(sym, vsym.tpe)
val body = if (sym.owner.isTrait) rhs else gen.mkAssignAndReturn(vsym, rhs)
DefDef(sym, body.changeOwner(vsym -> sym))
@@ -1455,8 +1445,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
private def isRepeatedParamArg(tree: Tree) = currentApplication match {
case Apply(fn, args) =>
- !args.isEmpty && (args.last eq tree) &&
- fn.tpe.params.length == args.length && isRepeatedParamType(fn.tpe.params.last.tpe)
+ ( args.nonEmpty
+ && (args.last eq tree)
+ && (fn.tpe.params.length == args.length)
+ && isRepeatedParamType(fn.tpe.params.last.tpe)
+ )
case _ =>
false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 981ba10183..2306575d74 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -60,8 +60,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val clazz = qual.symbol
val supername = nme.superName(name)
val superAcc = clazz.info.decl(supername).suchThat(_.alias == sym) orElse {
- debuglog("add super acc " + sym + sym.locationString + " to `" + clazz);//debug
- val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE) setAlias sym
+ debuglog(s"add super acc ${sym.fullLocationString} to $clazz")
+ val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | ARTIFACT) setAlias sym
val tpe = clazz.thisType memberType sym match {
case t if sym.isModule && !sym.isMethod => NullaryMethodType(t)
case t => t
@@ -293,7 +293,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
&& !sym.owner.isTrait
&& (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
&& (qual.symbol.info.member(sym.name) ne NoSymbol)
- && !needsProtectedAccessor(sym, tree.pos))
+ && !needsProtectedAccessor(sym, tree.pos)
+ )
if (shouldEnsureAccessor) {
log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass)
ensureAccessor(sel)
@@ -414,7 +415,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
val protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s)) orElse {
- val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos)
+ val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = ARTIFACT)
newAcc setInfoAndEnter accType(newAcc)
val code = DefDef(newAcc, {
@@ -425,7 +426,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
args.foldLeft(base)(Apply(_, _))
})
- debuglog("" + code)
+ debuglog("created protected accessor: " + code)
storeAccessorDefinition(clazz, code)
newAcc
}
@@ -437,7 +438,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case _ => mkApply(TypeApply(selection, targs))
}
}
- debuglog("Replaced " + tree + " with " + res)
+ debuglog(s"Replaced $tree with $res")
if (hasArgs) localTyper.typedOperator(res) else localTyper.typed(res)
}
@@ -476,7 +477,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val accName = nme.protSetterName(field.originalName)
val protectedAccessor = clazz.info decl accName orElse {
- val protAcc = clazz.newMethod(accName, field.pos)
+ val protAcc = clazz.newMethod(accName, field.pos, newFlags = ARTIFACT)
val paramTypes = List(clazz.typeOfThis, field.tpe)
val params = protAcc newSyntheticValueParams paramTypes
val accessorType = MethodType(params, UnitClass.tpe)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index cc3d980cf1..2bfad223f6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -77,7 +77,7 @@ trait SyntheticMethods extends ast.TreeDSL {
// like Tags and Arrays which are not robust and infer things
// which they shouldn't.
val accessorLub = (
- if (opt.experimental) {
+ if (settings.Xexperimental.value) {
global.weakLub(accessors map (_.tpe.finalResultType))._1 match {
case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents)
case tp => tp
diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala
index d82fbd7c77..45aa1bcbdb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala
@@ -10,7 +10,7 @@ trait Tags {
trait Tag {
self: Typer =>
- private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = beforeTyper {
+ private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = enteringTyper {
def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree))
wrapper(inferImplicit(
EmptyTree,
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 9bb88f152a..153fb76b3e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -278,7 +278,7 @@ abstract class TreeCheckers extends Analyzer {
def cond(s: Symbol) = !s.isTerm || s.isMethod || s == sym.owner
if (sym.owner != currentOwner) {
- val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse fail("DefTree can't find owner: ")
+ val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse { fail("DefTree can't find owner: ") ; NoSymbol }
if (sym.owner != expected)
fail("""|
| currentOwner chain: %s
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 236e523f3c..0cf8372ed7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -53,7 +53,7 @@ trait Typers extends Modes with Adaptations with Tags {
object UnTyper extends Traverser {
override def traverse(tree: Tree) = {
if (tree != EmptyTree) tree.tpe = null
- if (tree.hasSymbol) tree.symbol = NoSymbol
+ if (tree.hasSymbolField) tree.symbol = NoSymbol
super.traverse(tree)
}
}
@@ -91,7 +91,7 @@ trait Typers extends Modes with Adaptations with Tags {
// - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope)
// - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction
// this is disabled by: -Xoldpatmat or interactive compilation (we run it for scaladoc due to SI-5933)
- private def newPatternMatching = opt.virtPatmat && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id)
+ private def newPatternMatching = !settings.XoldPatmat.value && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id)
abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors {
import context0.unit
@@ -194,7 +194,7 @@ trait Typers extends Modes with Adaptations with Tags {
case PolyType(_, _) => EmptyTree
case _ =>
def wrapImplicit(from: Type): Tree = {
- val result = inferImplicit(tree, functionType(from :: Nil, to), reportAmbiguous, true, context, saveErrors)
+ val result = inferImplicit(tree, functionType(from.withoutAnnotations :: Nil, to), reportAmbiguous, true, context, saveErrors)
if (result.subst != EmptyTreeTypeSubstituter) {
result.subst traverse tree
notifyUndetparamsInferred(result.subst.from, result.subst.to)
@@ -242,7 +242,7 @@ trait Typers extends Modes with Adaptations with Tags {
* of its symbol was not volatile?
*/
protected def isStableExceptVolatile(tree: Tree) = {
- tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
+ tree.hasSymbolField && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
{ val savedTpe = tree.symbol.info
val savedSTABLE = tree.symbol getFlag STABLE
tree.symbol setInfo AnyRefClass.tpe
@@ -292,8 +292,7 @@ trait Typers extends Modes with Adaptations with Tags {
*/
def checkNonCyclic(pos: Position, tp: Type): Boolean = {
def checkNotLocked(sym: Symbol) = {
- sym.initialize
- sym.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false }
+ sym.initialize.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false }
}
tp match {
case TypeRef(pre, sym, args) =>
@@ -320,14 +319,14 @@ trait Typers extends Modes with Adaptations with Tags {
}
def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Boolean = try {
- if (!lockedSym.lock(CyclicReferenceError(pos, lockedSym))) false
+ if (!lockedSym.lock(CyclicReferenceError(pos, tp, lockedSym))) false
else checkNonCyclic(pos, tp)
} finally {
lockedSym.unlock()
}
def checkNonCyclic(sym: Symbol) {
- if (!checkNonCyclic(sym.pos, sym.tpe)) sym.setInfo(ErrorType)
+ if (!checkNonCyclic(sym.pos, sym.tpe_*)) sym.setInfo(ErrorType)
}
def checkNonCyclic(defn: Tree, tpt: Tree) {
@@ -599,23 +598,31 @@ trait Typers extends Modes with Adaptations with Tags {
}
/** Is `sym` defined in package object of package `pkg`?
+ * Since sym may be defined in some parent of the package object,
+ * we cannot inspect its owner only; we have to go through the
+ * info of the package object. However to avoid cycles we'll check
+ * what other ways we can before pushing that way.
*/
private def isInPackageObject(sym: Symbol, pkg: Symbol) = {
- def isInPkgObj(sym: Symbol) =
- !sym.owner.isPackage && {
- sym.owner.isPackageObjectClass &&
- sym.owner.owner == pkg ||
- pkg.isInitialized && {
- // need to be careful here to not get a cyclic reference during bootstrap
- val pkgobj = pkg.info.member(nme.PACKAGEkw)
- pkgobj.isInitialized &&
- (pkgobj.info.member(sym.name).alternatives contains sym)
- }
+ val pkgClass = if (pkg.isTerm) pkg.moduleClass else pkg
+ def matchesInfo = (
+ pkg.isInitialized && {
+ // need to be careful here to not get a cyclic reference during bootstrap
+ val module = pkg.info member nme.PACKAGEkw
+ module.isInitialized && (module.info.member(sym.name).alternatives contains sym)
}
- pkg.isPackageClass && {
+ )
+ def isInPkgObj(sym: Symbol) = (
+ !sym.isPackage
+ && !sym.owner.isPackageClass
+ && (sym.owner ne NoSymbol)
+ && (sym.owner.owner == pkgClass || matchesInfo)
+ )
+
+ pkgClass.isPackageClass && (
if (sym.isOverloaded) sym.alternatives forall isInPkgObj
else isInPkgObj(sym)
- }
+ )
}
/** Post-process an identifier or selection node, performing the following:
@@ -907,7 +914,7 @@ trait Typers extends Modes with Adaptations with Tags {
// but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else
// tree setType tree.tpe.normalize
tree
- } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) &&
+ } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) &&
!(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7)
// @M When not typing a higher-kinded type ((mode & HKmode) == 0)
// or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *,
@@ -915,7 +922,7 @@ trait Typers extends Modes with Adaptations with Tags {
// @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
MissingTypeParametersError(tree)
} else if ( // (7.1) @M: check kind-arity
- // @M: removed check for tree.hasSymbol and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
+ // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
(inHKMode(mode)) &&
// @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!!
// (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!)
@@ -1037,15 +1044,21 @@ trait Typers extends Modes with Adaptations with Tags {
def insertApply(): Tree = {
assert(!inHKMode(mode), modeString(mode)) //@M
- val qual = adaptToName(tree, nme.apply) match {
- case id @ Ident(_) =>
- val pre = if (id.symbol.owner.isPackageClass) id.symbol.owner.thisType
- else if (id.symbol.owner.isClass)
- context.enclosingSubClassContext(id.symbol.owner).prefix
- else NoPrefix
- stabilize(id, pre, EXPRmode | QUALmode, WildcardType)
- case sel @ Select(qualqual, _) =>
- stabilize(sel, qualqual.tpe, EXPRmode | QUALmode, WildcardType)
+ val adapted = adaptToName(tree, nme.apply)
+ def stabilize0(pre: Type): Tree = stabilize(adapted, pre, EXPRmode | QUALmode, WildcardType)
+ // TODO reconcile the overlap between Typers#stablize and TreeGen.stabilize
+ val qual = adapted match {
+ case This(_) =>
+ gen.stabilize(adapted)
+ case Ident(_) =>
+ val owner = adapted.symbol.owner
+ val pre =
+ if (owner.isPackageClass) owner.thisType
+ else if (owner.isClass) context.enclosingSubClassContext(owner).prefix
+ else NoPrefix
+ stabilize0(pre)
+ case Select(qualqual, _) =>
+ stabilize0(qualqual.tpe)
case other =>
other
}
@@ -1506,10 +1519,10 @@ trait Typers extends Modes with Adaptations with Tags {
// Determine
// - supertparams: Missing type parameters from supertype
// - supertpe: Given supertype, polymorphic in supertparams
- val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List()
+ val supertparams = if (supertpt.hasSymbolField) supertpt.symbol.typeParams else List()
var supertpe = supertpt.tpe
if (!supertparams.isEmpty)
- supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (_.tpeHK)))
+ supertpe = PolyType(supertparams, appliedType(supertpe.typeConstructor, supertparams map (_.tpeHK)))
// A method to replace a super reference by a New in a supercall
def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match {
@@ -1867,7 +1880,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
}
- treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe
+ treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe_*
}
/** Remove definition annotations from modifiers (they have been saved
@@ -1900,12 +1913,9 @@ trait Typers extends Modes with Adaptations with Tags {
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
checkNonCyclic(vdef, tpt1)
- if (sym.hasAnnotation(definitions.VolatileAttr)) {
- if (!sym.isMutable)
+ if (sym.hasAnnotation(definitions.VolatileAttr) && !sym.isMutable)
VolatileValueError(vdef)
- else if (sym.isFinal)
- FinalVolatileVarError(vdef)
- }
+
val rhs1 =
if (vdef.rhs.isEmpty) {
if (sym.isVariable && sym.owner.isTerm && !sym.isLazy && !isPastTyper)
@@ -2430,7 +2440,7 @@ trait Typers extends Modes with Adaptations with Tags {
val casesTyped = typedCases(cases, selectorTp, pt)
val (resTp, needAdapt) =
- if (opt.virtPatmat) ptOrLubPacked(casesTyped, pt)
+ if (!settings.XoldPatmat.value) ptOrLubPacked(casesTyped, pt)
else ptOrLub(casesTyped map (_.tpe), pt)
val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, resTp))
@@ -2446,7 +2456,7 @@ trait Typers extends Modes with Adaptations with Tags {
// TODO: add fallback __match sentinel to predef
val matchStrategy: Tree =
- if (!(newPatternMatching && opt.experimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
+ if (!(newPatternMatching && settings.Xexperimental.value && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match {
case SilentResultValue(ms) => ms
case _ => null
@@ -2691,16 +2701,13 @@ trait Typers extends Modes with Adaptations with Tags {
if (context.retyping) context.scope enter vparam.symbol
vparam.symbol
}
- val vparams = fun.vparams mapConserve (typedValDef)
- // for (vparam <- vparams) {
- // checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
- // }
+ val vparams = fun.vparams mapConserve typedValDef
val formals = vparamSyms map (_.tpe)
- val body1 = typed(fun.body, respt)
- val restpe = packedType(body1, fun.symbol).deconst.resultType
- val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe)
- // body = checkNoEscaping.locals(context.scope, restpe, body)
- treeCopy.Function(fun, vparams, body1).setType(funtpe)
+ val body1 = typed(fun.body, respt)
+ val restpe = packedType(body1, fun.symbol).deconst.resultType
+ val funtpe = appliedType(clazz, formals :+ restpe: _*)
+
+ treeCopy.Function(fun, vparams, body1) setType funtpe
}
}
}
@@ -2731,17 +2738,6 @@ trait Typers extends Modes with Adaptations with Tags {
case Some(imp1: Import) => imp1
case _ => log("unhandled import: "+imp+" in "+unit); imp
}
- private def isWarnablePureExpression(tree: Tree) = tree match {
- case EmptyTree | Literal(Constant(())) => false
- case _ =>
- !tree.isErrorTyped && (treeInfo isExprSafeToInline tree) && {
- val sym = tree.symbol
- (sym == null) || !(sym.isModule || sym.isLazy) || {
- debuglog("'Pure' but side-effecting expression in statement position: " + tree)
- false
- }
- }
- }
def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
val inBlock = exprOwner == context.owner
@@ -2778,7 +2774,7 @@ trait Typers extends Modes with Adaptations with Tags {
ConstructorsOrderError(stat)
}
- if (isWarnablePureExpression(result)) context.warning(stat.pos,
+ if (treeInfo.isPureExprForWarningPurposes(result)) context.warning(stat.pos,
"a pure expression does nothing in statement position; " +
"you may be omitting necessary parentheses"
)
@@ -2962,21 +2958,20 @@ trait Typers extends Modes with Adaptations with Tags {
def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree }
def preSelectOverloaded(fun: Tree): Tree = {
- if (fun.hasSymbol && fun.symbol.isOverloaded) {
+ if (fun.hasSymbolField && fun.symbol.isOverloaded) {
// remove alternatives with wrong number of parameters without looking at types.
- // less expensive than including them in inferMethodAlternatvie (see below).
+ // less expensive than including them in inferMethodAlternative (see below).
def shapeType(arg: Tree): Type = arg match {
case Function(vparams, body) =>
- functionType(vparams map (vparam => AnyClass.tpe), shapeType(body))
+ functionType(vparams map (_ => AnyClass.tpe), shapeType(body))
case AssignOrNamedArg(Ident(name), rhs) =>
NamedType(name, shapeType(rhs))
case _ =>
NothingClass.tpe
}
val argtypes = args map shapeType
- val pre = fun.symbol.tpe.prefix
-
- var sym = fun.symbol filter { alt =>
+ val pre = fun.symbol.tpe.prefix
+ var sym = fun.symbol filter { alt =>
// must use pt as expected type, not WildcardType (a tempting quick fix to #2665)
// now fixed by using isWeaklyCompatible in exprTypeArgs
// TODO: understand why exactly -- some types were not inferred anymore (`ant clean quick.bin` failed)
@@ -2987,16 +2982,15 @@ trait Typers extends Modes with Adaptations with Tags {
// Types: "refs = Array(Map(), Map())". I determined that inference fails if there are at
// least two invariant type parameters. See the test case I checked in to help backstop:
// pos/isApplicableSafe.scala.
- isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt)
+ isApplicableSafe(context.undetparams, followApply(pre memberType alt), argtypes, pt)
}
if (sym.isOverloaded) {
- val sym1 = sym filter (alt => {
- // eliminate functions that would result from tupling transforms
- // keeps alternatives with repeated params
- hasExactlyNumParams(followApply(alt.tpe), argtypes.length) ||
- // also keep alts which define at least one default
- alt.tpe.paramss.exists(_.exists(_.hasDefault))
- })
+ // eliminate functions that would result from tupling transforms
+ // keeps alternatives with repeated params
+ val sym1 = sym filter (alt =>
+ isApplicableBasedOnArity(pre memberType alt, argtypes.length, varargsStar = false, tuplingAllowed = false)
+ || alt.tpe.params.exists(_.hasDefault)
+ )
if (sym1 != NoSymbol) sym = sym1
}
if (sym == NoSymbol) fun
@@ -3010,16 +3004,19 @@ trait Typers extends Modes with Adaptations with Tags {
case OverloadedType(pre, alts) =>
def handleOverloaded = {
val undetparams = context.extractUndetparams()
-
- val argtpes = new ListBuffer[Type]
- val amode = forArgMode(fun, mode)
+ val argtpes = new ListBuffer[Type]
+ val amode = forArgMode(fun, mode)
val args1 = args map {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
// named args: only type the righthand sides ("unknown identifier" errors otherwise)
val rhs1 = typedArg(rhs, amode, BYVALmode, WildcardType)
argtpes += NamedType(name, rhs1.tpe.deconst)
// the assign is untyped; that's ok because we call doTypedApply
- atPos(arg.pos) { new AssignOrNamedArg(arg.lhs, rhs1) }
+ treeCopy.AssignOrNamedArg(arg, arg.lhs, rhs1)
+ case arg @ Typed(repeated, Ident(tpnme.WILDCARD_STAR)) =>
+ val arg1 = typedArg(arg, amode, BYVALmode, WildcardType)
+ argtpes += RepeatedType(arg1.tpe.deconst)
+ arg1
case arg =>
val arg1 = typedArg(arg, amode, BYVALmode, WildcardType)
argtpes += arg1.tpe.deconst
@@ -3029,7 +3026,7 @@ trait Typers extends Modes with Adaptations with Tags {
if (context.hasErrors)
setError(tree)
else {
- inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
+ inferMethodAlternative(fun, undetparams, argtpes.toList, pt)
doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
}
}
@@ -3038,17 +3035,16 @@ trait Typers extends Modes with Adaptations with Tags {
case mt @ MethodType(params, _) =>
val paramTypes = mt.paramTypes
// repeat vararg as often as needed, remove by-name
- val formals = formalTypes(paramTypes, args.length)
+ val argslen = args.length
+ val formals = formalTypes(paramTypes, argslen)
/** Try packing all arguments into a Tuple and apply `fun`
* to that. This is the last thing which is tried (after
* default arguments)
*/
def tryTupleApply: Option[Tree] = {
- // if 1 formal, 1 arg (a tuple), otherwise unmodified args
- val tupleArgs = actualArgs(tree.pos.makeTransparent, args, formals.length)
-
- if (!sameLength(tupleArgs, args) && !isUnitForVarArgs(args, params)) {
+ if (eligibleForTupleConversion(paramTypes, argslen) && !phase.erasedTypes) {
+ val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args)))
// expected one argument, but got 0 or >1 ==> try applying to tuple
// the inner "doTypedApply" does "extractUndetparams" => restore when it fails
val savedUndetparams = context.undetparams
@@ -3243,15 +3239,14 @@ trait Typers extends Modes with Adaptations with Tags {
} else arg1
}
val args1 = map2(args, formals)(typedArgToPoly)
- if (args1 exists { _.isErrorTyped }) duplErrTree
+ if (args1 exists {_.isErrorTyped}) duplErrTree
else {
- debuglog("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(_.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(_.tpe.bounds.lo) + ", parambounds = " + tparams.map(_.info)) //debug
+ debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug
// define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
// returns those undetparams which have not been instantiated.
val undetparams = inferMethodInstance(fun, tparams, args1, pt)
- val result = doTypedApply(tree, fun, args1, mode, pt)
- context.undetparams = undetparams
- result
+ try doTypedApply(tree, fun, args1, mode, pt)
+ finally context.undetparams = undetparams
}
}
handlePolymorphicCall
@@ -3365,25 +3360,26 @@ trait Typers extends Modes with Adaptations with Tags {
// println(util.Position.formatMessage(uncheckedPattern.pos, "made unchecked type test into a checked one", true))
val args = List(uncheckedPattern)
+ val app = atPos(uncheckedPattern.pos)(Apply(classTagExtractor, args))
// must call doTypedUnapply directly, as otherwise we get undesirable rewrites
// and re-typechecks of the target of the unapply call in PATTERNmode,
// this breaks down when the classTagExtractor (which defineds the unapply member) is not a simple reference to an object,
// but an arbitrary tree as is the case here
- doTypedUnapply(Apply(classTagExtractor, args), classTagExtractor, classTagExtractor, args, PATTERNmode, pt)
- }
+ doTypedUnapply(app, classTagExtractor, classTagExtractor, args, PATTERNmode, pt)
+ }
// if there's a ClassTag that allows us to turn the unchecked type test for `pt` into a checked type test
// return the corresponding extractor (an instance of ClassTag[`pt`])
- def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (!opt.virtPatmat || isPastTyper) None else {
+ def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (settings.XoldPatmat.value || isPastTyper) None else {
// only look at top-level type, can't (reliably) do anything about unchecked type args (in general)
pt.normalize.typeConstructor match {
// if at least one of the types in an intersection is checkable, use the checkable ones
// this avoids problems as in run/matchonseq.scala, where the expected type is `Coll with scala.collection.SeqLike`
// Coll is an abstract type, but SeqLike of course is not
- case RefinedType(parents, _) if (parents.length >= 2) && (parents.exists(tp => !infer.containsUnchecked(tp))) =>
+ case RefinedType(ps, _) if ps.length > 1 && (ps exists infer.isCheckable) =>
None
- case ptCheckable if infer.containsUnchecked(ptCheckable) =>
+ case ptCheckable if infer isUncheckable ptCheckable =>
val classTagExtractor = resolveClassTag(pos, ptCheckable)
if (classTagExtractor != EmptyTree && unapplyMember(classTagExtractor.tpe) != NoSymbol)
@@ -3547,35 +3543,23 @@ trait Typers extends Modes with Adaptations with Tags {
// local dummy fixes SI-5544
val localTyper = newTyper(context.make(ann, context.owner.newLocalDummy(ann.pos)))
localTyper.typed(ann, mode, annClass.tpe)
- } else {
- // Since a selfsym is supplied, the annotation should have
- // an extra "self" identifier in scope for type checking.
- // This is implemented by wrapping the rhs
- // in a function like "self => rhs" during type checking,
- // and then stripping the "self =>" and substituting
- // in the supplied selfsym.
+ }
+ else {
+ // Since a selfsym is supplied, the annotation should have an extra
+ // "self" identifier in scope for type checking. This is implemented
+ // by wrapping the rhs in a function like "self => rhs" during type
+ // checking, and then stripping the "self =>" and substituting in
+ // the supplied selfsym.
val funcparm = ValDef(NoMods, nme.self, TypeTree(selfsym.info), EmptyTree)
- val func = Function(List(funcparm), ann.duplicate)
- // The .duplicate of annot.constr
- // deals with problems that
- // accur if this annotation is
- // later typed again, which
- // the compiler sometimes does.
- // The problem is that "self"
- // ident's within annot.constr
- // will retain the old symbol
- // from the previous typing.
- val fun1clazz = FunctionClass(1)
- val funcType = typeRef(fun1clazz.tpe.prefix,
- fun1clazz,
- List(selfsym.info, annClass.tpe))
-
- (typed(func, mode, funcType): @unchecked) match {
- case t @ Function(List(arg), rhs) =>
- val subs =
- new TreeSymSubstituter(List(arg.symbol),List(selfsym))
- subs(rhs)
- }
+ // The .duplicate of annot.constr deals with problems that accur
+ // if this annotation is later typed again, which the compiler
+ // sometimes does. The problem is that "self" ident's within
+ // annot.constr will retain the old symbol from the previous typing.
+ val func = Function(funcparm :: Nil, ann.duplicate)
+ val funcType = appliedType(FunctionClass(1), selfsym.info, annClass.tpe_*)
+ val Function(arg :: Nil, rhs) = typed(func, mode, funcType)
+
+ rhs.substituteSymbols(arg.symbol :: Nil, selfsym :: Nil)
}
def annInfo(t: Tree): AnnotationInfo = t match {
@@ -4098,7 +4082,7 @@ trait Typers extends Modes with Adaptations with Tags {
if (name != tpnme.WILDCARD) namer.enterInScope(sym)
else context.scope.enter(sym)
- tree setSymbol sym setType sym.tpe
+ tree setSymbol sym setType sym.tpeHK
case name: TermName =>
val sym =
@@ -4194,7 +4178,7 @@ trait Typers extends Modes with Adaptations with Tags {
// in the special (though common) case where the types are equal, it pays to pack before comparing
// especially virtpatmat needs more aggressive unification of skolemized types
// this breaks src/library/scala/collection/immutable/TrieIterator.scala
- if ( opt.virtPatmat && !isPastTyper
+ if ( !settings.XoldPatmat.value && !isPastTyper
&& thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this)
&& thenTp =:= elseTp
) (thenp1.tpe.deconst, false) // use unpacked type. Important to deconst, as is done in ptOrLub, otherwise `if (???) 0 else 0` evaluates to 0 (SI-6331)
@@ -4267,7 +4251,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tpt1 = {
val tpt0 = typedTypeConstructor(tpt)
if (checkStablePrefixClassType(tpt0))
- if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
+ if (tpt0.hasSymbolField && !tpt0.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
notifyUndetparamsAdded(context.undetparams)
TypeTree().setOriginal(tpt0)
@@ -4297,7 +4281,7 @@ trait Typers extends Modes with Adaptations with Tags {
NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR)
setError(tpt)
}
- else if (!( tp == sym.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable
+ else if (!( tp == sym.thisSym.tpe_* // when there's no explicit self type -- with (#3612) or without self variable
// sym.thisSym.tpe == tp.typeOfThis (except for objects)
|| narrowRhs(tp) <:< tp.typeOfThis
|| phase.erasedTypes
@@ -4479,12 +4463,12 @@ trait Typers extends Modes with Adaptations with Tags {
else doTypedApply(tree, fun2, args, mode, pt)
/*
- if (fun2.hasSymbol && fun2.symbol.isConstructor && (mode & EXPRmode) != 0) {
+ if (fun2.hasSymbolField && fun2.symbol.isConstructor && (mode & EXPRmode) != 0) {
res.tpe = res.tpe.notNull
}
*/
// TODO: In theory we should be able to call:
- //if (fun2.hasSymbol && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
+ //if (fun2.hasSymbolField && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
// But this causes cyclic reference for Array class in Cleanup. It is easy to overcome this
// by calling ArrayClass.info here (or some other place before specialize).
if (fun2.symbol == Array_apply && !res.isErrorTyped) {
@@ -4639,6 +4623,24 @@ trait Typers extends Modes with Adaptations with Tags {
* @return ...
*/
def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = {
+ val t = typedSelectInternal(tree, qual, name)
+ // Checking for OverloadedTypes being handed out after overloading
+ // resolution has already happened.
+ if (isPastTyper) t.tpe match {
+ case OverloadedType(pre, alts) =>
+ if (alts forall (s => (s.owner == ObjectClass) || (s.owner == AnyClass) || isPrimitiveValueClass(s.owner))) ()
+ else if (settings.debug.value) printCaller(
+ s"""|Select received overloaded type during $phase, but typer is over.
+ |If this type reaches the backend, we are likely doomed to crash.
+ |$t has these overloads:
+ |${alts map (s => " " + s.defStringSeenAs(pre memberType s)) mkString "\n"}
+ |""".stripMargin
+ )("")
+ case _ =>
+ }
+ t
+ }
+ def typedSelectInternal(tree: Tree, qual: Tree, name: Name): Tree = {
def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map { t =>
dyna.wrapErrors(t, (_.typed1(t, mode, pt)))
}
@@ -4825,6 +4827,22 @@ trait Typers extends Modes with Adaptations with Tags {
defSym = rootMirror.EmptyPackageClass.tpe.nonPrivateMember(name)
defSym != NoSymbol
}
+ def correctForPackageObject(sym: Symbol): Symbol = {
+ if (sym.isTerm && isInPackageObject(sym, pre.typeSymbol)) {
+ val sym1 = pre member sym.name
+ if ((sym1 eq NoSymbol) || (sym eq sym1)) sym else {
+ qual = gen.mkAttributedQualifier(pre)
+ log(s"""
+ | !!! Overloaded package object member resolved incorrectly.
+ | prefix: $pre
+ | Discarded: ${sym.defString}
+ | Using: ${sym1.defString}
+ """.stripMargin)
+ sym1
+ }
+ }
+ else sym
+ }
def startingIdentContext = (
// ignore current variable scope in patterns to enforce linearity
if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context
@@ -4836,11 +4854,11 @@ trait Typers extends Modes with Adaptations with Tags {
// which are methods (note: if we don't do that
// case x :: xs in class List would return the :: method)
// unless they are stable or are accessors (the latter exception is for better error messages).
- def qualifies(sym: Symbol): Boolean = {
- sym.hasRawInfo && // this condition avoids crashing on self-referential pattern variables
- reallyExists(sym) &&
- ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR))
- }
+ def qualifies(sym: Symbol): Boolean = (
+ sym.hasRawInfo // this condition avoids crashing on self-referential pattern variables
+ && reallyExists(sym)
+ && ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR))
+ )
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
@@ -4848,32 +4866,17 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
+ // !!! FIXME. This call to lookupEntry is at the root of all the
+ // bad behavior with overloading in package objects. lookupEntry
+ // just takes the first symbol it finds in scope, ignoring the rest.
+ // When a selection on a package object arrives here, the first
+ // overload is always chosen. "correctForPackageObject" exists to
+ // undo that decision. Obviously it would be better not to do it in
+ // the first place; however other things seem to be tied to obtaining
+ // that ScopeEntry, specifically calculating the nesting depth.
defEntry = cx.scope.lookupEntry(name)
- if ((defEntry ne null) && qualifies(defEntry.sym)) {
- // Right here is where SI-1987, overloading in package objects, can be
- // seen to go wrong. There is an overloaded symbol, but when referring
- // to the unqualified identifier from elsewhere in the package, only
- // the last definition is visible. So overloading mis-resolves and is
- // definition-order dependent, bad things. See run/t1987.scala.
- //
- // I assume the actual problem involves how/where these symbols are entered
- // into the scope. But since I didn't figure out how to fix it that way, I
- // catch it here by looking up package-object-defined symbols in the prefix.
- if (isInPackageObject(defEntry.sym, pre.typeSymbol)) {
- defSym = pre.member(defEntry.sym.name)
- if (defSym ne defEntry.sym) {
- qual = gen.mkAttributedQualifier(pre)
- log(s"""
- | !!! Overloaded package object member resolved incorrectly.
- | prefix: $pre
- | Discarded: ${defEntry.sym.defString}
- | Using: ${defSym.defString}
- """.stripMargin)
- }
- }
- else
- defSym = defEntry.sym
- }
+ if ((defEntry ne null) && qualifies(defEntry.sym))
+ defSym = correctForPackageObject(defEntry.sym)
else {
cx = cx.enclClass
val foundSym = pre.member(name) filter qualifies
@@ -5036,7 +5039,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tree3 = stabilize(tree2, pre2, mode, pt)
// SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
// inference errors in pattern matching.
- tree3 setType dropRepeatedParamType(tree3.tpe)
+ tree3 setType dropIllegalStarTypes(tree3.tpe)
}
}
}
@@ -5071,7 +5074,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
if (tpt1.isErrorTyped) {
tpt1
- } else if (!tpt1.hasSymbol) {
+ } else if (!tpt1.hasSymbolField) {
AppliedTypeNoParametersError(tree, tpt1.tpe)
} else {
val tparams = tpt1.symbol.typeParams
@@ -5180,14 +5183,12 @@ trait Typers extends Modes with Adaptations with Tags {
var block1 = typed(tree.block, pt)
var catches1 = typedCases(tree.catches, ThrowableClass.tpe, pt)
- for (cdef <- catches1 if cdef.guard.isEmpty) {
- def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.")
- def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- cdef.pat match {
- case Bind(name, i @ Ident(_)) if unbound(i) => warn(name)
- case i @ Ident(name) if unbound(i) => warn(name)
- case _ =>
- }
+ for (cdef <- catches1; if treeInfo catchesThrowable cdef) {
+ val name = (treeInfo assignedNameOfPattern cdef).decoded
+ context.warning(cdef.pat.pos,
+ s"""|This catches all Throwables, which often has undesirable consequences.
+ |If intentional, use `case $name : Throwable` to clear this warning.""".stripMargin
+ )
}
val finalizer1 =
@@ -5443,7 +5444,7 @@ trait Typers extends Modes with Adaptations with Tags {
if (context.retyping &&
(tree.tpe ne null) && (tree.tpe.isErroneous || !(tree.tpe <:< pt))) {
tree.tpe = null
- if (tree.hasSymbol) tree.symbol = NoSymbol
+ if (tree.hasSymbolField) tree.symbol = NoSymbol
}
alreadyTyped = tree.tpe ne null
diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
index b9f2b9abd8..279096bddd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
@@ -67,6 +67,8 @@ trait Variances {
def varianceInType(tp: Type)(tparam: Symbol): Int = tp match {
case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) =>
VARIANCES
+ case BoundedWildcardType(bounds) =>
+ varianceInType(bounds)(tparam)
case SingleType(pre, sym) =>
varianceInType(pre)(tparam)
case TypeRef(pre, sym, args) =>
diff --git a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
index 554a96d627..75774e3498 100644
--- a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
+++ b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
@@ -14,11 +14,6 @@ trait FreshNameCreator {
*/
def newName(): String
def newName(prefix: String): String
-
- @deprecated("use newName(prefix)", "2.9.0")
- def newName(pos: scala.reflect.internal.util.Position, prefix: String): String = newName(prefix)
- @deprecated("use newName()", "2.9.0")
- def newName(pos: scala.reflect.internal.util.Position): String = newName()
}
object FreshNameCreator {
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index d1f3183f68..787291b13c 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -94,7 +94,6 @@ object ShowPickled extends Names {
case ANNOTATEDtpe => "ANNOTATEDtpe"
case ANNOTINFO => "ANNOTINFO"
case ANNOTARGARRAY => "ANNOTARGARRAY"
- // case DEBRUIJNINDEXtpe => "DEBRUIJNINDEXtpe"
case EXISTENTIALtpe => "EXISTENTIALtpe"
case TREE => "TREE"
case MODIFIERS => "MODIFIERS"
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 95135b84e0..bc8ded62d8 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -102,7 +102,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
})
var expr = new Transformer {
override def transform(tree: Tree): Tree =
- if (tree.hasSymbol && tree.symbol.isFreeTerm) {
+ if (tree.hasSymbolField && tree.symbol.isFreeTerm) {
tree match {
case Ident(_) =>
val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTerm))
diff --git a/src/continuations/library/scala/util/continuations/package.scala b/src/continuations/library/scala/util/continuations/package.scala
index 641f4594e4..93238d50e1 100644
--- a/src/continuations/library/scala/util/continuations/package.scala
+++ b/src/continuations/library/scala/util/continuations/package.scala
@@ -167,7 +167,7 @@ package object continuations {
}
def shiftUnitR[A,B](x: A): ControlContext[A,B,B] = {
- new ControlContext(null, x)
+ new ControlContext[A, B, B](null, x)
}
/**
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index 15025f85e3..c147dc483d 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -96,7 +96,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes {
if (!cpsEnabled) return bounds
val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe)
- if (isFunctionType(tparams.head.owner.tpe) || isPartialFunctionType(tparams.head.owner.tpe)) {
+ if (isFunctionType(tparams.head.owner.tpe_*) || isPartialFunctionType(tparams.head.owner.tpe_*)) {
vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs)
if (hasCpsParamTypes(targs.last))
bounds.reverse match {
@@ -356,7 +356,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes {
global.globalError("not a single cps annotation: " + xs)
xs(0)
}
-
+
def emptyOrSingleList(xs: List[AnnotationInfo]) = if (xs.isEmpty) Nil else List(single(xs))
def transChildrenInOrder(tree: Tree, tpe: Type, childTrees: List[Tree], byName: List[Tree]) = {
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 46c644bcd6..eab442aaef 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -57,7 +57,7 @@ trait CPSUtils {
protected def newMarker(sym: Symbol): AnnotationInfo = AnnotationInfo marker sym.tpe
protected def newCpsParamsMarker(tp1: Type, tp2: Type) =
- newMarker(appliedType(MarkerCPSTypes.tpe, List(tp1, tp2)))
+ newMarker(appliedType(MarkerCPSTypes, tp1, tp2))
// annotation checker
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index 8b39bf3961..ef13f8b1d8 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -172,7 +172,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
debuglog("transforming valdef " + vd.symbol)
if (getExternalAnswerTypeAnn(tpt.tpe).isEmpty) {
-
+
atOwner(vd.symbol) {
val rhs1 = transExpr(rhs, None, None)
@@ -471,7 +471,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
val sym: Symbol = (
currentOwner.newValue(newTermName(unit.fresh.newName("tmp")), tree.pos, Flags.SYNTHETIC)
setInfo valueTpe
- setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil))
+ setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil))
)
expr.changeOwner(currentOwner -> sym)
@@ -503,9 +503,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
// TODO: better yet: do without annotations on symbols
val spcVal = getAnswerTypeAnn(anfRhs.tpe)
- if (spcVal.isDefined) {
- tree.symbol.setAnnotations(List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil)))
- }
+ spcVal foreach (_ => tree.symbol setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil)))
(stms:::List(treeCopy.ValDef(tree, mods, name, tpt, anfRhs)), linearize(spc, spcVal)(unit, tree.pos))
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 4482bf2b7c..f4b0fb0419 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -56,7 +56,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
case _ =>
getExternalAnswerTypeAnn(tp) match {
case Some((res, outer)) =>
- appliedType(Context.tpe, List(removeAllCPSAnnotations(tp), res, outer))
+ appliedType(Context.tpeHK, List(removeAllCPSAnnotations(tp), res, outer))
case _ =>
removeAllCPSAnnotations(tp)
}
@@ -107,7 +107,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
TypeApply(funR, List(targs(0), targs(1))).setType(appliedType(funR.tpe,
List(targs(0).tpe, targs(1).tpe))),
args.map(transform(_))
- ).setType(appliedType(Context.tpe, List(targs(0).tpe,targs(1).tpe,targs(1).tpe)))
+ ).setType(appliedType(Context.tpeHK, List(targs(0).tpe,targs(1).tpe,targs(1).tpe)))
}
case Apply(TypeApply(fun, targs), args)
@@ -192,7 +192,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val targettp = transformCPSType(tree.tpe)
val pos = catches.head.pos
- val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
+ val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass, ThrowableClass.tpe, targettp))
val funDef = localTyper.typedPos(pos) {
ValDef(funSym, Match(EmptyTree, catches1))
}
diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala
index 376a56beed..d56a7f0fbe 100644
--- a/src/detach/plugin/scala/tools/detach/Detach.scala
+++ b/src/detach/plugin/scala/tools/detach/Detach.scala
@@ -206,7 +206,7 @@ abstract class Detach extends PluginComponent
symSet(capturedObjects, owner) += qsym
case Select(qual, name)
- if (qual.hasSymbol &&
+ if (qual.hasSymbolField &&
(sym.owner != owner) &&
!(sym.ownerChain contains ScalaPackageClass) &&
!(sym.owner hasFlag JAVA)) =>
@@ -284,7 +284,7 @@ abstract class Detach extends PluginComponent
def isOuter(sym: Symbol): Boolean =
sym.isOuterAccessor ||
sym.name.endsWith(nme.OUTER/*, nme.OUTER.length*/)
- if (tree.hasSymbol && isOuter(tree.symbol)) subst(from, to)
+ if (tree.hasSymbolField && isOuter(tree.symbol)) subst(from, to)
super.traverse(tree)
}
}
@@ -293,7 +293,7 @@ abstract class Detach extends PluginComponent
private class TreeTypeRefSubstituter(clazz: Symbol) extends Traverser {
override def traverse(tree: Tree) {
val sym = tree.symbol
- if (tree.hasSymbol && isRefClass(sym.tpe) &&
+ if (tree.hasSymbolField && isRefClass(sym.tpe) &&
(sym.owner.enclClass == clazz) &&
(sym.isValueParameter || sym.hasFlag(PARAMACCESSOR))) {
sym setInfo mkRemoteRefClass(sym.tpe)
@@ -329,7 +329,7 @@ abstract class Detach extends PluginComponent
}
val map = new mutable.HashMap[Symbol, Symbol]
override def traverse(tree: Tree) {
- if (tree.hasSymbol && tree.symbol != NoSymbol) {
+ if (tree.hasSymbolField && tree.symbol != NoSymbol) {
val sym = tree.symbol
if (sym.owner == from) {
val sym1 = map get sym match {
@@ -369,7 +369,7 @@ abstract class Detach extends PluginComponent
def removeAccessors(tree: Tree): Tree = tree match {
case Apply(fun, _) =>
removeAccessors(fun)
- case Select(qual, _) if tree.hasSymbol && tree.symbol.isOuterAccessor =>
+ case Select(qual, _) if tree.hasSymbolField && tree.symbol.isOuterAccessor =>
removeAccessors(qual)
case _ =>
tree
@@ -382,7 +382,7 @@ abstract class Detach extends PluginComponent
// transforms field assignment $outer.i$1.elem=..
// into setter $outer.i$1_=(..)
case Assign(lhs @ Select(qual1 @ Select(qual, name), name1), rhs)
- if qual1.hasSymbol && !qual1.symbol.isPrivateLocal &&
+ if qual1.hasSymbolField && !qual1.symbol.isPrivateLocal &&
isRemoteRefClass(qual1.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Assign1\n\tqual1="+qual1+", sel.tpe="+lhs.tpe+
@@ -398,7 +398,7 @@ abstract class Detach extends PluginComponent
// transforms local assignment this.x$1.elem=..
// into setter method this.x$1_=(..)
case Assign(lhs @ Select(qual, name), rhs)
- if qual.hasSymbol && qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Assign2"+
@@ -412,7 +412,7 @@ abstract class Detach extends PluginComponent
Apply(fun, List(super.transform(rhs))) setType lhs.tpe
case Assign(Select(qual, name), rhs)
- if qual.hasSymbol && (objs contains qual.symbol) =>
+ if qual.hasSymbolField && (objs contains qual.symbol) =>
val sym = qual.symbol
val proxy = proxySyms(objs indexOf sym)
if (DEBUG)
@@ -461,7 +461,7 @@ abstract class Detach extends PluginComponent
// transforms field $outer.name$1 into getter method $outer.name$1()
case Select(qual @ Select(_, name1), name)
- if qual.hasSymbol && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) &&
+ if qual.hasSymbolField && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) &&
!tree.symbol.isMethod =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select0\n\tqual="+qual+
@@ -500,7 +500,7 @@ abstract class Detach extends PluginComponent
// transforms field access $outer.i$1.elem
// into invocation of getter method $outer.i$1()
case Select(qual @ Select(qual1, name1), name)
- if qual.hasSymbol && !qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && !qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select2\n\tqual="+qual+
@@ -513,7 +513,7 @@ abstract class Detach extends PluginComponent
// transforms local access this.i$1.elem
// into invocation of getter method this.i$1()
case Select(qual, name)
- if qual.hasSymbol && qual.symbol.isPrivateLocal &&
+ if qual.hasSymbolField && qual.symbol.isPrivateLocal &&
isRemoteRefClass(qual.tpe) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select3\n\tqual="+qual+
@@ -523,7 +523,7 @@ abstract class Detach extends PluginComponent
Apply(fun, List()) setType tree.tpe
case Select(qual, name)
- if qual.hasSymbol && (objs contains qual.symbol) =>
+ if qual.hasSymbolField && (objs contains qual.symbol) =>
if (DEBUG)
println("\nTreeAccessorSubstituter: Select4\n\tqual="+qual+
", qual.tpe="+qual.tpe+", name="+name)//debug
diff --git a/src/library/scala/Application.scala b/src/library/scala/Application.scala
deleted file mode 100644
index 5b1098bd72..0000000000
--- a/src/library/scala/Application.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala
-
-import scala.compat.Platform.currentTime
-
-/** The `Application` trait can be used to quickly turn objects
- * into executable programs, but is ''not recommended''.
- * Here is an example:
- * {{{
- * object Main extends Application {
- * Console.println("Hello World!")
- * }
- * }}}
- * Here, object `Main` inherits the `main` method of `Application`.
- * The body of the `Main` object defines the main program. This technique
- * does not work if the main program depends on command-line arguments
- * (which are not accessible with the technique presented here).
- *
- * It is possible to time the execution of objects that inherit from class
- * `Application` by setting the global `scala.time`
- * property. Here is an example for benchmarking object `Main`:
- * {{{
- * java -Dscala.time Main
- * }}}
- * In practice the `Application` trait has a number of serious pitfalls:
- *
- * - Threaded code that references the object will block until static
- * initialization is complete. However, because the entire execution
- * of an `object` extending `Application` takes place during
- * static initialization, concurrent code will ''always'' deadlock if
- * it must synchronize with the enclosing object.
- * - As described above, there is no way to obtain the
- * command-line arguments because all code in body of an `object`
- * extending `Application` is run as part of the static initialization
- * which occurs before `Application`'s `main` method
- * even begins execution.
- * - Static initializers are run only once during program execution, and
- * JVM authors usually assume their execution to be relatively short.
- * Therefore, certain JVM configurations may become confused, or simply
- * fail to optimize or JIT the code in the body of an `object` extending
- * `Application`. This can lead to a significant performance degradation.
- *
- * It is recommended to use the [[scala.App]] trait instead.
- * {{{
- * object Main {
- * def main(args: Array[String]) {
- * //..
- * }
- * }
- * }}}
- *
- * @author Matthias Zenger
- * @version 1.0, 10/09/2003
- */
-@deprecated("use App instead", "2.9.0")
-trait Application {
-
- /** The time when the execution of this program started,
- * in milliseconds since 1 January 1970 UTC. */
- val executionStart: Long = currentTime
-
- /** The default main method.
- *
- * @param args the arguments passed to the main method
- */
- def main(args: Array[String]) {
- if (util.Properties propIsSet "scala.time") {
- val total = currentTime - executionStart
- Console.println("[total " + total + "ms]")
- }
- }
-}
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
index 880f3f4623..755071a14f 100644
--- a/src/library/scala/Option.scala
+++ b/src/library/scala/Option.scala
@@ -209,6 +209,15 @@ sealed abstract class Option[+A] extends Product with Serializable {
def withFilter(q: A => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
}
+ /** Tests whether the option contains a given value as an element.
+ *
+ * @param elem the element to test.
+ * @return `true` if the option has an element that is equal (as
+ * determined by `==`) to `elem`, `false` otherwise.
+ */
+ final def contains[A1 >: A](elem: A1): Boolean =
+ !isEmpty && this.get == elem
+
/** Returns true if this option is nonempty '''and''' the predicate
* $p returns true when applied to this $option's value.
* Otherwise, returns false.
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala
index fb43d56020..4078168bb3 100644
--- a/src/library/scala/StringContext.scala
+++ b/src/library/scala/StringContext.scala
@@ -120,7 +120,7 @@ case class StringContext(parts: String*) {
val bldr = new java.lang.StringBuilder(process(pi.next()))
while (ai.hasNext) {
bldr append ai.next
- bldr append treatEscapes(pi.next())
+ bldr append process(pi.next())
}
bldr.toString
}
diff --git a/src/library/scala/UninitializedFieldError.scala b/src/library/scala/UninitializedFieldError.scala
index a6e510a849..9485019aa0 100644
--- a/src/library/scala/UninitializedFieldError.scala
+++ b/src/library/scala/UninitializedFieldError.scala
@@ -18,8 +18,6 @@ package scala
*
* @since 2.7
*/
-final case class UninitializedFieldError(msg: String)
- extends RuntimeException(msg) {
- def this(obj: Any) =
- this(if (null != obj) obj.toString() else "null")
+final case class UninitializedFieldError(msg: String) extends RuntimeException(msg) {
+ def this(obj: Any) = this("" + obj)
}
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index a872bc0948..9167280910 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -261,11 +261,12 @@ trait GenTraversableOnce[+A] extends Any {
* @tparam B the type of accumulated results
* @param z the initial value for the accumulated result of the partition - this
* will typically be the neutral element for the `seqop` operator (e.g.
- * `Nil` for list concatenation or `0` for summation)
+ * `Nil` for list concatenation or `0` for summation) and may be evaluated
+ * more than once
* @param seqop an operator used to accumulate results within a partition
* @param combop an associative operator used to combine results from different partitions
*/
- def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B
+ def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B
/** Applies a binary operator to all elements of this $coll, going right to left.
* $willNotTerminateInf
diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala
index 56dd0bffff..8918fbb6c8 100644
--- a/src/library/scala/collection/IndexedSeq.scala
+++ b/src/library/scala/collection/IndexedSeq.scala
@@ -6,8 +6,6 @@
** |/ **
\* */
-
-
package scala.collection
import generic._
@@ -28,8 +26,13 @@ trait IndexedSeq[+A] extends Seq[A]
* @define coll indexed sequence
* @define Coll `IndexedSeq`
*/
-object IndexedSeq extends SeqFactory[IndexedSeq] {
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
+object IndexedSeq extends IndexedSeqFactory[IndexedSeq] {
+ // A single CBF which can be checked against to identify
+ // an indexed collection type.
+ override val ReusableCBF: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] {
+ override def apply() = newBuilder[Nothing]
+ }
def newBuilder[A]: Builder[A, IndexedSeq[A]] = immutable.IndexedSeq.newBuilder[A]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
}
-
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 8e4fdf537d..173ce2d71d 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -91,42 +91,6 @@ object JavaConversions extends WrapAsScala with WrapAsJava {
@deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSeqWrapper = Wrappers.MutableSeqWrapper
@deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSetWrapper = Wrappers.MutableSetWrapper
@deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val SeqWrapper = Wrappers.SeqWrapper
-
- // Note to implementors: the cavalcade of deprecated methods herein should
- // serve as a warning to any who follow: don't overload implicit methods.
-
- @deprecated("use bufferAsJavaList instead", "2.9.0")
- def asJavaList[A](b : mutable.Buffer[A]): ju.List[A] = bufferAsJavaList[A](b)
-
- @deprecated("use mutableSeqAsJavaList instead", "2.9.0")
- def asJavaList[A](b : mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList[A](b)
-
- @deprecated("use seqAsJavaList instead", "2.9.0")
- def asJavaList[A](b : Seq[A]): ju.List[A] = seqAsJavaList[A](b)
-
- @deprecated("use mutableSetAsJavaSet instead", "2.9.0")
- def asJavaSet[A](s : mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet[A](s)
-
- @deprecated("use setAsJavaSet instead", "2.9.0")
- def asJavaSet[A](s: Set[A]): ju.Set[A] = setAsJavaSet[A](s)
-
- @deprecated("use mutableMapAsJavaMap instead", "2.9.0")
- def asJavaMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = mutableMapAsJavaMap[A, B](m)
-
- @deprecated("use mapAsJavaMap instead", "2.9.0")
- def asJavaMap[A, B](m : Map[A, B]): ju.Map[A, B] = mapAsJavaMap[A, B](m)
-
- @deprecated("use iterableAsScalaIterable instead", "2.9.0")
- def asScalaIterable[A](i : jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable[A](i)
-
- @deprecated("use collectionAsScalaIterable instead", "2.9.0")
- def asScalaIterable[A](i : ju.Collection[A]): Iterable[A] = collectionAsScalaIterable[A](i)
-
- @deprecated("use mapAsScalaMap instead", "2.9.0")
- def asScalaMap[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap[A, B](m)
-
- @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 f8a9466caf..98afffe3b4 100755
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -67,37 +67,4 @@ object JavaConverters extends DecorateAsJava with DecorateAsScala {
type AsJavaEnumeration[A] = Decorators.AsJavaEnumeration[A]
@deprecated("Don't access these decorators directly.", "2.10.0")
type AsJavaDictionary[A, B] = Decorators.AsJavaDictionary[A, B]
-
- @deprecated("Use bufferAsJavaListConverter instead", "2.9.0")
- def asJavaListConverter[A](b : mutable.Buffer[A]): AsJava[ju.List[A]] = bufferAsJavaListConverter(b)
-
- @deprecated("Use mutableSeqAsJavaListConverter instead", "2.9.0")
- def asJavaListConverter[A](b : mutable.Seq[A]): AsJava[ju.List[A]] = mutableSeqAsJavaListConverter(b)
-
- @deprecated("Use seqAsJavaListConverter instead", "2.9.0")
- def asJavaListConverter[A](b : Seq[A]): AsJava[ju.List[A]] = seqAsJavaListConverter(b)
-
- @deprecated("Use mutableSetAsJavaSetConverter instead", "2.9.0")
- def asJavaSetConverter[A](s : mutable.Set[A]): AsJava[ju.Set[A]] = mutableSetAsJavaSetConverter(s)
-
- @deprecated("Use setAsJavaSetConverter instead", "2.9.0")
- def asJavaSetConverter[A](s : Set[A]): AsJava[ju.Set[A]] = setAsJavaSetConverter(s)
-
- @deprecated("use mutableMapAsJavaMapConverter instead", "2.9.0")
- def asJavaMapConverter[A, B](m : mutable.Map[A, B]): AsJava[ju.Map[A, B]] = mutableMapAsJavaMapConverter(m)
-
- @deprecated("Use mapAsJavaMapConverter instead", "2.9.0")
- def asJavaMapConverter[A, B](m : Map[A, B]): AsJava[ju.Map[A, B]] = mapAsJavaMapConverter(m)
-
- @deprecated("Use iterableAsScalaIterableConverter instead", "2.9.0")
- def asScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] = iterableAsScalaIterableConverter(i)
-
- @deprecated("Use collectionAsScalaIterableConverter instead", "2.9.0")
- def asScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] = collectionAsScalaIterableConverter(i)
-
- @deprecated("Use mapAsScalaMapConverter instead", "2.9.0")
- def asScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] = mapAsScalaMapConverter(m)
-
- @deprecated("Use propertiesAsScalaMapConverter instead", "2.9.0")
- def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] = propertiesAsScalaMapConverter(p)
}
diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala
index 188e0e8afd..70d46b1cdc 100755
--- a/src/library/scala/collection/LinearSeqOptimized.scala
+++ b/src/library/scala/collection/LinearSeqOptimized.scala
@@ -83,7 +83,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
}
override /*SeqLike*/
- def contains(elem: Any): Boolean = {
+ def contains[A1 >: A](elem: A1): Boolean = {
var these = this
while (!these.isEmpty) {
if (these.head == elem) return true
diff --git a/src/library/scala/collection/Searching.scala b/src/library/scala/collection/Searching.scala
new file mode 100644
index 0000000000..33e50365ee
--- /dev/null
+++ b/src/library/scala/collection/Searching.scala
@@ -0,0 +1,116 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.collection
+
+import scala.annotation.tailrec
+import scala.collection.generic.IsSeqLike
+import scala.math.Ordering
+
+/** A collection of wrappers that provide sequence classes with search functionality.
+ *
+ * Example usage:
+ * {{{
+ * import scala.collection.Searching._
+ * val l = List(1, 2, 3, 4, 5)
+ * l.search(3)
+ * // == Found(2)
+ * }}}
+ */
+object Searching {
+ sealed abstract class SearchResult {
+ def insertionPoint: Int
+ }
+
+ case class Found(foundIndex: Int) extends SearchResult {
+ override def insertionPoint = foundIndex
+ }
+ case class InsertionPoint(insertionPoint: Int) extends SearchResult
+
+ class SearchImpl[A, Repr](val coll: SeqLike[A, Repr]) {
+ /** Search the sorted sequence for a specific element. If the sequence is an
+ * `IndexedSeq`, a binary search is used. Otherwise, a linear search is used.
+ *
+ * The sequence should be sorted with the same `Ordering` before calling; otherwise,
+ * the results are undefined.
+ *
+ * @see [[scala.collection.IndexedSeq]]
+ * @see [[scala.math.Ordering]]
+ * @see [[scala.collection.SeqLike]], method `sorted`
+ *
+ * @param elem the element to find.
+ * @param ord the ordering to be used to compare elements.
+ *
+ * @return a `Found` value containing the index corresponding to the element in the
+ * sequence, or the `InsertionPoint` where the element would be inserted if
+ * the element is not in the sequence.
+ */
+ final def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult =
+ coll match {
+ case _: IndexedSeq[A] => binarySearch(elem, -1, coll.length)(ord)
+ case _ => linearSearch(coll.view, elem, 0)(ord)
+ }
+
+ /** Search within an interval in the sorted sequence for a specific element. If the
+ * sequence is an IndexedSeq, a binary search is used. Otherwise, a linear search
+ * is used.
+ *
+ * The sequence should be sorted with the same `Ordering` before calling; otherwise,
+ * the results are undefined.
+ *
+ * @see [[scala.collection.IndexedSeq]]
+ * @see [[scala.math.Ordering]]
+ * @see [[scala.collection.SeqLike]], method `sorted`
+ *
+ * @param elem the element to find.
+ * @param from the index where the search starts.
+ * @param to the index following where the search ends.
+ * @param ord the ordering to be used to compare elements.
+ *
+ * @return a `Found` value containing the index corresponding to the element in the
+ * sequence, or the `InsertionPoint` where the element would be inserted if
+ * the element is not in the sequence.
+ */
+ final def search[B >: A](elem: B, from: Int, to: Int)
+ (implicit ord: Ordering[B]): SearchResult =
+ coll match {
+ case _: IndexedSeq[A] => binarySearch(elem, from-1, to)(ord)
+ case _ => linearSearch(coll.view(from, to), elem, from)(ord)
+ }
+
+ @tailrec
+ private def binarySearch[B >: A](elem: B, from: Int, to: Int)
+ (implicit ord: Ordering[B]): SearchResult = {
+ if ((to-from) == 1) InsertionPoint(from) else {
+ val idx = from+(to-from)/2
+ math.signum(ord.compare(elem, coll(idx))) match {
+ case -1 => binarySearch(elem, from, idx)(ord)
+ case 1 => binarySearch(elem, idx, to)(ord)
+ case _ => Found(idx)
+ }
+ }
+ }
+
+ private def linearSearch[B >: A](c: SeqView[A, Repr], elem: B, offset: Int)
+ (implicit ord: Ordering[B]): SearchResult = {
+ var idx = offset
+ val it = c.iterator
+ while (it.hasNext) {
+ val cur = it.next()
+ if (ord.equiv(elem, cur)) return Found(idx)
+ else if (ord.lt(elem, cur)) return InsertionPoint(idx-1)
+ idx += 1
+ }
+ InsertionPoint(idx)
+ }
+
+ }
+
+ implicit def search[Repr, A](coll: Repr)
+ (implicit fr: IsSeqLike[Repr]): SearchImpl[fr.A, Repr] = new SearchImpl(fr.conversion(coll))
+}
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index cda8b1a0e4..a1749a480b 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -386,7 +386,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
* @return `true` if this $coll has an element that is equal (as
* determined by `==`) to `elem`, `false` otherwise.
*/
- def contains(elem: Any): Boolean = exists (_ == elem)
+ def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem)
/** Produces a new sequence which contains all elements of this $coll and also all elements of
* a given sequence. `xs union ys` is equivalent to `xs ++ ys`.
diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala
index 3783ef771f..7e77418996 100644
--- a/src/library/scala/collection/SeqProxyLike.scala
+++ b/src/library/scala/collection/SeqProxyLike.scala
@@ -50,7 +50,7 @@ trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A,
override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = self.lastIndexOfSlice(that)
override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = self.lastIndexOfSlice(that, end)
override def containsSlice[B](that: GenSeq[B]): Boolean = self.indexOfSlice(that) != -1
- override def contains(elem: Any): Boolean = self.contains(elem)
+ override def contains[A1 >: A](elem: A1): Boolean = self.contains(elem)
override def union[B >: A, That](that: GenSeq[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = self.union(that)(bf)
override def diff[B >: A](that: GenSeq[B]): Repr = self.diff(that)
override def intersect[B >: A](that: GenSeq[B]): Repr = self.intersect(that)
diff --git a/src/library/scala/collection/Sequentializable.scala.disabled b/src/library/scala/collection/Sequentializable.scala.disabled
deleted file mode 100644
index df457671a6..0000000000
--- a/src/library/scala/collection/Sequentializable.scala.disabled
+++ /dev/null
@@ -1,10 +0,0 @@
-package scala.collection
-
-
-
-
-trait Sequentializable[+T, +Repr] {
-
- def seq: Repr
-
-}
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index f912304680..a61d1354dc 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -184,7 +184,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
- def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)
+ def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala
index 6b347db7a0..91faed9e48 100644
--- a/src/library/scala/collection/generic/GenTraversableFactory.scala
+++ b/src/library/scala/collection/generic/GenTraversableFactory.scala
@@ -38,13 +38,10 @@ import scala.language.higherKinds
abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTraversableTemplate[X, CC]]
extends GenericCompanion[CC] {
- // A default implementation of GenericCanBuildFrom which can be cast
- // to whatever is desired.
- private class ReusableCBF extends GenericCanBuildFrom[Nothing] {
+ private[this] val ReusableCBFInstance: GenericCanBuildFrom[Nothing] = new GenericCanBuildFrom[Nothing] {
override def apply() = newBuilder[Nothing]
}
- // Working around SI-4789 by using a lazy val instead of an object.
- lazy val ReusableCBF: GenericCanBuildFrom[Nothing] = new ReusableCBF
+ def ReusableCBF: GenericCanBuildFrom[Nothing] = ReusableCBFInstance
/** A generic implementation of the `CanBuildFrom` trait, which forwards
* all calls to `apply(from)` to the `genericBuilder` method of
@@ -252,4 +249,3 @@ abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTrav
b.result
}
}
-
diff --git a/src/library/scala/collection/generic/IndexedSeqFactory.scala b/src/library/scala/collection/generic/IndexedSeqFactory.scala
new file mode 100644
index 0000000000..e5162c640b
--- /dev/null
+++ b/src/library/scala/collection/generic/IndexedSeqFactory.scala
@@ -0,0 +1,21 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.collection
+package generic
+
+import language.higherKinds
+
+/** A template for companion objects of IndexedSeq and subclasses thereof.
+ *
+ * @since 2.8
+ */
+abstract class IndexedSeqFactory[CC[X] <: IndexedSeq[X] with GenericTraversableTemplate[X, CC]] extends SeqFactory[CC] {
+ override def ReusableCBF: GenericCanBuildFrom[Nothing] =
+ scala.collection.IndexedSeq.ReusableCBF.asInstanceOf[GenericCanBuildFrom[Nothing]]
+}
diff --git a/src/library/scala/collection/generic/IsSeqLike.scala b/src/library/scala/collection/generic/IsSeqLike.scala
new file mode 100644
index 0000000000..9467510a2c
--- /dev/null
+++ b/src/library/scala/collection/generic/IsSeqLike.scala
@@ -0,0 +1,57 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.collection
+package generic
+
+/** Type class witnessing that a collection representation type `Repr` has
+ * elements of type `A` and has a conversion to `SeqLike[A, Repr]`.
+ *
+ * This type enables simple enrichment of `Seq`s with extension methods which
+ * can make full use of the mechanics of the Scala collections framework in
+ * their implementation.
+ *
+ * Example usage:
+ * {{{
+ * class FilterMapImpl[A, Repr](val r: SeqLike[A, Repr]) {
+ * final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That =
+ * r.flatMap(f(_))
+ * }
+ * implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsSeqLike[Repr]): FilterMapImpl[fr.A,Repr] =
+ * new FilterMapImpl(fr.conversion(r))
+ *
+ * val l = List(1, 2, 3, 4, 5)
+ * List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None)
+ * // == List(2, 4)
+ * }}}
+ *
+ * @see [[scala.collection.Seq]]
+ * @see [[scala.collection.generic.IsTraversableLike]]
+ */
+trait IsSeqLike[Repr] {
+ /** The type of elements we can traverse over. */
+ type A
+ /** A conversion from the representation type `Repr` to a `SeqLike[A,Repr]`. */
+ val conversion: Repr => SeqLike[A, Repr]
+}
+
+object IsSeqLike {
+ import language.higherKinds
+
+ implicit val stringRepr: IsSeqLike[String] { type A = Char } =
+ new IsSeqLike[String] {
+ type A = Char
+ val conversion = implicitly[String => SeqLike[Char, String]]
+ }
+
+ implicit def seqLikeRepr[C[_], A0](implicit conv: C[A0] => SeqLike[A0,C[A0]]): IsSeqLike[C[A0]] { type A = A0 } =
+ new IsSeqLike[C[A0]] {
+ type A = A0
+ val conversion = conv
+ }
+}
diff --git a/src/library/scala/collection/generic/SeqForwarder.scala b/src/library/scala/collection/generic/SeqForwarder.scala
index 10e8c37cbf..bdec165314 100644
--- a/src/library/scala/collection/generic/SeqForwarder.scala
+++ b/src/library/scala/collection/generic/SeqForwarder.scala
@@ -50,7 +50,7 @@ trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] {
override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = underlying lastIndexOfSlice that
override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = underlying.lastIndexOfSlice(that, end)
override def containsSlice[B](that: GenSeq[B]): Boolean = underlying containsSlice that
- override def contains(elem: Any): Boolean = underlying contains elem
+ override def contains[A1 >: A](elem: A1): Boolean = underlying contains elem
override def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = underlying.corresponds(that)(p)
override def indices: Range = underlying.indices
}
diff --git a/src/library/scala/collection/immutable/GenIterable.scala.disabled b/src/library/scala/collection/immutable/GenIterable.scala.disabled
deleted file mode 100644
index 858abd27aa..0000000000
--- a/src/library/scala/collection/immutable/GenIterable.scala.disabled
+++ /dev/null
@@ -1,37 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.collection
-package immutable
-
-
-import generic._
-import mutable.Builder
-
-
-/** A base trait for iterable collections that can be mutated.
- *
- * $possiblyparinfo
- *
- * $iterableInfo
- */
-trait GenIterable[+A] extends GenTraversable[A]
- with scala.collection.GenIterable[A]
- with scala.collection.GenIterableLike[A, GenIterable[A]]
-// with GenericTraversableTemplate[A, GenIterable]
-{
- def seq: Iterable[A]
- //override def companion: GenericCompanion[GenIterable] = GenIterable
-}
-
-
-// object GenIterable extends TraversableFactory[GenIterable] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder
-// }
-
diff --git a/src/library/scala/collection/immutable/GenMap.scala.disabled b/src/library/scala/collection/immutable/GenMap.scala.disabled
deleted file mode 100644
index eb7ef2951c..0000000000
--- a/src/library/scala/collection/immutable/GenMap.scala.disabled
+++ /dev/null
@@ -1,36 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.collection
-package immutable
-
-import generic._
-
-
-/** A base trait for maps that can be mutated.
- * $possiblyparinfo
- * $mapNote
- * $mapTags
- * @since 1.0
- * @author Matthias Zenger
- */
-trait GenMap[A, +B]
-extends GenIterable[(A, B)]
- with scala.collection.GenMap[A, B]
- with scala.collection.GenMapLike[A, B, GenMap[A, B]]
-{
- def seq: Map[A, B]
-}
-
-
-// object GenMap extends MapFactory[GenMap] {
-// def empty[A, B]: Map[A, B] = Map.empty
-
-// /** $mapCanBuildFromInfo */
-// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B]
-// }
diff --git a/src/library/scala/collection/immutable/GenSeq.scala.disabled b/src/library/scala/collection/immutable/GenSeq.scala.disabled
deleted file mode 100644
index b8bc420ec3..0000000000
--- a/src/library/scala/collection/immutable/GenSeq.scala.disabled
+++ /dev/null
@@ -1,49 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package immutable
-
-
-import generic._
-import mutable.Builder
-
-
-/** A subtrait of `collection.GenSeq` which represents sequences
- * that can be mutated.
- *
- * $possiblyparinfo
- *
- * $seqInfo
- *
- * The class adds an `update` method to `collection.Seq`.
- *
- * @define Coll `mutable.Seq`
- * @define coll mutable sequence
- */
-trait GenSeq[+A] extends GenIterable[A]
- with scala.collection.GenSeq[A]
- with scala.collection.GenSeqLike[A, GenSeq[A]]
-// with GenericTraversableTemplate[A, GenSeq]
-{
- def seq: Seq[A]
- //override def companion: GenericCompanion[GenSeq] = GenSeq
-}
-
-
-// object GenSeq extends SeqFactory[GenSeq] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder
-// }
-
-
-
-
-
diff --git a/src/library/scala/collection/immutable/GenSet.scala.disabled b/src/library/scala/collection/immutable/GenSet.scala.disabled
deleted file mode 100644
index 828219580e..0000000000
--- a/src/library/scala/collection/immutable/GenSet.scala.disabled
+++ /dev/null
@@ -1,43 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package immutable
-
-
-import generic._
-import mutable.Builder
-
-
-/** A generic trait for mutable sets.
- *
- * $possiblyparinfo
- * $setNote
- * $setTags
- *
- * @since 1.0
- * @author Matthias Zenger
- * @define Coll `mutable.Set`
- * @define coll mutable set
- */
-trait GenSet[A] extends GenIterable[A]
- with scala.collection.GenSet[A]
- with scala.collection.GenSetLike[A, GenSet[A]]
-// with GenericSetTemplate[A, GenSet]
-{
- //override def companion: GenericCompanion[GenSet] = GenSet
- def seq: Set[A]
-}
-
-
-// object GenSet extends TraversableFactory[GenSet] {
-// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A] = Set.newBuilder
-// }
diff --git a/src/library/scala/collection/immutable/GenTraversable.scala.disabled b/src/library/scala/collection/immutable/GenTraversable.scala.disabled
deleted file mode 100644
index 4a5cf12ebe..0000000000
--- a/src/library/scala/collection/immutable/GenTraversable.scala.disabled
+++ /dev/null
@@ -1,41 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package immutable
-
-
-import generic._
-import mutable.Builder
-
-
-/** A trait for traversable collections that can be mutated.
- *
- * $possiblyparinfo
- *
- * $traversableInfo
- * @define mutability mutable
- */
-trait GenTraversable[+A] extends scala.collection.GenTraversable[A]
- with scala.collection.GenTraversableLike[A, GenTraversable[A]]
-// with GenericTraversableTemplate[A, GenTraversable]
- with Mutable
-{
- def seq: Traversable[A]
- //override def companion: GenericCompanion[GenTraversable] = GenTraversable
-}
-
-
-// object GenTraversable extends TraversableFactory[GenTraversable] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenTraversable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenTraversable[A]] = Traversable.newBuilder
-// }
-
-
diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala
index b37edc4254..a5d5728191 100644
--- a/src/library/scala/collection/immutable/IndexedSeq.scala
+++ b/src/library/scala/collection/immutable/IndexedSeq.scala
@@ -31,11 +31,13 @@ trait IndexedSeq[+A] extends Seq[A]
* @define coll indexed sequence
* @define Coll `IndexedSeq`
*/
-object IndexedSeq extends SeqFactory[IndexedSeq] {
+object IndexedSeq extends IndexedSeqFactory[IndexedSeq] {
class Impl[A](buf: ArrayBuffer[A]) extends AbstractSeq[A] with IndexedSeq[A] with Serializable {
def length = buf.length
def apply(idx: Int) = buf.apply(idx)
}
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
def newBuilder[A]: Builder[A, IndexedSeq[A]] = Vector.newBuilder[A]
+
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
}
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 7a489bb100..47cac9a1d5 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -152,7 +152,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
* @usecase def mapConserve(f: A => A): List[A]
* @inheritdoc
*/
- def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = {
+ @inline final def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = {
@tailrec
def loop(mapped: ListBuffer[B], unchanged: List[A], pending: List[A]): List[B] =
if (pending.isEmpty) {
@@ -257,7 +257,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
(b.toList, these)
}
- override def takeWhile(p: A => Boolean): List[A] = {
+ @inline final override def takeWhile(p: A => Boolean): List[A] = {
val b = new ListBuffer[A]
var these = this
while (!these.isEmpty && p(these.head)) {
@@ -267,7 +267,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
b.toList
}
- override def dropWhile(p: A => Boolean): List[A] = {
+ @inline final override def dropWhile(p: A => Boolean): List[A] = {
@tailrec
def loop(xs: List[A]): List[A] =
if (xs.isEmpty || !p(xs.head)) xs
@@ -276,7 +276,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
loop(this)
}
- override def span(p: A => Boolean): (List[A], List[A]) = {
+ @inline final override def span(p: A => Boolean): (List[A], List[A]) = {
val b = new ListBuffer[A]
var these = this
while (!these.isEmpty && p(these.head)) {
@@ -286,6 +286,16 @@ sealed abstract class List[+A] extends AbstractSeq[A]
(b.toList, these)
}
+ // Overridden with an implementation identical to the inherited one (at this time)
+ // solely so it can be finalized and thus inlinable.
+ @inline final override def foreach[U](f: A => U) {
+ var these = this
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
+ }
+ }
+
override def reverse: List[A] = {
var result: List[A] = Nil
var these = this
@@ -301,18 +311,6 @@ sealed abstract class List[+A] extends AbstractSeq[A]
override def toStream : Stream[A] =
if (isEmpty) Stream.Empty
else new Stream.Cons(head, tail.toStream)
-
- @inline override final
- def foreach[B](f: A => B) {
- var these = this
- while (!these.isEmpty) {
- f(these.head)
- these = these.tail
- }
- }
-
- @deprecated("use `distinct` instead", "2.8.0")
- def removeDuplicates: List[A] = distinct
}
/** The empty list.
@@ -406,248 +404,6 @@ object List extends SeqFactory[List] {
override def empty[A]: List[A] = Nil
override def apply[A](xs: A*): List[A] = xs.toList
-
- /** Create a sorted list with element values `v,,>n+1,, = step(v,,n,,)`
- * where `v,,0,, = start` and elements are in the range between `start`
- * (inclusive) and `end` (exclusive).
- *
- * @param start the start value of the list
- * @param end the end value of the list
- * @param step the increment function of the list, which given `v,,n,,`,
- * computes `v,,n+1,,`. Must be monotonically increasing
- * or decreasing.
- * @return the sorted list of all integers in range `[start;end)`.
- */
- @deprecated("use `iterate` instead", "2.8.0")
- def range(start: Int, end: Int, step: Int => Int): List[Int] = {
- val up = step(start) > start
- val down = step(start) < start
- val b = new ListBuffer[Int]
- var i = start
- while ((!up || i < end) && (!down || i > end)) {
- b += i
- val next = step(i)
- if (i == next)
- throw new IllegalArgumentException("the step function did not make any progress on "+ i)
- i = next
- }
- b.toList
- }
-
- /** Create a list containing several copies of an element.
- *
- * @param n the length of the resulting list
- * @param elem the element composing the resulting list
- * @return a list composed of `n` elements all equal to `elem`
- */
- @deprecated("use `fill` instead", "2.8.0")
- def make[A](n: Int, elem: A): List[A] = {
- val b = new ListBuffer[A]
- var i = 0
- while (i < n) {
- b += elem
- i += 1
- }
- b.toList
- }
-
- /** Concatenate all the elements of a given list of lists.
- *
- * @param xss the list of lists that are to be concatenated
- * @return the concatenation of all the lists
- */
- @deprecated("use `xss.flatten` instead of `List.flatten(xss)`", "2.8.0")
- def flatten[A](xss: List[List[A]]): List[A] = {
- val b = new ListBuffer[A]
- for (xs <- xss) {
- var xc = xs
- while (!xc.isEmpty) {
- b += xc.head
- xc = xc.tail
- }
- }
- b.toList
- }
-
- /** Transforms a list of pairs into a pair of lists.
- *
- * @param xs the list of pairs to unzip
- * @return a pair of lists.
- */
- @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0")
- def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = {
- val b1 = new ListBuffer[A]
- val b2 = new ListBuffer[B]
- var xc = xs
- while (!xc.isEmpty) {
- b1 += xc.head._1
- b2 += xc.head._2
- xc = xc.tail
- }
- (b1.toList, b2.toList)
- }
-
- /** Transforms an iterable of pairs into a pair of lists.
- *
- * @param xs the iterable of pairs to unzip
- * @return a pair of lists.
- */
- @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0")
- def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) =
- xs.foldRight[(List[A], List[B])]((Nil, Nil)) {
- case ((x, y), (xs, ys)) => (x :: xs, y :: ys)
- }
-
- /**
- * Returns the `Left` values in the given `Iterable` of `Either`s.
- */
- @deprecated("use `xs collect { case Left(x: A) => x }` instead of `List.lefts(xs)`", "2.8.0")
- def lefts[A, B](es: Iterable[Either[A, B]]) =
- es.foldRight[List[A]](Nil)((e, as) => e match {
- case Left(a) => a :: as
- case Right(_) => as
- })
-
- /**
- * Returns the `Right` values in the given `Iterable` of `Either`s.
- */
- @deprecated("use `xs collect { case Right(x: B) => x }` instead of `List.rights(xs)`", "2.8.0")
- def rights[A, B](es: Iterable[Either[A, B]]) =
- es.foldRight[List[B]](Nil)((e, bs) => e match {
- case Left(_) => bs
- case Right(b) => b :: bs
- })
-
- /** Transforms an Iterable of Eithers into a pair of lists.
- *
- * @param es the iterable of Eithers to separate
- * @return a pair of lists.
- */
- @deprecated("use `(for (Left(x) <- es) yield x, for (Right(x) <- es) yield x)` instead", "2.8.0")
- def separate[A,B](es: Iterable[Either[A, B]]): (List[A], List[B]) =
- es.foldRight[(List[A], List[B])]((Nil, Nil)) {
- case (Left(a), (lefts, rights)) => (a :: lefts, rights)
- case (Right(b), (lefts, rights)) => (lefts, b :: rights)
- }
-
- /** Converts an iterator to a list.
- *
- * @param it the iterator to convert
- * @return a list that contains the elements returned by successive
- * calls to `it.next`
- */
- @deprecated("use `it.toList` instead of `List.toList(it)`", "2.8.0")
- def fromIterator[A](it: Iterator[A]): List[A] = it.toList
-
- /** Converts an array into a list.
- *
- * @param arr the array to convert
- * @return a list that contains the same elements than `arr`
- * in the same order
- */
- @deprecated("use `array.toList` instead of `List.fromArray(array)`", "2.8.0")
- def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length)
-
- /** Converts a range of an array into a list.
- *
- * @param arr the array to convert
- * @param start the first index to consider
- * @param len the length of the range to convert
- * @return a list that contains the same elements than `arr`
- * in the same order
- */
- @deprecated("use `array.view(start, end).toList` instead of `List.fromArray(array, start, end)`", "2.8.0")
- def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = {
- var res: List[A] = Nil
- var i = start + len
- while (i > start) {
- i -= 1
- res = arr(i) :: res
- }
- res
- }
-
- /** Returns the list resulting from applying the given function `f`
- * to corresponding elements of the argument lists.
- *
- * @param f function to apply to each pair of elements.
- * @return `[f(a,,0,,,b,,0,,), ..., f(a,,n,,,b,,n,,)]` if the lists are
- * `[a,,0,,, ..., a,,k,,]`, `[b,,0,,, ..., b,,l,,]` and
- * `n = min(k,l)`
- */
- @deprecated("use `(xs, ys).zipped.map(f)` instead of `List.map2(xs, ys)(f)`", "2.8.0")
- def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = {
- val b = new ListBuffer[C]
- var xc = xs
- var yc = ys
- while (!xc.isEmpty && !yc.isEmpty) {
- b += f(xc.head, yc.head)
- xc = xc.tail
- yc = yc.tail
- }
- b.toList
- }
-
- /** Tests whether the given predicate `p` holds
- * for all corresponding elements of the argument lists.
- *
- * @param f function to apply to each pair of elements.
- * @return `(p(a<sub>0</sub>,b<sub>0</sub>) &amp;&amp;
- * ... &amp;&amp; p(a<sub>n</sub>,b<sub>n</sub>))]`
- * if the lists are `[a<sub>0</sub>, ..., a<sub>k</sub>]`;
- * `[b<sub>0</sub>, ..., b<sub>l</sub>]`
- * and `n = min(k,l)`
- */
- @deprecated("use `(xs, ys).zipped.forall(f)` instead of `List.forall2(xs, ys)(f)`", "2.8.0")
- def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
- var xc = xs
- var yc = ys
- while (!xc.isEmpty && !yc.isEmpty) {
- if (!f(xc.head, yc.head)) return false
- xc = xc.tail
- yc = yc.tail
- }
- true
- }
-
- /** Tests whether the given predicate `p` holds
- * for some corresponding elements of the argument lists.
- *
- * @param f function to apply to each pair of elements.
- * @return `n != 0 &amp;&amp; (p(a<sub>0</sub>,b<sub>0</sub>) ||
- * ... || p(a<sub>n</sub>,b<sub>n</sub>))]` if the lists are
- * `[a<sub>0</sub>, ..., a<sub>k</sub>]`,
- * `[b<sub>0</sub>, ..., b<sub>l</sub>]` and
- * `n = min(k,l)`
- */
- @deprecated("use `(xs, ys).zipped.exists(f)` instead of `List.exists2(xs, ys)(f)`", "2.8.0")
- def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = {
- var xc = xs
- var yc = ys
- while (!xc.isEmpty && !yc.isEmpty) {
- if (f(xc.head, yc.head)) return true
- xc = xc.tail
- yc = yc.tail
- }
- false
- }
-
- /** Transposes a list of lists.
- * pre: All element lists have the same length.
- *
- * @param xss the list of lists
- * @return the transposed list of lists
- */
- @deprecated("use `xss.transpose` instead of `List.transpose(xss)`", "2.8.0")
- def transpose[A](xss: List[List[A]]): List[List[A]] = {
- val buf = new ListBuffer[List[A]]
- var yss = xss
- while (!yss.head.isEmpty) {
- buf += (yss map (_.head))
- yss = (yss map (_.tail))
- }
- buf.toList
- }
}
/** Only used for list serialization */
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 5662a11f93..ce04ef09af 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -182,7 +182,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
def containsTyped(x: T): Boolean =
isWithinBoundaries(x) && (((x - start) % step) == zero)
- override def contains(x: Any): Boolean =
+ override def contains[A1 >: T](x: A1): Boolean =
try containsTyped(x.asInstanceOf[T])
catch { case _: ClassCastException => false }
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 92ea5d3f04..ab303dde56 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -78,6 +78,7 @@ extends scala.collection.AbstractSeq[Int]
final val terminalElement = start + numRangeElements * step
override def last = if (isEmpty) Nil.last else lastElement
+ override def head = if (isEmpty) Nil.head else start
override def min[A1 >: Int](implicit ord: Ordering[A1]): Int =
if (ord eq Ordering.Int) {
diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala
index bb489dd80a..328d929fb9 100644
--- a/src/library/scala/collection/immutable/RedBlackTree.scala
+++ b/src/library/scala/collection/immutable/RedBlackTree.scala
@@ -74,17 +74,23 @@ object RedBlackTree {
result
}
- def foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U): Unit = if (tree ne null) {
- if (tree.left ne null) foreach(tree.left, f)
+
+ def foreach[A,B,U](tree:Tree[A,B], f:((A,B)) => U):Unit = if (tree ne null) _foreach(tree,f)
+
+ private[this] def _foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U) {
+ if (tree.left ne null) _foreach(tree.left, f)
f((tree.key, tree.value))
- if (tree.right ne null) foreach(tree.right, f)
- }
- def foreachKey[A, U](tree: Tree[A, _], f: A => U): Unit = if (tree ne null) {
- if (tree.left ne null) foreachKey(tree.left, f)
- f(tree.key)
- if (tree.right ne null) foreachKey(tree.right, f)
+ if (tree.right ne null) _foreach(tree.right, f)
}
+
+ def foreachKey[A, U](tree:Tree[A,_], f: A => U):Unit = if (tree ne null) _foreachKey(tree,f)
+ private[this] def _foreachKey[A, U](tree: Tree[A, _], f: A => U) {
+ if (tree.left ne null) _foreachKey(tree.left, f)
+ f((tree.key))
+ if (tree.right ne null) _foreachKey(tree.right, f)
+ }
+
def iterator[A, B](tree: Tree[A, B]): Iterator[(A, B)] = new EntriesIterator(tree)
def keysIterator[A, _](tree: Tree[A, _]): Iterator[A] = new KeysIterator(tree)
def valuesIterator[_, B](tree: Tree[_, B]): Iterator[B] = new ValuesIterator(tree)
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index a33bf2c9c5..895d073869 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -18,16 +18,10 @@ import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
*/
-object Vector extends SeqFactory[Vector] {
- private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] {
- override def apply() = newBuilder[Nothing]
- }
-
- private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF
-
- implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
- VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
+object Vector extends IndexedSeqFactory[Vector] {
def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A]
+ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
+ ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
override def empty[A]: Vector[A] = NIL
}
@@ -137,20 +131,17 @@ override def companion: GenericCompanion[Vector] = Vector
// SeqLike api
- override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf
- case _ => super.updated(index, elem)(bf)
- }
+ override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ else super.updated(index, elem)(bf)
- override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf
- case _ => super.+:(elem)(bf)
- }
+ override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf
+ else super.+:(elem)(bf)
- override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
- case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf
- case _ => super.:+(elem)(bf)
- }
+ override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That =
+ if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf
+ else super.:+(elem)(bf)
override def take(n: Int): Vector[A] = {
if (n <= 0)
diff --git a/src/library/scala/collection/mutable/GenIterable.scala.disabled b/src/library/scala/collection/mutable/GenIterable.scala.disabled
deleted file mode 100644
index e09981bc9b..0000000000
--- a/src/library/scala/collection/mutable/GenIterable.scala.disabled
+++ /dev/null
@@ -1,37 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.collection
-package mutable
-
-
-import generic._
-
-
-/** A base trait for iterable collections that can be mutated.
- *
- * $possiblyparinfo
- *
- * $iterableInfo
- */
-trait GenIterable[A] extends GenTraversable[A]
- with scala.collection.GenIterable[A]
- with scala.collection.GenIterableLike[A, GenIterable[A]]
-// with GenericTraversableTemplate[A, GenIterable]
-{
- def seq: Iterable[A]
- //override def companion: GenericCompanion[GenIterable] = GenIterable
-}
-
-
-// object GenIterable extends TraversableFactory[GenIterable] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder
-// }
-
-
diff --git a/src/library/scala/collection/mutable/GenMap.scala.disabled b/src/library/scala/collection/mutable/GenMap.scala.disabled
deleted file mode 100644
index eca63b43ce..0000000000
--- a/src/library/scala/collection/mutable/GenMap.scala.disabled
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-
-import generic._
-
-
-/** A base trait for maps that can be mutated.
- * $possiblyparinfo
- * $mapNote
- * $mapTags
- * @since 1.0
- * @author Matthias Zenger
- */
-trait GenMap[A, B]
-extends GenIterable[(A, B)]
- with scala.collection.GenMap[A, B]
- with scala.collection.GenMapLike[A, B, GenMap[A, B]]
-{
- def seq: Map[A, B]
-}
-
-
-// object GenMap extends MapFactory[GenMap] {
-// def empty[A, B]: Map[A, B] = Map.empty
-
-// /** $mapCanBuildFromInfo */
-// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B]
-// }
-
diff --git a/src/library/scala/collection/mutable/GenSeq.scala.disabled b/src/library/scala/collection/mutable/GenSeq.scala.disabled
deleted file mode 100644
index 53ec5acc34..0000000000
--- a/src/library/scala/collection/mutable/GenSeq.scala.disabled
+++ /dev/null
@@ -1,44 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-
-import generic._
-
-
-/** A subtrait of `collection.GenSeq` which represents sequences
- * that can be mutated.
- *
- * $possiblyparinfo
- *
- * $seqInfo
- *
- * The class adds an `update` method to `collection.Seq`.
- *
- * @define Coll `mutable.Seq`
- * @define coll mutable sequence
- */
-trait GenSeq[A] extends GenIterable[A]
- with scala.collection.GenSeq[A]
- with scala.collection.GenSeqLike[A, GenSeq[A]]
-// with GenericTraversableTemplate[A, GenSeq]
-{
- //override def companion: GenericCompanion[GenSeq] = GenSeq
- def seq: Seq[A]
-}
-
-
-// object GenSeq extends SeqFactory[GenSeq] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder
-// }
-
diff --git a/src/library/scala/collection/mutable/GenSet.scala.disabled b/src/library/scala/collection/mutable/GenSet.scala.disabled
deleted file mode 100644
index 9080abaf38..0000000000
--- a/src/library/scala/collection/mutable/GenSet.scala.disabled
+++ /dev/null
@@ -1,46 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-
-
-import generic._
-
-
-/** A generic trait for mutable sets.
- *
- * $possiblyparinfo
- * $setNote
- * $setTags
- *
- * @since 1.0
- * @author Matthias Zenger
- * @define Coll `mutable.Set`
- * @define coll mutable set
- */
-trait GenSet[A] extends GenIterable[A]
- with Growable[A]
- with scala.collection.GenSet[A]
- with scala.collection.GenSetLike[A, GenSet[A]]
-// with GenericSetTemplate[A, GenSet]
-{
- //override def companion: GenericCompanion[GenSet] = GenSet
- def seq: Set[A]
-}
-
-
-// object GenSet extends TraversableFactory[GenSet] {
-// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSet[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A]: Builder[A, GenSet[A]] = Set.newBuilder
-// }
-
-
diff --git a/src/library/scala/collection/mutable/GenTraversable.scala.disabled b/src/library/scala/collection/mutable/GenTraversable.scala.disabled
deleted file mode 100644
index e78e758c12..0000000000
--- a/src/library/scala/collection/mutable/GenTraversable.scala.disabled
+++ /dev/null
@@ -1,38 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-
-import generic._
-
-
-/** A trait for traversable collections that can be mutated.
- *
- * $possiblyparinfo
- *
- * $traversableInfo
- * @define mutability mutable
- */
-trait GenTraversable[A] extends scala.collection.GenTraversable[A]
- with scala.collection.GenTraversableLike[A, GenTraversable[A]]
-// with GenericTraversableTemplate[A, GenTraversable]
- with Mutable
-{
- def seq: Traversable[A]
- //override def companion: GenericCompanion[GenTraversable] = GenTraversable
-}
-
-// object GenTraversable extends TraversableFactory[GenTraversable] {
-// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
-// def newBuilder[A] = Traversable.newBuilder
-// }
-
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index cd743999bc..bced92e663 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -56,12 +56,18 @@ final class ListBuffer[A]
import scala.collection.Traversable
import scala.collection.immutable.ListSerializeEnd
+ /** Expected invariants:
+ * If start.isEmpty, last0 == null
+ * If start.nonEmpty, last0 != null
+ * If len == 0, start.isEmpty
+ * If len > 0, start.nonEmpty
+ */
private var start: List[A] = Nil
private var last0: ::[A] = _
private var exported: Boolean = false
private var len = 0
- protected def underlying: immutable.Seq[A] = start
+ protected def underlying: List[A] = start
private def writeObject(out: ObjectOutputStream) {
// write start
@@ -133,7 +139,7 @@ final class ListBuffer[A]
if (exported) copy()
if (n == 0) {
val newElem = new :: (x, start.tail);
- if (last0 eq start) {
+ if ((last0 eq null) || (last0 eq start)) {
last0 = newElem
}
start = newElem
@@ -162,7 +168,7 @@ final class ListBuffer[A]
*/
def += (x: A): this.type = {
if (exported) copy()
- if (start.isEmpty) {
+ if (isEmpty) {
last0 = new :: (x, Nil)
start = last0
} else {
@@ -184,6 +190,7 @@ final class ListBuffer[A]
*/
def clear() {
start = Nil
+ last0 = null
exported = false
len = 0
}
@@ -197,7 +204,7 @@ final class ListBuffer[A]
def +=: (x: A): this.type = {
if (exported) copy()
val newElem = new :: (x, start)
- if (start.isEmpty) last0 = newElem
+ if (isEmpty) last0 = newElem
start = newElem
len += 1
this
@@ -219,7 +226,7 @@ final class ListBuffer[A]
if (n == 0) {
while (!elems.isEmpty) {
val newElem = new :: (elems.head, start)
- if (start.isEmpty) last0 = newElem
+ if (isEmpty) last0 = newElem
start = newElem
elems = elems.tail
}
@@ -243,6 +250,15 @@ final class ListBuffer[A]
}
}
+ /** Reduce the length of the buffer, and null out last0
+ * if this reduces the length to 0.
+ */
+ private def reduceLengthBy(num: Int) {
+ len -= num
+ if (len <= 0) // obviously shouldn't be < 0, but still better not to leak
+ last0 = null
+ }
+
/** Removes a given number of elements on a given index position. May take
* time linear in the buffer size.
*
@@ -274,7 +290,7 @@ final class ListBuffer[A]
c -= 1
}
}
- len -= count1
+ reduceLengthBy(count1)
}
// Implementation of abstract method in Builder
@@ -285,7 +301,7 @@ final class ListBuffer[A]
* copied lazily, the first time it is mutated.
*/
override def toList: List[A] = {
- exported = !start.isEmpty
+ exported = !isEmpty
start
}
@@ -296,7 +312,7 @@ final class ListBuffer[A]
* @param xs the list to which elements are prepended
*/
def prependToList(xs: List[A]): List[A] = {
- if (start.isEmpty) xs
+ if (isEmpty) xs
else {
if (exported) copy()
last0.tl = xs
@@ -331,7 +347,7 @@ final class ListBuffer[A]
if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]]
cursor.asInstanceOf[::[A]].tl = cursor.tail.tail
}
- len -= 1
+ reduceLengthBy(1)
old
}
@@ -343,11 +359,12 @@ final class ListBuffer[A]
*/
override def -= (elem: A): this.type = {
if (exported) copy()
- if (start.isEmpty) {}
+ if (isEmpty) {}
else if (start.head == elem) {
start = start.tail
- len -= 1
- } else {
+ reduceLengthBy(1)
+ }
+ else {
var cursor = start
while (!cursor.tail.isEmpty && cursor.tail.head != elem) {
cursor = cursor.tail
@@ -357,7 +374,7 @@ final class ListBuffer[A]
if (z.tl == last0)
last0 = z
z.tl = cursor.tail.tail
- len -= 1
+ reduceLengthBy(1)
}
}
this
@@ -397,6 +414,7 @@ final class ListBuffer[A]
/** Copy contents of this buffer */
private def copy() {
+ if (isEmpty) return
var cursor = start
val limit = last0.tail
clear()
diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
index bc32537798..120b3d66a0 100644
--- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
+++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
@@ -73,14 +73,6 @@ class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQu
*/
override def head: A = synchronized { super.head }
- /** Returns the element with the highest priority in the queue,
- * or throws an error if there is no element contained in the queue.
- *
- * @return the element with the highest priority.
- */
- @deprecated("Use `head` instead.", "2.9.0")
- override def max: A = synchronized { super.max }
-
/** Removes all elements from the queue. After this operation is completed,
* the queue will be empty.
*/
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index f6fb32e152..0c0ff2b027 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -433,12 +433,13 @@ self: ParIterableLike[T, Repr, Sequential] =>
* @tparam S the type of accumulated results
* @param z the initial value for the accumulated result of the partition - this
* will typically be the neutral element for the `seqop` operator (e.g.
- * `Nil` for list concatenation or `0` for summation)
+ * `Nil` for list concatenation or `0` for summation) and may be evaluated
+ * more than once
* @param seqop an operator used to accumulate results within a partition
* @param combop an associative operator used to combine results from different partitions
*/
- def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = {
- tasksupport.executeAndWaitResult(new Aggregate(z, seqop, combop, splitter))
+ def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = {
+ tasksupport.executeAndWaitResult(new Aggregate(() => z, seqop, combop, splitter))
}
def foldLeft[S](z: S)(op: (S, T) => S): S = seq.foldLeft(z)(op)
@@ -936,8 +937,8 @@ self: ParIterableLike[T, Repr, Sequential] =>
(f: First, s: Second)
extends Composite[FR, SR, R, First, Second](f, s) {
def leaf(prevr: Option[R]) = {
- tasksupport.executeAndWaitResult(ft)
- tasksupport.executeAndWaitResult(st)
+ tasksupport.executeAndWaitResult(ft) : Any
+ tasksupport.executeAndWaitResult(st) : Any
mergeSubtasks
}
}
@@ -947,8 +948,8 @@ self: ParIterableLike[T, Repr, Sequential] =>
(f: First, s: Second)
extends Composite[FR, SR, R, First, Second](f, s) {
def leaf(prevr: Option[R]) = {
- val ftfuture = tasksupport.execute(ft)
- tasksupport.executeAndWaitResult(st)
+ val ftfuture: () => Any = tasksupport.execute(ft)
+ tasksupport.executeAndWaitResult(st) : Any
ftfuture()
mergeSubtasks
}
@@ -1006,10 +1007,10 @@ self: ParIterableLike[T, Repr, Sequential] =>
override def merge(that: Fold[U]) = result = op(result, that.result)
}
- protected[this] class Aggregate[S](z: S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T])
+ protected[this] class Aggregate[S](z: () => S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T])
extends Accessor[S, Aggregate[S]] {
@volatile var result: S = null.asInstanceOf[S]
- def leaf(prevr: Option[S]) = result = pit.foldLeft(z)(seqop)
+ def leaf(prevr: Option[S]) = result = pit.foldLeft(z())(seqop)
protected[this] def newSubtask(p: IterableSplitter[T]) = new Aggregate(z, seqop, combop, p)
override def merge(that: Aggregate[S]) = result = combop(result, that.result)
}
@@ -1505,31 +1506,3 @@ self: ParIterableLike[T, Repr, Sequential] =>
})
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
deleted file mode 100644
index 04bc8b8d29..0000000000
--- a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
+++ /dev/null
@@ -1,128 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-package scala.collection.parallel.immutable
-
-
-
-import scala.collection.immutable.NumericRange
-import scala.collection.parallel.Combiner
-import scala.collection.generic.CanCombineFrom
-import scala.collection.parallel.ParIterableIterator
-
-
-
-/** Parallel ranges for numeric types.
- *
- * $paralleliterableinfo
- *
- * $sideeffects
- *
- * @param range the sequential range this parallel range was obtained from
- *
- * @author Aleksandar Prokopec
- * @since 2.9
- *
- * @define Coll `immutable.ParRange`
- * @define coll immutable parallel range
- */
-@SerialVersionUID(1L)
-class ParNumericRange[T](val range: NumericRange[T])(implicit num: Integral[T])
-extends ParSeq[T]
- with Serializable
-{
-self =>
-
- def seq = range
-
- @inline final def length = range.length
-
- @inline final def apply(idx: Int) = range.apply(idx);
-
- def parallelIterator = new ParNumericRangeIterator with SCPI
-
- type SCPI = SignalContextPassingIterator[ParNumericRangeIterator]
-
- class ParNumericRangeIterator(range: NumericRange[T] = self.range, num: Integral[T] = self.num)
- extends ParIterator {
- me: SignalContextPassingIterator[ParNumericRangeIterator] =>
- override def toString = "ParNumericRangeIterator(over: " + range + ")"
- private var ind = 0
- private val len = range.length
-
- final def remaining = len - ind
-
- final def hasNext = ind < len
-
- final def next = if (hasNext) {
- val r = range.apply(ind)
- ind += 1
- r
- } else Iterator.empty.next
-
- private def rangeleft: NumericRange[T] = range.drop(ind)
-
- def dup = new ParNumericRangeIterator(rangeleft) with SCPI
-
- def split = {
- val rleft = rangeleft
- val elemleft = rleft.length
- if (elemleft < 2) Seq(new ParNumericRangeIterator(rleft) with SCPI)
- else Seq(
- new ParNumericRangeIterator(rleft.take(elemleft / 2)) with SCPI,
- new ParNumericRangeIterator(rleft.drop(elemleft / 2)) with SCPI
- )
- }
-
- def psplit(sizes: Int*) = {
- var rleft = rangeleft
- for (sz <- sizes) yield {
- val fronttaken = rleft.take(sz)
- rleft = rleft.drop(sz)
- new ParNumericRangeIterator(fronttaken) with SCPI
- }
- }
-
- /* accessors */
-
- override def foreach[U](f: T => U): Unit = {
- rangeleft.foreach(f)
- ind = len
- }
-
- override def reduce[U >: T](op: (U, U) => U): U = {
- val r = rangeleft.reduceLeft(op)
- ind = len
- r
- }
-
- /* transformers */
-
- override def map2combiner[S, That](f: T => S, cb: Combiner[S, That]): Combiner[S, That] = {
- while (hasNext) {
- cb += f(next)
- }
- cb
- }
- }
-
-}
-
-
-object ParNumericRange {
- def apply[T](start: T, end: T, step: T, inclusive: Boolean)(implicit num: Integral[T]) = new ParNumericRange[T](
- if (inclusive) NumericRange.inclusive(start, end, step)(num)
- else NumericRange.apply(start, end, step)(num)
- )
-}
-
-
-
-
-
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index 56cc06f99e..deff9eda3b 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -181,7 +181,7 @@ self =>
override def fold[U >: T](z: U)(op: (U, U) => U): U = foldLeft[U](z)(op)
- override def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop)
+ override def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop)
override def sum[U >: T](implicit num: Numeric[U]): U = {
var s = sum_quick(num, arr, until, i, num.zero)
diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala
index dae478f31a..8c2d62f5b1 100644
--- a/src/library/scala/io/Position.scala
+++ b/src/library/scala/io/Position.scala
@@ -68,14 +68,6 @@ abstract class Position {
}
object Position extends Position {
- /** The undefined position */
- @deprecated("This will be removed", "2.9.0")
- final val NOPOS = 0
-
- /** The first position in a source file */
- @deprecated("This will be removed", "2.9.0")
- final val FIRSTPOS = encode(1, 1)
-
def checkInput(line: Int, column: Int) {
if (line < 0)
throw new IllegalArgumentException(line + " < 0")
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index eb73d58d1c..a721fd647c 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -25,12 +25,6 @@ object BigDecimal {
private val maxCached = 512
val defaultMathContext = MathContext.DECIMAL128
- @deprecated("Use Long.MinValue", "2.9.0")
- val MinLong = new BigDecimal(BigDec valueOf Long.MinValue, defaultMathContext)
-
- @deprecated("Use Long.MaxValue", "2.9.0")
- val MaxLong = new BigDecimal(BigDec valueOf Long.MaxValue, defaultMathContext)
-
/** Cache ony for defaultMathContext using BigDecimals in a small range. */
private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1)
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 3eb41053f7..9218e41ceb 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -23,12 +23,6 @@ object BigInt {
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)
-
- @deprecated("Use Long.MaxValue", "2.9.0")
- val MaxLong = BigInt(Long.MaxValue)
-
/** Constructs a `BigInt` whose value is equal to that of the
* specified integer value.
*
diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala
index fbb98d0582..65d6084b0e 100644
--- a/src/library/scala/package.scala
+++ b/src/library/scala/package.scala
@@ -34,9 +34,6 @@ package object scala {
override def toString = "object AnyRef"
}
- @deprecated("instead of `@serializable class C`, use `class C extends Serializable`", "2.9.0")
- type serializable = annotation.serializable
-
@deprecated("instead of `@cloneable class C`, use `class C extends Cloneable`", "2.10.0")
type cloneable = annotation.cloneable
@@ -129,9 +126,8 @@ package object scala {
type deprecatedName = annotation.deprecatedName
type inline = annotation.inline
type native = annotation.native
- type noinline = noannotation.inline
+ type noinline = annotation.noinline
type remote = annotation.remote
- type serializable = annotation.serializable
type specialized = annotation.specialized
type transient = annotation.transient
type throws = annotation.throws
diff --git a/src/library/scala/parallel/package.scala.disabled b/src/library/scala/parallel/package.scala.disabled
deleted file mode 100644
index 45f5470d03..0000000000
--- a/src/library/scala/parallel/package.scala.disabled
+++ /dev/null
@@ -1,178 +0,0 @@
-package scala
-
-
-
-import scala.concurrent.forkjoin._
-
-
-/** This package object contains various parallel operations.
- *
- * @define invokingPar
- * Invoking a parallel computation creates a future which will
- * hold the result of the computation once it completes. Querying
- * the result of a future before its parallel computation has completed
- * will block the caller. For all practical concerns, the dependency
- * chain obtained by querying results of unfinished futures can have
- * arbitrary lengths. However, care must be taken not to create a
- * circular dependency, as this will result in a deadlock.
- *
- * Additionally, if the parallel computation performs a blocking call
- * (e.g. an I/O operation or waiting for a lock) other than waiting for a future,
- * it should do so by invoking the `block` method. This is another
- * form of waiting that could potentially create a circular dependency,
- * an the user should take care not to do this.
- *
- * Users should be aware that invoking a parallel computation has a
- * certain overhead. Parallel computations should not be invoked for
- * small computations, as this can lead to bad performance. A rule of the
- * thumb is having parallel computations equivalent to a loop
- * with 50000 arithmetic operations (at least). If a parallel computation
- * is invoked within another parallel computation, then it should be
- * computationally equivalent to a loop with 10000 arithmetic operations.
- */
-package object parallel {
-
- private[scala] val forkjoinpool = new ForkJoinPool()
-
- private class Task[T](body: =>T) extends RecursiveTask[T] with Future[T] {
- def compute = body
- def apply() = join()
- }
-
- private final def newTask[T](body: =>T) = new Task[T](body)
-
- private final def executeTask[T](task: RecursiveTask[T]) {
- if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) task.fork
- else forkjoinpool.execute(task)
- }
-
- /* public methods */
-
- /** Performs a call which can potentially block execution.
- *
- * Example:
- * {{{
- * val lock = new ReentrantLock
- *
- * // ... do something ...
- *
- * blocking {
- * if (!lock.hasLock) lock.lock()
- * }
- * }}}
- *
- * '''Note:''' calling methods that wait arbitrary amounts of time
- * (e.g. for I/O operations or locks) may severely decrease performance
- * or even result in deadlocks. This does not include waiting for
- * results of futures.
- */
- def blocking[T](body: =>T): T = {
- if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) {
- val blocker = new ForkJoinPool.ManagedBlocker {
- @volatile var done = false
- @volatile var result: Any = _
- def block() = {
- result = body
- done = true
- true
- }
- def isReleasable() = done
- }
- ForkJoinPool.managedBlock(blocker, true)
- blocker.result.asInstanceOf[T]
- } else body
- }
-
- /** Starts a parallel computation and returns a future.
- *
- * $invokingPar
- *
- * @tparam T the type of the result of the parallel computation
- * @param body the computation to be invoked in parallel
- * @return a future with the result
- */
- def par[T](body: =>T): Future[T] = {
- val task = newTask(body)
- executeTask(task)
- task
- }
-
- /** Starts 2 parallel computations and returns a future.
- *
- * $invokingPar
- *
- * @tparam T1 the type of the result of 1st the parallel computation
- * @tparam T2 the type of the result of 2nd the parallel computation
- * @param b1 the 1st computation to be invoked in parallel
- * @param b2 the 2nd computation to be invoked in parallel
- * @return a tuple of futures corresponding to parallel computations
- */
- def par[T1, T2](b1: =>T1, b2: =>T2): (Future[T1], Future[T2]) = {
- val t1 = newTask(b1)
- executeTask(t1)
- val t2 = newTask(b2)
- executeTask(t2)
- (t1, t2)
- }
-
- /** Starts 3 parallel computations and returns a future.
- *
- * $invokingPar
- *
- * @tparam T1 the type of the result of 1st the parallel computation
- * @tparam T2 the type of the result of 2nd the parallel computation
- * @tparam T3 the type of the result of 3rd the parallel computation
- * @param b1 the 1st computation to be invoked in parallel
- * @param b2 the 2nd computation to be invoked in parallel
- * @param b3 the 3rd computation to be invoked in parallel
- * @return a tuple of futures corresponding to parallel computations
- */
- def par[T1, T2, T3](b1: =>T1, b2: =>T2, b3: =>T3): (Future[T1], Future[T2], Future[T3]) = {
- val t1 = newTask(b1)
- executeTask(t1)
- val t2 = newTask(b2)
- executeTask(t2)
- val t3 = newTask(b3)
- executeTask(t3)
- (t1, t2, t3)
- }
-
- /** Starts 4 parallel computations and returns a future.
- *
- * $invokingPar
- *
- * @tparam T1 the type of the result of 1st the parallel computation
- * @tparam T2 the type of the result of 2nd the parallel computation
- * @tparam T3 the type of the result of 3rd the parallel computation
- * @tparam T4 the type of the result of 4th the parallel computation
- * @param b1 the 1st computation to be invoked in parallel
- * @param b2 the 2nd computation to be invoked in parallel
- * @param b3 the 3rd computation to be invoked in parallel
- * @param b4 the 4th computation to be invoked in parallel
- * @return a tuple of futures corresponding to parallel computations
- */
- def par[T1, T2, T3, T4](b1: =>T1, b2: =>T2, b3: =>T3, b4: =>T4): (Future[T1], Future[T2], Future[T3], Future[T4]) = {
- val t1 = newTask(b1)
- executeTask(t1)
- val t2 = newTask(b2)
- executeTask(t2)
- val t3 = newTask(b3)
- executeTask(t3)
- val t4 = newTask(b4)
- executeTask(t4)
- (t1, t2, t3, t4)
- }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 5c9e36450b..1e3fa78af3 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -26,8 +26,7 @@ import java.lang.reflect.{ Modifier, Method => JMethod }
* outside the API and subject to change or removal without notice.
*/
object ScalaRunTime {
- def isArray(x: AnyRef): Boolean = isArray(x, 1)
- def isArray(x: Any, atLevel: Int): Boolean =
+ def isArray(x: Any, atLevel: Int = 1): Boolean =
x != null && isArrayClass(x.getClass, atLevel)
private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean =
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 3655a0a019..63d049208a 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -131,7 +131,7 @@ import java.util.regex.{ Pattern, Matcher }
* @author Martin Odersky
* @version 1.1, 29/01/2008
*
- * @param regex A string representing a regular expression
+ * @param pattern The compiled pattern
* @param groupNames A mapping from names to indices in capture groups
*
* @define replacementString
@@ -144,41 +144,67 @@ import java.util.regex.{ Pattern, Matcher }
* to automatically escape these characters.
*/
@SerialVersionUID(-2094783597747625537L)
-class Regex(regex: String, groupNames: String*) extends Serializable {
+class Regex private[matching](val pattern: Pattern, groupNames: String*) extends Serializable {
outer =>
import Regex._
- /** The compiled pattern */
- val pattern = Pattern.compile(regex)
+ /**
+ * @param regex A string representing a regular expression
+ * @param groupNames A mapping from names to indices in capture groups
+ */
+ def this(regex: String, groupNames: String*) = this(Pattern.compile(regex), groupNames: _*)
- /** Tries to match target (whole match) and returns the matching subgroups.
- * if the pattern has no subgroups, then it returns an empty list on a
- * successful match.
- *
- * Note, however, that if some subgroup has not been matched, a `null` will
- * be returned for that subgroup.
+ /** Tries to match a [[java.lang.CharSequence]].
+ * If the match succeeds, the result is a list of the matching
+ * groups (or a `null` element if a group did not match any input).
+ * If the pattern specifies no groups, then the result will be an empty list
+ * on a successful match.
*
+ * This method attempts to match the entire input by default; to find the next
+ * matching subsequence, use an unanchored Regex.
+
* For example:
*
* {{{
* val p1 = "ab*c".r
- * val p2 = "a(b*)c".r
- *
* val p1Matches = "abbbc" match {
* case p1() => true
* case _ => false
* }
- *
+ * val p2 = "a(b*)c".r
* val numberOfB = "abbbc" match {
* case p2(b) => Some(b.length)
* case _ => None
* }
+ * val p3 = "b*".r.unanchored
+ * val p3Matches = "abbbc" match {
+ * case p3() => true
+ * case _ => false
+ * }
* }}}
*
- * @param target The string to match
+ * @param s The string to match
* @return The matches
*/
+ def unapplySeq(s: CharSequence): Option[Seq[String]] = {
+ val m = pattern matcher s
+ if (runMatcher(m)) Some(1 to m.groupCount map m.group)
+ else None
+ }
+
+ /** Tries to match on a [[scala.util.matching.Regex.Match]].
+ * A previously failed match results in None.
+ * If a successful match was made against the current pattern, then that result is used.
+ * Otherwise, this Regex is applied to the previously matched input,
+ * and the result of that match is used.
+ */
+ def unapplySeq(m: Match): Option[Seq[String]] =
+ if (m.matched == null) None
+ else if (m.matcher.pattern == this.pattern) Some(1 to m.groupCount map m.group)
+ else unapplySeq(m.matched)
+
+ @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.10.0")
def unapplySeq(target: Any): Option[List[String]] = target match {
case s: CharSequence =>
val m = pattern matcher s
@@ -187,6 +213,8 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
case m: Match => unapplySeq(m.matched)
case _ => None
}
+
+ // @see UnanchoredRegex
protected def runMatcher(m: Matcher) = m.matches()
/** Return all matches of this regexp in given character sequence as a [[scala.util.matching.Regex.MatchIterator]],
@@ -200,7 +228,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.util.matching.Regex.MatchIterator]] of all matches.
* @example {{{for (words <- """\w+""".r findAllIn "A simple example.") yield words}}}
*/
- def findAllIn(source: java.lang.CharSequence) = new Regex.MatchIterator(source, this, groupNames)
+ def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames)
/** Return all matches of this regexp in given character sequence as a
@@ -210,7 +238,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]] for all matches.
* @example {{{for (words <- """\w+""".r findAllMatchIn "A simple example.") yield words.start}}}
*/
- def findAllMatchIn(source: java.lang.CharSequence): Iterator[Match] = {
+ def findAllMatchIn(source: CharSequence): Iterator[Match] = {
val matchIterator = findAllIn(source)
new Iterator[Match] {
def hasNext = matchIterator.hasNext
@@ -228,7 +256,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return An [[scala.Option]] of the first matching string in the text.
* @example {{{"""\w+""".r findFirstIn "A simple example." foreach println // prints "A"}}}
*/
- def findFirstIn(source: java.lang.CharSequence): Option[String] = {
+ def findFirstIn(source: CharSequence): Option[String] = {
val m = pattern.matcher(source)
if (m.find) Some(m.group) else None
}
@@ -245,7 +273,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of [[scala.util.matching.Regex.Match]] of the first matching string in the text.
* @example {{{("""[a-z]""".r findFirstMatchIn "A simple example.") map (_.start) // returns Some(2), the index of the first match in the text}}}
*/
- def findFirstMatchIn(source: java.lang.CharSequence): Option[Match] = {
+ def findFirstMatchIn(source: CharSequence): Option[Match] = {
val m = pattern.matcher(source)
if (m.find) Some(new Match(source, m, groupNames)) else None
}
@@ -262,7 +290,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of the matched prefix.
* @example {{{"""[a-z]""".r findPrefixOf "A simple example." // returns None, since the text does not begin with a lowercase letter}}}
*/
- def findPrefixOf(source: java.lang.CharSequence): Option[String] = {
+ def findPrefixOf(source: CharSequence): Option[String] = {
val m = pattern.matcher(source)
if (m.lookingAt) Some(m.group) else None
}
@@ -279,7 +307,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return A [[scala.Option]] of the [[scala.util.matching.Regex.Match]] of the matched string.
* @example {{{"""\w+""".r findPrefixMatchOf "A simple example." map (_.after) // returns Some(" simple example.")}}}
*/
- def findPrefixMatchOf(source: java.lang.CharSequence): Option[Match] = {
+ def findPrefixMatchOf(source: CharSequence): Option[Match] = {
val m = pattern.matcher(source)
if (m.lookingAt) Some(new Match(source, m, groupNames)) else None
}
@@ -293,7 +321,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return The resulting string
* @example {{{"""\d+""".r replaceAllIn ("July 15", "<NUMBER>") // returns "July <NUMBER>"}}}
*/
- def replaceAllIn(target: java.lang.CharSequence, replacement: String): String = {
+ def replaceAllIn(target: CharSequence, replacement: String): String = {
val m = pattern.matcher(target)
m.replaceAll(replacement)
}
@@ -316,7 +344,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacer The function which maps a match to another string.
* @return The target string after replacements.
*/
- def replaceAllIn(target: java.lang.CharSequence, replacer: Match => String): String = {
+ def replaceAllIn(target: CharSequence, replacer: Match => String): String = {
val it = new Regex.MatchIterator(target, this, groupNames).replacementData
it foreach (md => it replace replacer(md))
it.replaced
@@ -343,7 +371,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacer The function which optionally maps a match to another string.
* @return The target string after replacements.
*/
- def replaceSomeIn(target: java.lang.CharSequence, replacer: Match => Option[String]): String = {
+ def replaceSomeIn(target: CharSequence, replacer: Match => Option[String]): String = {
val it = new Regex.MatchIterator(target, this, groupNames).replacementData
for (matchdata <- it ; replacement <- replacer(matchdata))
it replace replacement
@@ -359,7 +387,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @param replacement The string that will replace the match
* @return The resulting string
*/
- def replaceFirstIn(target: java.lang.CharSequence, replacement: String): String = {
+ def replaceFirstIn(target: CharSequence, replacement: String): String = {
val m = pattern.matcher(target)
m.replaceFirst(replacement)
}
@@ -370,7 +398,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return The array of strings computed by splitting the
* input around matches of this regexp
*/
- def split(toSplit: java.lang.CharSequence): Array[String] =
+ def split(toSplit: CharSequence): Array[String] =
pattern.split(toSplit)
/** Create a new Regex with the same pattern, but no requirement that
@@ -390,9 +418,11 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
*
* @return The new unanchored regex
*/
- def unanchored: UnanchoredRegex = new Regex(regex, groupNames: _*) with UnanchoredRegex { override def anchored = outer }
+ def unanchored: UnanchoredRegex = new Regex(pattern, groupNames: _*) with UnanchoredRegex { override def anchored = outer }
def anchored: Regex = this
+ def regex: String = pattern.pattern
+
/** The string defining the regular expression */
override def toString = regex
}
@@ -421,7 +451,7 @@ object Regex {
trait MatchData {
/** The source from where the match originated */
- val source: java.lang.CharSequence
+ val source: CharSequence
/** The names of the groups, or some empty sequence if one defined */
val groupNames: Seq[String]
@@ -459,25 +489,25 @@ object Regex {
/** The char sequence before first character of match,
* or `null` if nothing was matched */
- def before: java.lang.CharSequence =
+ def before: CharSequence =
if (start >= 0) source.subSequence(0, start)
else null
/** The char sequence before first character of match in group `i`,
* or `null` if nothing was matched for that group */
- def before(i: Int): java.lang.CharSequence =
+ def before(i: Int): CharSequence =
if (start(i) >= 0) source.subSequence(0, start(i))
else null
/** Returns char sequence after last character of match,
* or `null` if nothing was matched */
- def after: java.lang.CharSequence =
+ def after: CharSequence =
if (end >= 0) source.subSequence(end, source.length)
else null
/** The char sequence after last character of match in group `i`,
* or `null` if nothing was matched for that group */
- def after(i: Int): java.lang.CharSequence =
+ def after(i: Int): CharSequence =
if (end(i) >= 0) source.subSequence(end(i), source.length)
else null
@@ -501,8 +531,8 @@ object Regex {
/** Provides information about a succesful match.
*/
- class Match(val source: java.lang.CharSequence,
- matcher: Matcher,
+ class Match(val source: CharSequence,
+ private[matching] val matcher: Matcher,
val groupNames: Seq[String]) extends MatchData {
/** The index of the first matched character */
@@ -563,7 +593,7 @@ object Regex {
/** A class to step through a sequence of regex matches
*/
- class MatchIterator(val source: java.lang.CharSequence, val regex: Regex, val groupNames: Seq[String])
+ class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String])
extends AbstractIterator[String] with Iterator[String] with MatchData { self =>
protected[Regex] val matcher = regex.pattern.matcher(source)
diff --git a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala b/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala
index 520ac8cc2c..4e8504d346 100644
--- a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala
+++ b/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala
@@ -21,11 +21,12 @@ import scala.annotation.migration
* - `floatingPointNumber`
*/
trait JavaTokenParsers extends RegexParsers {
- /** Anything starting with an ASCII alphabetic character or underscore,
- * followed by zero or more repetitions of regex's `\w`.
+ /** Anything that is a valid Java identifier, according to
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8">The Java Language Spec</a>.
+ * Generally, this means a letter, followed by zero or more letters or numbers.
*/
def ident: Parser[String] =
- """[a-zA-Z_]\w*""".r
+ """\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*""".r
/** An integer, without sign or with a negative sign. */
def wholeNumber: Parser[String] =
"""-?\d+""".r
diff --git a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala b/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala
index 5d7386b5c1..3d04a3a00c 100644
--- a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala
+++ b/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala
@@ -50,7 +50,7 @@ class StdLexical extends Lexical with StdTokens {
def identChar = letter | elem('_')
// see `whitespace in `Scanners`
- def whitespace: Parser[Any] = rep(
+ def whitespace: Parser[Any] = rep[Any](
whitespaceChar
| '/' ~ '*' ~ comment
| '/' ~ '/' ~ rep( chrExcept(EofCh, '\n') )
diff --git a/src/library/scala/xml/dtd/DocType.scala b/src/library/scala/xml/dtd/DocType.scala
index 64aa7e2f74..78aacb2cea 100644
--- a/src/library/scala/xml/dtd/DocType.scala
+++ b/src/library/scala/xml/dtd/DocType.scala
@@ -15,7 +15,7 @@ package dtd
* @author Burak Emir
*
* @param name name of this DOCTYPE
- * @param extID None, or Some(external ID of this doctype)
+ * @param extID NoExternalID or the external ID of this doctype
* @param intSubset sequence of internal subset declarations
*/
case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl])
@@ -32,3 +32,9 @@ case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl])
"""<!DOCTYPE %s %s%s>""".format(name, extID.toString, intString)
}
}
+
+object DocType
+{
+ /** Creates a doctype with no external id, nor internal subset declarations. */
+ def apply(name: String): DocType = apply(name, NoExternalID, Nil)
+}
diff --git a/src/library/scala/xml/dtd/ExternalID.scala b/src/library/scala/xml/dtd/ExternalID.scala
index a0a5818d07..ccee5dbe5a 100644
--- a/src/library/scala/xml/dtd/ExternalID.scala
+++ b/src/library/scala/xml/dtd/ExternalID.scala
@@ -73,3 +73,14 @@ case class PublicID(publicId: String, systemId: String) extends ExternalID {
/** always empty */
def child = Nil
}
+
+/** A marker used when a `DocType` contains no external id.
+ *
+ * @author Michael Bayne
+ */
+object NoExternalID extends ExternalID {
+ val publicId = null
+ val systemId = null
+
+ override def toString = ""
+}
diff --git a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java
index 09cd485d6b..a9a56d124d 100644
--- a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java
+++ b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java
@@ -26,9 +26,35 @@ public class ASMTransformer implements ClassFileTransformer {
className.startsWith("instrumented/"));
}
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ public byte[] transform(final ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if (shouldTransform(className)) {
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
+ // this is copied verbatim from the superclass,
+ // except that we use the outer class loader
+ @Override protected String getCommonSuperClass(final String type1, final String type2) {
+ Class<?> c, d;
+ try {
+ c = Class.forName(type1.replace('/', '.'), false, classLoader);
+ d = Class.forName(type2.replace('/', '.'), false, classLoader);
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ if (c.isAssignableFrom(d)) {
+ return type1;
+ }
+ if (d.isAssignableFrom(c)) {
+ return type2;
+ }
+ if (c.isInterface() || d.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ c = c.getSuperclass();
+ } while (!c.isAssignableFrom(d));
+ return c.getName().replace('.', '/');
+ }
+ }
+ };
ProfilerVisitor visitor = new ProfilerVisitor(writer);
ClassReader reader = new ClassReader(classfileBuffer);
reader.accept(visitor, 0);
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
index ccc756c158..84d9832f97 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -70,10 +70,11 @@ class ConsoleRunner extends DirectRunner {
// true if a test path matches the --grep expression.
private def pathMatchesExpr(path: Path, expr: String) = {
def pred(p: Path) = file2String(p.toFile) contains expr
- def srcs = path.toDirectory.deepList() filter (_.hasExtension("scala", "java"))
+ def greppable(f: Path) = f.isFile && (f hasExtension ("scala", "java"))
+ def any(d: Path) = d.toDirectory.deepList() exists (f => greppable(f) && pred(f))
(path.isFile && pred(path)) ||
- (path.isDirectory && srcs.exists(pred)) ||
+ (path.isDirectory && any(path)) ||
(pred(path changeExtension "check"))
}
@@ -121,7 +122,7 @@ class ConsoleRunner extends DirectRunner {
val grepOption = parsed get "--grep"
val grepPaths = grepOption.toList flatMap { expr =>
val subjectDirs = testSetKinds map (srcDir / _ toDirectory)
- val testPaths = subjectDirs flatMap (_.files filter stdFilter)
+ val testPaths = subjectDirs flatMap (_.list filter stdFilter)
val paths = testPaths filter (p => pathMatchesExpr(p, expr))
if (paths.isEmpty)
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index 7a42853749..d4b9feecce 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -341,10 +341,34 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
val (scalaFiles, javaFiles) = g partition isScala
val allFiles = javaFiles ++ scalaFiles
+ /* The test can contain both java and scala files, each of which should be compiled with the corresponding
+ * compiler. Since the source files can reference each other both ways (java referencing scala classes and
+ * vice versa, the partest compilation routine attempts to reach a "bytecode fixpoint" between the two
+ * compilers -- that's when bytecode generated by each compiler implements the signatures expected by the other.
+ *
+ * In theory this property can't be guaranteed, as neither compiler can know what signatures the other
+ * compiler expects and how to implement them. (see SI-1240 for the full story)
+ *
+ * In practice, this happens in 3 steps:
+ * STEP1: feed all the files to scalac
+ * it will parse java files and obtain their expected signatures and generate bytecode for scala files
+ * STEP2: feed the java files to javac
+ * it will generate the bytecode for the java files and link to the scalac-generated bytecode for scala
+ * STEP3: only if there are both scala and java files, recompile the scala sources so they link to the correct
+ * java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the
+ * bytecode for java is already in place, we only feed the scala files to scalac so it will take the
+ * java signatures from the existing javac-generated bytecode
+ */
List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
- case (CompileSuccess, 1) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) // java + scala
- case (CompileSuccess, 2) if javaFiles.nonEmpty => javac(outDir, javaFiles, logFile) // java
- case (CompileSuccess, 3) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) // scala
+ case (CompileSuccess, 1) if scalaFiles.nonEmpty =>
+ compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile)
+ case (CompileSuccess, 2) if javaFiles.nonEmpty =>
+ javac(outDir, javaFiles, logFile)
+ case (CompileSuccess, 3) if scalaFiles.nonEmpty && javaFiles.nonEmpty =>
+ // TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests
+ // require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU
+ compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile)
+
case (outcome, _) => outcome
}
}
diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala
index df1c296d47..ccceeacb0a 100644
--- a/src/partest/scala/tools/partest/package.scala
+++ b/src/partest/scala/tools/partest/package.scala
@@ -45,7 +45,7 @@ package object partest {
def path2String(path: String) = file2String(new JFile(path))
def file2String(f: JFile) =
- try SFile(f).slurp()
+ try SFile(f).slurp(scala.io.Codec.UTF8)
catch { case _: FileNotFoundException => "" }
def basename(name: String): String = Path(name).stripExtension
@@ -74,7 +74,6 @@ package object partest {
def isPartestDebug: Boolean =
propOrEmpty("partest.debug") == "true"
-
import scala.language.experimental.macros
/**
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
index 539984c67f..86ea2c099b 100644
--- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
@@ -158,7 +158,7 @@ trait BaseTypeSeqs {
val parents = tp.parents
// Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG
val buf = new mutable.ListBuffer[Type]
- buf += tsym.tpe
+ buf += tsym.tpe_*
var btsSize = 1
if (parents.nonEmpty) {
val nparents = parents.length
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index 62ed130232..54570e478f 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -342,7 +342,7 @@ object ClassfileConstants {
case JAVA_ACC_PRIVATE => PRIVATE
case JAVA_ACC_PROTECTED => PROTECTED
case JAVA_ACC_FINAL => FINAL
- case JAVA_ACC_SYNTHETIC => SYNTHETIC
+ case JAVA_ACC_SYNTHETIC => SYNTHETIC | ARTIFACT // maybe should be just artifact?
case JAVA_ACC_STATIC => STATIC
case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED
case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT
@@ -372,7 +372,7 @@ object ClassfileConstants {
}
def methodFlags(jflags: Int): Long = {
initFields(jflags)
- translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE else 0)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0)
}
}
object FlagTranslation extends FlagTranslation { }
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 2bc9f02758..35acc2bcce 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -223,7 +223,7 @@ trait Definitions extends api.StandardDefinitions {
def fullyInitializeSymbol(sym: Symbol): Symbol = {
sym.initialize
fullyInitializeType(sym.info)
- fullyInitializeType(sym.tpe)
+ fullyInitializeType(sym.tpe_*)
sym
}
def fullyInitializeType(tp: Type): Type = {
@@ -312,6 +312,9 @@ trait Definitions extends api.StandardDefinitions {
lazy val ThrowableClass = getClassByName(sn.Throwable)
lazy val UninitializedErrorClass = requiredClass[UninitializedFieldError]
+ lazy val NPEConstructor = getMemberMethod(NullPointerExceptionClass, nme.CONSTRUCTOR) suchThat (_.paramss.flatten.isEmpty)
+ lazy val UninitializedFieldConstructor = UninitializedErrorClass.primaryConstructor
+
// fundamental reference classes
lazy val PartialFunctionClass = requiredClass[PartialFunction[_,_]]
lazy val AbstractPartialFunctionClass = requiredClass[scala.runtime.AbstractPartialFunction[_,_]]
@@ -407,7 +410,8 @@ trait Definitions extends api.StandardDefinitions {
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
def isJavaRepeatedParamType(tp: Type) = tp.typeSymbol == JavaRepeatedParamClass
def isRepeatedParamType(tp: Type) = isScalaRepeatedParamType(tp) || isJavaRepeatedParamType(tp)
- def isRepeated(param: Symbol) = isRepeatedParamType(param.tpe)
+ def isRepeated(param: Symbol) = isRepeatedParamType(param.tpe_*)
+ def isByName(param: Symbol) = isByNameParamType(param.tpe_*)
def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf
def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params)
@@ -546,7 +550,7 @@ trait Definitions extends api.StandardDefinitions {
// The given symbol represents either String.+ or StringAdd.+
def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+
- def isArrowAssoc(sym: Symbol) = ArrowAssocClass.tpe.decls.toList contains sym
+ def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass
// The given symbol is a method with the right name and signature to be a runnable java program.
def isJavaMainMethod(sym: Symbol) = (sym.name == nme.main) && (sym.info match {
@@ -666,6 +670,11 @@ trait Definitions extends api.StandardDefinitions {
case _ => Nil
}
+ def dropNullaryMethod(tp: Type) = tp match {
+ case NullaryMethodType(restpe) => restpe
+ case _ => tp
+ }
+
def unapplyUnwrap(tpe:Type) = tpe.finalResultType.normalize match {
case RefinedType(p :: _, _) => p.normalize
case tp => tp
@@ -730,7 +739,7 @@ trait Definitions extends api.StandardDefinitions {
* C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... en >: LBn <: UBn }.
*/
def classExistentialType(clazz: Symbol): Type =
- newExistentialType(clazz.typeParams, clazz.tpe)
+ newExistentialType(clazz.typeParams, clazz.tpe_*)
/** Given type U, creates a Type representing Class[_ <: U].
*/
@@ -859,6 +868,12 @@ trait Definitions extends api.StandardDefinitions {
removeRedundantObjects(parents)
}
+ /** Flatten curried parameter lists of a method type. */
+ def allParameters(tpe: Type): List[Symbol] = tpe match {
+ case MethodType(params, res) => params ::: allParameters(res)
+ case _ => Nil
+ }
+
def typeStringNoPackage(tp: Type) =
"" + tp stripPrefix tp.typeSymbol.enclosingPackage.fullName + "."
@@ -883,8 +898,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL)
lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL)
lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL)
- lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC)(_ => booltype)
- lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC)(_.typeConstructor)
+ lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_ => booltype)
+ lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_.typeConstructor)
lazy val Object_synchronized = newPolyMethod(1, ObjectClass, nme.synchronized_, FINAL)(tps =>
(Some(List(tps.head.typeConstructor)), tps.head.typeConstructor)
)
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index bb454b1df7..ce5d9daf3b 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -116,6 +116,20 @@ class ModifierFlags {
final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer
final val PRESUPER = 1L << 37 // value is evaluated before super call
final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit
+ final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode
+
+ /** Symbols which are marked ARTIFACT. (Expand this list?)
+ *
+ * - $outer fields and accessors
+ * - super accessors
+ * - protected accessors
+ * - lazy local accessors
+ * - bridge methods
+ * - default argument getters
+ * - evaluation-order preserving locals for right-associative and out-of-order named arguments
+ * - catch-expression storing vals
+ * - anything else which feels a setFlag(ARTIFACT)
+ */
// Overridden.
def flagToString(flag: Long): String = ""
@@ -165,7 +179,6 @@ class Flags extends ModifierFlags {
// A Java method's type is ``cooked'' by transforming raw types to existentials
final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED
- final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode
// ------- shift definitions -------------------------------------------------------
@@ -248,7 +261,7 @@ class Flags extends ModifierFlags {
/** These modifiers appear in TreePrinter output. */
final val PrintableFlags =
ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
- ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED
+ ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | ARTIFACT
/** When a symbol for a field is created, only these flags survive
* from Modifiers. Others which may be applied at creation time are:
@@ -420,7 +433,7 @@ class Flags extends ModifierFlags {
case VARARGS => "<varargs>" // (1L << 43)
case TRIEDCOOKING => "<triedcooking>" // (1L << 44)
case SYNCHRONIZED => "<synchronized>" // (1L << 45)
- case 0x400000000000L => "" // (1L << 46)
+ case ARTIFACT => "<artifact>" // (1L << 46)
case 0x800000000000L => "" // (1L << 47)
case 0x1000000000000L => "" // (1L << 48)
case 0x2000000000000L => "" // (1L << 49)
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index 43902c1930..ea8d6078ff 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -427,17 +427,17 @@ trait Importers extends api.Importers { self: SymbolTable =>
}
addFixup({
if (mytree != null) {
- val mysym = if (tree.hasSymbol) importSymbol(tree.symbol) else NoSymbol
+ val mysym = if (tree.hasSymbolField) importSymbol(tree.symbol) else NoSymbol
val mytpe = importType(tree.tpe)
mytree match {
case mytt: TypeTree =>
val tt = tree.asInstanceOf[from.TypeTree]
- if (mytree.hasSymbol) mytt.symbol = mysym
+ if (mytree.hasSymbolField) mytt.symbol = mysym
if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe)
if (tt.original != null) mytt.setOriginal(importTree(tt.original))
case _ =>
- if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol)
+ if (mytree.hasSymbolField) mytree.symbol = importSymbol(tree.symbol)
mytree.tpe = importType(tree.tpe)
}
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index fd5a7cf88b..eaa05bc89d 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -545,8 +545,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
case emptyValDef: AnyRef if emptyValDef eq self.emptyValDef =>
print("emptyValDef")
case tree: Tree =>
- val hasSymbol = tree.hasSymbol && tree.symbol != NoSymbol
- val isError = hasSymbol && tree.symbol.name.toString == nme.ERROR.toString
+ val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
+ val isError = hasSymbolField && tree.symbol.name.toString == nme.ERROR.toString
printProduct(
tree,
preamble = _ => {
@@ -559,7 +559,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
if (isError) print("<")
print(name)
if (isError) print(": error>")
- } else if (hasSymbol) {
+ } else if (hasSymbolField) {
tree match {
case _: Ident | _: Select | _: SelectFromTypeTree => print(tree.symbol)
case _ => print(tree.symbol.name)
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index 2424e75949..38e33c001c 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -48,6 +48,7 @@ abstract class SymbolTable extends macros.Universe
def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
def shouldLogAtThisPhase = false
+ def isPastTyper = false
@deprecated("Give us a reason", "2.10.0")
def abort(): Nothing = abort("unknown error")
@@ -65,7 +66,7 @@ abstract class SymbolTable extends macros.Universe
private[scala] def printCaller[T](msg: String)(result: T) = {
Console.err.println("%s: %s\nCalled from: %s".format(msg, result,
- (new Throwable).getStackTrace.drop(2).take(15).mkString("\n")))
+ (new Throwable).getStackTrace.drop(2).take(50).mkString("\n")))
result
}
@@ -133,7 +134,7 @@ abstract class SymbolTable extends macros.Universe
type RunId = Int
final val NoRunId = 0
- // sigh, this has to be public or atPhase doesn't inline.
+ // sigh, this has to be public or enteringPhase doesn't inline.
var phStack: List[Phase] = Nil
private[this] var ph: Phase = NoPhase
private[this] var per = NoPeriod
@@ -196,23 +197,17 @@ abstract class SymbolTable extends macros.Universe
p != NoPhase && phase.id > p.id
/** Perform given operation at given phase. */
- @inline final def atPhase[T](ph: Phase)(op: => T): T = {
+ @inline final def enteringPhase[T](ph: Phase)(op: => T): T = {
val saved = pushPhase(ph)
try op
finally popPhase(saved)
}
+ @inline final def exitingPhase[T](ph: Phase)(op: => T): T = enteringPhase(ph.next)(op)
+ @inline final def enteringPrevPhase[T](op: => T): T = enteringPhase(phase.prev)(op)
- /** Since when it is to be "at" a phase is inherently ambiguous,
- * a couple unambiguously named methods.
- */
- @inline final def beforePhase[T](ph: Phase)(op: => T): T = atPhase(ph)(op)
- @inline final def afterPhase[T](ph: Phase)(op: => T): T = atPhase(ph.next)(op)
- @inline final def afterCurrentPhase[T](op: => T): T = atPhase(phase.next)(op)
- @inline final def beforePrevPhase[T](op: => T): T = atPhase(phase.prev)(op)
-
- @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T =
- if (isAtPhaseAfter(target)) atPhase(target)(op) else op
+ @inline final def enteringPhaseNotLaterThan[T](target: Phase)(op: => T): T =
+ if (isAtPhaseAfter(target)) enteringPhase(target)(op) else op
final def isValid(period: Period): Boolean =
period != 0 && runId(period) == currentRunId && {
@@ -339,6 +334,11 @@ abstract class SymbolTable extends macros.Universe
/** Is this symbol table a part of a compiler universe?
*/
def isCompilerUniverse = false
+
+ @deprecated("Use enteringPhase", "2.10.0")
+ @inline final def atPhase[T](ph: Phase)(op: => T): T = enteringPhase(ph)(op)
+ @deprecated("Use enteringPhaseNotLaterThan", "2.10.0")
+ @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = enteringPhaseNotLaterThan(target)(op)
}
object SymbolTableStats {
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index a6f156f947..8cebfabe6f 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -8,7 +8,7 @@ package internal
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
-import util.Statistics
+import util.{ Statistics, shortClassOfInstance }
import Flags._
import scala.annotation.tailrec
import scala.reflect.io.AbstractFile
@@ -182,7 +182,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (isGADTSkolem) " (this is a GADT skolem)"
else ""
- def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$")
+ def shortSymbolClass = shortClassOfInstance(this)
def symbolCreationString: String = (
"%s%25s | %-40s | %s".format(
if (settings.uniqid.value) "%06d | ".format(id) else "",
@@ -642,7 +642,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isStaticModule = isModule && isStatic && !isMethod
final def isThisSym = isTerm && owner.thisSym == this
final def isError = hasFlag(IS_ERROR)
- final def isErroneous = isError || isInitialized && tpe.isErroneous
+ final def isErroneous = isError || isInitialized && tpe_*.isErroneous
def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem
@@ -709,10 +709,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
- def isSerializable = (
- info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass)
- || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated
- )
+ def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass)
def hasBridgeAnnotation = hasAnnotation(BridgeClass)
def isDeprecated = hasAnnotation(DeprecatedAttr)
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
@@ -808,6 +805,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isTopLevelModule = hasFlag(MODULE) && owner.isPackageClass
+ /** A helper function for isEffectivelyFinal. */
+ private def isNotOverridden = (
+ owner.isClass && (
+ owner.isEffectivelyFinal
+ || owner.isSealed && owner.children.forall(c => c.isEffectivelyFinal && (overridingSymbol(c) == NoSymbol))
+ )
+ )
+
/** Is this symbol effectively final? I.e, it cannot be overridden */
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
@@ -815,8 +820,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| isTerm && (
isPrivate
|| isLocal
- || owner.isClass && owner.isEffectivelyFinal
- )
+ || isNotOverridden
+ )
)
/** Is this symbol locally defined? I.e. not accessed from outside `this` instance */
@@ -1178,16 +1183,57 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
- /** Get type. The type of a symbol is:
- * for a type symbol, the type corresponding to the symbol itself,
- * @M you should use tpeHK for a type symbol with type parameters if
- * the kind of the type need not be *, as tpe introduces dummy arguments
- * to generate a type of kind *
- * for a term symbol, its usual type.
- * See the tpe/tpeHK overrides in TypeSymbol for more.
+ /** The "type" of this symbol. The type of a term symbol is its usual
+ * type. A TypeSymbol is more complicated; see that class for elaboration.
+ * Since tpe forwards to tpe_*, if you call it on a type symbol with unapplied
+ * type parameters, the type returned will contain dummies types. These will
+ * hide legitimate errors or create spurious ones if used as normal types.
+ */
+ final def tpe: Type = tpe_*
+
+ /** typeConstructor throws an exception when called on term
+ * symbols; this is a more forgiving alternative. Calls
+ * typeConstructor on TypeSymbols, returns info otherwise.
*/
- def tpe: Type = info
- def tpeHK: Type = tpe
+ def tpeHK: Type = info
+
+ /** Only applicable to TypeSymbols, it is the type corresponding
+ * to the symbol itself. For instance, the type of a List might
+ * be List[Int] - the same symbol's typeConstructor is simply List.
+ * One might be tempted to write that as List[_], and in some
+ * contexts this is possible, but it is discouraged because it is
+ * syntactically indistinguishable from and easily confused with the
+ * type List[T] forSome { type T; }, which can also be written List[_].
+ */
+ def typeConstructor: Type = (
+ // Avoiding a third override in NoSymbol to preserve bimorphism
+ if (this eq NoSymbol)
+ abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)")
+ else
+ abort("typeConstructor inapplicable for " + this)
+ )
+
+ /** The type of this symbol, guaranteed to be of kind *.
+ * If there are unapplied type parameters, they will be
+ * substituted with dummy type arguments derived from the
+ * type parameters. Such types are not valid in a general
+ * sense and will cause difficult-to-find bugs if allowed
+ * to roam free.
+ *
+ * If you call tpe_* explicitly to obtain these types,
+ * you are responsible for them as if it they were your own
+ * minor children.
+ */
+ def tpe_* : Type = info
+
+ // Alternate implementation of def tpe for warning about misuse,
+ // disabled to keep the method maximally hotspot-friendly:
+ // def tpe: Type = {
+ // val result = tpe_*
+ // if (settings.debug.value && result.typeArgs.nonEmpty)
+ // printCaller(s"""Call to ${this.tpe} created $result: call tpe_* or tpeHK""")("")
+ // result
+ // }
/** Get type info associated with symbol at current phase, after
* ensuring that symbol is initialized (i.e. type is completed).
@@ -1240,9 +1286,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** Set initial info. */
- def setInfo(info: Type): this.type = { info_=(info); this }
+ def setInfo(info: Type): this.type = { info_=(info); this }
/** Modifies this symbol's info in place. */
- def modifyInfo(f: Type => Type): this.type = setInfo(f(info))
+ def modifyInfo(f: Type => Type): this.type = setInfo(f(info))
/** Substitute second list of symbols for first in current info. */
def substInfo(syms0: List[Symbol], syms1: List[Symbol]): this.type =
if (syms0.isEmpty) this
@@ -1349,6 +1395,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (!isInitialized) info
this
}
+ def maybeInitialize = {
+ try { initialize ; true }
+ catch { case _: CyclicReference => debuglog("Hit cycle in maybeInitialize of $this") ; false }
+ }
/** Called when the programmer requests information that might require initialization of the underlying symbol.
*
@@ -1411,21 +1461,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* This is done in checkAccessible and overriding checks in refchecks
* We can't do this on class loading because it would result in infinite cycles.
*/
- final def cookJavaRawInfo() {
- if (hasFlag(TRIEDCOOKING)) return else setFlag(TRIEDCOOKING) // only try once...
- val oldInfo = info
- doCookJavaRawInfo()
- }
+ def cookJavaRawInfo(): Unit = {
+ // only try once...
+ if (this hasFlag TRIEDCOOKING)
+ return
- protected def doCookJavaRawInfo(): Unit
-
- /** The type constructor of a symbol is:
- * For a type symbol, the type corresponding to the symbol itself,
- * excluding parameters.
- * Not applicable for term symbols.
- */
- def typeConstructor: Type =
- abort("typeConstructor inapplicable for " + this)
+ this setFlag TRIEDCOOKING
+ info // force the current info
+ if (isJavaDefined || isType && owner.isJavaDefined)
+ this modifyInfo rawToExistential
+ else if (isOverloaded)
+ alternatives withFilter (_.isJavaDefined) foreach (_ modifyInfo rawToExistential)
+ }
/** The logic approximately boils down to finding the most recent phase
* which immediately follows any of parser, namer, typer, or erasure.
@@ -1449,7 +1496,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def unsafeTypeParams: List[Symbol] =
if (isMonomorphicType) Nil
- else atPhase(unsafeTypeParamPhase)(rawInfo.typeParams)
+ else enteringPhase(unsafeTypeParamPhase)(rawInfo.typeParams)
/** The type parameters of this symbol.
* assumption: if a type starts out as monomorphic, it will not acquire
@@ -1461,9 +1508,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// analogously to the "info" getter, here we allow for two completions:
// one: sourceCompleter to LazyType, two: LazyType to completed type
if (validTo == NoPeriod)
- atPhase(phaseOf(infos.validFrom))(rawInfo load this)
+ enteringPhase(phaseOf(infos.validFrom))(rawInfo load this)
if (validTo == NoPeriod)
- atPhase(phaseOf(infos.validFrom))(rawInfo load this)
+ enteringPhase(phaseOf(infos.validFrom))(rawInfo load this)
rawInfo.typeParams
}
@@ -1709,7 +1756,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def thisSym: Symbol = this
/** The type of `this` in a class, or else the type of the symbol itself. */
- def typeOfThis = thisSym.tpe
+ def typeOfThis = thisSym.tpe_*
/** If symbol is a class, the type <code>this.type</code> in this class,
* otherwise <code>NoPrefix</code>.
@@ -1885,7 +1932,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| (that.sourceFile eq null)
|| (this.sourceFile.path == that.sourceFile.path) // Cheap possibly wrong check, then expensive normalization
|| (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath)
- )
+ )
)
/** The internal representation of classes and objects:
@@ -2501,36 +2548,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
name = nme.expandedName(name.toTermName, base)
}
}
-
- protected def doCookJavaRawInfo() {
- def cook(sym: Symbol) {
- require(sym.isJavaDefined, sym)
- // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
- // object rawToExistentialInJava extends TypeMap {
- // def apply(tp: Type): Type = tp match {
- // // any symbol that occurs in a java sig, not just java symbols
- // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
- // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
- // val eparams = typeParamsToExistentials(sym, sym.typeParams)
- // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
- // case _ =>
- // mapOver(tp)
- // }
- // }
- val tpe1 = rawToExistential(sym.tpe)
- // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1)
- if (tpe1 ne sym.tpe) {
- sym.setInfo(tpe1)
- }
- }
-
- if (isJavaDefined)
- cook(this)
- else if (isOverloaded)
- for (sym2 <- alternatives)
- if (sym2.isJavaDefined)
- cook(sym2)
- }
}
implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol])
@@ -2622,6 +2639,20 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
owner.newNonClassSymbol(name, pos, newFlags)
}
+ /** Let's say you have a type definition
+ *
+ * {{{
+ * type T <: Number
+ * }}}
+ *
+ * and tsym is the symbol corresponding to T. Then
+ *
+ * {{{
+ * tsym is an instance of AbstractTypeSymbol
+ * tsym.info = TypeBounds(Nothing, Number)
+ * tsym.tpe = TypeRef(NoPrefix, T, List())
+ * }}}
+ */
class AbstractTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
extends TypeSymbol(initOwner, initPos, initName) {
type TypeOfClonedSymbol = TypeSymbol
@@ -2690,63 +2721,57 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private def newPrefix = if (this hasFlag EXISTENTIAL | PARAM) NoPrefix else owner.thisType
private def newTypeRef(targs: List[Type]) = typeRef(newPrefix, this, targs)
- /** Let's say you have a type definition
+ /** A polymorphic type symbol has two distinct "types":
*
- * {{{
- * type T <: Number
- * }}}
+ * tpe_* a TypeRef with: dummy type args, no unapplied type parameters, and kind *
+ * tpeHK a TypeRef with: no type args, unapplied type parameters, and
+ * kind (*,*,...,*) => * depending on the number of tparams.
*
- * and tsym is the symbol corresponding to T. Then
- *
- * {{{
- * tsym.info = TypeBounds(Nothing, Number)
- * tsym.tpe = TypeRef(NoPrefix, T, List())
- * }}}
- */
- override def tpe: Type = {
- if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
- if (tpePeriod != currentPeriod) {
- if (isValid(tpePeriod)) {
- tpePeriod = currentPeriod
- } else {
- if (isInitialized) tpePeriod = currentPeriod
- tpeCache = NoType
- val targs =
- if (phase.erasedTypes && this != ArrayClass) List()
- else unsafeTypeParams map (_.typeConstructor)
- //@M! use typeConstructor to generate dummy type arguments,
- // sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
- // memberType should be used instead, that's why it uses tpeHK and not tpe
- tpeCache = newTypeRef(targs)
- }
- }
- assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
+ * The dummy type args in tpe_* are created by wrapping a TypeRef
+ * around the type parameter symbols. Types containing dummies will
+ * hide errors or introduce spurious ones if they are passed around
+ * as if normal types. They should only be used in local operations
+ * where they will either be discarded immediately after, or will
+ * undergo substitution in which the dummies are replaced by actual
+ * type arguments.
+ */
+ override def tpe_* : Type = {
+ maybeUpdateTypeCache()
tpeCache
}
-
- /** @M -- tpe vs tpeHK:
- *
- * tpe: creates a TypeRef with dummy type arguments and kind *
- * tpeHK: creates a TypeRef with no type arguments but with type parameters
- *
- * If typeParams is nonEmpty, calling tpe may hide errors or
- * introduce spurious ones. (For example, when deriving a type from
- * the symbol of a type argument that may be higher-kinded.) As far
- * as I can tell, it only makes sense to call tpe in conjunction
- * with a substitution that replaces the generated dummy type
- * arguments by their actual types.
- *
- * TODO: the above conditions desperately need to be enforced by code.
- */
- override def tpeHK = typeConstructor // @M! used in memberType
-
override def typeConstructor: Type = {
+ maybeUpdateTyconCache()
+ tyconCache
+ }
+ override def tpeHK: Type = typeConstructor
+
+ private def maybeUpdateTyconCache() {
if ((tyconCache eq null) || tyconRunId != currentRunId) {
tyconCache = newTypeRef(Nil)
tyconRunId = currentRunId
}
assert(tyconCache ne null)
- tyconCache
+ }
+ private def maybeUpdateTypeCache() {
+ if (tpePeriod != currentPeriod) {
+ if (isValid(tpePeriod))
+ tpePeriod = currentPeriod
+ else
+ updateTypeCache() // perform the actual update
+ }
+ }
+ private def updateTypeCache() {
+ if (tpeCache eq NoType)
+ throw CyclicReference(this, typeConstructor)
+
+ if (isInitialized)
+ tpePeriod = currentPeriod
+
+ tpeCache = NoType // cycle marker
+ tpeCache = newTypeRef(
+ if (phase.erasedTypes && this != ArrayClass || unsafeTypeParams.isEmpty) Nil
+ else unsafeTypeParams map (_.typeConstructor)
+ )
}
override def info_=(tp: Type) {
@@ -2772,15 +2797,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* public class Test1<T extends Test3> {}
* info for T in Test1 should be >: Nothing <: Test3[_]
*/
- protected def doCookJavaRawInfo() {
- if (isJavaDefined || owner.isJavaDefined) {
- val tpe1 = rawToExistential(info)
- // println("cooking type: "+ this +": "+ info +" to "+ tpe1)
- if (tpe1 ne info) {
- setInfo(tpe1)
- }
- }
- }
if (Statistics.hotEnabled) Statistics.incCounter(typeSymbolCount)
}
@@ -3184,15 +3200,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def info: Type = NoType
override def existentialBound: Type = NoType
override def rawInfo: Type = NoType
- protected def doCookJavaRawInfo() {}
override def accessBoundary(base: Symbol): Symbol = enclosingRootClass
def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()")
override def originalEnclosingMethod = this
override def owner: Symbol =
abort("no-symbol does not have an owner")
- override def typeConstructor: Type =
- abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)")
}
protected def makeNoSymbol: NoSymbol = new NoSymbol
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index ebf0998573..6ce93d93b2 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -165,17 +165,36 @@ abstract class TreeGen extends macros.TreeBuilder {
This(sym.name.toTypeName) setSymbol sym setType sym.thisType
def mkAttributedIdent(sym: Symbol): Tree =
- Ident(sym.name) setSymbol sym setType sym.tpe
+ Ident(sym.name) setSymbol sym setType sym.tpeHK
def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = {
// Tests involving the repl fail without the .isEmptyPackage condition.
if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
mkAttributedIdent(sym)
else {
+ // Have to recognize anytime a selection is made on a package
+ // so it can be rewritten to foo.bar.`package`.name rather than
+ // foo.bar.name if name is in the package object.
+ // TODO - factor out the common logic between this and
+ // the Typers method "isInPackageObject", used in typedIdent.
+ val qualsym = (
+ if (qual.tpe ne null) qual.tpe.typeSymbol
+ else if (qual.symbol ne null) qual.symbol
+ else NoSymbol
+ )
+ val needsPackageQualifier = (
+ (sym ne null)
+ && qualsym.isPackage
+ && !sym.isDefinedInPackage
+ )
val pkgQualifier =
- if (sym != null && sym.owner.isPackageObjectClass && sym.effectiveOwner == qual.tpe.typeSymbol) {
- val obj = sym.owner.sourceModule
- Select(qual, nme.PACKAGE) setSymbol obj setType singleType(qual.tpe, obj)
+ if (needsPackageQualifier) {
+ // The owner of a symbol which requires package qualification may be the
+ // package object iself, but it also could be any superclass of the package
+ // object. In the latter case, we must go through the qualifier's info
+ // to obtain the right symbol.
+ val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE
+ Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject)
}
else qual
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 68decc27f5..66326c90e9 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -104,6 +104,34 @@ abstract class TreeInfo {
false
}
+ /** As if the name of the method didn't give it away,
+ * this logic is designed around issuing helpful
+ * warnings and minimizing spurious ones. That means
+ * don't reuse it for important matters like inlining
+ * decisions.
+ */
+ def isPureExprForWarningPurposes(tree: Tree) = tree match {
+ case EmptyTree | Literal(Constant(())) => false
+ case _ =>
+ def isWarnableRefTree = tree match {
+ case t: RefTree => isExprSafeToInline(t.qualifier) && t.symbol != null && t.symbol.isAccessor
+ case _ => false
+ }
+ def isWarnableSymbol = {
+ val sym = tree.symbol
+ (sym == null) || !(sym.isModule || sym.isLazy) || {
+ debuglog("'Pure' but side-effecting expression in statement position: " + tree)
+ false
+ }
+ }
+
+ ( !tree.isErrorTyped
+ && (isExprSafeToInline(tree) || isWarnableRefTree)
+ && isWarnableSymbol
+ )
+ }
+
+
@deprecated("Use isExprSafeToInline instead", "2.10.0")
def isPureExpr(tree: Tree) = isExprSafeToInline(tree)
@@ -397,15 +425,31 @@ abstract class TreeInfo {
case _ => false
}
- /** Does this CaseDef catch Throwable? */
- def catchesThrowable(cdef: CaseDef) = catchesAllOf(cdef, ThrowableClass.tpe)
+ private def hasNoSymbol(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- /** Does this CaseDef catch everything of a certain Type? */
- def catchesAllOf(cdef: CaseDef, threshold: Type) =
- isDefaultCase(cdef) || (cdef.guard.isEmpty && (unbind(cdef.pat) match {
- case Typed(Ident(nme.WILDCARD), tpt) => (tpt.tpe != null) && (threshold <:< tpt.tpe)
- case _ => false
- }))
+ /** If this CaseDef assigns a name to its top-level pattern,
+ * in the form 'expr @ pattern' or 'expr: pattern', returns
+ * the name. Otherwise, nme.NO_NAME.
+ *
+ * Note: in the case of Constant patterns such as 'case x @ "" =>',
+ * the pattern matcher eliminates the binding and inlines the constant,
+ * so as far as this method is likely to be able to determine,
+ * the name is NO_NAME.
+ */
+ def assignedNameOfPattern(cdef: CaseDef): Name = cdef.pat match {
+ case Bind(name, _) => name
+ case Ident(name) => name
+ case _ => nme.NO_NAME
+ }
+
+ /** Does this CaseDef catch Throwable? */
+ def catchesThrowable(cdef: CaseDef) = (
+ cdef.guard.isEmpty && (unbind(cdef.pat) match {
+ case Ident(nme.WILDCARD) => true
+ case i@Ident(name) => hasNoSymbol(i)
+ case _ => false
+ })
+ )
/** Is this pattern node a catch-all or type-test pattern? */
def isCatchCase(cdef: CaseDef) = cdef match {
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index d6b4f18855..4bb88145b3 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -31,7 +31,8 @@ trait Trees extends api.Trees { self: SymbolTable =>
def symbol: Symbol = null //!!!OPT!!! symbol is about 3% of hot compile times -- megamorphic dispatch?
def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) }
def setSymbol(sym: Symbol): this.type = { symbol = sym; this }
- def hasSymbol = false
+ def hasSymbolField = false
+ @deprecated("Use hasSymbolField", "2.11.0") def hasSymbol = hasSymbolField
def isDef = false
@@ -62,7 +63,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
private[scala] def copyAttrs(tree: Tree): this.type = {
rawatt = tree.rawatt
tpe = tree.tpe
- if (hasSymbol) symbol = tree.symbol
+ if (hasSymbolField) symbol = tree.symbol
this
}
@@ -210,7 +211,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
trait TypTree extends Tree with TypTreeApi
abstract class SymTree extends Tree with SymTreeContextApi {
- override def hasSymbol = true
+ override def hasSymbolField = true
override var symbol: Symbol = NoSymbol
}
@@ -413,6 +414,16 @@ trait Trees extends api.Trees { self: SymbolTable =>
def ApplyConstructor(tpt: Tree, args: List[Tree]) = Apply(Select(New(tpt), nme.CONSTRUCTOR), args)
+ // Creates a constructor call from the constructor symbol. This is
+ // to avoid winding up with an OverloadedType for the constructor call.
+ def NewFromConstructor(constructor: Symbol, args: Tree*) = {
+ assert(constructor.isConstructor, constructor)
+ val instance = New(TypeTree(constructor.owner.tpe))
+ val init = Select(instance, nme.CONSTRUCTOR) setSymbol constructor
+
+ Apply(init, args.toList)
+ }
+
case class ApplyDynamic(qual: Tree, args: List[Tree]) extends SymTree with TermTree
case class Super(qual: Tree, mix: TypeName) extends TermTree with SuperApi {
@@ -1403,7 +1414,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe)
- if (tree.hasSymbol) {
+ if (tree.hasSymbolField) {
subst(from, to)
tree match {
case Ident(name0) if tree.symbol != NoSymbol =>
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 403bf7d492..1d3567b381 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -22,6 +22,8 @@ import util.ThreeValues._
// internal: error
case WildcardType =>
// internal: unknown
+ case BoundedWildcardType(bounds) =>
+ // internal: unknown
case NoType =>
case NoPrefix =>
case ThisType(sym) =>
@@ -66,9 +68,7 @@ import util.ThreeValues._
// a type variable
// Replace occurrences of type parameters with type vars, where
// inst is the instantiation and constr is a list of bounds.
- case DeBruijnIndex(level, index, args)
- // for dependent method types: a type referring to a method parameter.
- case ErasedValueType(tref)
+ case ErasedValueType(clazz, underlying)
// only used during erasure of derived value classes.
*/
@@ -91,6 +91,7 @@ trait Types extends api.Types { self: SymbolTable =>
private final val printLubs = sys.props contains "scalac.debug.lub"
private final val traceTypeVars = sys.props contains "scalac.debug.tvar"
+ private final val breakCycles = settings.breakCycles.value
/** In case anyone wants to turn off lub verification without reverting anything. */
private final val verifyLubs = true
/** In case anyone wants to turn off type parameter bounds being used
@@ -735,6 +736,7 @@ trait Types extends api.Types { self: SymbolTable =>
* }}}
*/
def memberInfo(sym: Symbol): Type = {
+ require(sym ne NoSymbol, this)
sym.info.asSeenFrom(this, sym.owner)
}
@@ -1037,69 +1039,66 @@ trait Types extends api.Types { self: SymbolTable =>
}
def findMembers(excludedFlags: Long, requiredFlags: Long): Scope = {
- // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
- // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
- // without this, the matchesType call would lead to type variables on both sides
- // of a subtyping/equality judgement, which can lead to recursive types being constructed.
- // See (t0851) for a situation where this happens.
- val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
-
- if (Statistics.canEnable) Statistics.incCounter(findMembersCount)
- val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMembersNanos) else null
-
- //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var members: Scope = null
- var required = requiredFlags
- var excluded = excludedFlags | DEFERRED
- var continue = true
- var self: Type = null
- while (continue) {
- continue = false
- val bcs0 = baseClasses
- var bcs = bcs0
- while (!bcs.isEmpty) {
- val decls = bcs.head.info.decls
- var entry = decls.elems
- while (entry ne null) {
- val sym = entry.sym
- val flags = sym.flags
- if ((flags & required) == required) {
- val excl = flags & excluded
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- (flags & PrivateLocal) != PrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (members eq null) members = newFindMemberScope
- var others: ScopeEntry = members.lookupEntry(sym.name)
- var symtpe: Type = null
- while ((others ne null) && {
- val other = others.sym
- (other ne sym) &&
- ((other.owner eq sym.owner) ||
- (flags & PRIVATE) != 0 || {
- if (self eq null) self = this.narrow
- if (symtpe eq null) symtpe = self.memberType(sym)
- !(self.memberType(other) matches symtpe)
- })}) {
- others = members lookupNextEntry others
+ def findMembersInternal: Scope = {
+ var members: Scope = null
+ if (Statistics.canEnable) Statistics.incCounter(findMembersCount)
+ val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMembersNanos) else null
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var required = requiredFlags
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.elems
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (members eq null) members = newFindMemberScope
+ var others: ScopeEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.sym
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = members lookupNextEntry others
+ }
+ if (others eq null) members enter sym
+ } else if (excl == DEFERRED) {
+ continue = true
}
- if (others eq null) members enter sym
- } else if (excl == DEFERRED) {
- continue = true
}
- }
- entry = entry.next
- } // while (entry ne null)
- // excluded = excluded | LOCAL
- bcs = bcs.tail
- } // while (!bcs.isEmpty)
- required |= DEFERRED
- excluded &= ~(DEFERRED.toLong)
- } // while (continue)
- if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- if (members eq null) EmptyScope else members
+ entry = entry.next
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = bcs.tail
+ } // while (!bcs.isEmpty)
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
+ } // while (continue)
+ if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
+ if (members eq null) EmptyScope else members
+ }
+
+ if (this.isGround) findMembersInternal
+ else suspendingTypeVars(typeVarsInType(this))(findMembersInternal)
}
/**
@@ -1113,102 +1112,98 @@ trait Types extends api.Types { self: SymbolTable =>
*/
//TODO: use narrow only for modules? (correct? efficiency gain?)
def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = {
- // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
- // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
- // without this, the matchesType call would lead to type variables on both sides
- // of a subtyping/equality judgement, which can lead to recursive types being constructed.
- // See (t0851) for a situation where this happens.
- val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
-
- if (Statistics.canEnable) Statistics.incCounter(findMemberCount)
- val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMemberNanos) else null
-
- //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var member: Symbol = NoSymbol
- var members: List[Symbol] = null
- var lastM: ::[Symbol] = null
- var membertpe: Type = null
- var required = requiredFlags
- var excluded = excludedFlags | DEFERRED
- var continue = true
- var self: Type = null
-
- while (continue) {
- continue = false
- val bcs0 = baseClasses
- var bcs = bcs0
- while (!bcs.isEmpty) {
- val decls = bcs.head.info.decls
- var entry = decls.lookupEntry(name)
- while (entry ne null) {
- val sym = entry.sym
- val flags = sym.flags
- if ((flags & required) == required) {
- val excl = flags & excluded
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- (flags & PrivateLocal) != PrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (name.isTypeName || stableOnly && sym.isStable) {
- if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- return sym
- } else if (member eq NoSymbol) {
- member = sym
- } else if (members eq null) {
- if ((member ne sym) &&
- ((member.owner eq sym.owner) ||
- (flags & PRIVATE) != 0 || {
- if (self eq null) self = this.narrow
- if (membertpe eq null) membertpe = self.memberType(member)
- !(membertpe matches self.memberType(sym))
- })) {
- lastM = new ::(sym, null)
- members = member :: lastM
- }
- } else {
- var others: List[Symbol] = members
- var symtpe: Type = null
- while ((others ne null) && {
- val other = others.head
- (other ne sym) &&
- ((other.owner eq sym.owner) ||
+ def findMemberInternal: Symbol = {
+ var member: Symbol = NoSymbol
+ var members: List[Symbol] = null
+ var lastM: ::[Symbol] = null
+ if (Statistics.canEnable) Statistics.incCounter(findMemberCount)
+ val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMemberNanos) else null
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var membertpe: Type = null
+ var required = requiredFlags
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.lookupEntry(name)
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (name.isTypeName || stableOnly && sym.isStable) {
+ if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
+ return sym
+ } else if (member eq NoSymbol) {
+ member = sym
+ } else if (members eq null) {
+ if ((member ne sym) &&
+ ((member.owner eq sym.owner) ||
(flags & PRIVATE) != 0 || {
if (self eq null) self = this.narrow
- if (symtpe eq null) symtpe = self.memberType(sym)
- !(self.memberType(other) matches symtpe)
- })}) {
- others = others.tail
- }
- if (others eq null) {
- val lastM1 = new ::(sym, null)
- lastM.tl = lastM1
- lastM = lastM1
+ if (membertpe eq null) membertpe = self.memberType(member)
+ !(membertpe matches self.memberType(sym))
+ })) {
+ lastM = new ::(sym, null)
+ members = member :: lastM
+ }
+ } else {
+ var others: List[Symbol] = members
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.head
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = others.tail
+ }
+ if (others eq null) {
+ val lastM1 = new ::(sym, null)
+ lastM.tl = lastM1
+ lastM = lastM1
+ }
}
+ } else if (excl == DEFERRED) {
+ continue = true
}
- } else if (excl == DEFERRED) {
- continue = true
}
- }
- entry = decls lookupNextEntry entry
- } // while (entry ne null)
- // excluded = excluded | LOCAL
- bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
- } // while (!bcs.isEmpty)
- required |= DEFERRED
- excluded &= ~(DEFERRED.toLong)
- } // while (continue)
- if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- if (members eq null) {
- if (member == NoSymbol) if (Statistics.canEnable) Statistics.incCounter(noMemberCount)
- member
- } else {
- if (Statistics.canEnable) Statistics.incCounter(multMemberCount)
- lastM.tl = Nil
- baseClasses.head.newOverloaded(this, members)
+ entry = decls lookupNextEntry entry
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
+ } // while (!bcs.isEmpty)
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
+ } // while (continue)
+ if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
+ if (members eq null) {
+ if (member == NoSymbol) if (Statistics.canEnable) Statistics.incCounter(noMemberCount)
+ member
+ } else {
+ if (Statistics.canEnable) Statistics.incCounter(multMemberCount)
+ lastM.tl = Nil
+ baseClasses.head.newOverloaded(this, members)
+ }
}
+
+ if (this.isGround) findMemberInternal
+ else suspendingTypeVars(typeVarsInType(this))(findMemberInternal)
}
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
@@ -1412,7 +1407,7 @@ trait Types extends api.Types { self: SymbolTable =>
def apply(sym: Symbol): Type = (
if (!phase.erasedTypes) unique(new UniqueThisType(sym))
else if (sym.isImplClass) sym.typeOfThis
- else sym.tpe
+ else sym.tpe_*
)
}
@@ -1623,6 +1618,38 @@ trait Types extends api.Types { self: SymbolTable =>
)
}
+ protected def computeBaseClasses(tpe: Type): List[Symbol] = {
+ val parents = tpe.parents // adriaan says tpe.parents does work sometimes, so call it only once
+ val baseTail = (
+ if (parents.isEmpty || parents.head.isInstanceOf[PackageTypeRef]) Nil
+ else {
+ //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
+ // optimized, since this seems to be performance critical
+ val superclazz = parents.head // parents.isEmpty was already excluded
+ var mixins = parents.tail
+ val sbcs = superclazz.baseClasses
+ var bcs = sbcs
+ def isNew(clazz: Symbol): Boolean = (
+ superclazz.baseTypeIndex(clazz) < 0 &&
+ { var p = bcs;
+ while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
+ p eq sbcs
+ }
+ )
+ while (!mixins.isEmpty) {
+ def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
+ if (mbcs.isEmpty) bcs
+ else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
+ else addMixinBaseClasses(mbcs.tail)
+ bcs = addMixinBaseClasses(mixins.head.baseClasses)
+ mixins = mixins.tail
+ }
+ bcs
+ }
+ )
+ tpe.typeSymbol :: baseTail
+ }
+
protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = {
val period = tpe.baseTypeSeqPeriod
if (period != currentPeriod) {
@@ -1642,7 +1669,7 @@ trait Types extends api.Types { self: SymbolTable =>
val paramToVarMap = varToParamMap map (_.swap)
val varToParam = new TypeMap {
def apply(tp: Type) = varToParamMap get tp match {
- case Some(sym) => sym.tpe
+ case Some(sym) => sym.tpe_*
case _ => mapOver(tp)
}
}
@@ -1661,7 +1688,7 @@ trait Types extends api.Types { self: SymbolTable =>
tpe.baseTypeSeqCache = undetBaseTypeSeq
tpe.baseTypeSeqCache =
if (tpe.typeSymbol.isRefinementClass)
- tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe)
+ tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe_*)
else
compoundBaseTypeSeq(tpe)
} finally {
@@ -1683,41 +1710,61 @@ trait Types extends api.Types { self: SymbolTable =>
throw new TypeError("illegal cyclic inheritance involving " + tpe.typeSymbol)
}
- protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = {
- def computeBaseClasses: List[Symbol] =
- if (tpe.parents.isEmpty) List(tpe.typeSymbol)
- else {
- //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG
- // optimized, since this seems to be performance critical
- val superclazz = tpe.firstParent
- var mixins = tpe.parents.tail
- val sbcs = superclazz.baseClasses
- var bcs = sbcs
- def isNew(clazz: Symbol): Boolean =
- superclazz.baseTypeIndex(clazz) < 0 &&
- { var p = bcs;
- while ((p ne sbcs) && (p.head != clazz)) p = p.tail;
- p eq sbcs
- }
- while (!mixins.isEmpty) {
- def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] =
- if (mbcs.isEmpty) bcs
- else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail)
- else addMixinBaseClasses(mbcs.tail)
- bcs = addMixinBaseClasses(mixins.head.baseClasses)
- mixins = mixins.tail
+ object baseClassesCycleMonitor {
+ private var open: List[Symbol] = Nil
+ @inline private def cycleLog(msg: => String) {
+ if (settings.debug.value)
+ Console.err.println(msg)
+ }
+ def size = open.size
+ def push(clazz: Symbol) {
+ cycleLog("+ " + (" " * size) + clazz.fullNameString)
+ open ::= clazz
+ }
+ def pop(clazz: Symbol) {
+ assert(open.head eq clazz, (clazz, open))
+ open = open.tail
+ }
+ def isOpen(clazz: Symbol) = open contains clazz
+ }
+
+ protected def defineBaseClassesOfCompoundType(tpe: CompoundType) {
+ def define = defineBaseClassesOfCompoundType(tpe, force = false)
+ if (isPastTyper || !breakCycles) define
+ else tpe match {
+ // non-empty parents helpfully excludes all package classes
+ case tpe @ ClassInfoType(_ :: _, _, clazz) if !clazz.isAnonOrRefinementClass =>
+ // Cycle: force update
+ if (baseClassesCycleMonitor isOpen clazz)
+ defineBaseClassesOfCompoundType(tpe, force = true)
+ else {
+ baseClassesCycleMonitor push clazz
+ try define
+ finally baseClassesCycleMonitor pop clazz
}
- tpe.typeSymbol :: bcs
- }
+ case _ =>
+ define
+ }
+ }
+ private def defineBaseClassesOfCompoundType(tpe: CompoundType, force: Boolean) {
val period = tpe.baseClassesPeriod
- if (period != currentPeriod) {
+ if (period == currentPeriod) {
+ if (force && breakCycles) {
+ def what = tpe.typeSymbol + " in " + tpe.typeSymbol.owner.fullNameString
+ val bcs = computeBaseClasses(tpe)
+ tpe.baseClassesCache = bcs
+ warning(s"Breaking cycle in base class computation of $what ($bcs)")
+ }
+ }
+ else {
tpe.baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, baseClassesNanos) else null
try {
tpe.baseClassesCache = null
- tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
- } finally {
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses(tpe))(tpe.typeSymbol :: _.baseClasses.tail)
+ }
+ finally {
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
}
}
@@ -2815,9 +2862,13 @@ trait Types extends api.Types { self: SymbolTable =>
override def kind = "OverloadedType"
}
- def overloadedType(pre: Type, alternatives: List[Symbol]): Type =
- if (alternatives.tail.isEmpty) pre memberType alternatives.head
- else OverloadedType(pre, alternatives)
+ /** The canonical creator for OverloadedTypes.
+ */
+ def overloadedType(pre: Type, alternatives: List[Symbol]): Type = alternatives match {
+ case Nil => NoType
+ case alt :: Nil => pre memberType alt
+ case _ => OverloadedType(pre, alternatives)
+ }
/** A class remembering a type instantiation for some a set of overloaded
* polymorphic symbols.
@@ -3074,7 +3125,10 @@ trait Types extends api.Types { self: SymbolTable =>
// invariant: before mutating constr, save old state in undoLog
// (undoLog is used to reset constraints to avoid piling up unrelated ones)
def setInst(tp: Type) {
-// assert(!(tp containsTp this), this)
+ if (tp eq this) {
+ log(s"TypeVar cycle: called setInst passing $this to itself.")
+ return
+ }
undoLog record this
// if we were compared against later typeskolems, repack the existential,
// because skolems are only compatible if they were created at the same level
@@ -3219,16 +3273,19 @@ trait Types extends api.Types { self: SymbolTable =>
def registerTypeEquality(tp: Type, typeVarLHS: Boolean): Boolean = {
// println("regTypeEq: "+(safeToString, debugString(tp), tp.getClass, if (typeVarLHS) "in LHS" else "in RHS", if (suspended) "ZZ" else if (constr.instValid) "IV" else "")) //@MDEBUG
-// println("constr: "+ constr)
- def checkIsSameType(tp: Type) =
- if(typeVarLHS) constr.inst =:= tp
- else tp =:= constr.inst
+ def checkIsSameType(tp: Type) = (
+ if (typeVarLHS) constr.inst =:= tp
+ else tp =:= constr.inst
+ )
if (suspended) tp =:= origin
else if (constr.instValid) checkIsSameType(tp)
else isRelatable(tp) && {
val newInst = wildcardToTypeVarMap(tp)
- (constr isWithinBounds newInst) && { setInst(tp); true }
+ (constr isWithinBounds newInst) && {
+ setInst(newInst)
+ true
+ }
}
}
@@ -3402,22 +3459,12 @@ trait Types extends api.Types { self: SymbolTable =>
case class NamedType(name: Name, tp: Type) extends Type {
override def safeToString: String = name.toString +": "+ tp
}
-
- /** A De Bruijn index referring to a previous type argument. Only used
- * as a serialization format.
+ /** As with NamedType, used only when calling isApplicable.
+ * Records that the application has a wildcard star (aka _*)
+ * at the end of it.
*/
- case class DeBruijnIndex(level: Int, idx: Int, args: List[Type]) extends Type {
- override def safeToString: String = "De Bruijn index("+level+","+idx+")"
- }
-
- /** A binder defining data associated with De Bruijn indices. Only used
- * as a serialization format.
- */
- case class DeBruijnBinder(pnames: List[Name], ptypes: List[Type], restpe: Type) extends Type {
- override def safeToString = {
- val kind = if (pnames.head.isTypeName) "poly" else "method"
- "De Bruijn "+kind+"("+(pnames mkString ",")+";"+(ptypes mkString ",")+";"+restpe+")"
- }
+ case class RepeatedType(tp: Type) extends Type {
+ override def safeToString: String = tp + ": _*"
}
/** A temporary type representing the erasure of a user-defined value type.
@@ -3553,12 +3600,6 @@ trait Types extends api.Types { self: SymbolTable =>
val pre1 = pre match {
case x: SuperType if sym1.isEffectivelyFinal || sym1.isDeferred =>
x.thistpe
- case _: CompoundType if sym1.isClass =>
- // sharpen prefix so that it is maximal and still contains the class.
- pre.parents.reverse dropWhile (_.member(sym1.name) != sym1) match {
- case Nil => pre
- case parent :: _ => parent
- }
case _ => pre
}
if (pre eq pre1) TypeRef(pre, sym1, args)
@@ -3640,16 +3681,16 @@ trait Types extends api.Types { self: SymbolTable =>
tycon match {
case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing
- case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args)
+ case TypeRef(pre, sym, Nil) => copyTypeRef(tycon, pre, sym, args)
+ case TypeRef(pre, sym, bogons) => debugwarn(s"Dropping $bogons from $tycon in appliedType.") ; copyTypeRef(tycon, pre, sym, args)
case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
case ExistentialType(tparams, restpe) => newExistentialType(tparams, appliedType(restpe, args))
case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
- case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check
- case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args))
+ case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // @PP: Can this be right?
+ case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) // @PP: Can this be right?
case tv@TypeVar(_, _) => tv.applyArgs(args)
case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self)
- case ErrorType => tycon
- case WildcardType => tycon // needed for neg/t0226
+ case ErrorType | WildcardType => tycon
case _ => abort(debugString(tycon))
}
}
@@ -3812,12 +3853,16 @@ trait Types extends api.Types { self: SymbolTable =>
// This is the specified behavior.
protected def etaExpandKeepsStar = false
- object dropRepeatedParamType extends TypeMap {
+ /** Turn any T* types into Seq[T] except when
+ * in method parameter position.
+ */
+ object dropIllegalStarTypes extends TypeMap {
def apply(tp: Type): Type = tp match {
case MethodType(params, restpe) =>
- MethodType(params, apply(restpe))
- case PolyType(tparams, restpe) =>
- PolyType(tparams, apply(restpe))
+ // Not mapping over params
+ val restpe1 = apply(restpe)
+ if (restpe eq restpe1) tp
+ else MethodType(params, restpe1)
case TypeRef(_, RepeatedParamClass, arg :: Nil) =>
seqType(arg)
case _ =>
@@ -3825,50 +3870,6 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
- object toDeBruijn extends TypeMap {
- private var paramStack: List[List[Symbol]] = Nil
- def mkDebruijnBinder(params: List[Symbol], restpe: Type) = {
- paramStack = params :: paramStack
- try {
- DeBruijnBinder(params map (_.name), params map (p => this(p.info)), this(restpe))
- } finally paramStack = paramStack.tail
- }
- def apply(tp: Type): Type = tp match {
- case PolyType(tparams, restpe) =>
- mkDebruijnBinder(tparams, restpe)
- case MethodType(params, restpe) =>
- mkDebruijnBinder(params, restpe)
- case TypeRef(NoPrefix, sym, args) =>
- val level = paramStack indexWhere (_ contains sym)
- if (level < 0) mapOver(tp)
- else DeBruijnIndex(level, paramStack(level) indexOf sym, args mapConserve this)
- case _ =>
- mapOver(tp)
- }
- }
-
- def fromDeBruijn(owner: Symbol) = new TypeMap {
- private var paramStack: List[List[Symbol]] = Nil
- def apply(tp: Type): Type = tp match {
- case DeBruijnBinder(pnames, ptypes, restpe) =>
- val isType = pnames.head.isTypeName
- val newParams = for (name <- pnames) yield
- if (isType) owner.newTypeParameter(name.toTypeName)
- else owner.newValueParameter(name.toTermName)
- paramStack = newParams :: paramStack
- try {
- foreach2(newParams, ptypes)((p, t) => p setInfo this(t))
- val restpe1 = this(restpe)
- if (isType) PolyType(newParams, restpe1)
- else MethodType(newParams, restpe1)
- } finally paramStack = paramStack.tail
- case DeBruijnIndex(level, idx, args) =>
- TypeRef(NoPrefix, paramStack(level)(idx), args map this)
- case _ =>
- mapOver(tp)
- }
- }
-
// Hash consing --------------------------------------------------------------
private val initialUniquesCapacity = 4096
@@ -4191,10 +4192,6 @@ trait Types extends api.Types { self: SymbolTable =>
if ((annots1 eq annots) && (atp1 eq atp)) tp
else if (annots1.isEmpty) atp1
else AnnotatedType(annots1, atp1, selfsym)
- case DeBruijnIndex(shift, idx, args) =>
- val args1 = args mapConserve this
- if (args1 eq args) tp
- else DeBruijnIndex(shift, idx, args1)
/*
case ErrorType => tp
case WildcardType => tp
@@ -4363,6 +4360,20 @@ trait Types extends api.Types { self: SymbolTable =>
mapOver(tp)
}
}
+ /***
+ *@M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible
+ object rawToExistentialInJava extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ // any symbol that occurs in a java sig, not just java symbols
+ // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14
+ case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty =>
+ val eparams = typeParamsToExistentials(sym, sym.typeParams)
+ existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe)))
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ */
/** Used by existentialAbstraction.
*/
@@ -4597,16 +4608,18 @@ trait Types extends api.Types { self: SymbolTable =>
tp
}
- def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
- @tailrec def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type =
- if (from.isEmpty) tp
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
- else if (matches(from.head, sym)) toType(tp, to.head)
- else subst(tp, sym, from.tail, to.tail)
+ @tailrec private def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type = (
+ if (from.isEmpty) tp
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
+ else if (matches(from.head, sym)) toType(tp, to.head)
+ else subst(tp, sym, from.tail, to.tail)
+ )
- val boundSyms = tp0.boundSyms
- val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0
- val tp = mapOver(tp1)
+ def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
+ val boundSyms = tp0.boundSyms
+ val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0
+ val tp = mapOver(tp1)
+ def substFor(sym: Symbol) = subst(tp, sym, from, to)
tp match {
// @M
@@ -4621,9 +4634,11 @@ trait Types extends api.Types { self: SymbolTable =>
// (must not recurse --> loops)
// 3) replacing m by List in m[Int] should yield List[Int], not just List
case TypeRef(NoPrefix, sym, args) =>
- appliedType(subst(tp, sym, from, to), args) // if args.isEmpty, appliedType is the identity
+ val tcon = substFor(sym)
+ if ((tp eq tcon) || args.isEmpty) tcon
+ else appliedType(tcon.typeConstructor, args)
case SingleType(NoPrefix, sym) =>
- subst(tp, sym, from, to)
+ substFor(sym)
case _ =>
tp
}
@@ -4632,29 +4647,35 @@ trait Types extends api.Types { self: SymbolTable =>
/** A map to implement the `substSym` method. */
class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) {
+ def this(pairs: (Symbol, Symbol)*) = this(pairs.toList.map(_._1), pairs.toList.map(_._2))
+
protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
case TypeRef(pre, _, args) => copyTypeRef(fromtp, pre, sym, args)
case SingleType(pre, _) => singleType(pre, sym)
}
- override def apply(tp: Type): Type = if (from.isEmpty) tp else {
- @tailrec def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol =
- if (from.isEmpty) sym
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
- else if (matches(from.head, sym)) to.head
- else subst(sym, from.tail, to.tail)
- tp match {
+ @tailrec private def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = (
+ if (from.isEmpty) sym
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
+ else if (matches(from.head, sym)) to.head
+ else subst(sym, from.tail, to.tail)
+ )
+ private def substFor(sym: Symbol) = subst(sym, from, to)
+
+ override def apply(tp: Type): Type = (
+ if (from.isEmpty) tp
+ else tp match {
case TypeRef(pre, sym, args) if pre ne NoPrefix =>
- val newSym = subst(sym, from, to)
+ val newSym = substFor(sym)
// mapOver takes care of subst'ing in args
mapOver ( if (sym eq newSym) tp else copyTypeRef(tp, pre, newSym, args) )
// assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams))
case SingleType(pre, sym) if pre ne NoPrefix =>
- val newSym = subst(sym, from, to)
+ val newSym = substFor(sym)
mapOver( if (sym eq newSym) tp else singleType(pre, newSym) )
case _ =>
super.apply(tp)
}
- }
+ )
override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
object trans extends TypeMapTransformer {
@@ -5115,28 +5136,18 @@ trait Types extends api.Types { self: SymbolTable =>
class SubTypePair(val tp1: Type, val tp2: Type) {
override def hashCode = tp1.hashCode * 41 + tp2.hashCode
- override def equals(other: Any) = other match {
+ override def equals(other: Any) = (this eq other.asInstanceOf[AnyRef]) || (other match {
+ // suspend TypeVars in types compared by =:=,
+ // since we don't want to mutate them simply to check whether a subtype test is pending
+ // in addition to making subtyping "more correct" for type vars,
+ // it should avoid the stackoverflow that's been plaguing us (https://groups.google.com/d/topic/scala-internals/2gHzNjtB4xA/discussion)
+ // this method is only called when subtyping hits a recursion threshold (subsametypeRecursions >= LogPendingSubTypesThreshold)
case stp: SubTypePair =>
- // suspend TypeVars in types compared by =:=,
- // since we don't want to mutate them simply to check whether a subtype test is pending
- // in addition to making subtyping "more correct" for type vars,
- // it should avoid the stackoverflow that's been plaguing us (https://groups.google.com/d/topic/scala-internals/2gHzNjtB4xA/discussion)
- // this method is only called when subtyping hits a recursion threshold (subsametypeRecursions >= LogPendingSubTypesThreshold)
- def suspend(tp: Type) =
- if (tp.isGround) null else suspendTypeVarsInType(tp)
- def revive(suspension: List[TypeVar]) =
- if (suspension ne null) suspension foreach (_.suspended = false)
-
- val suspensions = Array(tp1, stp.tp1, tp2, stp.tp2) map suspend
-
- val sameTypes = (tp1 =:= stp.tp1) && (tp2 =:= stp.tp2)
-
- suspensions foreach revive
-
- sameTypes
+ val tvars = List(tp1, stp.tp1, tp2, stp.tp2) flatMap (t => if (t.isGround) Nil else typeVarsInType(t))
+ suspendingTypeVars(tvars)(tp1 =:= stp.tp1 && tp2 =:= stp.tp2)
case _ =>
false
- }
+ })
override def toString = tp1+" <:<? "+tp2
}
@@ -5208,32 +5219,33 @@ trait Types extends api.Types { self: SymbolTable =>
def isPopulated(tp1: Type, tp2: Type): Boolean = {
def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
- assert(sym1 == sym2)
+ assert(sym1 == sym2, (sym1, sym2))
pre1 =:= pre2 &&
- forall3(args1, args2, sym1.typeParams) { (arg1, arg2, tparam) =>
- //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
+ forall3(args1, args2, sym1.typeParams)((arg1, arg2, tparam) =>
if (tparam.variance == 0) arg1 =:= arg2
- else if (arg1.isInstanceOf[TypeVar])
- // if left-hand argument is a typevar, make it compatible with variance
- // this is for more precise pattern matching
- // todo: work this in the spec of this method
- // also: think what happens if there are embedded typevars?
- if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1
- else true
- }
+ // if left-hand argument is a typevar, make it compatible with variance
+ // this is for more precise pattern matching
+ // todo: work this in the spec of this method
+ // also: think what happens if there are embedded typevars?
+ else arg1 match {
+ case _: TypeVar => if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1
+ case _ => true
+ }
+ )
case (et: ExistentialType, _) =>
et.withTypeVars(isConsistent(_, tp2))
case (_, et: ExistentialType) =>
et.withTypeVars(isConsistent(tp1, _))
}
- def check(tp1: Type, tp2: Type) =
+ def check(tp1: Type, tp2: Type) = (
if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL))
tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol)
else tp1.baseClasses forall (bc =>
tp2.baseTypeIndex(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
+ )
- check(tp1, tp2)/* && check(tp2, tp1)*/ // need to investgate why this can't be made symmetric -- neg/gadts1 fails, and run/existials also.
+ check(tp1, tp2) && check(tp2, tp1)
}
/** Does a pattern of type `patType` need an outer test when executed against
@@ -5316,13 +5328,15 @@ trait Types extends api.Types { self: SymbolTable =>
try {
val before = undoLog.log
var result = false
-
- try result = {
- isSameType1(tp1, tp2)
- } finally if (!result) undoLog.undoTo(before)
+ try {
+ result = isSameType1(tp1, tp2)
+ }
+ finally if (!result) undoLog.undoTo(before)
result
- } finally undoLog.unlock()
- } finally {
+ }
+ finally undoLog.unlock()
+ }
+ finally {
subsametypeRecursions -= 1
// XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866)
// it doesn't help to keep separate recursion counts for the three methods that now share it
@@ -5604,12 +5618,12 @@ trait Types extends api.Types { self: SymbolTable =>
}
tp1 match {
case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp2, true)
+ return tv.registerTypeEquality(tp2, typeVarLHS = true)
case _ =>
}
tp2 match {
case tv @ TypeVar(_,_) =>
- return tv.registerTypeEquality(tp1, false)
+ return tv.registerTypeEquality(tp1, typeVarLHS = false)
case _ =>
}
tp1 match {
@@ -5790,7 +5804,6 @@ trait Types extends api.Types { self: SymbolTable =>
private def isInternalTypeNotUsedAsTypeArg(tp: Type): Boolean = tp match {
case AntiPolyType(pre, targs) => true
case ClassInfoType(parents, defs, clazz) => true
- case DeBruijnIndex(level, index, args) => true
case ErasedValueType(tref) => true
case NoPrefix => true
case NoType => true
@@ -6138,6 +6151,7 @@ trait Types extends api.Types { self: SymbolTable =>
* than member `sym2` of `tp2`?
*/
private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Int): Boolean = {
+ require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth)))
val info1 = tp1.memberInfo(sym1)
val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
//System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
@@ -6452,25 +6466,27 @@ trait Types extends api.Types { self: SymbolTable =>
* @See baseTypeSeq for a definition of sorted and upwards closed.
*/
private def lubList(ts: List[Type], depth: Int): List[Type] = {
- // Matching the type params of one of the initial types means dummies.
- val initialTypeParams = ts map (_.typeParams)
- def isHotForTs(xs: List[Type]) = initialTypeParams contains (xs map (_.typeSymbol))
+ var lubListDepth = 0
+ // This catches some recursive situations which would otherwise
+ // befuddle us, e.g. pos/hklub0.scala
+ def isHotForTs(xs: List[Type]) = ts exists (_.typeParams == xs.map(_.typeSymbol))
def elimHigherOrderTypeParam(tp: Type) = tp match {
- case TypeRef(pre, sym, args) if args.nonEmpty && isHotForTs(args) => tp.typeConstructor
- case _ => tp
+ case TypeRef(_, _, args) if args.nonEmpty && isHotForTs(args) =>
+ logResult("Retracting dummies from " + tp + " in lublist")(tp.typeConstructor)
+ case _ => tp
}
- var lubListDepth = 0
- def loop(tsBts: List[List[Type]]): List[Type] = {
+ // pretypes is a tail-recursion-preserving accumulator.
+ @annotation.tailrec def loop(pretypes: List[Type], tsBts: List[List[Type]]): List[Type] = {
lubListDepth += 1
- if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) Nil
- else if (tsBts.tail.isEmpty) tsBts.head
+ if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) pretypes.reverse
+ else if (tsBts.tail.isEmpty) pretypes.reverse ++ tsBts.head
else {
// ts0 is the 1-dimensional frontier of symbols cutting through 2-dimensional tsBts.
// Invariant: all symbols "under" (closer to the first row) the frontier
// are smaller (according to _.isLess) than the ones "on and beyond" the frontier
- val ts0 = tsBts map (_.head)
+ val ts0 = tsBts map (_.head)
// Is the frontier made up of types with the same symbol?
val isUniformFrontier = (ts0: @unchecked) match {
@@ -6483,23 +6499,23 @@ trait Types extends api.Types { self: SymbolTable =>
// merging, strip targs that refer to bound tparams (when we're computing the lub of type
// constructors.) Also filter out all types that are a subtype of some other type.
if (isUniformFrontier) {
- if (settings.debug.value || printLubs) {
- val fbounds = findRecursiveBounds(ts0)
- if (fbounds.nonEmpty) {
- println("Encountered " + fbounds.size + " recursive bounds while lubbing " + ts0.size + " types.")
- for ((p0, p1) <- fbounds) {
- val desc = if (p0 == p1) "its own bounds" else "the bounds of " + p1
-
- println(" " + p0.fullLocationString + " appears in " + desc)
- println(" " + p1 + " " + p1.info.bounds)
+ val fbounds = findRecursiveBounds(ts0) map (_._2)
+ val tcLubList = typeConstructorLubList(ts0)
+ def isRecursive(tp: Type) = tp.typeSymbol.typeParams exists fbounds.contains
+
+ val ts1 = ts0 map { t =>
+ if (isRecursive(t)) {
+ tcLubList map (t baseType _.typeSymbol) find (t => !isRecursive(t)) match {
+ case Some(tp) => logResult(s"Breaking recursion in lublist, substituting weaker type.\n Was: $t\n Now")(tp)
+ case _ => t
}
- println("")
}
+ else t
}
val tails = tsBts map (_.tail)
- mergePrefixAndArgs(elimSub(ts0 map elimHigherOrderTypeParam, depth), 1, depth) match {
- case Some(tp) => tp :: loop(tails)
- case _ => loop(tails)
+ mergePrefixAndArgs(elimSub(ts1, depth) map elimHigherOrderTypeParam, 1, depth) match {
+ case Some(tp) => loop(tp :: pretypes, tails)
+ case _ => loop(pretypes, tails)
}
}
else {
@@ -6516,7 +6532,7 @@ trait Types extends api.Types { self: SymbolTable =>
printLubMatrix((ts zip tsBts).toMap, lubListDepth)
}
- loop(newtps)
+ loop(pretypes, newtps)
}
}
}
@@ -6525,7 +6541,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (printLubs)
printLubMatrix((ts zip initialBTSes).toMap, depth)
- loop(initialBTSes)
+ loop(Nil, initialBTSes)
}
/** The minimal symbol of a list of types (as determined by `Symbol.isLess`). */
@@ -6663,6 +6679,23 @@ trait Types extends api.Types { self: SymbolTable =>
private val lubResults = new mutable.HashMap[(Int, List[Type]), Type]
private val glbResults = new mutable.HashMap[(Int, List[Type]), Type]
+ /** Given a list of types, finds all the base classes they have in
+ * common, then returns a list of type constructors derived directly
+ * from the symbols (so any more specific type information is ignored.)
+ * The list is filtered such that every type constructor in the list
+ * expects the same number of type arguments, which is chosen based
+ * on the deepest class among the common baseclasses.
+ */
+ def typeConstructorLubList(ts: List[Type]): List[Type] = {
+ val bcs = ts.flatMap(_.baseClasses).distinct sortWith (_ isLess _)
+ val tcons = bcs filter (clazz => ts forall (_.typeSymbol isSubClass clazz))
+
+ tcons map (_.typeConstructor) match {
+ case Nil => Nil
+ case t :: ts => t :: ts.filter(_.typeParams.size == t.typeParams.size)
+ }
+ }
+
def lub(ts: List[Type]): Type = ts match {
case List() => NothingClass.tpe
case List(t) => t
@@ -6670,8 +6703,20 @@ trait Types extends api.Types { self: SymbolTable =>
if (Statistics.canEnable) Statistics.incCounter(lubCount)
val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, lubNanos) else null
try {
- lub(ts, lubDepth(ts))
- } finally {
+ val res = lub(ts, lubDepth(ts))
+ // If the number of unapplied type parameters in all incoming
+ // types is consistent, and the lub does not match that, return
+ // the type constructor of the calculated lub instead. This
+ // is because lubbing type constructors tends to result in types
+ // which have been applied to dummies or Nothing.
+ ts.map(_.typeParams.size).distinct match {
+ case x :: Nil if res.typeParams.size != x =>
+ logResult(s"Stripping type args from lub because $res is not consistent with $ts")(res.typeConstructor)
+ case _ =>
+ res
+ }
+ }
+ finally {
lubResults.clear()
glbResults.clear()
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
@@ -6705,13 +6750,13 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
def lub1(ts0: List[Type]): Type = {
- val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
+ val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
val lubBaseTypes: List[Type] = lubList(ts, depth)
- val lubParents = spanningTypes(lubBaseTypes)
- val lubOwner = commonOwner(ts)
- val lubBase = intersectionType(lubParents, lubOwner)
+ val lubParents = spanningTypes(lubBaseTypes)
+ val lubOwner = commonOwner(ts)
+ val lubBase = intersectionType(lubParents, lubOwner)
val lubType =
- if (phase.erasedTypes || depth == 0) lubBase
+ if (phase.erasedTypes || depth == 0 ) lubBase
else {
val lubRefined = refinedType(lubParents, lubOwner)
val lubThisType = lubRefined.typeSymbol.thisType
@@ -6728,6 +6773,7 @@ trait Types extends api.Types { self: SymbolTable =>
val syms = narrowts map (t =>
t.nonPrivateMember(proto.name).suchThat(sym =>
sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t)))
+
if (syms contains NoSymbol) NoSymbol
else {
val symtypes =
@@ -6754,10 +6800,8 @@ trait Types extends api.Types { self: SymbolTable =>
// add a refinement symbol for all non-class members of lubBase
// which are refined by every type in ts.
for (sym <- lubBase.nonPrivateMembers ; if !excludeFromLub(sym)) {
- try {
- val lsym = lubsym(sym)
- if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lsym, depth)
- } catch {
+ try lubsym(sym) andAlso (addMember(lubThisType, lubRefined, _, depth))
+ catch {
case ex: NoCommonType =>
}
}
@@ -6954,15 +6998,22 @@ trait Types extends api.Types { self: SymbolTable =>
}
tvs.reverse
}
- /** Make each type var in this type use its original type for comparisons instead
- * of collecting constraints.
- */
- def suspendTypeVarsInType(tp: Type): List[TypeVar] = {
- val tvs = typeVarsInType(tp)
- // !!! Is it somehow guaranteed that this will not break under nesting?
- // In general one has to save and restore the contents of the field...
+
+ // If this type contains type variables, put them to sleep for a while.
+ // Don't just wipe them out by replacing them by the corresponding type
+ // parameter, as that messes up (e.g.) type variables in type refinements.
+ // Without this, the matchesType call would lead to type variables on both
+ // sides of a subtyping/equality judgement, which can lead to recursive types
+ // being constructed. See pos/t0851 for a situation where this happens.
+ def suspendingTypeVarsInType[T](tp: Type)(op: => T): T =
+ suspendingTypeVars(typeVarsInType(tp))(op)
+
+ @inline final def suspendingTypeVars[T](tvs: List[TypeVar])(op: => T): T = {
+ val saved = tvs map (_.suspended)
tvs foreach (_.suspended = true)
- tvs
+
+ try op
+ finally foreach2(tvs, saved)(_.suspended = _)
}
/** Compute lub (if `variance == 1`) or glb (if `variance == -1`) of given list
@@ -7001,18 +7052,16 @@ trait Types extends api.Types { self: SymbolTable =>
debuglog("transposed irregular matrix!?" +(tps, argss))
None
case Some(argsst) =>
- val args = map2(sym.typeParams, argsst) { (tparam, as) =>
- if (depth == 0) {
- if (tparam.variance == variance) {
- // Take the intersection of the upper bounds of the type parameters
- // rather than falling all the way back to "Any", otherwise we end up not
- // conforming to bounds.
- val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass)
- if (bounds0.isEmpty) AnyClass.tpe
- else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym)))
- }
- else if (tparam.variance == -variance) NothingClass.tpe
- else NoType
+ val args = map2(sym.typeParams, argsst) { (tparam, as0) =>
+ val as = as0.distinct
+ if (as.size == 1) as.head
+ else if (depth == 0) {
+ log("Giving up merging args: can't unify %s under %s".format(as.mkString(", "), tparam.fullLocationString))
+ // Don't return "Any" (or "Nothing") when we have to give up due to
+ // recursion depth. Return NoType, which prevents us from poisoning
+ // lublist's results. It can recognize the recursion and deal with it, but
+ // only if we aren't returning invalid types.
+ NoType
}
else {
if (tparam.variance == variance) lub(as, decr(depth))
@@ -7021,7 +7070,7 @@ trait Types extends api.Types { self: SymbolTable =>
val l = lub(as, decr(depth))
val g = glb(as, decr(depth))
if (l <:< g) l
- else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
+ else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
// just err on the conservative side, i.e. with a bound that is too high.
// if(!(tparam.info.bounds contains tparam)) //@M can't deal with f-bounds, see #2251
@@ -7069,6 +7118,14 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ def isJavaVarargsAncestor(clazz: Symbol) = (
+ clazz.isClass
+ && clazz.isJavaDefined
+ && (clazz.info.nonPrivateDecls exists isJavaVarArgsMethod)
+ )
+ def inheritsJavaVarArgsMethod(clazz: Symbol) =
+ clazz.thisType.baseClasses exists isJavaVarargsAncestor
+
/** All types in list must be polytypes with type parameter lists of
* same length as tparams.
* Returns list of list of bounds infos, where corresponding type
@@ -7181,6 +7238,12 @@ trait Types extends api.Types { self: SymbolTable =>
else (ps :+ SerializableClass.tpe).toList
)
+ /** Members of the given class, other than those inherited
+ * from Any or AnyRef.
+ */
+ def nonTrivialMembers(clazz: Symbol): Iterable[Symbol] =
+ clazz.info.members filterNot (sym => sym.owner == ObjectClass || sym.owner == AnyClass)
+
def objToAny(tp: Type): Type =
if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe
else tp
diff --git a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala
index 16747af08a..94b2f77ff9 100644
--- a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala
+++ b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala
@@ -56,7 +56,7 @@ object PickleFormat {
* | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref}
* | 43 ANNOTINFO len_Nat AnnotInfoBody
* | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref}
- * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat
+ * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat /* no longer needed */
* | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref}
* | 49 TREE len_Nat 1 EMPTYtree
* | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref}
@@ -161,7 +161,7 @@ object PickleFormat {
final val ANNOTARGARRAY = 44
final val SUPERtpe = 46
- final val DEBRUIJNINDEXtpe = 47
+ final val DEBRUIJNINDEXtpe = 47 // no longer generated
final val EXISTENTIALtpe = 48
final val TREE = 49 // prefix code that means a tree is coming
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index b158a1ac26..ca47ef7e26 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -853,7 +853,7 @@ abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ {
private val p = phase
override def complete(sym: Symbol) : Unit = try {
val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType`
- atPhase(p) (sym setInfo tp)
+ enteringPhase(p) (sym setInfo tp)
if (currentRunId != definedAtRunId)
sym.setInfo(adaptToNewRunMap(tp))
}
@@ -871,7 +871,7 @@ abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ {
super.complete(sym)
var alias = at(j, readSymbol)
if (alias.isOverloaded)
- alias = atPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt))))
+ alias = enteringPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt))))
sym.asInstanceOf[TermSymbol].setAlias(alias)
}
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index 459326e96f..844ecf908a 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -47,4 +47,5 @@ abstract class MutableSettings extends AbsSettings {
def XoldPatmat: BooleanSetting
def XnoPatmatAnalysis: BooleanSetting
def XfullLubs: BooleanSetting
+ def breakCycles: BooleanSetting
}
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index 977398909f..fd3934b3d6 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -69,7 +69,7 @@ trait Erasure {
//
// This requires that cls.isClass.
protected def rebindInnerClass(pre: Type, cls: Symbol): Type = {
- if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass?
+ if (cls.owner.isClass) cls.owner.tpe_* else pre // why not cls.isNestedClass?
}
def unboxDerivedValueClassMethod(clazz: Symbol): Symbol =
diff --git a/src/reflect/scala/reflect/internal/util/Set.scala b/src/reflect/scala/reflect/internal/util/Set.scala
index d708a09de7..94743f2069 100644
--- a/src/reflect/scala/reflect/internal/util/Set.scala
+++ b/src/reflect/scala/reflect/internal/util/Set.scala
@@ -18,8 +18,6 @@ abstract class Set[T <: AnyRef] {
def apply(x: T): Boolean = contains(x)
- @deprecated("use `iterator` instead", "2.9.0") def elements = iterator
-
def contains(x: T): Boolean =
findEntry(x) ne null
diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala
index 281ade8134..e4ad8559e2 100644
--- a/src/reflect/scala/reflect/internal/util/StringOps.scala
+++ b/src/reflect/scala/reflect/internal/util/StringOps.scala
@@ -34,6 +34,14 @@ trait StringOps {
s.substring(0, idx + 1)
}
}
+ def longestCommonPrefix(xs: List[String]): String = {
+ if (xs.isEmpty || xs.contains("")) ""
+ else xs.head.head match {
+ case ch =>
+ if (xs.tail forall (_.head == ch)) "" + ch + longestCommonPrefix(xs map (_.tail))
+ else ""
+ }
+ }
def decompose(str: String, sep: Char): List[String] = {
def ws(start: Int): List[String] =
diff --git a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala
index fa83f70f3a..46d80e9680 100644
--- a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala
+++ b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala
@@ -129,7 +129,7 @@ trait TraceSymbolActivity {
}
ph
}
- private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body)
+ private def runBeforeErasure[T](body: => T): T = enteringPhase(findErasurePhase)(body)
def showAllSymbols() {
if (!enabled) return
diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala
new file mode 100644
index 0000000000..83c8bf67ba
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/util/package.scala
@@ -0,0 +1,34 @@
+package scala
+package reflect
+package internal
+
+package object util {
+ import StringOps.longestCommonPrefix
+
+ // Shorten a name like Symbols$FooSymbol to FooSymbol.
+ private def shortenName(name: String): String = {
+ if (name == "") return ""
+ val segments = (name split '$').toList
+ val last = segments.last
+
+ if (last.length == 0)
+ segments takeRight 2 mkString "$"
+ else
+ last
+ }
+
+ def shortClassOfInstance(x: AnyRef): String = shortClass(x.getClass)
+ def shortClass(clazz: Class[_]): String = {
+ val name: String = (clazz.getName split '.').last
+ def isModule = name endsWith "$" // object
+ def isAnon = (name split '$').last forall (_.isDigit) // anonymous class
+
+ if (isModule)
+ (name split '$' filterNot (_ == "")).last + "$"
+ else if (isAnon) {
+ val parents = clazz.getSuperclass :: clazz.getInterfaces.toList
+ parents map (c => shortClass(c)) mkString " with "
+ }
+ else shortenName(name)
+ }
+}
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 2d08cd887b..f517c30fe6 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -1107,7 +1107,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
constructorCache enter (jconstr, constr)
val tparams = jconstr.getTypeParameters.toList map createTypeParameter
val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala
- setMethType(constr, tparams, paramtpes, clazz.tpe)
+ setMethType(constr, tparams, paramtpes, clazz.tpe_*)
constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe))
copyAnnotations(constr, jconstr)
constr
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index 0e0cf3fc40..7d04202455 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -43,6 +43,7 @@ private[reflect] class Settings extends MutableSettings {
val printtypes = new BooleanSetting(false)
val uniqid = new BooleanSetting(false)
val verbose = new BooleanSetting(false)
+ val breakCycles = new BooleanSetting(false)
val Yrecursion = new IntSetting(0)
val maxClassfileName = new IntSetting(255)
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index 61663f6181..2b192ce570 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -28,7 +28,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
debugInfo("completing "+sym+"/"+clazz.fullName)
assert(sym == clazz || sym == module || sym == module.moduleClass)
// try {
- atPhaseNotLaterThan(picklerPhase) {
+ enteringPhaseNotLaterThan(picklerPhase) {
val loadingMirror = mirrorThatLoaded(sym)
val javaClass = loadingMirror.javaClass(clazz.javaClassName)
loadingMirror.unpickleClass(clazz, module, javaClass)
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 00f6952dc1..366b4319c3 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -118,7 +118,8 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb
override def name_=(x: Name) = synchronized { super.name_=(x) }
override def rawname = synchronized { super.rawname }
override def typeConstructor: Type = synchronized { super.typeConstructor }
- override def tpe: Type = synchronized { super.tpe }
+ override def tpe_* : Type = synchronized { super.tpe_* }
+ override def tpeHK : Type = synchronized { super.tpeHK }
}
trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol {
diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala b/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala
index 1500b81050..489a05ecd0 100644
--- a/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala
+++ b/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala
@@ -50,7 +50,7 @@ trait Rule[-In, +Out, +A, +X] extends (In => Result[Out, A, X]) {
lazy val choices = Rule.this :: other :: Nil
}
- def orError[In2 <: In] = this orElse(error[In2])
+ def orError[In2 <: In] = this orElse error[Any]
def |[In2 <: In, Out2 >: Out, A2 >: A, X2 >: X](other : => Rule[In2, Out2, A2, X2]) = orElse(other)
diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
index e88efa1bfd..76dc0eaf1e 100644
--- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
+++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala
@@ -167,57 +167,10 @@ object ScalaSigEntryParsers extends RulesWithState with MemoisableRules {
val symbolInfo = nameRef ~ symbolRef ~ nat ~ (symbolRef?) ~ ref ~ get ^~~~~~^ SymbolInfo
- def symHeader(key: Int) = (key -~ none | (key + 64) -~ nat)
+ def symHeader(key: Int): EntryParser[Any] = (key -~ none | (key + 64) -~ nat)
def symbolEntry(key : Int) = symHeader(key) -~ symbolInfo
- /***************************************************
- * Symbol table attribute format:
- * Symtab = nentries_Nat {Entry}
- * Entry = 1 TERMNAME len_Nat NameInfo
- * | 2 TYPENAME len_Nat NameInfo
- * | 3 NONEsym len_Nat
- * | 4 TYPEsym len_Nat SymbolInfo
- * | 5 ALIASsym len_Nat SymbolInfo
- * | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref]
- * | 7 MODULEsym len_Nat SymbolInfo
- * | 8 VALsym len_Nat [defaultGetter_Ref /* no longer needed*/] SymbolInfo [alias_Ref]
- * | 9 EXTref len_Nat name_Ref [owner_Ref]
- * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref]
- * | 11 NOtpe len_Nat
- * | 12 NOPREFIXtpe len_Nat
- * | 13 THIStpe len_Nat sym_Ref
- * | 14 SINGLEtpe len_Nat type_Ref sym_Ref
- * | 15 CONSTANTtpe len_Nat constant_Ref
- * | 16 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref}
- * | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref
- * | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref}
- * | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref}
- * | 20 METHODtpe len_Nat tpe_Ref {sym_Ref}
- * | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref}
- * | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {sym_Ref} /* no longer needed */
- * | 52 SUPERtpe len_Nat tpe_Ref tpe_Ref
- * | 24 LITERALunit len_Nat
- * | 25 LITERALboolean len_Nat value_Long
- * | 26 LITERALbyte len_Nat value_Long
- * | 27 LITERALshort len_Nat value_Long
- * | 28 LITERALchar len_Nat value_Long
- * | 29 LITERALint len_Nat value_Long
- * | 30 LITERALlong len_Nat value_Long
- * | 31 LITERALfloat len_Nat value_Long
- * | 32 LITERALdouble len_Nat value_Long
- * | 33 LITERALstring len_Nat name_Ref
- * | 34 LITERALnull len_Nat
- * | 35 LITERALclass len_Nat tpe_Ref
- * | 36 LITERALenum len_Nat sym_Ref
- * | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody
- * | 41 CHILDREN len_Nat sym_Ref {sym_Ref}
- * | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref}
- * | 43 ANNOTINFO len_Nat AnnotInfoBody
- * | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref}
- * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat
- * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref}
- */
val noSymbol = 3 -^ NoSymbol
val typeSymbol = symbolEntry(4) ^^ TypeSymbol as "typeSymbol"
val aliasSymbol = symbolEntry(5) ^^ AliasSymbol as "alias"
@@ -260,10 +213,9 @@ object ScalaSigEntryParsers extends RulesWithState with MemoisableRules {
22 -~ typeRef ~ (symbolRef*) ^~^ MethodType,
42 -~ typeRef ~ (attribTreeRef*) ^~^ AnnotatedType,
51 -~ typeRef ~ symbolRef ~ (attribTreeRef*) ^~~^ AnnotatedWithSelfType,
- 47 -~ typeLevel ~ typeIndex ^~^ DeBruijnIndexType,
48 -~ typeRef ~ (symbolRef*) ^~^ ExistentialType) as "type"
- lazy val literal = oneOf(
+ lazy val literal: EntryParser[Any] = oneOf(
24 -^ (()),
25 -~ longValue ^^ (_ != 0L),
26 -~ longValue ^^ (_.toByte),
diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala
index 411a87e4bb..f3d449b87f 100644
--- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala
+++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala
@@ -381,7 +381,6 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) {
toString(typeRef, sep)
}
case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => toString(typeRef, sep)
- //case DeBruijnIndexType(typeLevel, typeIndex) =>
case ExistentialType(typeRef, symbols) => {
val refs = symbols.map(toString _).filter(!_.startsWith("_")).map("type " + _)
toString(typeRef, sep) + (if (refs.size > 0) refs.mkString(" forSome {", "; ", "}") else "")
diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala
index 543ddbe186..0444e701f2 100644
--- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala
+++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala
@@ -22,5 +22,4 @@ case class PolyType(typeRef : Type, symbols : Seq[TypeSymbol]) extends Type
case class PolyTypeWithCons(typeRef : Type, symbols : Seq[TypeSymbol], cons: String) extends Type
case class AnnotatedType(typeRef : Type, attribTreeRefs : List[Int]) extends Type
case class AnnotatedWithSelfType(typeRef : Type, symbol : Symbol, attribTreeRefs : List[Int]) extends Type
-case class DeBruijnIndexType(typeLevel : Int, typeIndex : Int) extends Type
case class ExistentialType(typeRef : Type, symbols : Seq[Symbol]) extends Type
diff --git a/src/swing/scala/swing/ComboBox.scala b/src/swing/scala/swing/ComboBox.scala
index c7a457d082..67e39cfe3b 100644
--- a/src/swing/scala/swing/ComboBox.scala
+++ b/src/swing/scala/swing/ComboBox.scala
@@ -182,7 +182,7 @@ class ComboBox[A](items: Seq[A]) extends Component with Publisher {
* of the component to its own defaults _after_ the renderer has been
* configured. That's Swing's principle of most suprise.
*/
- def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getRenderer)
+ def renderer: ListView.Renderer[A] = ListView.Renderer.wrap[A](peer.getRenderer)
def renderer_=(r: ListView.Renderer[A]) { peer.setRenderer(r.peer) }
/* XXX: currently not safe to expose:
diff --git a/src/swing/scala/swing/Font.scala.disabled b/src/swing/scala/swing/Font.scala.disabled
deleted file mode 100644
index 9e21eb859c..0000000000
--- a/src/swing/scala/swing/Font.scala.disabled
+++ /dev/null
@@ -1,70 +0,0 @@
-package scala.swing
-
-/*object Font {
- def apply(fontFormat: Int, fontFile: java.io.File) = java.awt.Font.createFont(fontFormat, fontFile)
- def apply(fontFormat: Int, fontStream: java.io.InputStream) = java.awt.Font.createFont(fontFormat, fontStream)
- def decode(str: String) = java.awt.Font.decode(str)
-
- /* TODO: finish implementation
- /**
- * See [java.awt.Font.getFont].
- */
- def get(attributes: Map[_ <: java.text.AttributedCharacterIterator.Attribute, _]) =
- java.awt.Font.getFont(ImmutableMapWrapper(attributes))
-
- import java.{util => ju}
- private case class ImmutableMapWrapper[A, B](underlying : Map[A, B])(t : ClassTag[A]) extends ju.AbstractMap[A, B] {
- self =>
- override def size = underlying.size
-
- override def put(k : A, v : B) =
- throw new UnsupportedOperationException("This is a wrapper that does not support mutation")
- override def remove(k : AnyRef) =
- throw new UnsupportedOperationException("This is a wrapper that does not support mutation")
-
- override def entrySet : ju.Set[ju.Map.Entry[A, B]] = new ju.AbstractSet[ju.Map.Entry[A, B]] {
- def size = self.size
-
- def iterator = new ju.Iterator[ju.Map.Entry[A, B]] {
- val ui = underlying.iterator
- var prev : Option[A] = None
-
- def hasNext = ui.hasNext
-
- def next = {
- val (k, v) = ui.next
- prev = Some(k)
- new ju.Map.Entry[A, B] {
- def getKey = k
- def getValue = v
- def setValue(v1 : B) = self.put(k, v1)
- override def equals(other : Any) = other match {
- case e : ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue
- case _ => false
- }
- }
- }
-
- def remove = prev match {
- case Some(k) => val v = self.remove(k.asInstanceOf[AnyRef]) ; prev = None ; v
- case _ => throw new IllegalStateException("next must be called at least once before remove")
- }
- }
- }
- }
- */
-
- /**
- * See [java.awt.Font.getFont].
- */
- def get(nm: String) = java.awt.Font.getFont(nm)
- /**
- * See [java.awt.Font.getFont].
- */
- def get(nm: String, font: Font) = java.awt.Font.getFont(nm, font)
-
- def Insets(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height)
- def Rectangle(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height)
- def Point(x: Int, y: Int) = new Point(x, y)
- def Dimension(x: Int, y: Int) = new Dimension(x, y)
-}*/ \ No newline at end of file
diff --git a/src/swing/scala/swing/ListView.scala b/src/swing/scala/swing/ListView.scala
index 282d24696e..22850bac42 100644
--- a/src/swing/scala/swing/ListView.scala
+++ b/src/swing/scala/swing/ListView.scala
@@ -216,7 +216,7 @@ class ListView[A] extends Component {
def adjusting = peer.getSelectionModel.getValueIsAdjusting
}
- def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getCellRenderer)
+ def renderer: ListView.Renderer[A] = ListView.Renderer.wrap[A](peer.getCellRenderer)
def renderer_=(r: ListView.Renderer[A]) { peer.setCellRenderer(r.peer) }
def fixedCellWidth = peer.getFixedCellWidth
diff --git a/src/swing/scala/swing/TabbedPane.scala b/src/swing/scala/swing/TabbedPane.scala
index ca1eb2b64c..03e8c12c9c 100644
--- a/src/swing/scala/swing/TabbedPane.scala
+++ b/src/swing/scala/swing/TabbedPane.scala
@@ -112,9 +112,6 @@ class TabbedPane extends Component with Publisher {
*/
def tabPlacement_=(b: Alignment.Value) { peer.setTabPlacement(b.id) }
- @deprecated("Use tabPlacement_=() instead.", "2.9.1")
- def tabPlacement(b: Alignment.Value) { peer.setTabPlacement(b.id) }
-
/**
* The current page selection
*/