diff options
Diffstat (limited to 'src')
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() = { |