summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala14
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala33
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala27
-rw-r--r--src/library/scala/collection/immutable/List.scala63
-rw-r--r--src/library/scala/collection/immutable/Set.scala46
-rw-r--r--src/library/scala/collection/immutable/Stream.scala8
-rw-r--r--src/library/scala/util/matching/Regex.scala39
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala8
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala6
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala58
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/Collections.scala34
-rw-r--r--src/reflect/scala/reflect/macros/Attachments.scala5
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/Settings.scala7
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala10
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala4
-rw-r--r--test/files/jvm/t6941/Analyzed_1.scala2
-rw-r--r--test/files/neg/missing-param-type-tuple.check6
-rw-r--r--test/files/pos/t7322.scala11
-rw-r--r--test/files/pos/t8170.scala27
-rw-r--r--test/files/pos/t8170b.scala25
-rw-r--r--test/files/run/t8233-bcode.flags1
-rw-r--r--test/files/run/t8233-bcode.scala18
-rw-r--r--test/files/run/t8233.scala18
-rw-r--r--test/scaladoc/resources/SI-4014_0.scala4
-rw-r--r--test/scaladoc/resources/SI-4014_1.scala5
-rw-r--r--test/scaladoc/resources/SI-4014_2.scala6
-rw-r--r--test/scaladoc/run/t7124.check3
-rw-r--r--test/scaladoc/run/t7124.scala22
-rw-r--r--test/scaladoc/scalacheck/HtmlFactoryTest.scala46
43 files changed, 506 insertions, 135 deletions
diff --git a/.mailmap b/.mailmap
index 810bda030c..7cab5ed019 100644
--- a/.mailmap
+++ b/.mailmap
@@ -10,6 +10,7 @@ Aleksandar Prokopec <aleksandar.prokopec@epfl.ch> <aleksandar@lampmac14.epfl.ch>
Aleksandar Prokopec <aleksandar.prokopec@epfl.ch> <axel22@gmail.com>
Alex Cruise <alex@cluonflux.com>
Alex Cruise <alex@cluonflux.com> <alex@metaforsoftware.com>
+A. P. Marki <som.snytt@gmail.com>
Antonio Cunei <antonio.cunei@typesafe.com>
Antonio Cunei <antonio.cunei@typesafe.com> <antonio.cunei@epfl.ch>
Buraq Emir <buraq@epfl.ch>
@@ -71,5 +72,6 @@ Unknown Committer <lost.soul@typesafe.com> <USER@epfl.ch>
Unknown Committer <lost.soul@typesafe.com> <noreply@epfl.ch>
Viktor Klang <viktor.klang@gmail.com>
Vincent Cremet <cremet@epfl.ch>
+Vladimir Nikolaev <vladimir.nikolaev9@gmail.com>
Vojin Jovanovic <vojin.jovanovic@epfl.ch>
Vojin Jovanovic <vojin.jovanovic@epfl.ch> <gvojin@gmail.com>
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 23a2e0b37f..e3d2bf14a0 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1225,7 +1225,7 @@ self =>
// Like Swiss cheese, with holes
def stringCheese: Tree = atPos(in.offset) {
val start = in.offset
- val interpolator = in.name
+ val interpolator = in.name.encoded // ident() for INTERPOLATIONID
val partsBuf = new ListBuffer[Tree]
val exprBuf = new ListBuffer[Tree]
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 1332d01dbd..9ba38b021d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1007,8 +1007,15 @@ abstract class GenICode extends SubComponent {
}
// emit conversion
- if (generatedType != expectedType)
- adapt(generatedType, expectedType, resCtx, tree.pos)
+ if (generatedType != expectedType) {
+ tree match {
+ case Literal(Constant(null)) if generatedType == NullReference =>
+ // literal null on the stack (as opposed to a boxed null, see SI-8233),
+ // we can bypass `adapt` which would otherwise emitt a redundant [DROP, CONSTANT(null)]
+ case _ =>
+ adapt(generatedType, expectedType, resCtx, tree.pos)
+ }
+ }
resCtx
}
@@ -1058,6 +1065,9 @@ abstract class GenICode extends SubComponent {
case (NothingReference, _) =>
ctx.bb.emit(THROW(ThrowableClass))
ctx.bb.enterIgnoreMode()
+ case (NullReference, REFERENCE(_)) =>
+ // SI-8223 we can't assume that the stack contains a `null`, it might contain a Null$
+ ctx.bb.emit(Seq(DROP(from), CONSTANT(Constant(null))))
case _ if from isAssignabledTo to =>
()
case (_, UNIT) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 90c15bca61..55f45257dc 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -55,23 +55,26 @@ abstract class Pickler extends SubComponent {
case _ =>
}
}
- // If there are any erroneous types in the tree, then we will crash
- // when we pickle it: so let's report an error instead. We know next
- // to nothing about what happened, but our supposition is a lot better
- // than "bad type: <error>" in terms of explanatory power.
- for (t <- unit.body) {
- if (t.isErroneous) {
- unit.error(t.pos, "erroneous or inaccessible type")
- return
- }
- if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) {
- unit.error(t.pos, "macro has not been expanded")
- return
- }
+ try {
+ pickle(unit.body)
+ } catch {
+ case e: FatalError =>
+ for (t <- unit.body) {
+ // If there are any erroneous types in the tree, then we will crash
+ // when we pickle it: so let's report an error instead. We know next
+ // to nothing about what happened, but our supposition is a lot better
+ // than "bad type: <error>" in terms of explanatory power.
+ //
+ // OPT: do this only as a recovery after fatal error. Checking in advance was expensive.
+ if (t.isErroneous) {
+ if (settings.debug) e.printStackTrace()
+ unit.error(t.pos, "erroneous or inaccessible type")
+ return
+ }
+ }
+ throw e
}
-
- pickle(unit.body)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 0a013995b6..a60310f900 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -522,6 +522,8 @@ abstract class Erasure extends AddInterfaces
class Eraser(_context: Context) extends Typer(_context) with TypeAdapter {
val typer = this.asInstanceOf[analyzer.Typer]
+ override protected def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = tree
+
/** Replace member references as follows:
*
* - `x == y` for == in class Any becomes `x equals y` with equals in class Object.
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 42c929baed..c59b726076 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -439,10 +439,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else
specializedTypeVars(sym.typeParams zip args collect { case (tp, arg) if tp.isSpecialized => arg })
- case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: tparams.map(_.info))
+ case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: mapList(tparams)(symInfo)) // OPT
// since this method may be run at phase typer (before uncurry, where NMTs are eliminated)
case NullaryMethodType(resTpe) => specializedTypeVars(resTpe)
- case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: argSyms.map(_.tpe))
+ case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: mapList(argSyms)(symTpe)) // OPT
case ExistentialType(_, res) => specializedTypeVars(res)
case AnnotatedType(_, tp) => specializedTypeVars(tp)
case TypeBounds(lo, hi) => specializedTypeVars(lo :: hi :: Nil)
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index b471d16ddd..5973c70583 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -128,6 +128,7 @@ abstract class TailCalls extends Transform {
logResult(msg)(method.newValue(nme.THIS, pos, SYNTHETIC) setInfo currentClass.typeOfThis)
}
override def toString = s"${method.name} tparams=$tparams tailPos=$tailPos label=$label label info=${label.info}"
+
}
object EmptyTailContext extends TailContext {
@@ -185,6 +186,18 @@ abstract class TailCalls extends Transform {
private def noTailContext() = new ClonedTailContext(ctx, tailPos = false)
private def yesTailContext() = new ClonedTailContext(ctx, tailPos = true)
+
+ override def transformUnit(unit: CompilationUnit): Unit = {
+ try {
+ super.transformUnit(unit)
+ } finally {
+ // OPT clear these after each compilation unit
+ failPositions.clear()
+ failReasons.clear()
+ accessed.clear()
+ }
+ }
+
/** Rewrite this tree to contain no tail recursive calls */
def transform(tree: Tree, nctx: TailContext): Tree = {
val saved = ctx
@@ -218,12 +231,12 @@ abstract class TailCalls extends Transform {
*/
def fail(reason: String) = {
debuglog("Cannot rewrite recursive call at: " + fun.pos + " because: " + reason)
- failReasons(ctx) = reason
+ if (ctx.isMandatory) failReasons(ctx) = reason
treeCopy.Apply(tree, noTailTransform(target), transformArgs)
}
/* Position of failure is that of the tree being considered. */
def failHere(reason: String) = {
- failPositions(ctx) = fun.pos
+ if (ctx.isMandatory) failPositions(ctx) = fun.pos
fail(reason)
}
def rewriteTailCall(recv: Tree): Tree = {
@@ -237,7 +250,8 @@ abstract class TailCalls extends Transform {
if (!ctx.isEligible) fail("it is neither private nor final so can be overridden")
else if (!isRecursiveCall) {
- if (receiverIsSuper) failHere("it contains a recursive call targeting a supertype")
+ if (ctx.isMandatory && receiverIsSuper) // OPT expensive check, avoid unless we will actually report the error
+ failHere("it contains a recursive call targeting a supertype")
else failHere(defaultReason)
}
else if (!matchesTypeArgs) failHere("it is called recursively with different type arguments")
@@ -245,6 +259,11 @@ abstract class TailCalls extends Transform {
else if (!receiverIsSame) failHere("it changes type of 'this' on a polymorphic recursive call")
else rewriteTailCall(receiver)
}
+
+ def isEligible(tree: DefDef) = {
+ val sym = tree.symbol
+ !(sym.hasAccessorFlag || sym.isConstructor)
+ }
tree match {
case ValDef(_, _, _, _) =>
@@ -253,7 +272,7 @@ abstract class TailCalls extends Transform {
super.transform(tree)
- case dd @ DefDef(_, name, _, vparamss0, _, rhs0) if !dd.symbol.hasAccessorFlag =>
+ case dd @ DefDef(_, name, _, vparamss0, _, rhs0) if isEligible(dd) =>
val newCtx = new DefDefTailContext(dd)
if (newCtx.isMandatory && !(newCtx containsRecursiveCall rhs0))
unit.error(tree.pos, "@tailrec annotated method contains no recursive calls")
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 4d0eda2377..2043eb5d5d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -418,7 +418,7 @@ trait ContextErrors {
case TypeRef(_, _, arg :: _) if arg.typeSymbol == TupleClass(funArity) && funArity > 1 =>
sm"""|
|Note: The expected type requires a one-argument function accepting a $funArity-Tuple.
- | Consider a pattern matching anoynmous function, `{ case $example => ... }`"""
+ | Consider a pattern matching anonymous function, `{ case $example => ... }`"""
case _ => ""
}
case _ => ""
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 598b12b00d..e5907e1a0f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1303,7 +1303,7 @@ trait Contexts { self: Analyzer =>
var renamed = false
var selectors = tree.selectors
def current = selectors.head
- while (selectors.nonEmpty && result == NoSymbol) {
+ while ((selectors ne Nil) && result == NoSymbol) {
if (current.rename == name.toTermName)
result = qual.tpe.nonLocalMember( // new to address #2733: consider only non-local members for imports
if (name.isTypeName) current.name.toTypeName else current.name)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 847211945c..776920ed42 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -788,7 +788,7 @@ trait Implicits {
final class LocalShadower extends Shadower {
val shadowed = util.HashSet[Name](512)
def addInfos(infos: Infos) {
- shadowed addEntries infos.map(_.name)
+ infos.foreach(i => shadowed.addEntry(i.name))
}
def isShadowed(name: Name) = shadowed(name)
}
@@ -805,7 +805,6 @@ trait Implicits {
private def isIneligible(info: ImplicitInfo) = (
info.isCyclicOrErroneous
|| isView && (info.sym eq Predef_conforms)
- || shadower.isShadowed(info.name)
|| (!context.macrosEnabled && info.sym.isTermMacro)
)
@@ -814,6 +813,7 @@ trait Implicits {
def survives(info: ImplicitInfo) = (
!isIneligible(info) // cyclic, erroneous, shadowed, or specially excluded
&& isPlausiblyCompatible(info.tpe, wildPt) // optimization to avoid matchesPt
+ && !shadower.isShadowed(info.name) // OPT rare, only check for plausible candidates
&& matchesPt(info) // stable and matches expected type
)
/** The implicits that are not valid because they come later in the source and
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 27e8698676..645f267a21 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1069,8 +1069,9 @@ trait Namers extends MethodSynthesis {
}
def overriddenSymbol(resTp: Type) = {
+ lazy val schema: Type = methodTypeSchema(resTp) // OPT create once. Must be lazy to avoid cycles in neg/t5093.scala
intersectionType(methOwner.info.parents).nonPrivateMember(meth.name).filter { sym =>
- sym != NoSymbol && (site.memberType(sym) matches methodTypeSchema(resTp))
+ sym != NoSymbol && (site.memberType(sym) matches schema)
}
}
// TODO: see whether this or something similar would work instead:
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 68d724b6fc..f7684b93af 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1596,6 +1596,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
}
+ private def checkUnexpandedMacro(t: Tree) =
+ if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro)
+ unit.error(t.pos, "macro has not been expanded")
+
override def transform(tree: Tree): Tree = {
val savedLocalTyper = localTyper
val savedCurrentApplication = currentApplication
@@ -1755,6 +1759,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
varianceValidator.traverse(tt.original) // See SI-7872
case _ =>
}
+
+ checkUnexpandedMacro(result)
+
result
} catch {
case ex: TypeError =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
index 995f98cc2c..57f27a05fd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -46,7 +46,7 @@ trait StdAttachments {
* The parameter is of type `Any`, because macros can expand both into trees and into annotations.
*/
def hasMacroExpansionAttachment(any: Any): Boolean = any match {
- case tree: Tree => tree.attachments.get[MacroExpansionAttachment].isDefined
+ case tree: Tree => tree.hasAttachment[MacroExpansionAttachment]
case _ => false
}
@@ -96,7 +96,7 @@ trait StdAttachments {
*/
def isMacroExpansionSuppressed(tree: Tree): Boolean =
( settings.Ymacroexpand.value == settings.MacroExpand.None // SI-6812
- || tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined
+ || tree.hasAttachment[SuppressMacroExpansionAttachment.type]
|| (tree match {
// we have to account for the fact that during typechecking an expandee might become wrapped,
// i.e. surrounded by an inferred implicit argument application or by an inferred type argument application.
@@ -150,7 +150,7 @@ trait StdAttachments {
/** Determines whether a tree should or should not be adapted,
* because someone has put MacroImplRefAttachment on it.
*/
- def isMacroImplRef(tree: Tree): Boolean = tree.attachments.get[MacroImplRefAttachment.type].isDefined
+ def isMacroImplRef(tree: Tree): Boolean = tree.hasAttachment[MacroImplRefAttachment.type]
/** Since mkInvoke, the applyDynamic/selectDynamic/etc desugarer, is disconnected
* from typedNamedApply, the applyDynamicNamed argument rewriter, the latter
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9776b1e80e..101e1526fe 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -579,7 +579,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
* 3. Turn tree type into stable type if possible and required by context.
* 4. Give getClass calls a more precise type based on the type of the target of the call.
*/
- private def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = {
+ protected def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = {
+
// Side effect time! Don't be an idiot like me and think you
// can move "val sym = tree.symbol" before this line, because
// inferExprAlternative side-effects the tree's symbol.
@@ -992,7 +993,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def adaptMismatchedSkolems() = {
def canIgnoreMismatch = (
!context.reportErrors && isPastTyper
- || tree.attachments.get[MacroExpansionAttachment].isDefined
+ || tree.hasAttachment[MacroExpansionAttachment]
)
def bound = pt match {
case ExistentialType(qs, _) => qs
@@ -2232,14 +2233,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
DeprecatedParamNameError(p, n)
}
}
- }
- if (meth.isStructuralRefinementMember)
- checkMethodStructuralCompatible(ddef)
+ if (meth.isStructuralRefinementMember)
+ checkMethodStructuralCompatible(ddef)
- if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match {
- case List(param) :: _ if !param.isImplicit =>
- checkFeature(ddef.pos, ImplicitConversionsFeature, meth.toString)
- case _ =>
+ if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match {
+ case List(param) :: _ if !param.isImplicit =>
+ checkFeature(ddef.pos, ImplicitConversionsFeature, meth.toString)
+ case _ =>
+ }
}
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
@@ -3411,7 +3412,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
// val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
// precise(foo) : foo.type => foo.type
- val restpe = mt.resultType(args1 map (arg => gen stableTypeFor arg orElse arg.tpe))
+ val restpe = mt.resultType(mapList(args1)(arg => gen stableTypeFor arg orElse arg.tpe))
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if (mode.inPatternMode) => rtp
case _ => tp
@@ -3831,7 +3832,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// lifted out of typed1 because it's needed in typedImplicit0
protected def typedTypeApply(tree: Tree, mode: Mode, fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
- inferPolyAlternatives(fun, args map (_.tpe))
+ inferPolyAlternatives(fun, mapList(args)(treeTpe))
val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree)
val args1 = if (sameLength(args, tparams)) {
//@M: in case TypeApply we can't check the kind-arities of the type arguments,
@@ -3851,7 +3852,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
typedTypeApply(tree, mode, fun setType fun.tpe.widen, args)
case PolyType(tparams, restpe) if tparams.nonEmpty =>
if (sameLength(tparams, args)) {
- val targs = args map (_.tpe)
+ val targs = mapList(args)(treeTpe)
checkBounds(tree, NoPrefix, NoSymbol, tparams, targs, "")
if (isPredefClassOf(fun.symbol))
typedClassOf(tree, args.head, noGen = true)
@@ -4871,7 +4872,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
typedHigherKindedType(arg, mode, pt)
}
- val argtypes = args1 map (_.tpe)
+ val argtypes = mapList(args1)(treeTpe)
foreach2(args, tparams) { (arg, tparam) =>
// note: can't use args1 in selector, because Binds got replaced
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 90aabc5a9a..c3728fa02a 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -325,36 +325,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
// Create a proxy for Java serialization that allows us to avoid mutation
// during de-serialization. This is the Serialization Proxy Pattern.
- protected final def writeReplace(): AnyRef = new SerializationProxy(this)
-}
-
-@SerialVersionUID(1L)
-private class SerializationProxy[B](@transient private var orig: List[B]) extends Serializable {
-
- private def writeObject(out: ObjectOutputStream) {
- var xs: List[B] = orig
- while (!xs.isEmpty) {
- out.writeObject(xs.head)
- xs = xs.tail
- }
- out.writeObject(ListSerializeEnd)
- }
-
- // Java serialization calls this before readResolve during de-serialization.
- // Read the whole list and store it in `orig`.
- private def readObject(in: ObjectInputStream) {
- val builder = List.newBuilder[B]
- while (true) in.readObject match {
- case ListSerializeEnd =>
- orig = builder.result()
- return
- case a =>
- builder += a.asInstanceOf[B]
- }
- }
-
- // Provide the result stored in `orig` for Java serialization
- private def readResolve(): AnyRef = orig
+ protected final def writeReplace(): AnyRef = new List.SerializationProxy(this)
}
/** The empty list.
@@ -385,8 +356,7 @@ case object Nil extends List[Nothing] {
* @version 1.0, 15/07/2003
* @since 2.8
*/
-final case class ::[B](private val hd: B, private[scala] var tl: List[B]) extends List[B] {
- override def head : B = hd
+final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
@@ -405,6 +375,35 @@ object List extends SeqFactory[List] {
override def empty[A]: List[A] = Nil
override def apply[A](xs: A*): List[A] = xs.toList
+
+ @SerialVersionUID(1L)
+ private class SerializationProxy[A](@transient private var orig: List[A]) extends Serializable {
+
+ private def writeObject(out: ObjectOutputStream) {
+ var xs: List[A] = orig
+ while (!xs.isEmpty) {
+ out.writeObject(xs.head)
+ xs = xs.tail
+ }
+ out.writeObject(ListSerializeEnd)
+ }
+
+ // Java serialization calls this before readResolve during de-serialization.
+ // Read the whole list and store it in `orig`.
+ private def readObject(in: ObjectInputStream) {
+ val builder = List.newBuilder[A]
+ while (true) in.readObject match {
+ case ListSerializeEnd =>
+ orig = builder.result()
+ return
+ case a =>
+ builder += a.asInstanceOf[A]
+ }
+ }
+
+ // Provide the result stored in `orig` for Java serialization
+ private def readResolve(): AnyRef = orig
+ }
}
/** Only used for list serialization */
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index e21a8dfa8a..0fbf7942d4 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -82,6 +82,16 @@ object Set extends ImmutableSetFactory[Set] {
override def foreach[U](f: A => U): Unit = {
f(elem1)
}
+ override def exists(f: A => Boolean): Boolean = {
+ f(elem1)
+ }
+ override def forall(f: A => Boolean): Boolean = {
+ f(elem1)
+ }
+ override def find(f: A => Boolean): Option[A] = {
+ if (f(elem1)) Some(elem1)
+ else None
+ }
}
/** An optimized representation for immutable sets of size 2 */
@@ -102,6 +112,17 @@ object Set extends ImmutableSetFactory[Set] {
override def foreach[U](f: A => U): Unit = {
f(elem1); f(elem2)
}
+ override def exists(f: A => Boolean): Boolean = {
+ f(elem1) || f(elem2)
+ }
+ override def forall(f: A => Boolean): Boolean = {
+ f(elem1) && f(elem2)
+ }
+ override def find(f: A => Boolean): Option[A] = {
+ if (f(elem1)) Some(elem1)
+ else if (f(elem2)) Some(elem2)
+ else None
+ }
}
/** An optimized representation for immutable sets of size 3 */
@@ -123,6 +144,18 @@ object Set extends ImmutableSetFactory[Set] {
override def foreach[U](f: A => U): Unit = {
f(elem1); f(elem2); f(elem3)
}
+ override def exists(f: A => Boolean): Boolean = {
+ f(elem1) || f(elem2) || f(elem3)
+ }
+ override def forall(f: A => Boolean): Boolean = {
+ f(elem1) && f(elem2) && f(elem3)
+ }
+ override def find(f: A => Boolean): Option[A] = {
+ if (f(elem1)) Some(elem1)
+ else if (f(elem2)) Some(elem2)
+ else if (f(elem3)) Some(elem3)
+ else None
+ }
}
/** An optimized representation for immutable sets of size 4 */
@@ -145,6 +178,19 @@ object Set extends ImmutableSetFactory[Set] {
override def foreach[U](f: A => U): Unit = {
f(elem1); f(elem2); f(elem3); f(elem4)
}
+ override def exists(f: A => Boolean): Boolean = {
+ f(elem1) || f(elem2) || f(elem3) || f(elem4)
+ }
+ override def forall(f: A => Boolean): Boolean = {
+ f(elem1) && f(elem2) && f(elem3) && f(elem4)
+ }
+ override def find(f: A => Boolean): Option[A] = {
+ if (f(elem1)) Some(elem1)
+ else if (f(elem2)) Some(elem2)
+ else if (f(elem3)) Some(elem3)
+ else if (f(elem4)) Some(elem4)
+ else None
+ }
}
}
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 49c3b4c3cd..60de147477 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -1108,11 +1108,15 @@ object Stream extends SeqFactory[Stream] {
override def isEmpty = false
override def head = hd
@volatile private[this] var tlVal: Stream[A] = _
- def tailDefined: Boolean = tlVal ne null
+ @volatile private[this] var tlGen = tl _
+ def tailDefined: Boolean = tlGen eq null
override def tail: Stream[A] = {
if (!tailDefined)
synchronized {
- if (!tailDefined) tlVal = tl
+ if (!tailDefined) {
+ tlVal = tlGen()
+ tlGen = null
+ }
}
tlVal
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 86132bb876..b70426a145 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -67,7 +67,21 @@ import java.util.regex.{ Pattern, Matcher }
* Regex, such as `findFirstIn` or `findAllIn`, or using it as an extractor in a
* pattern match.
*
- * Note, however, that when Regex is used as an extractor in a pattern match, it
+ * Note that, when calling `findAllIn`, the resulting [[scala.util.matching.Regex.MatchIterator]]
+ * needs to be initialized (by calling `hasNext` or `next()`, or causing these to be
+ * called) before information about a match can be retrieved:
+ *
+ * {{{
+ * val msg = "I love Scala"
+ *
+ * // val start = " ".r.findAllIn(msg).start // throws an IllegalStateException
+ *
+ * val matches = " ".r.findAllIn(msg)
+ * matches.hasNext // initializes the matcher
+ * val start = matches.start
+ * }}}
+ *
+ * When Regex is used as an extractor in a pattern match, note that it
* only succeeds if the whole text can be matched. For this reason, one usually
* calls a method to find the matching substrings, and then use it as an extractor
* to break match into subgroups.
@@ -267,6 +281,10 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends
* that can be queried for data such as the text that precedes the
* match, subgroups, etc.
*
+ * Attempting to retrieve information about a match before initializing
+ * the iterator can result in [[java.lang.IllegalStateException]]s. See
+ * [[scala.util.matching.Regex.MatchIterator]] for details.
+ *
* @param source The text to match against.
* @return A [[scala.util.matching.Regex.MatchIterator]] of all matches.
* @example {{{for (words <- """\w+""".r findAllIn "A simple example.") yield words}}}
@@ -476,15 +494,7 @@ trait UnanchoredRegex extends Regex {
}
/** This object defines inner classes that describe
- * regex matches and helper objects. The class hierarchy
- * is as follows:
- *
- * {{{
- * MatchData
- * / \
- * MatchIterator Match
- * }}}
- *
+ * regex matches and helper objects.
*/
object Regex {
@@ -634,7 +644,14 @@ object Regex {
def unapplySeq(m: Match): Option[Seq[String]] = if (m.groupCount > 0) Some(1 to m.groupCount map m.group) else None
}
- /** A class to step through a sequence of regex matches
+ /** A class to step through a sequence of regex matches.
+ *
+ * All methods inherited from [[scala.util.matching.Regex.MatchData]] will throw
+ * an [[java.lang.IllegalStateException]] until the matcher is initialized by
+ * calling `hasNext` or `next()` or causing these methods to be called, such as
+ * by invoking `toString` or iterating through the iterator's elements.
+ *
+ * @see [[java.util.regex.Matcher]]
*/
class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String])
extends AbstractIterator[String] with Iterator[String] with MatchData { self =>
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 4fde57ed02..d634034fe9 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -48,7 +48,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
/** Tests for, get, or remove an annotation */
def hasAnnotation(cls: Symbol): Boolean =
//OPT inlined from exists to save on #closures; was: annotations exists (_ matches cls)
- dropOtherAnnotations(annotations, cls).nonEmpty
+ dropOtherAnnotations(annotations, cls) ne Nil
def getAnnotation(cls: Symbol): Option[AnnotationInfo] =
//OPT inlined from exists to save on #closures; was: annotations find (_ matches cls)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index f49ddaf6ca..26914fecc1 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -3404,8 +3404,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* @return the new list of info-adjusted symbols
*/
def deriveSymbols(syms: List[Symbol], symFn: Symbol => Symbol): List[Symbol] = {
- val syms1 = syms map symFn
- syms1 map (_ substInfo (syms, syms1))
+ val syms1 = mapList(syms)(symFn)
+ mapList(syms1)(_ substInfo (syms, syms1))
}
/** Derives a new Type by first deriving new symbols as in deriveSymbols,
@@ -3445,9 +3445,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* @return the newly created, info-adjusted symbols
*/
def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] =
- cloneSymbols(syms) map (_ modifyInfo infoFn)
+ mapList(cloneSymbols(syms))(_ modifyInfo infoFn)
def cloneSymbolsAtOwnerAndModify(syms: List[Symbol], owner: Symbol, infoFn: Type => Type): List[Symbol] =
- cloneSymbolsAtOwner(syms, owner) map (_ modifyInfo infoFn)
+ mapList(cloneSymbolsAtOwner(syms, owner))(_ modifyInfo infoFn)
/** Functions which perform the standard clone/substituting on the given symbols and type,
* then call the creator function with the new symbols and type as arguments.
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index e602a12175..29fdba2781 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -49,10 +49,10 @@ abstract class TreeGen extends macros.TreeBuilder {
mkMethodCall(Select(receiver, method), targs, args)
def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree =
- Apply(mkTypeApply(target, targs map TypeTree), args)
+ Apply(mkTypeApply(target, mapList(targs)(TypeTree)), args)
def mkNullaryCall(method: Symbol, targs: List[Type]): Tree =
- mkTypeApply(mkAttributedRef(method), targs map TypeTree)
+ mkTypeApply(mkAttributedRef(method), mapList(targs)(TypeTree))
/** Builds a reference to value whose type is given stable prefix.
* The type must be suitable for this. For example, it
@@ -281,7 +281,7 @@ abstract class TreeGen extends macros.TreeBuilder {
case tree :: Nil if flattenUnary =>
tree
case _ =>
- Apply(scalaDot(TupleClass(elems.length).companionModule.name), elems)
+ Apply(scalaDot(TupleClass(elems.length).name.toTermName), elems)
}
def mkTupleType(elems: List[Tree], flattenUnary: Boolean = true): Tree = elems match {
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 497a7c91b1..7bab15b0f4 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -284,17 +284,17 @@ abstract class TreeInfo {
/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
* same object?
*/
- def isSelfConstrCall(tree: Tree): Boolean = tree match {
- case Applied(Ident(nme.CONSTRUCTOR), _, _) => true
- case Applied(Select(This(_), nme.CONSTRUCTOR), _, _) => true
- case _ => false
+ def isSelfConstrCall(tree: Tree): Boolean = dissectApplied(tree).core match {
+ case Ident(nme.CONSTRUCTOR) => true
+ case Select(This(_), nme.CONSTRUCTOR) => true
+ case _ => false
}
/** Is tree a super constructor call?
*/
- def isSuperConstrCall(tree: Tree): Boolean = tree match {
- case Applied(Select(Super(_, _), nme.CONSTRUCTOR), _, _) => true
- case _ => false
+ def isSuperConstrCall(tree: Tree): Boolean = dissectApplied(tree).core match {
+ case Select(Super(_, _), nme.CONSTRUCTOR) => true
+ case _ => false
}
/**
@@ -848,8 +848,10 @@ abstract class TreeInfo {
case _ => false
})
- def isMacroApplication(tree: Tree): Boolean =
- !tree.isDef && tree.symbol != null && tree.symbol.isTermMacro && !tree.symbol.isErroneous
+ def isMacroApplication(tree: Tree): Boolean = !tree.isDef && {
+ val sym = tree.symbol
+ sym != null && sym.isTermMacro && !sym.isErroneous
+ }
def isMacroApplicationOrBlock(tree: Tree): Boolean = tree match {
case Block(_, expr) => isMacroApplicationOrBlock(expr)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 9ddaea4c62..53c528a2bb 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1977,7 +1977,7 @@ trait Types
def pendingVolatiles = _pendingVolatiles
class ArgsTypeRef(pre0: Type, sym0: Symbol, args0: List[Type]) extends TypeRef(pre0, sym0, args0) {
- require(args0.nonEmpty, this)
+ require(args0 ne Nil, this)
/** No unapplied type params size it has (should have) equally as many args. */
override def isHigherKinded = false
@@ -1988,12 +1988,39 @@ trait Types
// too little information is known to determine its kind, and
// it later turns out not to have kind *. See SI-4070. Only
// logging it for now.
- if (sym.typeParams.size != args.size)
+ val tparams = sym.typeParams
+ if (tparams.size != args.size)
devWarning(s"$this.transform($tp), but tparams.isEmpty and args=$args")
-
- val GenPolyType(tparams, result) = asSeenFromOwner(tp)
- assert((tparams eq Nil) || tparams == sym.typeParams, (tparams, sym.typeParams))
- result.instantiateTypeParams(sym.typeParams, args)
+ def asSeenFromInstantiated(tp: Type) =
+ asSeenFromOwner(tp).instantiateTypeParams(tparams, args)
+ // If we're called with a poly type, and we were to run the `asSeenFrom`, over the entire
+ // type, we can end up with new symbols for the type parameters (clones from TypeMap).
+ // The subsequent substitution of type arguments would fail. This problem showed up during
+ // the fix for SI-8046, however the solution taken there wasn't quite right, and led to
+ // SI-8170.
+ //
+ // Now, we detect the PolyType before both the ASF *and* the substitution, and just operate
+ // on the result type.
+ //
+ // TODO: Revisit this and explore the questions raised:
+ //
+ // AM: I like this better than the old code, but is there any way the tparams would need the ASF treatment as well?
+ // JZ: I think its largely irrelevant, as they are no longer referred to in the result type.
+ // In fact, you can get away with returning a type of kind * here and the sky doesn't fall:
+ // `case PolyType(`tparams`, result) => asSeenFromInstantiated(result)`
+ // But I thought it was better to retain the kind.
+ // AM: I've been experimenting with apply-type-args-then-ASF, but running into cycles.
+ // In general, it seems iffy the tparams can never occur in the result
+ // then we might as well represent the type as a no-arg typeref.
+ // AM: I've also been trying to track down uses of transform (pretty generic name for something that
+ // does not seem that widely applicable).
+ // It's kind of a helper for computing baseType (since it tries to propagate our type args to some
+ // other type, which has to be related to this type for that to make sense).
+ //
+ tp match {
+ case PolyType(`tparams`, result) => PolyType(tparams, asSeenFromInstantiated(result))
+ case _ => asSeenFromInstantiated(tp)
+ }
}
// note: does not go through typeRef. There's no need to because
@@ -2035,7 +2062,7 @@ trait Types
// to a java or scala symbol, but it does matter whether it occurs in java or scala code.
// TypeRefs w/o type params that occur in java signatures/code are considered raw types, and are
// represented as existential types.
- override def isHigherKinded = typeParams.nonEmpty
+ override def isHigherKinded = (typeParams ne Nil)
override def typeParams = if (isDefinitionsInitialized) sym.typeParams else sym.unsafeTypeParams
private def isRaw = !phase.erasedTypes && isRawIfWithoutArgs(sym)
@@ -2221,7 +2248,7 @@ trait Types
//OPT specialize hashCode
override final def computeHashCode = {
import scala.util.hashing.MurmurHash3._
- val hasArgs = args.nonEmpty
+ val hasArgs = args ne Nil
var h = productSeed
h = mix(h, pre.hashCode)
h = mix(h, sym.hashCode)
@@ -2412,7 +2439,7 @@ trait Types
object TypeRef extends TypeRefExtractor {
def apply(pre: Type, sym: Symbol, args: List[Type]): Type = unique({
- if (args.nonEmpty) {
+ if (args ne Nil) {
if (sym.isAliasType) new AliasArgsTypeRef(pre, sym, args)
else if (sym.isAbstractType) new AbstractArgsTypeRef(pre, sym, args)
else new ClassArgsTypeRef(pre, sym, args)
@@ -2485,7 +2512,7 @@ trait Types
true
}
- def isImplicit = params.nonEmpty && params.head.isImplicit
+ def isImplicit = (params ne Nil) && params.head.isImplicit
def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized?
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
@@ -2493,7 +2520,7 @@ trait Types
override def paramss: List[List[Symbol]] = params :: resultType.paramss
- override def paramTypes = params map (_.tpe)
+ override def paramTypes = mapList(params)(symTpe) // OPT use mapList rather than .map
override def boundSyms = resultType.boundSyms ++ params
@@ -4120,7 +4147,7 @@ trait Types
&& (variance.isCovariant || isSubType(t2, t1, depth))
)
- corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg)
+ corresponds3(tps1, tps2, mapList(tparams)(_.variance))(isSubArg)
}
def specializesSym(tp: Type, sym: Symbol, depth: Depth): Boolean = {
@@ -4304,7 +4331,7 @@ trait Types
}
def instantiatedBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): List[TypeBounds] =
- tparams map (_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds)
+ mapList(tparams)(_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds)
def elimAnonymousClass(t: Type) = t match {
case TypeRef(pre, clazz, Nil) if clazz.isAnonymousClass =>
@@ -4553,7 +4580,10 @@ trait Types
private[scala] val typeIsExistentiallyBound = (tp: Type) => tp.typeSymbol.isExistentiallyBound
private[scala] val typeIsErroneous = (tp: Type) => tp.isErroneous
private[scala] val symTypeIsError = (sym: Symbol) => sym.tpe.isError
- private[scala] val typeHasAnnotations = (tp: Type) => tp.annotations.nonEmpty
+ private[scala] val treeTpe = (t: Tree) => t.tpe
+ private[scala] val symTpe = (sym: Symbol) => sym.tpe
+ private[scala] val symInfo = (sym: Symbol) => sym.info
+ private[scala] val typeHasAnnotations = (tp: Type) => tp.annotations ne Nil
private[scala] val boundsContainType = (bounds: TypeBounds, tp: Type) => bounds containsType tp
private[scala] val typeListIsEmpty = (ts: List[Type]) => ts.isEmpty
private[scala] val typeIsSubTypeOfSerializable = (tp: Type) => tp <:< SerializableTpe
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 09f4389b82..f427813c01 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -861,7 +861,7 @@ private[internal] trait TypeMaps {
class InstantiateDependentMap(params: List[Symbol], actuals0: List[Type]) extends TypeMap with KeepOnlyTypeConstraints {
private val actuals = actuals0.toIndexedSeq
private val existentials = new Array[Symbol](actuals.size)
- def existentialsNeeded: List[Symbol] = existentials.filter(_ ne null).toList
+ def existentialsNeeded: List[Symbol] = existentials.iterator.filter(_ ne null).toList
private object StableArg {
def unapply(param: Symbol) = Arg unapply param map actuals filter (tp =>
diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala
index 7cc2952c96..d128521be8 100644
--- a/src/reflect/scala/reflect/internal/util/Collections.scala
+++ b/src/reflect/scala/reflect/internal/util/Collections.scala
@@ -47,6 +47,30 @@ trait Collections {
final def mforeach[A](xss: List[List[A]])(f: A => Unit) = xss foreach (_ foreach f)
final def mforeach[A](xss: Traversable[Traversable[A]])(f: A => Unit) = xss foreach (_ foreach f)
+ /** A version of List#map, specialized for List, and optimized to avoid allocation if `as` is empty */
+ final def mapList[A, B](as: List[A])(f: A => B): List[B] = if (as eq Nil) Nil else {
+ val head = new ::[B](f(as.head), Nil)
+ var tail: ::[B] = head
+ var rest = as.tail
+ while (rest ne Nil) {
+ val next = new ::(f(rest.head), Nil)
+ tail.tl = next
+ tail = next
+ rest = rest.tail
+ }
+ head
+ }
+
+ final def collectFirst[A, B](as: List[A])(pf: PartialFunction[A, B]): Option[B] = {
+ @tailrec
+ def loop(rest: List[A]): Option[B] = rest match {
+ case Nil => None
+ case a :: as if pf.isDefinedAt(a) => Some(pf(a))
+ case a :: as => loop(as)
+ }
+ loop(as)
+ }
+
final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = {
val lb = new ListBuffer[C]
var ys1 = xs1
@@ -99,15 +123,19 @@ trait Collections {
else f(xs1.head, xs2.head, xs3.head) :: map3(xs1.tail, xs2.tail, xs3.tail)(f)
}
final def flatMap2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => List[C]): List[C] = {
- val lb = new ListBuffer[C]
+ var lb: ListBuffer[C] = null
var ys1 = xs1
var ys2 = xs2
while (!ys1.isEmpty && !ys2.isEmpty) {
- lb ++= f(ys1.head, ys2.head)
+ val cs = f(ys1.head, ys2.head)
+ if (cs ne Nil) {
+ if (lb eq null) lb = new ListBuffer[C]
+ lb ++= cs
+ }
ys1 = ys1.tail
ys2 = ys2.tail
}
- lb.toList
+ if (lb eq null) Nil else lb.result
}
final def flatCollect[A, B](elems: List[A])(pf: PartialFunction[A, Traversable[B]]): List[B] = {
diff --git a/src/reflect/scala/reflect/macros/Attachments.scala b/src/reflect/scala/reflect/macros/Attachments.scala
index 039e75fbee..5ccdc15a03 100644
--- a/src/reflect/scala/reflect/macros/Attachments.scala
+++ b/src/reflect/scala/reflect/macros/Attachments.scala
@@ -43,7 +43,7 @@ abstract class Attachments { self =>
/** Check underlying payload contains an instance of type `T`. */
def contains[T: ClassTag]: Boolean =
- all exists matchesTag[T]
+ !isEmpty && (all exists matchesTag[T])
/** Creates a copy of this attachment with the payload slot of T added/updated with the provided value.
* Replaces an existing payload of the same type, if exists.
@@ -57,6 +57,8 @@ abstract class Attachments { self =>
if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }]
else new NonemptyAttachments[Pos](this.pos, newAll)
}
+
+ def isEmpty: Boolean = true
}
// SI-7018: This used to be an inner class of `Attachments`, but that led to a memory leak in the
@@ -64,4 +66,5 @@ abstract class Attachments { self =>
private final class NonemptyAttachments[P >: Null](override val pos: P, override val all: Set[Any]) extends Attachments {
type Pos = P
def withPos(newPos: Pos) = new NonemptyAttachments(newPos, all)
+ override def isEmpty: Boolean = false
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
index e5dbaa3fd5..5ea1443a19 100644
--- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala
@@ -122,6 +122,11 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
"Hide the members inherited by the given comma separated, fully qualified implicit conversions. Add dot (.) to include default conversions."
)
+ val docAuthor = BooleanSetting (
+ "-author",
+ "Include authors."
+ )
+
val docDiagrams = BooleanSetting (
"-diagrams",
"Create inheritance diagrams for classes, traits and packages."
@@ -207,7 +212,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
// For improved help output.
def scaladocSpecific = Set[Settings#Setting](
docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator, docRootContent, useStupidTypes,
- docDiagrams, docDiagramsDebug, docDiagramsDotPath,
+ docAuthor, docDiagrams, docDiagramsDebug, docDiagramsDotPath,
docDiagramsDotTimeout, docDiagramsDotRestart,
docImplicits, docImplicitsDebug, docImplicitsShowAll, docImplicitsHide,
docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses,
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
index 119d4e0143..26ee005d3e 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
@@ -351,6 +351,14 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
if (mbr.comment.isEmpty) NodeSeq.Empty
else <div class="comment cmt">{ commentToHtml(mbr.comment) }</div>
+ val authorComment =
+ if (! s.docAuthor || mbr.comment.isEmpty ||
+ mbr.comment.isDefined && mbr.comment.get.authors.isEmpty) NodeSeq.Empty
+ else <div class="comment cmt">
+ {if (mbr.comment.get.authors.size > 1) <h6>Authors:</h6> else <h6>Author:</h6>}
+ { mbr.comment.get.authors map bodyToHtml}
+ </div>
+
val paramComments = {
val prs: List[ParameterEntity] = mbr match {
case cls: Class => cls.typeParams ::: cls.valueParams.flatten
@@ -681,7 +689,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
val typeHierarchy = createDiagram(_.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram")
val contentHierarchy = createDiagram(_.contentDiagram, "Content Hierarchy", "content-diagram")
- memberComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy
+ memberComment ++ authorComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy
}
def boundsToHtml(hi: Option[TypeEntity], lo: Option[TypeEntity], hasLinks: Boolean): NodeSeq = {
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
index 8f217e087c..ef84ac42ba 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -10,6 +10,7 @@ import diagram._
import scala.collection._
import scala.util.matching.Regex
+import scala.reflect.macros.internal.macroImpl
import symtab.Flags
import io._
@@ -80,7 +81,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def inTemplate: TemplateImpl = inTpl
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
- def annotations = sym.annotations.map(makeAnnotation)
+ def annotations = sym.annotations.filterNot(_.tpe =:= typeOf[macroImpl]).map(makeAnnotation)
def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject
def isType = sym.name.isTypeName
}
@@ -145,6 +146,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
* any abstract terms, otherwise it would fail compilation. So we reset the DEFERRED flag. */
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED) && (!isImplicitlyInherited)) fgs += Paragraph(Text("abstract"))
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
+ if (sym.isMacro) fgs += Paragraph(Text("macro"))
fgs.toList
}
def deprecation =
diff --git a/test/files/jvm/t6941/Analyzed_1.scala b/test/files/jvm/t6941/Analyzed_1.scala
index 549abd5e64..b6951f71ee 100644
--- a/test/files/jvm/t6941/Analyzed_1.scala
+++ b/test/files/jvm/t6941/Analyzed_1.scala
@@ -6,6 +6,6 @@ class SameBytecode {
}
def b(xs: List[Int]) = xs match {
- case xs: ::[Int] => xs.hd$1
+ case xs: ::[Int] => xs.head
}
} \ No newline at end of file
diff --git a/test/files/neg/missing-param-type-tuple.check b/test/files/neg/missing-param-type-tuple.check
index bc46ba1023..3a4258ff8c 100644
--- a/test/files/neg/missing-param-type-tuple.check
+++ b/test/files/neg/missing-param-type-tuple.check
@@ -1,6 +1,6 @@
missing-param-type-tuple.scala:3: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
- Consider a pattern matching anoynmous function, `{ case (a, b) => ... }`
+ Consider a pattern matching anonymous function, `{ case (a, b) => ... }`
val x: ((Int, Int)) => Int = (a, b) => 0
^
missing-param-type-tuple.scala:3: error: missing parameter type
@@ -8,7 +8,7 @@ missing-param-type-tuple.scala:3: error: missing parameter type
^
missing-param-type-tuple.scala:5: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 3-Tuple.
- Consider a pattern matching anoynmous function, `{ case (param1, ..., param3) => ... }`
+ Consider a pattern matching anonymous function, `{ case (param1, ..., param3) => ... }`
val y: ((Int, Int, Int)) => Int = (a, b, !!) => 0
^
missing-param-type-tuple.scala:5: error: missing parameter type
@@ -19,7 +19,7 @@ missing-param-type-tuple.scala:5: error: missing parameter type
^
missing-param-type-tuple.scala:7: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 3-Tuple.
- Consider a pattern matching anoynmous function, `{ case (param1, ..., param3) => ... }`
+ Consider a pattern matching anonymous function, `{ case (param1, ..., param3) => ... }`
val z: ((Int, Int, Int)) => Int = (a, NotAVariablePatternName, c) => 0
^
missing-param-type-tuple.scala:7: error: missing parameter type
diff --git a/test/files/pos/t7322.scala b/test/files/pos/t7322.scala
new file mode 100644
index 0000000000..006bf89e9f
--- /dev/null
+++ b/test/files/pos/t7322.scala
@@ -0,0 +1,11 @@
+
+package object t7322 {
+ implicit class X(sc: StringContext) {
+ def x_?(args: Any*) = "hi there"
+ }
+}
+package t7322 {
+ trait Y {
+ x_?"junk" // assume that if it compiles, it works
+ }
+}
diff --git a/test/files/pos/t8170.scala b/test/files/pos/t8170.scala
new file mode 100644
index 0000000000..b65f4b8572
--- /dev/null
+++ b/test/files/pos/t8170.scala
@@ -0,0 +1,27 @@
+object O {
+ trait X
+ trait B extends A {
+ override type T[F1 <: X] = F1
+ }
+ trait A {
+ type T[F <: X]
+ }
+}
+
+object Test {
+ import O._
+ val a: B = ???
+ val b: a.T[X] = ???
+ b.ensuring(x => true) // trigger an implicit search
+}
+
+
+/*
+this = {AliasArgsTypeRef@3004}"Test#7680.a#14899.T#14823[O#7702.X#7793]"
+ sym = type T#14823
+ info = namer: [F#14824 <: O#7703.X#7793]F#14824
+result = {AbstractNoArgsTypeRef@3237}"F#24451"
+tp = {PolyType@3235}"[F#14824 <: O#7703.X#7793]F#14824"
+tparams =
+ (0) = {AbstractTypeSymbol@3247}"type F#24451"
+*/ \ No newline at end of file
diff --git a/test/files/pos/t8170b.scala b/test/files/pos/t8170b.scala
new file mode 100644
index 0000000000..53036f6c8a
--- /dev/null
+++ b/test/files/pos/t8170b.scala
@@ -0,0 +1,25 @@
+import language._
+
+object ScalaZeee {
+ trait HFold[M[_], U] {
+ type Apply[E, A <: U] <: U
+ }
+ trait GenericCons[M[_], H, +T <: GenericList[M]] extends GenericList[M] {
+ val tail: T
+ override type Folded[N[X] >: M[X], U, F <: HFold[N, U]] = F#Apply[H, tail.Folded[N, U, F]]
+ }
+ val KNil: GenericList[Nothing] = ???
+ sealed trait GenericList[+M[_]] {
+ type Folded[N[X] >: M[X], U, F <: HFold[N, U]] <: U
+ }
+}
+
+object TypelevelUsage {
+ import ScalaZeee._
+ type T = GenericCons[Some, String, KNil.type]
+ val klist1: T = ???
+ type T2 = klist1.Folded[Option, Int, HFold[Option, Int]]
+ val count2: T2 = ???
+
+ count2.ensuring(x => true).toChar // trigger an implicit search
+}
diff --git a/test/files/run/t8233-bcode.flags b/test/files/run/t8233-bcode.flags
new file mode 100644
index 0000000000..c30091d3de
--- /dev/null
+++ b/test/files/run/t8233-bcode.flags
@@ -0,0 +1 @@
+-Ybackend:GenBCode
diff --git a/test/files/run/t8233-bcode.scala b/test/files/run/t8233-bcode.scala
new file mode 100644
index 0000000000..fae1c2b702
--- /dev/null
+++ b/test/files/run/t8233-bcode.scala
@@ -0,0 +1,18 @@
+object Test {
+ def bar(s: String) = s;
+ val o: Option[Null] = None
+ def nullReference {
+ val a: Null = o.get
+ bar(a) // Was: VerifyError under GenICode
+ }
+
+ def literal {
+ val a: Null = null
+ bar(a)
+ }
+
+ def main(args: Array[String]) = {
+ try { nullReference } catch { case _: NoSuchElementException => }
+ literal
+ }
+}
diff --git a/test/files/run/t8233.scala b/test/files/run/t8233.scala
new file mode 100644
index 0000000000..fae1c2b702
--- /dev/null
+++ b/test/files/run/t8233.scala
@@ -0,0 +1,18 @@
+object Test {
+ def bar(s: String) = s;
+ val o: Option[Null] = None
+ def nullReference {
+ val a: Null = o.get
+ bar(a) // Was: VerifyError under GenICode
+ }
+
+ def literal {
+ val a: Null = null
+ bar(a)
+ }
+
+ def main(args: Array[String]) = {
+ try { nullReference } catch { case _: NoSuchElementException => }
+ literal
+ }
+}
diff --git a/test/scaladoc/resources/SI-4014_0.scala b/test/scaladoc/resources/SI-4014_0.scala
new file mode 100644
index 0000000000..c398fcc1e0
--- /dev/null
+++ b/test/scaladoc/resources/SI-4014_0.scala
@@ -0,0 +1,4 @@
+/** A template without authors.
+ *
+ */
+trait Foo \ No newline at end of file
diff --git a/test/scaladoc/resources/SI-4014_1.scala b/test/scaladoc/resources/SI-4014_1.scala
new file mode 100644
index 0000000000..34386b515e
--- /dev/null
+++ b/test/scaladoc/resources/SI-4014_1.scala
@@ -0,0 +1,5 @@
+/** A template with one author.
+ *
+ * @author The Only Author
+ */
+trait Foo \ No newline at end of file
diff --git a/test/scaladoc/resources/SI-4014_2.scala b/test/scaladoc/resources/SI-4014_2.scala
new file mode 100644
index 0000000000..514f7a1e4c
--- /dev/null
+++ b/test/scaladoc/resources/SI-4014_2.scala
@@ -0,0 +1,6 @@
+/** A template with more than one author.
+ *
+ * @author The First Author
+ * @author The Second Author
+ */
+trait Foo \ No newline at end of file
diff --git a/test/scaladoc/run/t7124.check b/test/scaladoc/run/t7124.check
new file mode 100644
index 0000000000..96b627a322
--- /dev/null
+++ b/test/scaladoc/run/t7124.check
@@ -0,0 +1,3 @@
+List()
+List(Paragraph(Text(macro)))
+Done.
diff --git a/test/scaladoc/run/t7124.scala b/test/scaladoc/run/t7124.scala
new file mode 100644
index 0000000000..e8272000d2
--- /dev/null
+++ b/test/scaladoc/run/t7124.scala
@@ -0,0 +1,22 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ import scala.language.experimental.macros
+ class Test {
+ def print(): Unit = macro ???
+ }
+ """
+
+ def scaladocSettings = ""
+
+ def testModel(root: Package) = {
+ import access._
+ val p = root._class("Test")._method("print")
+
+ println(p.annotations) // no annotations
+ println(p.flags) // a 'macro' flag
+ }
+}
diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
index 03348b81d2..56328ea875 100644
--- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala
+++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
@@ -47,6 +47,7 @@ object Test extends Properties("HtmlFactory") {
settings.scaladocQuietRun = true
settings.nowarn.value = true
settings.classpath.value = getClasspath
+ settings.docAuthor.value = true
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
new DocFactory(reporter, settings)
@@ -563,12 +564,13 @@ object Test extends Properties("HtmlFactory") {
property("Comment inheritance: Correct explicit inheritance for override") =
checkText("explicit-inheritance-override.scala")(
(Some("InheritDocDerived"),
- """def function[T](arg1: T, arg2: String): Double
+ """def function[T](arg1: T, arg2: String): Double
Starting line
Starting line
The base comment. And another sentence...
The base comment. And another sentence...
Ending line
+ Author: StartAuthor a Scala developer EndAuthor
T StartT the type of the first argument EndT
arg1 Start1 The T term comment End1
arg2 Start2 The string comment End2
@@ -589,12 +591,13 @@ object Test extends Properties("HtmlFactory") {
property("Comment inheritance: Correct explicit inheritance for usecase") =
checkText("explicit-inheritance-usecase.scala")(
(Some("UseCaseInheritDoc"),
- """def function[T](arg1: T, arg2: String): Double
+ """def function[T](arg1: T, arg2: String): Double
[use case] Starting line
[use case] Starting line
The base comment. And another sentence...
The base comment. And another sentence...
Ending line
+ Author: StartAuthor a Scala developer EndAuthor
T StartT the type of the first argument EndT
arg1 Start1 The T term comment End1
arg2 Start2 The string comment End2
@@ -663,6 +666,45 @@ object Test extends Properties("HtmlFactory") {
}
}
+ property("SI-4014: Scaladoc omits @author: no authors") = {
+ val noAuthors = createTemplates("SI-4014_0.scala")("Foo.html")
+
+ noAuthors match {
+ case node: scala.xml.Node => {
+ val s = node.toString
+ ! s.contains("Author")
+ }
+ case _ => false
+ }
+ }
+
+ property("SI-4014: Scaladoc omits @author: one author") = {
+ val oneAuthor = createTemplates("SI-4014_1.scala")("Foo.html")
+
+ oneAuthor match {
+ case node: scala.xml.Node => {
+ val s = node.toString
+ s.contains("<h6>Author:</h6>")
+ s.contains("<p>The Only Author\n</p>")
+ }
+ case _ => false
+ }
+ }
+
+ property("SI-4014: Scaladoc omits @author: two authors") = {
+ val twoAuthors = createTemplates("SI-4014_2.scala")("Foo.html")
+
+ twoAuthors match {
+ case node: scala.xml.Node => {
+ val s = node.toString
+ s.contains("<h6>Authors:</h6>")
+ s.contains("<p>The First Author\n</p>")
+ s.contains("<p>The Second Author\n</p>")
+ }
+ case _ => false
+ }
+ }
+
{
val files = createTemplates("basic.scala")
//println(files)