summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala18
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaVersion.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala15
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala0
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala66
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--src/library/scala/collection/immutable/Map.scala2
-rw-r--r--src/library/scala/collection/immutable/Set.scala2
-rw-r--r--src/library/scala/collection/mutable/FlatHashTable.scala4
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala12
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala15
-rw-r--r--src/library/scala/collection/mutable/OpenHashMap.scala4
-rw-r--r--src/library/scala/util/Properties.scala6
-rw-r--r--src/library/scala/util/matching/Regex.scala46
-rw-r--r--src/reflect/scala/reflect/internal/BaseTypeSeqs.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Depth.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala33
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala1
-rw-r--r--src/reflect/scala/reflect/internal/TypeDebugging.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala27
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala2
-rw-r--r--src/reflect/scala/reflect/internal/transform/RefChecks.scala0
-rw-r--r--src/reflect/scala/reflect/io/ZipArchive.scala76
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedOps.scala11
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ExprTyper.scala14
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala33
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala7
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplProps.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala10
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/Page.scala27
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala10
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala2
43 files changed, 363 insertions, 214 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c1b0733895..819887f959 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -953,10 +953,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
definitions.isDefinitionsInitialized
&& rootMirror.isMirrorInitialized
)
- override def isPastTyper = (
+ override def isPastTyper = isPast(currentRun.typerPhase)
+ def isPast(phase: Phase) = (
(curRun ne null)
&& isGlobalInitialized // defense against init order issues
- && (globalPhase.id > currentRun.typerPhase.id)
+ && (globalPhase.id > phase.id)
)
// TODO - trim these to the absolute minimum.
diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
index dfd5b07a3b..c18f220d95 100644
--- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
@@ -446,9 +446,10 @@ abstract class ScalaPrimitives {
inform(s"Unknown primitive method $cls.$method")
else alts foreach (s =>
addPrimitive(s,
- s.info.paramTypes match {
- case tp :: _ if code == ADD && tp =:= StringTpe => CONCAT
- case _ => code
+ if (code != ADD) code
+ else exitingTyper(s.info).paramTypes match {
+ case tp :: _ if tp =:= StringTpe => CONCAT
+ case _ => code
}
)
)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 76d042ce3b..37dea477c6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -1264,14 +1264,22 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
def genEqEqPrimitive(l: Tree, r: Tree, success: asm.Label, failure: asm.Label, targetIfNoJump: asm.Label, pos: Position) {
/* True if the equality comparison is between values that require the use of the rich equality
- * comparator (scala.runtime.Comparator.equals). This is the case when either side of the
+ * comparator (scala.runtime.BoxesRunTime.equals). This is the case when either side of the
* comparison might have a run-time type subtype of java.lang.Number or java.lang.Character.
- * When it is statically known that both sides are equal and subtypes of Number of Character,
- * not using the rich equality is possible (their own equals method will do ok.)
+ *
+ * When it is statically known that both sides are equal and subtypes of Number or Character,
+ * not using the rich equality is possible (their own equals method will do ok), except for
+ * java.lang.Float and java.lang.Double: their `equals` have different behavior around `NaN`
+ * and `-0.0`, see Javadoc (scala-dev#329).
*/
val mustUseAnyComparator: Boolean = {
- val areSameFinals = l.tpe.isFinalType && r.tpe.isFinalType && (l.tpe =:= r.tpe)
- !areSameFinals && platform.isMaybeBoxed(l.tpe.typeSymbol) && platform.isMaybeBoxed(r.tpe.typeSymbol)
+ platform.isMaybeBoxed(l.tpe.typeSymbol) && platform.isMaybeBoxed(r.tpe.typeSymbol) && {
+ val areSameFinals = l.tpe.isFinalType && r.tpe.isFinalType && (l.tpe =:= r.tpe) && {
+ val sym = l.tpe.typeSymbol
+ sym != BoxedFloatClass && sym != BoxedDoubleClass
+ }
+ !areSameFinals
+ }
}
if (mustUseAnyComparator) {
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index f1f5f37c36..224de97734 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -77,10 +77,10 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
if (reader != null) {
reader.read match {
case 'a' | 'A' =>
- new Throwable().printStackTrace()
+ new Throwable().printStackTrace(writer)
System.exit(1)
case 's' | 'S' =>
- new Throwable().printStackTrace()
+ new Throwable().printStackTrace(writer)
writer.println()
writer.flush()
case _ =>
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala
index 0b051ef89d..c38de753c8 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala
@@ -127,7 +127,7 @@ abstract class ScalaBuild extends Ordered[ScalaBuild] {
def unparse: String
}
/**
- * A development, test, nightly, snapshot or other "unofficial" build
+ * A development, test, integration, snapshot or other "unofficial" build
*/
case class Development(id: String) extends ScalaBuild {
def unparse = s"-${id}"
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index d948d151a6..dd44366692 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -122,11 +122,16 @@ abstract class SymbolLoaders {
* and give them `completer` as type.
*/
def enterClassAndModule(root: Symbol, name: String, getCompleter: (ClassSymbol, ModuleSymbol) => SymbolLoader) {
- val clazz = newClass(root, name)
- val module = newModule(root, name)
- val completer = getCompleter(clazz, module)
- enterClass(root, clazz, completer)
- enterModule(root, module, completer)
+ val clazz0 = newClass(root, name)
+ val module0 = newModule(root, name)
+ val completer = getCompleter(clazz0, module0)
+ // enterClass/Module may return an existing symbol instead of the ones we created above
+ // this may happen when there's both sources and binaries on the classpath, but the class
+ // name is different from the file name, so the classpath can't match the binary and source
+ // representation. `companionModule/Class` prefers the source version, so we should be careful
+ // to reuse the symbols returned below.
+ val clazz = enterClass(root, clazz0, completer)
+ val module = enterModule(root, module0, completer)
if (!clazz.isAnonymousClass) {
// Diagnostic for SI-7147
def msg: String = {
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ /dev/null
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 744b9c8a8e..9e3e8ff455 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -84,7 +84,7 @@ abstract class TailCalls extends Transform {
* </p>
* <p>
* Assumes: `Uncurry` has been run already, and no multiple
- * parameter lists exit.
+ * parameter lists exist.
* </p>
*/
class TailCallElimination(unit: CompilationUnit) extends Transformer {
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index dcffd7a6ab..f35dd6556f 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -342,12 +342,16 @@ abstract class UnCurry extends InfoTransform
* the whole tree with it.
*/
private def replaceElidableTree(tree: Tree): Tree = {
+ def elisionOf(t: Type): Tree = t.typeSymbol match {
+ case StringClass => Literal(Constant("")) setType t
+ case _ => gen.mkZero(t)
+ }
tree match {
case DefDef(_,_,_,_,_,rhs) =>
- val rhs1 = if (rhs == EmptyTree) rhs else Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe
+ val rhs1 = if (rhs == EmptyTree) rhs else Block(Nil, elisionOf(rhs.tpe)) setType rhs.tpe
deriveDefDef(tree)(_ => rhs1) setSymbol tree.symbol setType tree.tpe
case _ =>
- gen.mkZero(tree.tpe) setType tree.tpe
+ elisionOf(tree.tpe)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index d349597b14..7a3b8d2ab6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -62,11 +62,10 @@ trait Contexts { self: Analyzer =>
def warnUnusedImports(unit: CompilationUnit) = if (!unit.isJava) {
for (imps <- allImportInfos.remove(unit)) {
- for (imp <- imps.reverse.distinct) {
+ for (imp <- imps.distinct.reverse) {
val used = allUsedSelectors(imp)
- def isMask(s: ImportSelector) = s.name != nme.WILDCARD && s.rename == nme.WILDCARD
- imp.tree.selectors filterNot (s => isMask(s) || used(s)) foreach { sel =>
+ imp.tree.selectors filterNot (s => isMaskImport(s) || used(s)) foreach { sel =>
reporter.warning(imp posOf sel, "Unused import")
}
}
@@ -74,6 +73,10 @@ trait Contexts { self: Analyzer =>
}
}
+ def isMaskImport(s: ImportSelector): Boolean = s.name != nme.WILDCARD && s.rename == nme.WILDCARD
+ def isIndividualImport(s: ImportSelector): Boolean = s.name != nme.WILDCARD && s.rename != nme.WILDCARD
+ def isWildcardImport(s: ImportSelector): Boolean = s.name == nme.WILDCARD
+
var lastAccessCheckDetails: String = ""
/** List of symbols to import from in a root context. Typically that
@@ -1193,27 +1196,33 @@ trait Contexts { self: Analyzer =>
res
}
- final def lookupCompanionOf(original: Symbol): Symbol = {
- if (original.isModuleClass) original.sourceModule
- else lookupScopeEntry(original) match {
- case null => NoSymbol
- case entry => entry.owner.lookupCompanion(original)
+ final def lookupCompanionInIncompleteOwner(original: Symbol): Symbol = {
+ /* Search scopes in current and enclosing contexts for the definition of `symbol` */
+ def lookupScopeEntry(symbol: Symbol): ScopeEntry = {
+ var res: ScopeEntry = null
+ var ctx = this
+ while (res == null && ctx.outer != ctx) {
+ val s = ctx.scope lookupSymbolEntry symbol
+ if (s != null)
+ res = s
+ else
+ ctx = ctx.outer
+ }
+ res
}
- }
- /** Search scopes in current and enclosing contexts for the definition of `symbol` */
- private def lookupScopeEntry(symbol: Symbol): ScopeEntry = {
- var res: ScopeEntry = null
- var ctx = this
- while (res == null && ctx.outer != ctx) {
- val s = ctx.scope lookupSymbolEntry symbol
- if (s != null)
- res = s
- else
- ctx = ctx.outer
+ // 1) Must be owned by the same Scope, to ensure that in
+ // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object.
+ // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions.
+ lookupScopeEntry(original) match {
+ case null => NoSymbol
+ case entry =>
+ def isCompanion(sym: Symbol): Boolean =
+ (original.isModule && sym.isClass || sym.isModule && original.isClass) && sym.isCoDefinedWith(original)
+ entry.owner.lookupNameInSameScopeAs(original, original.name.companionName).filter(isCompanion)
}
- res
}
+
} //class Context
/** A `Context` focussed on an `Import` tree */
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 395bda234b..28169c9da1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1955,9 +1955,12 @@ trait Namers extends MethodSynthesis {
// Doing this generally would trigger cycles; that's what we also
// use the lower-level scan through the current Context as a fall back.
if (!currentRun.compiles(owner)) owner.initialize
- original.companionSymbol orElse {
- ctx.lookupCompanionOf(original)
- }
+
+ if (original.isModuleClass) original.sourceModule
+ else if (!owner.isTerm && owner.hasCompleteInfo)
+ original.companionSymbol
+ else
+ ctx.lookupCompanionInIncompleteOwner(original)
}
/** A version of `Symbol#linkedClassOfClass` that works with local companions, ala `companionSymbolOf`. */
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 990edcd86d..50743a922a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -112,7 +112,7 @@ abstract class TreeCheckers extends Analyzer {
else if (prevTrees exists (t => (t eq tree) || (t.symbol == sym)))
()
else {
- val s1 = (prevTrees map wholetreestr).sorted.distinct
+ val s1 = (prevTrees map wholetreestr).distinct.sorted
val s2 = wholetreestr(tree)
if (s1 contains s2) ()
else movedMsgs += ("\n** %s moved:\n** Previously:\n%s\n** Currently:\n%s".format(ownerstr(sym), s1 mkString ", ", s2))
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index b66dbf21c0..36b9a65334 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -11,6 +11,7 @@ import scala.collection.mutable.ListBuffer
import scala.util.control.Exception.ultimately
import symtab.Flags._
import PartialFunction._
+import scala.annotation.tailrec
/** An interface to enable higher configurability of diagnostic messages
* regarding type errors. This is barely a beginning as error messages are
@@ -274,19 +275,54 @@ trait TypeDiagnostics {
if (AnyRefTpe <:< req) notAnyRefMessage(found) else ""
}
+ def finalOwners(tpe: Type): Boolean = (tpe.prefix == NoPrefix) || recursivelyFinal(tpe)
+
+ @tailrec
+ final def recursivelyFinal(tpe: Type): Boolean = {
+ val prefix = tpe.prefix
+ if (prefix != NoPrefix) {
+ if (prefix.typeSymbol.isFinal) {
+ recursivelyFinal(prefix)
+ } else {
+ false
+ }
+ } else {
+ true
+ }
+ }
+
// TODO - figure out how to avoid doing any work at all
// when the message will never be seen. I though context.reportErrors
// being false would do that, but if I return "<suppressed>" under
// that condition, I see it.
def foundReqMsg(found: Type, req: Type): String = {
- def baseMessage = (
- ";\n found : " + found.toLongString + existentialContext(found) + explainAlias(found) +
- "\n required: " + req + existentialContext(req) + explainAlias(req)
- )
- ( withDisambiguation(Nil, found, req)(baseMessage)
- + explainVariance(found, req)
- + explainAnyVsAnyRef(found, req)
- )
+ val foundWiden = found.widen
+ val reqWiden = req.widen
+ val sameNamesDifferentPrefixes =
+ foundWiden.typeSymbol.name == reqWiden.typeSymbol.name &&
+ foundWiden.prefix.typeSymbol != reqWiden.prefix.typeSymbol
+ val easilyMistakable =
+ sameNamesDifferentPrefixes &&
+ !req.typeSymbol.isConstant &&
+ finalOwners(foundWiden) && finalOwners(reqWiden) &&
+ !found.typeSymbol.isTypeParameterOrSkolem && !req.typeSymbol.isTypeParameterOrSkolem
+
+ if (easilyMistakable) {
+ val longestNameLength = foundWiden.nameAndArgsString.length max reqWiden.nameAndArgsString.length
+ val paddedFoundName = foundWiden.nameAndArgsString.padTo(longestNameLength, ' ')
+ val paddedReqName = reqWiden.nameAndArgsString.padTo(longestNameLength, ' ')
+ ";\n found : " + (paddedFoundName + s" (in ${found.prefix.typeSymbol.fullNameString}) ") + explainAlias(found) +
+ "\n required: " + (paddedReqName + s" (in ${req.prefix.typeSymbol.fullNameString}) ") + explainAlias(req)
+ } else {
+ def baseMessage = {
+ ";\n found : " + found.toLongString + existentialContext(found) + explainAlias(found) +
+ "\n required: " + req + existentialContext(req) + explainAlias(req)
+ }
+ (withDisambiguation(Nil, found, req)(baseMessage)
+ + explainVariance(found, req)
+ + explainAnyVsAnyRef(found, req)
+ )
+ }
}
def typePatternAdvice(sym: Symbol, ptSym: Symbol) = {
@@ -315,14 +351,6 @@ trait TypeDiagnostics {
def restoreName() = sym.name = savedName
def modifyName(f: String => String) = sym setName newTypeName(f(sym.name.toString))
- /** Prepend java.lang, scala., or Predef. if this type originated
- * in one of those.
- */
- def qualifyDefaultNamespaces() = {
- val intersect = Set(trueOwner, aliasOwner) intersect UnqualifiedOwners
- if (intersect.nonEmpty && tp.typeSymbolDirect.name == tp.typeSymbol.name) preQualify()
- }
-
// functions to manipulate the name
def preQualify() = modifyName(trueOwner.fullName + "." + _)
def postQualify() = if (!(postQualifiedWith contains trueOwner)) { postQualifiedWith ::= trueOwner; modifyName(_ + "(in " + trueOwner + ")") }
@@ -414,12 +442,6 @@ trait TypeDiagnostics {
if (td1 string_== td2)
tds foreach (_.nameQualify())
- // If they have the same simple name, and either of them is in the
- // scala package or predef, qualify with scala so it is not confusing why
- // e.g. java.util.Iterator and Iterator are different types.
- if (td1 name_== td2)
- tds foreach (_.qualifyDefaultNamespaces())
-
// If they still print identically:
// a) If they are type parameters with different owners, append (in <owner>)
// b) Failing that, the best we can do is append "(some other)" to the latter.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e4b2c652c3..2cbd9475fc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3333,15 +3333,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def handleOverloaded = {
val undetparams = context.undetparams
- def funArgTypes(tps: List[Type]) = tps.map { tp =>
- val relTp = tp.asSeenFrom(pre, fun.symbol.owner)
+ def funArgTypes(tpAlts: List[(Type, Symbol)]) = tpAlts.map { case (tp, alt) =>
+ val relTp = tp.asSeenFrom(pre, alt.owner)
val argTps = functionOrSamArgTypes(relTp)
//println(s"funArgTypes $argTps from $relTp")
argTps.map(approximateAbstracts)
}
- def functionProto(argTps: List[Type]): Type =
- try functionType(funArgTypes(argTps).transpose.map(lub), WildcardType)
+ def functionProto(argTpWithAlt: List[(Type, Symbol)]): Type =
+ try functionType(funArgTypes(argTpWithAlt).transpose.map(lub), WildcardType)
catch { case _: IllegalArgumentException => WildcardType }
// To propagate as much information as possible to typedFunction, which uses the expected type to
@@ -3355,21 +3355,21 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// do not receive special treatment: they are typed under WildcardType.)
val altArgPts =
if (settings.isScala212 && args.exists(treeInfo.isFunctionMissingParamType))
- try alts.map(alt => formalTypes(alt.info.paramTypes, argslen)).transpose // do least amount of work up front
+ try alts.map(alt => formalTypes(alt.info.paramTypes, argslen).map(ft => (ft, alt))).transpose // do least amount of work up front
catch { case _: IllegalArgumentException => args.map(_ => Nil) } // fail safe in case formalTypes fails to align to argslen
else args.map(_ => Nil) // will type under argPt == WildcardType
val (args1, argTpes) = context.savingUndeterminedTypeParams() {
val amode = forArgMode(fun, mode)
- map2(args, altArgPts) { (arg, argPts) =>
+ map2(args, altArgPts) { (arg, argPtAlts) =>
def typedArg0(tree: Tree) = {
// if we have an overloaded HOF such as `(f: Int => Int)Int <and> (f: Char => Char)Char`,
// and we're typing a function like `x => x` for the argument, try to collapse
// the overloaded type into a single function type from which `typedFunction`
// can derive the argument type for `x` in the function literal above
val argPt =
- if (argPts.nonEmpty && treeInfo.isFunctionMissingParamType(tree)) functionProto(argPts)
+ if (argPtAlts.nonEmpty && treeInfo.isFunctionMissingParamType(tree)) functionProto(argPtAlts)
else WildcardType
val argTyped = typedArg(tree, amode, BYVALmode, argPt)
@@ -4666,19 +4666,20 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart)
- val erred = qual1.isErroneous || args.exists(_.isErroneous)
+ val erred = qual1.exists(_.isErroneous) || args.exists(_.isErroneous)
if (erred) reportError(error) else {
val convo = convertToAssignment(fun, qual1, name, args)
silent(op = _.typed1(convo, mode, pt)) match {
case SilentResultValue(t) => t
- case err: SilentTypeError => reportError(SilentTypeError(advice1(convo, error.errors, err), error.warnings))
+ case err: SilentTypeError => reportError(
+ SilentTypeError(advice1(convo, error.errors, err), error.warnings)
+ )
}
}
- }
- else {
+ } else {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
val Apply(Select(qual2, _), args2) = tree
- val erred = qual2.isErroneous || args2.exists(_.isErroneous)
+ val erred = qual2.exists(_.isErroneous) || args2.exists(_.isErroneous)
reportError {
if (erred) error else SilentTypeError(advice2(error.errors), error.warnings)
}
diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala
index cbdf7b39f5..4107b6414d 100644
--- a/src/library/scala/collection/immutable/Map.scala
+++ b/src/library/scala/collection/immutable/Map.scala
@@ -198,7 +198,7 @@ object Map extends ImmutableMapFactory[Map] {
else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4)
else if (key == key3) new Map4(key1, value1, key2, value2, key3, value, key4, value4)
else if (key == key4) new Map4(key1, value1, key2, value2, key3, value3, key4, value)
- else new HashMap + ((key1, value1), (key2, value2), (key3, value3), (key4, value4), (key, value))
+ else (new HashMap).updated(key1,value1).updated(key2, value2).updated(key3, value3).updated(key4, value4).updated(key, value)
def + [V1 >: V](kv: (K, V1)): Map[K, V1] = updated(kv._1, kv._2)
def - (key: K): Map[K, V] =
if (key == key1) new Map3(key2, value2, key3, value3, key4, value4)
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index 047ea736bd..0f16f97cb0 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -193,7 +193,7 @@ object Set extends ImmutableSetFactory[Set] {
elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4
def + (elem: A): Set[A] =
if (contains(elem)) this
- else new HashSet[A] + (elem1, elem2, elem3, elem4, elem)
+ else new HashSet[A] + elem1 + elem2 + elem3 + elem4 + elem
def - (elem: A): Set[A] =
if (elem == elem1) new Set3(elem2, elem3, elem4)
else if (elem == elem2) new Set3(elem1, elem3, elem4)
diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala
index 8c4115b1dd..0d8799282f 100644
--- a/src/library/scala/collection/mutable/FlatHashTable.scala
+++ b/src/library/scala/collection/mutable/FlatHashTable.scala
@@ -47,9 +47,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] {
@transient protected var seedvalue: Int = tableSizeSeed
- import HashTable.powerOfTwo
-
- protected def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
+ protected def capacity(expectedSize: Int) = HashTable.nextPositivePowerOfTwo(expectedSize)
/** The initial size of the hash table.
*/
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
index 11ff1f0893..de61ebb796 100644
--- a/src/library/scala/collection/mutable/HashMap.scala
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -73,10 +73,18 @@ extends AbstractMap[A, B]
}
override def getOrElseUpdate(key: A, defaultValue: => B): B = {
- val i = index(elemHashCode(key))
+ val hash = elemHashCode(key)
+ val i = index(hash)
val entry = findEntry(key, i)
if (entry != null) entry.value
- else addEntry(createNewEntry(key, defaultValue), i)
+ else {
+ val table0 = table
+ val default = defaultValue
+ // Avoid recomputing index if the `defaultValue()` hasn't triggered
+ // a table resize.
+ val newEntryIndex = if (table0 eq table) i else index(hash)
+ addEntry(createNewEntry(key, default), newEntryIndex)
+ }
}
/* inlined HashTable.findEntry0 to preserve its visibility */
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index 445217ebef..01ec1defad 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -12,7 +12,7 @@ package scala
package collection
package mutable
-import java.lang.Integer.rotateRight
+import java.lang.Integer.{numberOfLeadingZeros, rotateRight}
import scala.util.hashing.byteswap32
/** This class can be used to construct data structures that are based
@@ -405,7 +405,7 @@ private[collection] object HashTable {
private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = ((thr.toLong * loadFactorDenum) / _loadFactor).toInt
- private[collection] final def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
+ private[collection] final def capacity(expectedSize: Int) = nextPositivePowerOfTwo(expectedSize)
trait HashUtils[KeyType] {
protected final def sizeMapBucketBitSize = 5
@@ -433,16 +433,7 @@ private[collection] object HashTable {
/**
* Returns a power of two >= `target`.
*/
- private[collection] def powerOfTwo(target: Int): Int = {
- /* See http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html */
- var c = target - 1
- c |= c >>> 1
- c |= c >>> 2
- c |= c >>> 4
- c |= c >>> 8
- c |= c >>> 16
- c + 1
- }
+ private[collection] def nextPositivePowerOfTwo(target: Int): Int = 1 << -numberOfLeadingZeros(target - 1)
class Contents[A, Entry >: Null <: HashEntry[A, Entry]](
val loadFactor: Int,
diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala
index ca08f475ce..b2e9ee27b9 100644
--- a/src/library/scala/collection/mutable/OpenHashMap.scala
+++ b/src/library/scala/collection/mutable/OpenHashMap.scala
@@ -31,8 +31,6 @@ object OpenHashMap {
final private class OpenEntry[Key, Value](var key: Key,
var hash: Int,
var value: Option[Value])
-
- private[mutable] def nextPositivePowerOfTwo(i : Int) = 1 << (32 - Integer.numberOfLeadingZeros(i - 1))
}
/** A mutable hash map based on an open hashing scheme. The precise scheme is
@@ -67,7 +65,7 @@ extends AbstractMap[Key, Value]
override def empty: OpenHashMap[Key, Value] = OpenHashMap.empty[Key, Value]
- private[this] val actualInitialSize = OpenHashMap.nextPositivePowerOfTwo(initialSize)
+ private[this] val actualInitialSize = HashTable.nextPositivePowerOfTwo(initialSize)
private var mask = actualInitialSize - 1
diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala
index 7b21351cf6..29a635fcbe 100644
--- a/src/library/scala/util/Properties.scala
+++ b/src/library/scala/util/Properties.scala
@@ -154,6 +154,12 @@ private[scala] trait PropertiesTrait {
/* Some runtime values. */
private[scala] def isAvian = javaVmName contains "Avian"
+ private[scala] def coloredOutputEnabled: Boolean = propOrElse("scala.color", "auto") match {
+ case "auto" => System.console() != null && !isWin
+ case a if a.toLowerCase() == "true" => true
+ case _ => false
+ }
+
// This is looking for javac, tools.jar, etc.
// Tries JDK_HOME first, then the more common but likely jre JAVA_HOME,
// and finally the system property based javaHome.
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index ea9f02f85b..4822fe02b4 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -41,11 +41,13 @@ import java.util.regex.{ Pattern, Matcher }
* implicitly for strings:
*
* {{{
- * val date = """(\d\d\d\d)-(\d\d)-(\d\d)""".r
+ * val date = raw"(\d{4})-(\d{2})-(\d{2})".r
* }}}
*
* Since escapes are not processed in multi-line string literals, using triple quotes
* avoids having to escape the backslash character, so that `"\\d"` can be written `"""\d"""`.
+ * The same result is achieved with certain interpolators, such as `raw"\d".r` or
+ * a custom interpolator `r"\d"` that also compiles the `Regex`.
*
* === Extraction ===
* To extract the capturing groups when a `Regex` is matched, use it as
@@ -116,29 +118,41 @@ import java.util.regex.{ Pattern, Matcher }
* while (mi.hasNext) {
* val d = mi.next
* if (mi.group(1).toInt < 1960) println(s"$d: An oldie but goodie.")
+ * }
* }}}
*
- * Note that `findAllIn` finds matches that don't overlap. (See [[findAllIn]] for more examples.)
+ * Although the `MatchIterator` returned by `findAllIn` is used like any `Iterator`,
+ * with alternating calls to `hasNext` and `next`, `hasNext` has the additional
+ * side effect of advancing the underlying matcher to the next unconsumed match.
+ * This effect is visible in the `MatchData` representing the "current match".
*
* {{{
- * val num = """(\d+)""".r
- * val all = num.findAllIn("123").toList // List("123"), not List("123", "23", "3")
+ * val r = "(ab+c)".r
+ * val s = "xxxabcyyyabbczzz"
+ * r.findAllIn(s).start // 3
+ * val mi = r.findAllIn(s)
+ * mi.hasNext // true
+ * mi.start // 3
+ * mi.next() // "abc"
+ * mi.start // 3
+ * mi.hasNext // true
+ * mi.start // 9
+ * mi.next() // "abbc"
* }}}
*
- * Also, the "current match" of a `MatchIterator` may be advanced by either `hasNext` or `next`.
- * By comparison, the `Iterator[Match]` returned by `findAllMatchIn` or `findAllIn.matchData`
- * produces `Match` objects that remain valid after the iterator is advanced.
+ * The example shows that methods on `MatchData` such as `start` will advance to
+ * the first match, if necessary. It also shows that `hasNext` will advance to
+ * the next unconsumed match, if `next` has already returned the current match.
+ *
+ * The current `MatchData` can be captured using the `matchData` method.
+ * Alternatively, `findAllMatchIn` returns an `Iterator[Match]`, where there
+ * is no interaction between the iterator and `Match` objects it has already produced.
+ *
+ * Note that `findAllIn` finds matches that don't overlap. (See [[findAllIn]] for more examples.)
*
* {{{
- * val ns = num.findAllIn("1 2 3")
- * ns.start // 0
- * ns.hasNext // true
- * ns.start // 2
- * val ms = num.findAllMatchIn("1 2 3")
- * val m = ms.next()
- * m.start // 0
- * ms.hasNext // true
- * m.start // still 0
+ * val num = raw"(\d+)".r
+ * val all = num.findAllIn("123").toList // List("123"), not List("123", "23", "3")
* }}}
*
* === Replace Text ===
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
index 0ef52213e5..1cdefff2e9 100644
--- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
@@ -33,6 +33,9 @@ trait BaseTypeSeqs {
protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) =
new BaseTypeSeq(parents, elems)
+ protected def newMappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) =
+ new MappedBaseTypeSeq(orig, f)
+
/** Note: constructor is protected to force everyone to use the factory method newBaseTypeSeq instead.
* This is necessary because when run from reflection every base type sequence needs to have a
* SynchronizedBaseTypeSeq as mixin.
@@ -125,7 +128,7 @@ trait BaseTypeSeqs {
newBaseTypeSeq(parents, arr)
}
- def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f)
+ def lateMap(f: Type => Type): BaseTypeSeq = newMappedBaseTypeSeq(this, f)
def exists(p: Type => Boolean): Boolean = elems exists p
diff --git a/src/reflect/scala/reflect/internal/Depth.scala b/src/reflect/scala/reflect/internal/Depth.scala
index a330e0accb..5e7202f8bf 100644
--- a/src/reflect/scala/reflect/internal/Depth.scala
+++ b/src/reflect/scala/reflect/internal/Depth.scala
@@ -5,7 +5,7 @@ package internal
import Depth._
final class Depth private (val depth: Int) extends AnyVal with Ordered[Depth] {
- def max(that: Depth): Depth = if (this < that) that else this
+ def max(that: Depth): Depth = if (this.depth < that.depth) that else this
def decr(n: Int): Depth = if (isAnyDepth) this else Depth(depth - n)
def incr(n: Int): Depth = if (isAnyDepth) this else Depth(depth + n)
def decr: Depth = decr(1)
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 9d39ef8b42..055f7c9d5b 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -296,11 +296,13 @@ trait Names extends api.Names {
*/
final def pos(s: String, start: Int): Int = {
var i = pos(s.charAt(0), start)
- while (i + s.length() <= len) {
+ val sLen = s.length()
+ if (sLen == 1) return i
+ while (i + sLen <= len) {
var j = 1
while (s.charAt(j) == chrs(index + i + j)) {
j += 1
- if (j == s.length()) return i
+ if (j == sLen) return i
}
i = pos(s.charAt(0), i + 1)
}
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 51fb31d36d..0435a2c1cf 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -291,25 +291,6 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
null
}
- final def lookupCompanion(original: Symbol): Symbol = {
- lookupSymbolEntry(original) match {
- case null =>
- case entry =>
- var e = lookupEntry(original.name.companionName)
- while (e != null) {
- // 1) Must be owned by the same Scope, to ensure that in
- // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object.
- // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions.
- def isClassAndModule(sym1: Symbol, sym2: Symbol) = sym1.isClass && sym2.isModule
- if ((e.owner eq entry.owner) && (isClassAndModule(original, e.sym) || isClassAndModule(e.sym, original))) {
- return if (e.sym.isCoDefinedWith(original)) e.sym else NoSymbol
- }
- e = lookupNextEntry(e)
- }
- }
- NoSymbol
- }
-
/** lookup a symbol entry matching given name.
* @note from Martin: I believe this is a hotspot or will be one
* in future versions of the type system. I have reverted the previous
@@ -345,6 +326,20 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
e
}
+ final def lookupNameInSameScopeAs(original: Symbol, companionName: Name): Symbol = {
+ lookupSymbolEntry(original) match {
+ case null =>
+ case entry =>
+ var e = lookupEntry(companionName)
+ while (e != null) {
+ if (e.owner eq entry.owner) return e.sym
+ e = lookupNextEntry(e)
+ }
+ }
+ NoSymbol
+ }
+
+
/** TODO - we can test this more efficiently than checking isSubScope
* in both directions. However the size test might be enough to quickly
* rule out most failures.
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 890a5796e9..9d71136fc5 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -809,7 +809,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isDerivedValueClass =
isClass && !hasFlag(PACKAGE | TRAIT) &&
- info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass
+ !phase.erasedTypes && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass
final def isMethodWithExtension =
isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) && !isMacro && !isSpecialized
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 1aef30819a..933afbea2b 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -274,6 +274,7 @@ abstract class TreeInfo {
def mayBeVarGetter(sym: Symbol): Boolean = sym.info match {
case NullaryMethodType(_) => sym.owner.isClass && !sym.isStable
case PolyType(_, NullaryMethodType(_)) => sym.owner.isClass && !sym.isStable
+ case PolyType(_, mt @ MethodType(_, _))=> mt.isImplicit && sym.owner.isClass && !sym.isStable
case mt @ MethodType(_, _) => mt.isImplicit && sym.owner.isClass && !sym.isStable
case _ => false
}
diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala
index e9050b4e33..58359e66d9 100644
--- a/src/reflect/scala/reflect/internal/TypeDebugging.scala
+++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala
@@ -59,7 +59,7 @@ trait TypeDebugging {
object typeDebug {
import scala.Console._
- private val colorsOk = sys.props contains "scala.color"
+ private val colorsOk = scala.util.Properties.coloredOutputEnabled
private def inColor(s: String, color: String) = if (colorsOk && s != "") color + s + RESET else s
private def inBold(s: String, color: String) = if (colorsOk && s != "") color + BOLD + s + RESET else s
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index b46f071717..dc12ef9352 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -967,6 +967,8 @@ trait Types
*/
def directObjectString = safeToString
+ def nameAndArgsString = typeSymbol.name.toString
+
/** A test whether a type contains any unification type variables.
* Overridden with custom logic except where trivially true.
*/
@@ -2321,6 +2323,8 @@ trait Types
private def preString = if (needsPreString) pre.prefixString else ""
private def argsString = if (args.isEmpty) "" else args.mkString("[", ",", "]")
+ override def nameAndArgsString = typeSymbol.name.toString + argsString
+
private def refinementDecls = fullyInitializeScope(decls) filter (sym => sym.isPossibleInRefinement && sym.isPublic)
private def refinementString = (
if (sym.isStructuralRefinement)
@@ -2728,6 +2732,19 @@ trait Types
arg.toString
}
+ override def nameAndArgsString: String = underlying match {
+ case TypeRef(_, sym, args) if !settings.debug && isRepresentableWithWildcards =>
+ sym.name + wildcardArgsString(quantified.toSet, args).mkString("[", ",", "]")
+ case TypeRef(_, sym, args) =>
+ sym.name + args.mkString("[", ",", "]") + existentialClauses
+ case _ => underlying.typeSymbol.name + existentialClauses
+ }
+
+ private def existentialClauses = {
+ val str = quantified map (_.existentialToString) mkString (" forSome { ", "; ", " }")
+ if (settings.explaintypes) "(" + str + ")" else str
+ }
+
/** An existential can only be printed with wildcards if:
* - the underlying type is a typeref
* - every quantified variable appears at most once as a type argument and
@@ -2746,7 +2763,7 @@ trait Types
tpe.typeSymbol.isRefinementClass && (tpe.parents exists isQuantified)
}
val (wildcardArgs, otherArgs) = args partition (arg => qset contains arg.typeSymbol)
- wildcardArgs.distinct == wildcardArgs &&
+ wildcardArgs.toSet.size == wildcardArgs.size &&
!(otherArgs exists (arg => isQuantified(arg))) &&
!(wildcardArgs exists (arg => isQuantified(arg.typeSymbol.info.bounds))) &&
!(qset contains sym) &&
@@ -2756,17 +2773,13 @@ trait Types
}
override def safeToString: String = {
- def clauses = {
- val str = quantified map (_.existentialToString) mkString (" forSome { ", "; ", " }")
- if (settings.explaintypes) "(" + str + ")" else str
- }
underlying match {
case TypeRef(pre, sym, args) if !settings.debug && isRepresentableWithWildcards =>
"" + TypeRef(pre, sym, Nil) + wildcardArgsString(quantified.toSet, args).mkString("[", ", ", "]")
case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
- "(" + underlying + ")" + clauses
+ "(" + underlying + ")" + existentialClauses
case _ =>
- "" + underlying + clauses
+ "" + underlying + existentialClauses
}
}
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index 08ccac8069..b4152c9b8c 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -377,7 +377,7 @@ abstract class UnPickler {
def readThisType(): Type = {
val sym = readSymbolRef() match {
- case stub: StubSymbol => stub.setFlag(PACKAGE)
+ case stub: StubSymbol => stub.setFlag(PACKAGE | MODULE)
case sym => sym
}
ThisType(sym)
diff --git a/src/reflect/scala/reflect/internal/transform/RefChecks.scala b/src/reflect/scala/reflect/internal/transform/RefChecks.scala
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/reflect/scala/reflect/internal/transform/RefChecks.scala
+++ /dev/null
diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala
index 262ab22ce9..f4e1633af4 100644
--- a/src/reflect/scala/reflect/io/ZipArchive.scala
+++ b/src/reflect/scala/reflect/io/ZipArchive.scala
@@ -27,6 +27,8 @@ import scala.annotation.tailrec
* ''Note: This library is considered experimental and should not be used unless you know what you are doing.''
*/
object ZipArchive {
+ private[io] val closeZipFile = sys.props.get("scala.classpath.closeZip").map(_.toBoolean).getOrElse(false)
+
/**
* @param file a File
* @return A ZipArchive if `file` is a readable zip file, otherwise null.
@@ -120,31 +122,69 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq
}
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
final class FileZipArchive(file: JFile) extends ZipArchive(file) {
+ private[this] def openZipFile(): ZipFile = try {
+ new ZipFile(file)
+ } catch {
+ case ioe: IOException => throw new IOException("Error accessing " + file.getPath, ioe)
+ }
+
+ private[this] class LazyEntry(
+ name: String,
+ time: Long,
+ size: Int
+ ) extends Entry(name) {
+ override def lastModified: Long = time // could be stale
+ override def input: InputStream = {
+ val zipFile = openZipFile()
+ val entry = zipFile.getEntry(name)
+ val delegate = zipFile.getInputStream(entry)
+ new FilterInputStream(delegate) {
+ override def close(): Unit = { zipFile.close() }
+ }
+ }
+ override def sizeOption: Option[Int] = Some(size) // could be stale
+ }
+
+ // keeps a file handle open to ZipFile, which forbids file mutation
+ // on Windows, and leaks memory on all OS (typically by stopping
+ // classloaders from being garbage collected). But is slightly
+ // faster than LazyEntry.
+ private[this] class LeakyEntry(
+ zipFile: ZipFile,
+ zipEntry: ZipEntry
+ ) extends Entry(zipEntry.getName) {
+ override def lastModified: Long = zipEntry.getTime
+ override def input: InputStream = zipFile.getInputStream(zipEntry)
+ override def sizeOption: Option[Int] = Some(zipEntry.getSize.toInt)
+ }
+
lazy val (root, allDirs) = {
val root = new DirEntry("/")
val dirs = mutable.HashMap[String, DirEntry]("/" -> root)
- val zipFile = try {
- new ZipFile(file)
- } catch {
- case ioe: IOException => throw new IOException("Error accessing " + file.getPath, ioe)
- }
-
+ val zipFile = openZipFile()
val enum = zipFile.entries()
- while (enum.hasMoreElements) {
- val zipEntry = enum.nextElement
- val dir = getDir(dirs, zipEntry)
- if (zipEntry.isDirectory) dir
- else {
- class FileEntry() extends Entry(zipEntry.getName) {
- override def getArchive = zipFile
- override def lastModified = zipEntry.getTime()
- override def input = getArchive getInputStream zipEntry
- override def sizeOption = Some(zipEntry.getSize().toInt)
+ try {
+ while (enum.hasMoreElements) {
+ val zipEntry = enum.nextElement
+ val dir = getDir(dirs, zipEntry)
+ if (zipEntry.isDirectory) dir
+ else {
+ val f =
+ if (ZipArchive.closeZipFile)
+ new LazyEntry(
+ zipEntry.getName(),
+ zipEntry.getTime(),
+ zipEntry.getSize().toInt
+ )
+ else
+ new LeakyEntry(zipFile, zipEntry)
+
+ dir.entries(f.name) = f
}
- val f = new FileEntry()
- dir.entries(f.name) = f
}
+ } finally {
+ if (ZipArchive.closeZipFile) zipFile.close()
}
(root, dirs)
}
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
index f0d96e0fd6..eadafc8abb 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
@@ -18,6 +18,12 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable
if (elems.exists(_.isInstanceOf[RefinedType])) new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq
else new BaseTypeSeq(parents, elems)
+ override protected def newMappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) =
+ // MappedBaseTypeSeq's are used rarely enough that we unconditionally mixin the synchronized
+ // wrapper, rather than doing this conditionally. A previous attempt to do that broke the "late"
+ // part of the "lateMap" contract in inspecting the mapped elements.
+ new MappedBaseTypeSeq(orig, f) with SynchronizedBaseTypeSeq
+
trait SynchronizedBaseTypeSeq extends BaseTypeSeq {
override def apply(i: Int): Type = gilSynchronized { super.apply(i) }
override def rawElem(i: Int) = gilSynchronized { super.rawElem(i) }
@@ -28,11 +34,6 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable
override def exists(p: Type => Boolean): Boolean = gilSynchronized { super.exists(p) }
override lazy val maxDepth = gilSynchronized { maxDepthOfElems }
override def toString = gilSynchronized { super.toString }
-
- override def lateMap(f: Type => Type): BaseTypeSeq =
- // only need to synchronize BaseTypeSeqs if they contain refined types
- if (map(f).toList.exists(_.isInstanceOf[RefinedType])) new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq
- else new MappedBaseTypeSeq(this, f)
}
// Scopes
diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
index 01e3a90950..f68705211f 100644
--- a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
@@ -13,6 +13,12 @@ trait ExprTyper {
import global.{ reporter => _, Import => _, _ }
import naming.freshInternalVarName
+ private def doInterpret(code: String): IR.Result = {
+ // interpret/interpretSynthetic may change the phase, which would have unintended effects on types.
+ val savedPhase = phase
+ try interpretSynthetic(code) finally phase = savedPhase
+ }
+
def symbolOfLine(code: String): Symbol = {
def asExpr(): Symbol = {
val name = freshInternalVarName()
@@ -21,7 +27,7 @@ trait ExprTyper {
// behind a def and strip the NullaryMethodType which wraps the expr.
val line = "def " + name + " = " + code
- interpretSynthetic(line) match {
+ doInterpret(line) match {
case IR.Success =>
val sym0 = symbolOfTerm(name)
// drop NullaryMethodType
@@ -32,7 +38,7 @@ trait ExprTyper {
def asDefn(): Symbol = {
val old = repl.definedSymbolList.toSet
- interpretSynthetic(code) match {
+ doInterpret(code) match {
case IR.Success =>
repl.definedSymbolList filterNot old match {
case Nil => NoSymbol
@@ -43,7 +49,7 @@ trait ExprTyper {
}
}
def asError(): Symbol = {
- interpretSynthetic(code)
+ doInterpret(code)
NoSymbol
}
beSilentDuring(asExpr()) orElse beSilentDuring(asDefn()) orElse asError()
@@ -72,7 +78,7 @@ trait ExprTyper {
def asProperType(): Option[Type] = {
val name = freshInternalVarName()
val line = "def %s: %s = ???" format (name, typeString)
- interpretSynthetic(line) match {
+ doInterpret(line) match {
case IR.Success =>
val sym0 = symbolOfTerm(name)
Some(sym0.asMethod.returnType)
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 9635f320fe..8be4d159f1 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -768,7 +768,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
result
}
- private object paste extends Pasted(prompt) {
+ private object paste extends Pasted(replProps.promptText) {
def interpret(line: String) = intp interpret line
def echo(message: String) = ILoop.this echo message
diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
index d6c0dafaf2..f455e71476 100644
--- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -213,29 +213,40 @@ trait MemberHandlers {
class ImportHandler(imp: Import) extends MemberHandler(imp) {
val Import(expr, selectors) = imp
+
def targetType = intp.global.rootMirror.getModuleIfDefined("" + expr) match {
case NoSymbol => intp.typeOfExpression("" + expr)
- case sym => sym.thisType
+ case sym => sym.tpe
}
- private def importableTargetMembers = importableMembers(targetType).toList
- // wildcard imports, e.g. import foo._
- private def selectorWild = selectors filter (_.name == nme.USCOREkw)
- // renamed imports, e.g. import foo.{ bar => baz }
- private def selectorRenames = selectors map (_.rename) filterNot (_ == null)
+
+ private def isFlattenedSymbol(sym: Symbol) =
+ sym.owner.isPackageClass &&
+ sym.name.containsName(nme.NAME_JOIN_STRING) &&
+ sym.owner.info.member(sym.name.take(sym.name.indexOf(nme.NAME_JOIN_STRING))) != NoSymbol
+
+ private def importableTargetMembers =
+ importableMembers(exitingTyper(targetType)).filterNot(isFlattenedSymbol).toList
+
+ // non-wildcard imports
+ private def individualSelectors = selectors filter analyzer.isIndividualImport
/** Whether this import includes a wildcard import */
- val importsWildcard = selectorWild.nonEmpty
+ val importsWildcard = selectors exists analyzer.isWildcardImport
def implicitSymbols = importedSymbols filter (_.isImplicit)
def importedSymbols = individualSymbols ++ wildcardSymbols
- private val selectorNames = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames) toSet
- lazy val individualSymbols: List[Symbol] = exitingTyper(importableTargetMembers filter (m => selectorNames(m.name)))
- lazy val wildcardSymbols: List[Symbol] = exitingTyper(if (importsWildcard) importableTargetMembers else Nil)
+ lazy val importableSymbolsWithRenames = {
+ val selectorRenameMap = individualSelectors.flatMap(x => x.name.bothNames zip x.rename.bothNames).toMap
+ importableTargetMembers flatMap (m => selectorRenameMap.get(m.name) map (m -> _))
+ }
+
+ lazy val individualSymbols: List[Symbol] = importableSymbolsWithRenames map (_._1)
+ lazy val wildcardSymbols: List[Symbol] = if (importsWildcard) importableTargetMembers else Nil
/** Complete list of names imported by a wildcard */
lazy val wildcardNames: List[Name] = wildcardSymbols map (_.name)
- lazy val individualNames: List[Name] = individualSymbols map (_.name)
+ lazy val individualNames: List[Name] = importableSymbolsWithRenames map (_._2)
/** The names imported by this statement */
override lazy val importedNames: List[Name] = wildcardNames ++ individualNames
diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index 3a7eda1b77..7ab5e5bb42 100644
--- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
@@ -38,10 +38,9 @@ abstract class Pasted(prompt: String) {
def matchesContinue(line: String) = matchesString(line, ContinueString)
def running = isRunning
- private def matchesString(line: String, target: String): Boolean = (
- (line startsWith target) ||
- (line.nonEmpty && spacey(line.head) && matchesString(line.tail, target))
- )
+ private def matchesString(line: String, target: String): Boolean =
+ line.startsWith(target) || (line.nonEmpty && spacey(line.head) && matchesString(line.tail, target))
+
private def stripString(line: String, target: String) = line indexOf target match {
case -1 => line
case idx => line drop (idx + target.length)
diff --git a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
index f3115d9800..a86069f198 100644
--- a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
@@ -17,7 +17,7 @@ class ReplProps {
private def int(name: String) = Prop[Int](name)
// This property is used in TypeDebugging. Let's recycle it.
- val colorOk = bool("scala.color")
+ val colorOk = Properties.coloredOutputEnabled
val info = bool("scala.repl.info")
val debug = bool("scala.repl.debug")
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
index 7f4e52e88d..2524fb75fb 100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
@@ -74,9 +74,8 @@ object EntityLink {
def unapply(el: EntityLink): Option[(Inline, LinkTo)] = Some((el.title, el.link))
}
final case class HtmlTag(data: String) extends Inline {
- private val Pattern = """(?ms)\A<(/?)(.*?)[\s>].*\z""".r
private val (isEnd, tagName) = data match {
- case Pattern(s1, s2) =>
+ case HtmlTag.Pattern(s1, s2) =>
(! s1.isEmpty, Some(s2.toLowerCase))
case _ =>
(false, None)
@@ -86,8 +85,13 @@ final case class HtmlTag(data: String) extends Inline {
isEnd && tagName == open.tagName
}
+ def close = tagName collect {
+ case name if !HtmlTag.TagsNotToClose(name) && !data.endsWith(s"</$name>") => HtmlTag(s"</$name>")
+ }
+}
+object HtmlTag {
+ private val Pattern = """(?ms)\A<(/?)(.*?)[\s>].*\z""".r
private val TagsNotToClose = Set("br", "img")
- def close = tagName collect { case name if !TagsNotToClose(name) => HtmlTag(s"</$name>") }
}
/** The summary of a comment, usually its first sentence. There must be exactly one summary per body. */
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/Page.scala b/src/scaladoc/scala/tools/nsc/doc/html/Page.scala
index c720c4939f..a84f77919d 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/Page.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/Page.scala
@@ -7,7 +7,7 @@ package scala
package tools.nsc.doc.html
import scala.tools.nsc.doc.model._
-import scala.tools.nsc.doc.base.comment
+import scala.tools.nsc.doc.base.comment._
import java.io.{FileOutputStream, File}
import scala.reflect.NameTransformer
import java.nio.channels.Channels
@@ -106,16 +106,21 @@ abstract class Page {
case dtpl: DocTemplateEntity => dtpl.companion.isDefined
case _ => false
}
+}
- protected def inlineToStr(inl: comment.Inline): String = inl match {
- case comment.Chain(items) => items flatMap (inlineToStr(_)) mkString ""
- case comment.Italic(in) => inlineToStr(in)
- case comment.Bold(in) => inlineToStr(in)
- case comment.Underline(in) => inlineToStr(in)
- case comment.Monospace(in) => inlineToStr(in)
- case comment.Text(text) => text
- case comment.Summary(in) => inlineToStr(in)
- case comment.EntityLink(comment.Text(text), _) => text
- case _ => inl.toString
+object Page {
+ def inlineToStr(inl: Inline): String = inl match {
+ case Chain(items) => items flatMap (inlineToStr(_)) mkString ""
+ case Italic(in) => inlineToStr(in)
+ case Bold(in) => inlineToStr(in)
+ case Underline(in) => inlineToStr(in)
+ case Superscript(in) => inlineToStr(in)
+ case Subscript(in) => inlineToStr(in)
+ case Link(raw, title) => inlineToStr(title)
+ case Monospace(in) => inlineToStr(in)
+ case Text(text) => text
+ case Summary(in) => inlineToStr(in)
+ case HtmlTag(tag) => "<[^>]*>".r.replaceAllIn(tag, "")
+ case EntityLink(in, _) => inlineToStr(in)
}
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
index 54bf42bbd5..fb2bf5049f 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala
@@ -90,13 +90,13 @@ trait EntityPage extends HtmlPage {
mbr match {
case dtpl: DocTemplateEntity =>
dtpl.companion.fold(<span class="separator"></span>) { c: DocTemplateEntity =>
- <a class="object" href={relativeLinkTo(c)} title={c.comment.fold("")(com => inlineToStr(com.short))}></a>
+ <a class="object" href={relativeLinkTo(c)} title={c.comment.fold("")(com => Page.inlineToStr(com.short))}></a>
}
case _ => <span class="separator"></span>
}
}
- <a class={mbr.kind} href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => inlineToStr(com.short))}></a>
- <a href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => inlineToStr(com.short))}>
+ <a class={mbr.kind} href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => Page.inlineToStr(com.short))}></a>
+ <a href={relativeLinkTo(mbr)} title={mbr.comment.fold("")(com => Page.inlineToStr(com.short))}>
{mbr.name}
</a>
</li>
@@ -897,7 +897,7 @@ trait EntityPage extends HtmlPage {
}
}
if (!nameLink.isEmpty)
- <a title={mbr.comment.fold("")(c => inlineToStr(c.short))} href={nameLink}>
+ <a title={mbr.comment.fold("")(c => Page.inlineToStr(c.short))} href={nameLink}>
{nameHtml}
</a>
else nameHtml
@@ -1065,7 +1065,7 @@ trait EntityPage extends HtmlPage {
body.blocks flatMap (blockToStr(_)) mkString ""
private def blockToStr(block: comment.Block): String = block match {
- case comment.Paragraph(in) => inlineToStr(in)
+ case comment.Paragraph(in) => Page.inlineToStr(in)
case _ => block.toString
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala
index 8f58a7b845..28304e76c7 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala
@@ -87,7 +87,7 @@ class IndexScript(universe: doc.Universe) extends Page {
/** Gets the short description i.e. the first sentence of the docstring */
def shortDesc(mbr: MemberEntity): String = mbr.comment.fold("") { c =>
- inlineToStr(c.short).replaceAll("\n", "")
+ Page.inlineToStr(c.short).replaceAll("\n", "")
}
/** Returns the json representation of the supplied members */