summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala46
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/library/scala/collection/Searching.scala12
-rw-r--r--src/library/scala/io/BufferedSource.scala2
-rw-r--r--src/library/scala/util/matching/Regex.scala10
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala41
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/DocFactory.scala6
12 files changed, 120 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 35eab94333..cb785de4b3 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1169,8 +1169,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (option) reporter.warning(pos, msg)
else if (!(warnings contains pos)) warnings += ((pos, msg))
def summarize() =
- if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings))
- warning("there were %d %s warning(s); re-run with %s for details".format(warnings.size, what, option.name))
+ if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings)){
+ val warningEvent = if (warnings.size > 1) s"were ${ warnings.size } $what warnings" else s"was one $what warning"
+ warning(s"there $warningEvent; re-run with ${ option.name } for details")
+ }
}
def newSourceFile(code: String, filename: String = "<console>") =
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 714f189ead..d9d1192772 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -328,11 +328,14 @@ abstract class TailCalls extends Transform {
)
case CaseDef(pat, guard, body) =>
+ // CaseDefs are already translated and guards were moved into the body.
+ // If this was not the case, guards would have to be transformed here as well.
+ assert(guard.isEmpty)
deriveCaseDef(tree)(transform)
case If(cond, thenp, elsep) =>
treeCopy.If(tree,
- cond,
+ noTailTransform(cond),
transform(thenp),
transform(elsep)
)
@@ -363,7 +366,7 @@ abstract class TailCalls extends Transform {
rewriteApply(tapply, fun, targs, vargs)
case Apply(fun, args) if fun.symbol == Boolean_or || fun.symbol == Boolean_and =>
- treeCopy.Apply(tree, fun, transformTrees(args))
+ treeCopy.Apply(tree, noTailTransform(fun), transformTrees(args))
// this is to detect tailcalls in translated matches
// it's a one-argument call to a label that is in a tailposition and that looks like label(x) {x}
diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
index fa6e5399eb..5a70d4c524 100644
--- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
@@ -190,6 +190,16 @@ trait AnalyzerPlugins { self: Analyzer =>
def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Option[Tree] = None
/**
+ * Figures out whether the given macro definition is blackbox or whitebox.
+ *
+ * Default implementation provided in `self.standardIsBlackbox` loads the macro impl binding
+ * and fetches boxity from the "isBlackbox" field of the macro signature.
+ *
+ * $nonCumulativeReturnValueDoc.
+ */
+ def pluginsIsBlackbox(macroDef: Symbol): Option[Boolean] = None
+
+ /**
* Expands an application of a def macro (i.e. of a symbol that has the MACRO flag set),
* possibly using the current typer mode and the provided prototype.
*
@@ -375,6 +385,14 @@ trait AnalyzerPlugins { self: Analyzer =>
def custom(plugin: MacroPlugin) = plugin.pluginsTypedMacroBody(typer, ddef)
})
+ /** @see MacroPlugin.pluginsIsBlackbox */
+ def pluginsIsBlackbox(macroDef: Symbol): Boolean = invoke(new NonCumulativeOp[Boolean] {
+ def position = macroDef.pos
+ def description = "compute boxity for this macro definition"
+ def default = standardIsBlackbox(macroDef)
+ def custom(plugin: MacroPlugin) = plugin.pluginsIsBlackbox(macroDef)
+ })
+
/** @see MacroPlugin.pluginsMacroExpand */
def pluginsMacroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = invoke(new NonCumulativeOp[Tree] {
def position = expandee.pos
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index f4456998c0..ef74beec62 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -263,7 +263,12 @@ trait Macros extends MacroRuntimes with Traces with Helpers {
}
def isBlackbox(expandee: Tree): Boolean = isBlackbox(dissectApplied(expandee).core.symbol)
- def isBlackbox(macroDef: Symbol): Boolean = {
+ def isBlackbox(macroDef: Symbol): Boolean = pluginsIsBlackbox(macroDef)
+
+ /** Default implementation of `isBlackbox`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsIsBlackbox for more details)
+ */
+ def standardIsBlackbox(macroDef: Symbol): Boolean = {
val fastTrackBoxity = fastTrack.get(macroDef).map(_.isBlackbox)
val bindingBoxity = loadMacroImplBinding(macroDef).map(_.isBlackbox)
fastTrackBoxity orElse bindingBoxity getOrElse false
@@ -417,9 +422,10 @@ trait Macros extends MacroRuntimes with Traces with Helpers {
val wrappedArgs = mapWithIndex(args)((arg, j) => {
val fingerprint = implParams(min(j, implParams.length - 1))
+ val duplicatedArg = duplicateAndKeepPositions(arg)
fingerprint match {
- case LiftedTyped => context.Expr[Nothing](arg.duplicate)(TypeTag.Nothing) // TODO: SI-5752
- case LiftedUntyped => arg.duplicate
+ case LiftedTyped => context.Expr[Nothing](duplicatedArg)(TypeTag.Nothing) // TODO: SI-5752
+ case LiftedUntyped => duplicatedArg
case _ => abort(s"unexpected fingerprint $fingerprint in $binding with paramss being $paramss " +
s"corresponding to arg $arg in $argss")
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 9b9e641cad..b6d37ab9a7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -12,21 +12,47 @@ import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import symtab.Flags._
-/** This phase adds super accessors for all super calls that either
+/** This phase performs the following functions, each of which could be split out in a
+ * mini-phase:
+ *
+ * (1) Adds super accessors for all super calls that either
* appear in a trait or have as a target a member of some outer class.
- * It also replaces references to parameter accessors with aliases
- * by super references to these aliases. The phase also checks that
- * symbols accessed from super are not abstract, or are overridden by
- * an abstract override. Finally, the phase also mangles the names
- * of class-members which are private up to an enclosing non-package
- * class, in order to avoid overriding conflicts.
*
- * This phase also sets SPECIALIZED flag on type parameters with
+ * (2) Converts references to parameter fields that have the same name as a corresponding
+ * public parameter field in a superclass to a reference to the superclass
+ * field (corresponding = super class field is initialized with subclass field).
+ * This info is pre-computed by the `alias` field in Typer. `dotc` follows a different
+ * route; it computes everything in SuperAccessors and changes the subclass field
+ * to a forwarder instead of manipulating references. This is more modular.
+ *
+ * (3) Adds protected accessors if the access to the protected member happens
+ * in a class which is not a subclass of the member's owner.
+ *
+ * (4) Mangles the names of class-members which are
+ * private up to an enclosing non-package class, in order to avoid overriding conflicts.
+ * This is a dubious, and it would be better to deprecate class-qualified privates.
+ *
+ * (5) This phase also sets SPECIALIZED flag on type parameters with
* `@specialized` annotation. We put this logic here because the
* flag must be set before pickling.
*
- * @author Martin Odersky
- * @version 1.0
+ * It also checks that:
+ *
+ * (1) Symbols accessed from super are not abstract, or are overridden by
+ * an abstract override.
+ *
+ * (2) If a symbol accessed accessed from super is defined in a real class (not a trait),
+ * there are no abstract members which override this member in Java's rules
+ * (see SI-4989; such an access would lead to illegal bytecode)
+ *
+ * (3) Super calls do not go to some synthetic members of Any (see isDisallowed)
+ *
+ * (4) Super calls do not go to synthetic field accessors
+ *
+ * (5) A class and its companion object do not both define a class or module with the
+ * same name.
+ *
+ * TODO: Rename phase to "Accessors" because it handles more than just super accessors
*/
abstract class SuperAccessors extends transform.Transform with transform.TypingTransformers {
import global._
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 66b1c2d87a..9a4d5e3c06 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4399,7 +4399,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (retry) {
val Select(qual, name) = fun
tryTypedArgs(args, forArgMode(fun, mode)) match {
- case Some(args1) =>
+ case Some(args1) if !args1.exists(arg => arg.exists(_.isErroneous)) =>
val qual1 =
if (!pt.isError) adaptToArguments(qual, name, args1, pt, reportAmbiguous = true, saveErrors = true)
else qual
diff --git a/src/library/scala/collection/Searching.scala b/src/library/scala/collection/Searching.scala
index fec4bbf502..b68124b3f8 100644
--- a/src/library/scala/collection/Searching.scala
+++ b/src/library/scala/collection/Searching.scala
@@ -54,7 +54,7 @@ object Searching {
*/
final def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult =
coll match {
- case _: IndexedSeq[A] => binarySearch(elem, -1, coll.length)(ord)
+ case _: IndexedSeq[A] => binarySearch(elem, 0, coll.length)(ord)
case _ => linearSearch(coll.view, elem, 0)(ord)
}
@@ -81,18 +81,18 @@ object Searching {
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 _: IndexedSeq[A] => binarySearch(elem, from, 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
+ if (to == from) InsertionPoint(from) else {
+ val idx = from+(to-from-1)/2
math.signum(ord.compare(elem, coll(idx))) match {
case -1 => binarySearch(elem, from, idx)(ord)
- case 1 => binarySearch(elem, idx, to)(ord)
+ case 1 => binarySearch(elem, idx + 1, to)(ord)
case _ => Found(idx)
}
}
@@ -105,7 +105,7 @@ object Searching {
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)
+ else if (ord.lt(elem, cur)) return InsertionPoint(idx)
idx += 1
}
InsertionPoint(idx)
diff --git a/src/library/scala/io/BufferedSource.scala b/src/library/scala/io/BufferedSource.scala
index 1c87a1f421..52fa525b24 100644
--- a/src/library/scala/io/BufferedSource.scala
+++ b/src/library/scala/io/BufferedSource.scala
@@ -93,7 +93,7 @@ class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val cod
val buf = new Array[Char](bufferSize)
var n = 0
while (n != -1) {
- n = charReader.read(buf)
+ n = allReader.read(buf)
if (n>0) sb.appendAll(buf, 0, n)
}
sb.result
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 6743b9e42a..f35ea566ba 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -274,12 +274,18 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends
// @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]],
+ /** Return all non-overlapping matches of this regexp in given character
+ * sequence as a [[scala.util.matching.Regex.MatchIterator]],
* which is a special [[scala.collection.Iterator]] that returns the
* matched strings, but can also be converted into a normal iterator
* that returns objects of type [[scala.util.matching.Regex.Match]]
* that can be queried for data such as the text that precedes the
* match, subgroups, etc.
+ *
+ * Where potential matches overlap, the first possible match is returned,
+ * followed by the next match that is completely after the first. For
+ * instance, `"hat[^a]+".r` will match `hath` and `hattth` in the string
+ * `"hathatthattthatttt"`.
*
* Attempting to retrieve information about a match before initializing
* the iterator can result in [[java.lang.IllegalStateException]]s. See
@@ -292,7 +298,7 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends
def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames)
- /** Return all matches of this regexp in given character sequence as a
+ /** Return all non-overlapping matches of this regexp in given character sequence as a
* [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]].
*
* @param source The text to match against.
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index fcc377ba32..2ce861898f 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -596,18 +596,26 @@ trait Printers extends api.Printers { self: SymbolTable =>
}
}
- protected def emptyTree(tree: Tree) = tree match {
- case EmptyTree | build.SyntacticEmptyTypeTree() => true
- case _ => false
+ object EmptyTypeTree {
+ def unapply(tt: TypeTree): Boolean = tt match {
+ case build.SyntacticEmptyTypeTree() if tt.wasEmpty || tt.isEmpty => true
+ case _ => false
+ }
}
+ protected def isEmptyTree(tree: Tree) =
+ tree match {
+ case EmptyTree | EmptyTypeTree() => true
+ case _ => false
+ }
+
protected def originalTypeTrees(trees: List[Tree]) =
- trees.filter(!emptyTree(_)) map {
- case tt: TypeTree => tt.original
- case tree => tree
+ trees.filter(!isEmptyTree(_)) map {
+ case tt: TypeTree if tt.original != null => tt.original
+ case tree => tree
}
- val defaultClasses = List(tpnme.AnyRef)
+ val defaultClasses = List(tpnme.AnyRef, tpnme.Object)
val defaultTraitsForCase = List(tpnme.Product, tpnme.Serializable)
protected def removeDefaultTypesFromList(trees: List[Tree])(classesToRemove: List[Name] = defaultClasses)(traitsToRemove: List[Name]) = {
def removeDefaultTraitsFromList(trees: List[Tree], traitsToRemove: List[Name]): List[Tree] =
@@ -623,9 +631,10 @@ trait Printers extends api.Printers { self: SymbolTable =>
removeDefaultTraitsFromList(removeDefaultClassesFromList(trees, classesToRemove), traitsToRemove)
}
- protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) =
+ protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) =
originalTypeTrees(trees) filter {
case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_)
+ case tt: TypeTree if tt.tpe != null => !(classesToRemove contains(newTypeName(tt.tpe.toString())))
case _ => true
}
@@ -637,7 +646,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
}
override def printOpt(prefix: String, tree: Tree) =
- if (!emptyTree(tree)) super.printOpt(prefix, tree)
+ if (!isEmptyTree(tree)) super.printOpt(prefix, tree)
override def printColumn(ts: List[Tree], start: String, sep: String, end: String) = {
super.printColumn(ts.filter(!syntheticToRemove(_)), start, sep, end)
@@ -952,7 +961,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
def printTp = print("(", tp, ")")
tp match {
- case EmptyTree | build.SyntacticEmptyTypeTree() => printTp
+ case EmptyTree | EmptyTypeTree() => printTp
// case for untypechecked trees
case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp // remove double arg - 5: 5: @unchecked
case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp
@@ -963,7 +972,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
// print only fun when targs are TypeTrees with empty original
case TypeApply(fun, targs) =>
- if (targs.exists(emptyTree(_))) {
+ if (targs.exists(isEmptyTree(_))) {
print(fun)
} else super.printTree(tree)
@@ -984,8 +993,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
case treeInfo.Unapplied(body) =>
body match {
case Select(qual, name) if name == nme.unapply => print(qual)
- case TypeApply(Select(qual, name), args) if name == nme.unapply || name == nme.unapplySeq =>
- print(TypeApply(qual, args))
+ case TypeApply(Select(qual, name), _) if name == nme.unapply || name == nme.unapplySeq =>
+ print(qual)
case _ => print(body)
}
case _ => print(fun)
@@ -1061,7 +1070,11 @@ trait Printers extends api.Printers { self: SymbolTable =>
print("(", qualifier, ")#", blankForOperatorName(selector), printedName(selector))
case tt: TypeTree =>
- if (!emptyTree(tt)) print(tt.original)
+ if (!isEmptyTree(tt)) {
+ val original = tt.original
+ if (original != null) print(original)
+ else super.printTree(tree)
+ }
case AppliedTypeTree(tp, args) =>
// it's possible to have (=> String) => String type but Function1[=> String, String] is not correct
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index ad8a2594dd..2caa30d27e 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -97,6 +97,8 @@ trait ReificationSupport { self: SymbolTable =>
def toStats(tree: Tree): List[Tree] = tree match {
case EmptyTree => Nil
case SyntacticBlock(stats) => stats
+ case defn if defn.isDef => defn :: Nil
+ case imp: Import => imp :: Nil
case _ => throw new IllegalArgumentException(s"can't flatten $tree")
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
index dce52af56a..47ddfb8aa9 100644
--- a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala
@@ -95,11 +95,11 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
val documentError: PartialFunction[Throwable, Unit] = {
case NoCompilerRunException =>
reporter.info(null, "No documentation generated with unsuccessful compiler run", force = false)
- case _: ClassNotFoundException =>
- ()
+ case e @ (_:ClassNotFoundException | _:IllegalAccessException | _:InstantiationException | _:SecurityException | _:ClassCastException) =>
+ reporter.error(null, s"Cannot load the doclet class ${settings.docgenerator.value} (specified with ${settings.docgenerator.name}): $e. Leaving the default settings will generate the html version of scaladoc.")
}
- /** Generate document(s) for all `files` containing scaladoc documenataion.
+ /** Generate document(s) for all `files` containing scaladoc documentation.
* @param files The list of paths (relative to the compiler's source path, or absolute) of files to document. */
def document(files: List[String]) {
def generate() = {