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/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.scala32
-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/Set.scala46
-rw-r--r--src/library/scala/collection/immutable/Stream.scala8
-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.scala4
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala21
-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/model/ModelFactory.scala4
-rw-r--r--test/files/pos/t7322.scala11
-rw-r--r--test/files/run/t7700.check2
-rw-r--r--test/files/run/t7700.scala17
-rw-r--r--test/scaladoc/run/t7124.check3
-rw-r--r--test/scaladoc/run/t7124.scala22
27 files changed, 249 insertions, 80 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/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 3791af1629..c59b726076 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -306,6 +306,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Return the specialized name of 'sym' in the given environment. It
* guarantees the same result regardless of the map order by sorting
* type variables alphabetically.
+ *
+ * !!! Is this safe in the face of the following?
+ * scala> trait T { def foo[A] = 0}; object O extends T { override def foo[B] = 0 }
*/
private def specializedName(sym: Symbol, env: TypeEnv): TermName = {
val tvars = (
@@ -391,13 +394,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* enclosing member with the annotation.
*/
private def needsSpecialization(env: TypeEnv, sym: Symbol): Boolean = (
- !sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) && (
+ !hasUnspecializableAnnotation(sym) && (
specializedTypeVars(sym).intersect(env.keySet).diff(wasSpecializedForTypeVars(sym)).nonEmpty
|| sym.isClassConstructor && (sym.enclClass.typeParams exists (_.isSpecialized))
|| isNormalizedMember(sym) && info(sym).typeBoundsIn(env)
)
)
+ private def hasUnspecializableAnnotation(sym: Symbol): Boolean =
+ sym.ownerChain.exists(_ hasAnnotation UnspecializedClass)
+
def isNormalizedMember(m: Symbol) = m.isSpecialized && (info get m exists {
case NormalizedMember(_) => true
case _ => false
@@ -433,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)
@@ -907,16 +913,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
if (sym.isMethod) {
- val stvars = specializedTypeVars(sym)
- if (stvars.nonEmpty)
- debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", ")))
+ if (hasUnspecializableAnnotation(sym)) {
+ List()
+ } else {
+ val stvars = specializedTypeVars(sym)
+ if (stvars.nonEmpty)
+ debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", ")))
- val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps
- val tps2 = tps1 filter stvars
- if (!sym.isDeferred)
- addConcreteSpecMethod(sym)
+ val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps
+ val tps2 = tps1 filter stvars
+ if (!sym.isDeferred)
+ addConcreteSpecMethod(sym)
- specializeOn(tps2)
+ specializeOn(tps2)
+ }
}
else Nil
}
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/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/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..145b4a3f1f 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
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..2acf901d0e 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
@@ -2035,7 +2035,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 +2221,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 +2412,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 +2485,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 +2493,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 +4120,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 +4304,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 +4553,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/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/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/run/t7700.check b/test/files/run/t7700.check
new file mode 100644
index 0000000000..ca8e686984
--- /dev/null
+++ b/test/files/run/t7700.check
@@ -0,0 +1,2 @@
+public abstract java.lang.Object C.bar(java.lang.Object)
+public abstract java.lang.Object C.foo(java.lang.Object)
diff --git a/test/files/run/t7700.scala b/test/files/run/t7700.scala
new file mode 100644
index 0000000000..76d16b808c
--- /dev/null
+++ b/test/files/run/t7700.scala
@@ -0,0 +1,17 @@
+import scala.annotation._
+
+trait C[@specialized U] {
+ @unspecialized
+ def foo(u: U): U
+ @unspecialized
+ def bar[A](u: U) = u
+}
+
+object Test extends App {
+ val declared = classOf[C[_]].getDeclaredMethods.sortBy(_.getName)
+ println(declared.mkString("\n"))
+ object CInt extends C[Int] { def foo(i: Int) = i }
+ object CAny extends C[Any] { def foo(a: Any) = a }
+ assert(CInt.foo(1) == 1)
+ assert(CAny.foo("") == "")
+}
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
+ }
+}