summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2012-08-16 10:22:25 +0200
committerLukas Rytz <lukas.rytz@epfl.ch>2012-08-16 14:24:14 +0200
commitffa9b1afc9168e699cfa568a94f84e40b5cc62b7 (patch)
tree389408cc60c0eacee6059b0e4178ccdd61ce1e12 /src
parent3ccaa1026e7e74d99fe39c9608e28c48b422e2c9 (diff)
parente05122cdb38c5c6bd4900247f371fa23b46f9c22 (diff)
downloadscala-ffa9b1afc9168e699cfa568a94f84e40b5cc62b7.tar.gz
scala-ffa9b1afc9168e699cfa568a94f84e40b5cc62b7.tar.bz2
scala-ffa9b1afc9168e699cfa568a94f84e40b5cc62b7.zip
Merge remote-tracking branch 'upstream/2.10.x' into merge-210
Required a few changes of `HIDDEN` -> `ARTIFACT` and `isHidden` -> `isArtifact` Conflicts: src/reflect/scala/reflect/internal/Flags.scala
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Printers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala16
-rw-r--r--src/compiler/scala/tools/nsc/doc/Settings.scala18
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala9
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js15
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala549
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala53
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala6
-rw-r--r--src/ensime/.ensime.SAMPLE17
-rw-r--r--src/ensime/README.md11
-rw-r--r--src/library/scala/collection/SeqLike.scala2
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala5
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala30
-rw-r--r--src/reflect/scala/reflect/internal/HasFlags.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala5
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala7
31 files changed, 467 insertions, 348 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Printers.scala b/src/compiler/scala/tools/nsc/ast/Printers.scala
index 8b92f0acd6..885fc3f518 100644
--- a/src/compiler/scala/tools/nsc/ast/Printers.scala
+++ b/src/compiler/scala/tools/nsc/ast/Printers.scala
@@ -278,6 +278,7 @@ trait Printers extends reflect.internal.Printers { this: Global =>
def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value)
def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value)
+ def asCompactDebugString(t: Tree): String = render(t, newCompactTreePrinter, true, true, true)
def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream))
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 9ed9cfe267..73f5ec7b3c 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -191,7 +191,7 @@ abstract class TreeBuilder {
} else {
val x = freshTermName()
Block(
- List(ValDef(Modifiers(SYNTHETIC | HIDDEN), x, TypeTree(), stripParens(left))),
+ List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))),
Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x))))
}
} else {
@@ -488,7 +488,7 @@ abstract class TreeBuilder {
def makeCatchFromExpr(catchExpr: Tree): CaseDef = {
val binder = freshTermName("x")
val pat = Bind(binder, Typed(Ident(nme.WILDCARD), Ident(tpnme.Throwable)))
- val catchDef = ValDef(Modifiers(HIDDEN), freshTermName("catchExpr"), TypeTree(), catchExpr)
+ val catchDef = ValDef(Modifiers(ARTIFACT), freshTermName("catchExpr"), TypeTree(), catchExpr)
val catchFn = Ident(catchDef.name)
val body = atPos(catchExpr.pos.makeTransparent)(Block(
List(catchDef),
@@ -562,7 +562,7 @@ abstract class TreeBuilder {
val tmp = freshTermName()
val firstDef =
atPos(matchExpr.pos) {
- ValDef(Modifiers(PrivateLocal | SYNTHETIC | HIDDEN | (mods.flags & LAZY)),
+ ValDef(Modifiers(PrivateLocal | SYNTHETIC | ARTIFACT | (mods.flags & LAZY)),
tmp, TypeTree(), matchExpr)
}
var cnt = 0
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index bbd826ee26..1a9201fd67 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -295,7 +295,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
- if (sym.isHidden) ACC_SYNTHETIC else 0,
+ if (sym.isArtifact) ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
if (sym.isVarargsMethod) ACC_VARARGS else 0,
if (sym.hasFlag(Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0
@@ -851,7 +851,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// generic information could disappear as a consequence of a seemingly
// unrelated change.
settings.Ynogenericsig.value
- || sym.isHidden
+ || sym.isArtifact
|| sym.isLiftedMethod
|| sym.isBridge
|| (sym.ownerChain exists (_.isImplClass))
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index e7e47a9ea8..d3b24a19f4 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -728,7 +728,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// generic information could disappear as a consequence of a seemingly
// unrelated change.
settings.Ynogenericsig.value
- || sym.isHidden
+ || sym.isArtifact
|| sym.isLiftedMethod
|| sym.isBridge
|| (sym.ownerChain exists (_.isImplClass))
@@ -866,7 +866,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
def genField(f: IField) {
debuglog("Adding field: " + f.symbol.fullName)
-
+
val jfield = jclass.addNewField(
javaFieldFlags(f.symbol),
javaName(f.symbol),
@@ -1021,7 +1021,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
method = m
jmethod = clinitMethod
-
+
computeLocalVarsIndex(m)
genCode(m)
case None =>
@@ -1116,7 +1116,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet
}
debuglog("Potentially conflicting names for forwarders: " + conflictingNames)
-
+
for (m <- moduleClass.info.membersBasedOnFlags(ExcludedForwarderFlags, Flags.METHOD)) {
if (m.isType || m.isDeferred || (m.owner eq ObjectClass) || m.isConstructor)
debuglog("No forwarder for '%s' from %s to '%s'".format(m, className, moduleClass))
@@ -1308,7 +1308,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
jclass.getType())
}
}
-
+
style match {
case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype)
case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype)
@@ -1815,7 +1815,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
* Synthetic locals are skipped. All variables are method-scoped.
*/
private def genLocalVariableTable(m: IMethod, jcode: JCode) {
- val vars = m.locals filterNot (_.sym.isHidden)
+ val vars = m.locals filterNot (_.sym.isArtifact)
if (vars.isEmpty) return
val pool = jclass.getConstantPool
@@ -1889,7 +1889,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
*/
def computeLocalVarsIndex(m: IMethod) {
var idx = if (m.symbol.isStaticMember) 0 else 1;
-
+
for (l <- m.params) {
debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
l.index = idx
@@ -1977,7 +1977,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
- if (sym.isHidden) ACC_SYNTHETIC else 0,
+ if (sym.isArtifact) ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
if (sym.isVarargsMethod) ACC_VARARGS else 0,
if (sym.hasFlag(Flags.SYNCHRONIZED)) JAVA_ACC_SYNCHRONIZED else 0
diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala
index 720b1347ef..dbc34bd7b3 100644
--- a/src/compiler/scala/tools/nsc/doc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/doc/Settings.scala
@@ -111,6 +111,12 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
"only use it if you haven't defined usecase for implicitly inherited members."
)
+ val docImplicitsHide = MultiStringSetting (
+ "-implicits-hide",
+ "implicit(s)",
+ "Hide the members inherited by the given comma separated, fully qualified implicit conversions. Add dot (.) to include default conversions."
+ )
+
val docDiagrams = BooleanSetting (
"-diagrams",
"Create inheritance diagrams for classes, traits and packages."
@@ -203,7 +209,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator, docRootContent, useStupidTypes,
docDiagrams, docDiagramsDebug, docDiagramsDotPath,
docDiagramsDotTimeout, docDiagramsDotRestart,
- docImplicits, docImplicitsDebug, docImplicitsShowAll,
+ docImplicits, docImplicitsDebug, docImplicitsShowAll, docImplicitsHide,
docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses,
docNoPrefixes, docNoLinkWarnings, docRawOutput, docSkipPackages,
docExpandAllTypes, docGroups
@@ -224,6 +230,14 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
def skipPackage(qname: String) =
skipPackageNames(qname.toLowerCase)
+ lazy val hiddenImplicits: Set[String] = {
+ if (docImplicitsHide.value.isEmpty) hardcoded.commonConversionTargets
+ else docImplicitsHide.value.toSet flatMap { name: String =>
+ if(name == ".") hardcoded.commonConversionTargets
+ else Set(name)
+ }
+ }
+
/**
* This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty,
* but ultimately scaladoc has to be useful. :)
@@ -264,7 +278,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
}
/** Common conversion targets that affect any class in Scala */
- val commonConversionTargets = List(
+ val commonConversionTargets = Set(
"scala.Predef.any2stringfmt",
"scala.Predef.any2stringadd",
"scala.Predef.any2ArrowAssoc",
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 5977acc0c2..1f68781777 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -148,8 +148,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<div id="ancestors">
<span class="filtertype">Implicitly<br/>
</span>
- <ol id="implicits">
- { tpl.conversions.map(conv => <li class="in" name={ conv.conversionQualifiedName }><span>{ "by " + conv.conversionShortName }</span></li>) }
+ <ol id="implicits"> {
+ tpl.conversions.map { conv =>
+ val name = conv.conversionQualifiedName
+ val hide = universe.settings.hiddenImplicits(name)
+ <li class="in" name={ name } data-hidden={ hide.toString }><span>{ "by " + conv.conversionShortName }</span></li>
+ }
+ }
</ol>
</div>
else NodeSeq.Empty
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
index afd0293fe1..5920fdfdb2 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -4,12 +4,11 @@
$(document).ready(function(){
var isHiddenClass = function (name) {
return name == 'scala.Any' ||
- name == 'scala.AnyRef' ||
- name == 'scala.Predef.any2stringfmt' ||
- name == 'scala.Predef.any2stringadd' ||
- name == 'scala.Predef.any2ArrowAssoc' ||
- name == 'scala.Predef.any2Ensuring' ||
- name == 'scala.collection.TraversableOnce.alternateImplicit'
+ name == 'scala.AnyRef';
+ };
+
+ var isHidden = function (elem) {
+ return $(elem).attr("data-hidden") == 'true';
};
$("#linearization li:gt(0)").filter(function(){
@@ -17,7 +16,7 @@ $(document).ready(function(){
}).removeClass("in").addClass("out");
$("#implicits li").filter(function(){
- return isHiddenClass($(this).attr("name"));
+ return isHidden(this);
}).removeClass("in").addClass("out");
// Pre-filter members
@@ -113,7 +112,7 @@ $(document).ready(function(){
var filteredImplicits =
$("#implicits li.out").filter(function() {
- return ! isHiddenClass($(this).attr("name"));
+ return ! isHidden(this);
});
filteredImplicits.removeClass("out").addClass("in");
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 46b2a11d4a..6d193c30f7 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -530,8 +530,8 @@ trait ImplicitConversion {
/** The members inherited by this implicit conversion */
def members: List[MemberEntity]
- /** Is this a common implicit conversion (aka conversion that affects all classes, in Predef?) */
- def isCommonConversion: Boolean
+ /** Is this a hidden implicit conversion (as specified in the settings) */
+ def isHiddenConversion: Boolean
}
/** Shadowing captures the information that the member is shadowed by some other members
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index a962ec4007..ed8541f692 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -1075,7 +1075,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def classExcluded(clazz: TemplateEntity): Boolean = settings.hardcoded.isExcluded(clazz.qualifiedName)
// the implicit conversions that are excluded from the pages should not appear in the diagram
- def implicitExcluded(convertorMethod: String): Boolean = settings.hardcoded.commonConversionTargets.contains(convertorMethod)
+ def implicitExcluded(convertorMethod: String): Boolean = settings.hiddenImplicits(convertorMethod)
// whether or not to create a page for an {abstract,alias} type
def typeShouldDocument(bSym: Symbol, inTpl: DocTemplateImpl) =
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 5a0cc602e5..327436ed20 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -113,9 +113,9 @@ trait ModelFactoryImplicitSupport {
conversions = conversions.filter((ic: ImplicitConversionImpl) =>
hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName))
- // Put the class-specific conversions in front
+ // Put the visible conversions in front
val (ownConversions, commonConversions) =
- conversions.partition(!_.isCommonConversion)
+ conversions.partition(!_.isHiddenConversion)
ownConversions ::: commonConversions
}
@@ -416,7 +416,7 @@ trait ModelFactoryImplicitSupport {
lazy val members: List[MemberEntity] = memberImpls
- def isCommonConversion = hardcoded.commonConversionTargets.contains(conversionQualifiedName)
+ def isHiddenConversion = settings.hiddenImplicits(conversionQualifiedName)
override def toString = "Implcit conversion from " + sym.tpe + " to " + toType + " done by " + convSym
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 66a815465d..b358785714 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -869,10 +869,10 @@ abstract class ClassfileParser {
}
else in.skip(attrLen)
case tpnme.SyntheticATTR =>
- sym.setFlag(SYNTHETIC | HIDDEN)
+ sym.setFlag(SYNTHETIC | ARTIFACT)
in.skip(attrLen)
case tpnme.BridgeATTR =>
- sym.setFlag(BRIDGE | HIDDEN)
+ sym.setFlag(BRIDGE | ARTIFACT)
in.skip(attrLen)
case tpnme.DeprecatedATTR =>
val arg = Literal(Constant("see corresponding Javadoc for more information."))
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 4c4b7dcff4..4715a5d340 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -413,7 +413,7 @@ abstract class Erasure extends AddInterfaces
if (!bridgeNeeded)
return
- val newFlags = (member.flags | BRIDGE | HIDDEN) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
+ val newFlags = (member.flags | BRIDGE | ARTIFACT) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
val bridge = other.cloneSymbolImpl(owner, newFlags) setPos owner.pos
debuglog("generating bridge from %s (%s): %s to %s: %s".format(
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 34f5ac611c..c5494b5b1f 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -95,7 +95,7 @@ abstract class ExplicitOuter extends InfoTransform
else findOrElse(clazz.info.decls)(_.outerSource == clazz)(NoSymbol)
}
def newOuterAccessor(clazz: Symbol) = {
- val accFlags = SYNTHETIC | HIDDEN | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 )
+ val accFlags = SYNTHETIC | ARTIFACT | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 )
val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags)
val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType
@@ -104,7 +104,7 @@ abstract class ExplicitOuter extends InfoTransform
sym setInfo MethodType(Nil, restpe)
}
def newOuterField(clazz: Symbol) = {
- val accFlags = SYNTHETIC | HIDDEN | PARAMACCESSOR | ( if (clazz.isEffectivelyFinal) PrivateLocal else PROTECTED )
+ val accFlags = SYNTHETIC | ARTIFACT | PARAMACCESSOR | ( if (clazz.isEffectivelyFinal) PrivateLocal else PROTECTED )
val sym = clazz.newValue(nme.OUTER_LOCAL, clazz.pos, accFlags)
sym setInfo clazz.outerClass.thisType
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 0579d7bb96..982b7a680e 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -35,7 +35,7 @@ abstract class OverridingPairs {
*
*/
protected def exclude(sym: Symbol): Boolean =
- sym.isConstructor || sym.isPrivateLocal || sym.isHidden
+ sym.isConstructor || sym.isPrivateLocal || sym.isArtifact
/** The parents of base (may also be refined).
*/
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index e6c886b6d6..58914b61d8 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -797,7 +797,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
var specializingOn = specializedParams(sym)
val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info)
- // I think the last condition should be !sym.isHidden, but that made the
+ // I think the last condition should be !sym.isArtifact, but that made the
// compiler start warning about Tuple1.scala and Tuple2.scala claiming
// their type parameters are used in non-specializable positions. Why is
// unusedStvars.nonEmpty for these classes???
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 7c5d458fee..c8bf70e9e0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -11,6 +11,7 @@ import reflect.internal.util.Statistics
import scala.reflect.macros.util._
import java.lang.{Class => jClass}
import java.lang.reflect.{Array => jArray, Method => jMethod}
+import scala.reflect.internal.util.Collections._
/**
* Code to deal with macros, namely with:
@@ -48,6 +49,171 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val globalMacroCache = collection.mutable.Map[Any, Any]()
val perRunMacroCache = perRunCaches.newMap[Symbol, collection.mutable.Map[Any, Any]]
+ /** `MacroImplBinding` and its companion module are responsible for
+ * serialization/deserialization of macro def -> impl bindings.
+ *
+ * The first officially released version of macros persisted these bindings across compilation runs
+ * using a neat trick. The right-hand side of a macro definition (which contains a reference to a macro impl)
+ * was typechecked and then put verbatim into an annotation on the macro definition.
+ *
+ * This solution is very simple, but unfortunately it's also lacking. If we use it, then
+ * signatures of macro defs become transitively dependent on scala-reflect.jar
+ * (because they refer to macro impls, and macro impls refer to scala.reflect.macros.Context defined in scala-reflect.jar).
+ * More details can be found in comments to https://issues.scala-lang.org/browse/SI-5940.
+ *
+ * Therefore we have to avoid putting macro impls into binding pickles and come up with our own serialization format.
+ * Situation is further complicated by the fact that it's not enough to just pickle macro impl's class name and method name,
+ * because macro expansion needs some knowledge about the shape of macro impl's signature (which we can't pickle).
+ * Hence we precompute necessary stuff (e.g. the layout of type parameters) when compiling macro defs.
+ */
+
+ /** Represents all the information that a macro definition needs to know about its implementation.
+ * Includes a path to load the implementation via Java reflection,
+ * and various accounting information necessary when composing an argument list for the reflective invocation.
+ */
+ private case class MacroImplBinding(
+ // Java class name of the class that contains the macro implementation
+ // is used to load the corresponding object with Java reflection
+ val className: String,
+ // method name of the macro implementation
+ // `className` and `methName` are all we need to reflectively invoke a macro implementation
+ // because macro implementations cannot be overloaded
+ val methName: String,
+ // flattens the macro impl's parameter lists having symbols replaced with metadata
+ // currently metadata is an index of the type parameter corresponding to that type tag (if applicable)
+ // f.ex. for: def impl[T: AbsTypeTag, U: AbsTypeTag, V](c: Context)(x: c.Expr[T]): (U, V) = ???
+ // `signature` will be equal to List(-1, -1, 0, 1)
+ val signature: List[Int],
+ // type arguments part of a macro impl ref (the right-hand side of a macro definition)
+ // these trees don't refer to a macro impl, so we can pickle them as is
+ val targs: List[Tree])
+
+ /** Macro def -> macro impl bindings are serialized into a `macroImpl` annotation
+ * with synthetic content that carries the payload described in `MacroImplBinding`.
+ *
+ * For example, for a pair of macro definition and macro implementation:
+ * def impl(c: scala.reflect.macros.Context): c.Expr[Unit] = c.literalUnit;
+ * def foo: Unit = macro impl
+ *
+ * We will have the following annotation added on the macro definition `foo`:
+ *
+ * @scala.reflect.macros.internal.macroImpl(
+ * `macro`(
+ * "signature" = List(-1),
+ * "methodName" = "impl",
+ * "versionFormat" = 1,
+ * "className" = "Macros$"))
+ */
+ private object MacroImplBinding {
+ val versionFormat = 1
+
+ def pickleAtom(obj: Any): Tree =
+ obj match {
+ case list: List[_] => Apply(Ident(ListModule), list map pickleAtom)
+ case s: String => Literal(Constant(s))
+ case i: Int => Literal(Constant(i))
+ }
+
+ def unpickleAtom(tree: Tree): Any =
+ tree match {
+ case Apply(list @ Ident(_), args) if list.symbol == ListModule => args map unpickleAtom
+ case Literal(Constant(s: String)) => s
+ case Literal(Constant(i: Int)) => i
+ }
+
+ def pickle(macroImplRef: Tree): Tree = {
+ val macroImpl = macroImplRef.symbol
+ val paramss = macroImpl.paramss
+
+ // this logic relies on the assumptions that were valid for the old macro prototype
+ // namely that macro implementations can only be defined in top-level classes and modules
+ // with the new prototype that materialized in a SIP, macros need to be statically accessible, which is different
+ // for example, a macro def could be defined in a trait that is implemented by an object
+ // there are some more clever cases when seemingly non-static method ends up being statically accessible
+ // however, the code below doesn't account for these guys, because it'd take a look of time to get it right
+ // for now I leave it as a todo and move along to more the important stuff
+ // [Eugene] relies on the fact that macro implementations can only be defined in static classes
+ // [Martin to Eugene++] There's similar logic buried in Symbol#flatname. Maybe we can refactor?
+ // [Eugene] we will refactor once I get my hands on https://issues.scala-lang.org/browse/SI-5498
+ def className: String = {
+ def loop(sym: Symbol): String = sym match {
+ case sym if sym.owner.isPackageClass =>
+ val suffix = if (sym.isModuleClass) "$" else ""
+ sym.fullName + suffix
+ case sym =>
+ val separator = if (sym.owner.isModuleClass) "" else "$"
+ loop(sym.owner) + separator + sym.javaSimpleName.toString
+ }
+
+ loop(macroImpl.owner.enclClass)
+ }
+
+ def signature: List[Int] = {
+ val transformed = transformTypeTagEvidenceParams(paramss, (param, tparam) => tparam)
+ transformed.flatten map (p => if (p.isTerm) -1 else p.paramPos)
+ }
+
+ val payload = List[(String, Any)](
+ "versionFormat" -> versionFormat,
+ "className" -> className,
+ "methodName" -> macroImpl.name.toString,
+ "signature" -> signature
+ )
+
+ // the shape of the nucleus is chosen arbitrarily. it doesn't carry any payload.
+ // it's only necessary as a stub `fun` for an Apply node that carries metadata in its `args`
+ // so don't try to find a program element named "macro" that corresponds to the nucleus
+ // I just named it "macro", because it's macro-related, but I could as well name it "foobar"
+ val nucleus = Ident(newTermName("macro"))
+ val wrapped = Apply(nucleus, payload map { case (k, v) => Assign(pickleAtom(k), pickleAtom(v)) })
+ val pickle = gen.mkTypeApply(wrapped, treeInfo.typeArguments(macroImplRef.duplicate))
+
+ // assign NoType to all freshly created AST nodes
+ // otherwise pickler will choke on tree.tpe being null
+ // there's another gotcha
+ // if you don't assign a ConstantType to a constant
+ // then pickling will crash
+ new Transformer {
+ override def transform(tree: Tree) = {
+ tree match {
+ case Literal(const @ Constant(x)) if tree.tpe == null => tree setType ConstantType(const)
+ case _ if tree.tpe == null => tree setType NoType
+ case _ => ;
+ }
+ super.transform(tree)
+ }
+ }.transform(pickle)
+ }
+
+ def unpickle(pickle: Tree): MacroImplBinding = {
+ val (wrapped, targs) =
+ pickle match {
+ case TypeApply(wrapped, targs) => (wrapped, targs)
+ case wrapped => (wrapped, Nil)
+ }
+ val Apply(_, pickledPayload) = wrapped
+ val payload = pickledPayload.map{ case Assign(k, v) => (unpickleAtom(k), unpickleAtom(v)) }.toMap
+
+ val pickleVersionFormat = payload("versionFormat").asInstanceOf[Int]
+ if (versionFormat != pickleVersionFormat) throw new Error("macro impl binding format mismatch: expected $versionFormat, actual $pickleVersionFormat")
+
+ val className = payload("className").asInstanceOf[String]
+ val methodName = payload("methodName").asInstanceOf[String]
+ val signature = payload("signature").asInstanceOf[List[Int]]
+ MacroImplBinding(className, methodName, signature, targs)
+ }
+ }
+
+ private def bindMacroImpl(macroDef: Symbol, macroImplRef: Tree): Unit = {
+ val pickle = MacroImplBinding.pickle(macroImplRef)
+ macroDef withAnnotation AnnotationInfo(MacroImplAnnotation.tpe, List(pickle), Nil)
+ }
+
+ private def loadMacroImplBinding(macroDef: Symbol): MacroImplBinding = {
+ val Some(AnnotationInfo(_, List(pickle), _)) = macroDef.getAnnotation(MacroImplAnnotation)
+ MacroImplBinding.unpickle(pickle)
+ }
+
/** A list of compatible macro implementation signatures.
*
* In the example above:
@@ -144,32 +310,22 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroTraceVerbose("macroImplSigs are: ")(paramsss, implRetTpe)
}
- private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Option[Symbol]): List[List[Symbol]] = {
- if (paramss.length == 0)
+ private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = {
+ import definitions.{ AbsTypeTagClass, MacroContextClass }
+ if (paramss.isEmpty || paramss.last.isEmpty)
return paramss
- val wannabe = if (paramss.head.length == 1) paramss.head.head else NoSymbol
- val contextParam = if (wannabe != NoSymbol && wannabe.tpe <:< definitions.MacroContextClass.tpe) wannabe else NoSymbol
-
- val lastParamList0 = paramss.lastOption getOrElse Nil
- val lastParamList = lastParamList0 flatMap (param => param.tpe match {
- case TypeRef(SingleType(NoPrefix, contextParam), sym, List(tparam)) =>
- var wannabe = sym
- while (wannabe.isAliasType) wannabe = wannabe.info.typeSymbol
- if (wannabe != definitions.AbsTypeTagClass)
- List(param)
- else
- transform(param, tparam.typeSymbol) map (_ :: Nil) getOrElse Nil
- case _ =>
- List(param)
- })
-
- var result = paramss.dropRight(1) :+ lastParamList
- if (lastParamList0.isEmpty ^ lastParamList.isEmpty) {
- result = result dropRight 1
+ val ContextParam = paramss.head match {
+ case p :: Nil => p filter (_.tpe <:< definitions.MacroContextClass.tpe)
+ case _ => NoSymbol
}
-
- result
+ def isTag(sym: Symbol): Boolean = (sym == AbsTypeTagClass) || (sym.isAliasType && isTag(sym.info.typeSymbol))
+ def transformTag(param: Symbol): Symbol = param.tpe match {
+ case TypeRef(SingleType(NoPrefix, ContextParam), sym, tp :: Nil) if isTag(sym) => transform(param, tp.typeSymbol)
+ case _ => param
+ }
+ val last = paramss.last map transformTag filterNot (_ eq NoSymbol)
+ if (last.isEmpty) paramss.init else paramss.init :+ last
}
/** As specified above, body of a macro definition must reference its implementation.
@@ -186,6 +342,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
import typer.context
macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos))
+ val macroDef = ddef.symbol
+ val defpos = macroDef.pos
+ val implpos = ddef.rhs.pos
+ assert(macroDef.isTermMacro, ddef)
+
if (fastTrack contains ddef.symbol) {
macroLogVerbose("typecheck terminated unexpectedly: macro is hardwired")
assert(!ddef.tpt.isEmpty, "hardwired macros must provide result type")
@@ -207,17 +368,18 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
}
- var hasErrors = false
+ var _hasError = false
+ def hasError = _hasError
+ def setError(): Unit = {
+ _hasError = true
+ macroDef setFlag IS_ERROR
+ }
def reportError(pos: Position, msg: String) = {
- hasErrors = true
+ setError()
context.error(pos, msg)
+ macroDef setFlag IS_ERROR
}
- val macroDef = ddef.symbol
- val defpos = macroDef.pos
- val implpos = ddef.rhs.pos
- assert(macroDef.isTermMacro, ddef)
-
def invalidBodyError() =
reportError(defpos,
"macro body has wrong shape:" +
@@ -275,7 +437,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val rhs = ddef.rhs
validatePreTyper(rhs)
- if (hasErrors) macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ if (hasError) macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
// we use typed1 instead of typed, because otherwise adapt is going to mess us up
// if adapt sees <qualifier>.<method>, it will want to perform eta-expansion and will fail
@@ -284,7 +446,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
def typecheckRhs(rhs: Tree): Tree = {
try {
val prevNumErrors = reporter.ERROR.count // [Eugene] funnily enough, the isErroneous check is not enough
- var rhs1 = if (hasErrors) EmptyTree else typer.typed1(rhs, EXPRmode, WildcardType)
+ var rhs1 = if (hasError) EmptyTree else typer.typed1(rhs, EXPRmode, WildcardType)
def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
def rhsNeedsMacroExpansion = rhs1.symbol != null && rhs1.symbol.isTermMacro && !rhs1.symbol.isErroneous
while (!typecheckedWithErrors && rhsNeedsMacroExpansion) {
@@ -313,35 +475,41 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val prevNumErrors = reporter.ERROR.count // funnily enough, the isErroneous check is not enough
var rhs1 = typecheckRhs(rhs)
- def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
- hasErrors = hasErrors || typecheckedWithErrors
- if (typecheckedWithErrors) macroTraceVerbose("body of a macro def failed to typecheck: ")(ddef)
-
val macroImpl = rhs1.symbol
- macroDef withAnnotation AnnotationInfo(MacroImplAnnotation.tpe, List(rhs1), Nil)
- if (!hasErrors) {
- if (macroImpl == null) {
- invalidBodyError()
- } else {
- if (!macroImpl.isMethod)
+ def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
+ if (typecheckedWithErrors) {
+ setError()
+ macroTraceVerbose("body of a macro def failed to typecheck: ")(ddef)
+ } else {
+ if (!hasError) {
+ if (macroImpl == null) {
invalidBodyError()
- if (macroImpl.isOverloaded)
- reportError(implpos, "macro implementation cannot be overloaded")
- if (!macroImpl.typeParams.isEmpty && (!rhs1.isInstanceOf[TypeApply]))
- reportError(implpos, "macro implementation reference needs type arguments")
- if (!hasErrors)
- validatePostTyper(rhs1)
+ } else {
+ if (!macroImpl.isMethod)
+ invalidBodyError()
+ if (!macroImpl.isPublic)
+ reportError(implpos, "macro implementation must be public")
+ if (macroImpl.isOverloaded)
+ reportError(implpos, "macro implementation cannot be overloaded")
+ if (!macroImpl.typeParams.isEmpty && (!rhs1.isInstanceOf[TypeApply]))
+ reportError(implpos, "macro implementation reference needs type arguments")
+ if (!hasError)
+ validatePostTyper(rhs1)
+ }
+ if (hasError)
+ macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ }
+ if (!hasError) {
+ bindMacroImpl(macroDef, rhs1) // we must bind right over here, because return type inference needs this info
}
- if (hasErrors)
- macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
}
- if (!hasErrors) {
+ if (!hasError) {
def checkCompatibility(reqparamss: List[List[Symbol]], actparamss: List[List[Symbol]], reqres: Type, actres: Type): List[String] = {
- var hasErrors = false
+ var hasError = false
var errors = List[String]()
def compatibilityError(msg: String) {
- hasErrors = true
+ hasError = true
errors :+= msg
}
@@ -364,7 +532,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
}
- if (!hasErrors) {
+ if (!hasError) {
try {
for ((rparams, aparams) <- reqparamss zip actparamss) {
if (rparams.length < aparams.length)
@@ -374,7 +542,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
// if the implementation signature is already deemed to be incompatible, we bail out
// otherwise, high-order type magic employed below might crash in weird ways
- if (!hasErrors) {
+ if (!hasError) {
for ((rparams, aparams) <- reqparamss zip actparamss) {
for ((rparam, aparam) <- rparams zip aparams) {
def isRepeated(param: Symbol) = param.tpe.typeSymbol == RepeatedParamClass
@@ -387,7 +555,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
compatibilityError("types incompatible for parameter "+rparam.name+": corresponding is not a vararg parameter")
if (!isRepeated(rparam) && isRepeated(aparam))
compatibilityError("types incompatible for parameter "+aparam.name+": corresponding is not a vararg parameter")
- if (!hasErrors) {
+ if (!hasError) {
var atpe = aparam.tpe.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars)
atpe = atpe.dealias // SI-5706
// strip the { type PrefixType = ... } refinement off the Context or otherwise we get compatibility errors
@@ -400,11 +568,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
}
}
- if (!hasErrors) {
+ if (!hasError) {
val atpe = actres.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars)
checkSubType("return type", atpe, reqres)
}
- if (!hasErrors) {
+ if (!hasError) {
val targs = solvedTypes(tvars, tparams, tparams map varianceInType(actres), false,
lubDepth(flatactparams map (_.tpe)) max lubDepth(flatreqparams map (_.tpe)))
val boundsOk = typer.silent(_.infer.checkBounds(ddef, NoPrefix, NoSymbol, tparams, targs, ""))
@@ -429,7 +597,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
var actparamss = macroImpl.paramss
- actparamss = transformTypeTagEvidenceParams(actparamss, (param, tparam) => None)
+ actparamss = transformTypeTagEvidenceParams(actparamss, (param, tparam) => NoSymbol)
val rettpe = if (!ddef.tpt.isEmpty) typer.typedType(ddef.tpt).tpe else computeMacroDefTypeFromMacroImpl(ddef, macroDef, macroImpl)
val (reqparamsss0, reqres0) = macroImplSigs(macroDef, ddef.tparams, ddef.vparamss, rettpe)
@@ -443,7 +611,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
}
- if (!hasErrors) {
+ if (!hasError) {
val reqres = reqres0
val actres = macroImpl.tpe.finalResultType
def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = {
@@ -482,15 +650,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
}
- // if this macro definition is erroneous, then there's no sense in expanding its usages
- // in the previous prototype macro implementations were magically generated from macro definitions
- // so macro definitions and its usages couldn't be compiled in the same compilation run
- // however, now definitions and implementations are decoupled, so it's everything is possible
- // hence, we now use IS_ERROR flag to serve as an indicator that given macro definition is broken
- if (hasErrors) {
- macroDef setFlag IS_ERROR
- }
-
rhs1
}
@@ -526,17 +685,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// sym.paramPos is unreliable (see another case below)
val tparams = macroImpl.typeParams map (_.deSkolemize)
val paramPos = tparams indexOf sym.deSkolemize
- val sym1 = if (paramPos == -1) sym else {
- val ann = macroDef.getAnnotation(MacroImplAnnotation)
- ann match {
- case Some(ann) =>
- val TypeApply(_, implRefTargs) = ann.args(0)
- val implRefTarg = implRefTargs(paramPos).tpe.typeSymbol
- implRefTarg
- case None =>
- sym
- }
- }
+ val sym1 =
+ if (paramPos == -1) sym
+ else loadMacroImplBinding(macroDef).targs(paramPos).tpe.typeSymbol
TypeRef(pre, sym1, args)
case tpe =>
tpe
@@ -550,7 +701,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// val defParamss = macroDef.paramss
val defParamss = mmap(macroDdef.vparamss)(_.symbol)
var implParamss = macroImpl.paramss
- implParamss = transformTypeTagEvidenceParams(implParamss, (param, tparam) => None)
+ implParamss = transformTypeTagEvidenceParams(implParamss, (param, tparam) => NoSymbol)
val implCtxParam = if (implParamss.length > 0 && implParamss(0).length > 0) implParamss(0)(0) else null
def implParamToDefParam(implParam: Symbol): Symbol = {
@@ -619,118 +770,42 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* 3) Loads the companion of that enclosing class from the macro classloader.
* 4) Resolves macro implementation within the loaded companion.
*
- * @return Some(runtime) if macro implementation can be loaded successfully from either of the mirrors,
- * None otherwise.
+ * @return Requested runtime if macro implementation can be loaded successfully from either of the mirrors,
+ * null otherwise.
*/
type MacroRuntime = List[Any] => Any
- private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, Option[MacroRuntime]]
- private def macroRuntime(macroDef: Symbol): Option[MacroRuntime] = {
+ private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, MacroRuntime]
+ private def macroRuntime(macroDef: Symbol): MacroRuntime = {
macroTraceVerbose("looking for macro implementation: ")(macroDef)
if (fastTrack contains macroDef) {
macroLogVerbose("macro expansion is serviced by a fast track")
- Some(fastTrack(macroDef))
+ fastTrack(macroDef)
} else {
macroRuntimesCache.getOrElseUpdate(macroDef, {
- val runtime = {
- macroTraceVerbose("macroDef is annotated with: ")(macroDef.annotations)
-
- val ann = macroDef.getAnnotation(MacroImplAnnotation)
- if (ann == None) { macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef); return None }
-
- val macroImpl = ann.get.args(0).symbol
- if (macroImpl == NoSymbol) { macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef); return None }
- macroLogVerbose("resolved implementation %s at %s".format(macroImpl, macroImpl.pos))
- if (macroImpl.isErroneous) { macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef); return None }
-
- // [Eugene++] I don't use Scala reflection here, because it seems to interfere with JIT magic
- // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20%
- // I'm not sure what's the reason - for me it's pure voodoo
- def loadMacroImpl(cl: ClassLoader): Option[(Object, jMethod)] = {
- try {
- // this logic relies on the assumptions that were valid for the old macro prototype
- // namely that macro implementations can only be defined in top-level classes and modules
- // with the new prototype that materialized in a SIP, macros need to be statically accessible, which is different
- // for example, a macro def could be defined in a trait that is implemented by an object
- // there are some more clever cases when seemingly non-static method ends up being statically accessible
- // however, the code below doesn't account for these guys, because it'd take a look of time to get it right
- // for now I leave it as a todo and move along to more the important stuff
-
- macroTraceVerbose("loading implementation class: ")(macroImpl.owner.fullName)
- macroTraceVerbose("classloader is: ")(ReflectionUtils.show(cl))
-
- // [Eugene] relies on the fact that macro implementations can only be defined in static classes
- // [Martin to Eugene++] There's similar logic buried in Symbol#flatname. Maybe we can refactor?
- def classfile(sym: Symbol): String = {
- def recur(sym: Symbol): String = sym match {
- case sym if sym.owner.isPackageClass =>
- val suffix = if (sym.isModuleClass) "$" else ""
- sym.fullName + suffix
- case sym =>
- val separator = if (sym.owner.isModuleClass) "" else "$"
- recur(sym.owner) + separator + sym.javaSimpleName.toString
- }
-
- if (sym.isClass || sym.isModule) recur(sym)
- else recur(sym.enclClass)
- }
-
- // [Eugene++] this doesn't work for inner classes
- // neither does macroImpl.owner.javaClassName, so I had to roll my own implementation
- //val receiverName = macroImpl.owner.fullName
- val implClassName = classfile(macroImpl.owner)
- val implObj = try {
- val implObjClass = jClass.forName(implClassName, true, cl)
- implObjClass getField "MODULE$" get null
- } catch {
- case ex: NoSuchFieldException => macroTraceVerbose("exception when loading implObj: ")(ex); null
- case ex: NoClassDefFoundError => macroTraceVerbose("exception when loading implObj: ")(ex); null
- case ex: ClassNotFoundException => macroTraceVerbose("exception when loading implObj: ")(ex); null
- }
-
- if (implObj == null) None
- else {
- // [Eugene++] doh, it seems that I need to copy/paste Scala reflection logic
- // see `JavaMirrors.methodToJava` or whatever it's called now
- val implMeth = {
- def typeToJavaClass(tpe: Type): jClass[_] = tpe match {
- case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
- case TypeRef(_, ArrayClass, List(elemtpe)) => jArray.newInstance(typeToJavaClass(elemtpe), 0).getClass
- case TypeRef(_, sym: ClassSymbol, _) => jClass.forName(classfile(sym), true, cl)
- case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
- }
-
- val paramClasses = transformedType(macroImpl).paramTypes map typeToJavaClass
- try implObj.getClass getDeclaredMethod (macroImpl.name.toString, paramClasses: _*)
- catch {
- case ex: NoSuchMethodException =>
- val expandedName =
- if (macroImpl.isPrivate) nme.expandedName(macroImpl.name.toTermName, macroImpl.owner).toString
- else macroImpl.name.toString
- implObj.getClass getDeclaredMethod (expandedName, paramClasses: _*)
- }
- }
- macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMeth))
- Some((implObj, implMeth))
- }
- } catch {
- case ex: ClassNotFoundException =>
- macroTraceVerbose("implementation class failed to load: ")(ex.toString)
- None
- case ex: NoSuchMethodException =>
- macroTraceVerbose("implementation method failed to load: ")(ex.toString)
- None
- }
- }
-
- loadMacroImpl(macroClassloader) map {
- case (implObj, implMeth) =>
- def runtime(args: List[Any]) = implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*).asInstanceOf[Any]
- runtime _
- }
+ val binding = loadMacroImplBinding(macroDef)
+ val className = binding.className
+ val methName = binding.methName
+ macroLogVerbose(s"resolved implementation as $className.$methName")
+
+ // [Eugene++] I don't use Scala reflection here, because it seems to interfere with JIT magic
+ // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20%
+ // I'm not sure what's the reason - for me it's pure voodoo
+ try {
+ macroTraceVerbose("loading implementation class: ")(className)
+ macroTraceVerbose("classloader is: ")(ReflectionUtils.show(macroClassloader))
+ val implObj = ReflectionUtils.staticSingletonInstance(macroClassloader, className)
+ // relies on the fact that macro impls cannot be overloaded
+ // so every methName can resolve to at maximum one method
+ val implMeths = implObj.getClass.getDeclaredMethods.find(_.getName == methName)
+ val implMeth = implMeths getOrElse { throw new NoSuchMethodException(s"$className.$methName") }
+ macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMeth))
+ (args: List[Any]) => implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*)
+ } catch {
+ case ex: Exception =>
+ macroTraceVerbose(s"macro runtime failed to load: ")(ex.toString)
+ macroDef setFlag IS_ERROR
+ null
}
-
- if (runtime == None) macroDef setFlag IS_ERROR
- runtime
})
}
}
@@ -755,7 +830,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
*/
private def macroArgs(typer: Typer, expandee: Tree): Option[List[Any]] = {
val macroDef = expandee.symbol
- val runtime = macroRuntime(macroDef) orElse { return None }
val prefixTree = expandee.collect{ case Select(qual, name) => qual }.headOption.getOrElse(EmptyTree)
val context = expandee.attachments.get[MacroRuntimeAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee))
var typeArgs = List[Tree]()
@@ -771,6 +845,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
case _ =>
}
collectMacroArgs(expandee)
+
+ val argcDoesntMatch = macroDef.paramss.length != exprArgs.length
+ val nullaryArgsEmptyParams = exprArgs.isEmpty && macroDef.paramss == List(List())
+ if (argcDoesntMatch && !nullaryArgsEmptyParams) { typer.TyperErrorGen.MacroPartialApplicationError(expandee); return None }
+
var argss: List[List[Any]] = List(context) :: exprArgs.toList
macroTraceVerbose("argss: ")(argss)
val rawArgss =
@@ -787,33 +866,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
return None
}
} else {
- val ann = macroDef.getAnnotation(MacroImplAnnotation).getOrElse(throw new Error("assertion failed. %s: %s".format(macroDef, macroDef.annotations)))
- val macroImpl = ann.args(0).symbol
- var paramss = macroImpl.paramss
- val tparams = macroImpl.typeParams
- macroTraceVerbose("paramss: ")(paramss)
-
- // we need to take care of all possible combos of nullary/empty-paramlist macro defs vs nullary/empty-arglist invocations
- // nullary def + nullary invocation => paramss and argss match, everything is okay
- // nullary def + empty-arglist invocation => illegal Scala code, impossible, everything is okay
- // empty-paramlist def + nullary invocation => uh-oh, we need to append a List() to argss
- // empty-paramlist def + empty-arglist invocation => paramss and argss match, everything is okay
- // that's almost it, but we need to account for the fact that paramss might have context bounds that mask the empty last paramlist
- val paramss_without_evidences = transformTypeTagEvidenceParams(paramss, (param, tparam) => None)
- val isEmptyParamlistDef = paramss_without_evidences.nonEmpty && paramss_without_evidences.last.isEmpty
- val isEmptyArglistInvocation = argss.nonEmpty && argss.last.isEmpty
- if (isEmptyParamlistDef && !isEmptyArglistInvocation) {
- macroLogVerbose("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss")
- argss = argss :+ Nil
- }
-
- // nb! check partial application against paramss without evidences
- val numParamLists = paramss_without_evidences.length
- val numArgLists = argss.length
- if (numParamLists != numArgLists) {
- typer.TyperErrorGen.MacroPartialApplicationError(expandee)
- return None
- }
+ val binding = loadMacroImplBinding(macroDef)
+ macroTraceVerbose("binding: ")(binding)
// if paramss have typetag context bounds, add an arglist to argss if necessary and instantiate the corresponding evidences
// consider the following example:
@@ -831,43 +885,41 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// then T and U need to be inferred from the lexical scope of the call using ``asSeenFrom''
// whereas V won't be resolved by asSeenFrom and need to be loaded directly from ``expandee'' which needs to contain a TypeApply node
// also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim
- val resolved = collection.mutable.Map[Symbol, Type]()
- paramss = transformTypeTagEvidenceParams(paramss, (param, tparam) => {
- val TypeApply(_, implRefTargs) = ann.args(0)
- var implRefTarg = implRefTargs(tparam.paramPos).tpe.typeSymbol
- val tpe = if (implRefTarg.isTypeParameterOrSkolem) {
- if (implRefTarg.owner == macroDef) {
+ val tags = binding.signature filter (_ != -1) map (paramPos => {
+ val targ = binding.targs(paramPos).tpe.typeSymbol
+ val tpe = if (targ.isTypeParameterOrSkolem) {
+ if (targ.owner == macroDef) {
// [Eugene] doesn't work when macro def is compiled separately from its usages
- // then implRefTarg is not a skolem and isn't equal to any of macroDef.typeParams
- // val paramPos = implRefTarg.deSkolemize.paramPos
- val paramPos = macroDef.typeParams.indexWhere(_.name == implRefTarg.name)
- typeArgs(paramPos).tpe
+ // then targ is not a skolem and isn't equal to any of macroDef.typeParams
+ // val argPos = targ.deSkolemize.paramPos
+ val argPos = macroDef.typeParams.indexWhere(_.name == targ.name)
+ typeArgs(argPos).tpe
} else
- implRefTarg.tpe.asSeenFrom(
+ targ.tpe.asSeenFrom(
if (prefixTree == EmptyTree) macroDef.owner.tpe else prefixTree.tpe,
macroDef.owner)
} else
- implRefTarg.tpe
- macroLogVerbose("resolved tparam %s as %s".format(tparam, tpe))
- resolved(tparam) = tpe
- param.tpe.typeSymbol match {
- case definitions.AbsTypeTagClass =>
- // do nothing
- case _ =>
- throw new Error("unsupported tpe: " + tpe)
- }
- Some(tparam)
+ targ.tpe
+ if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe)
+ })
+ val hasImplicitParams = macroDef.paramss.flatten.lastOption exists (_.isImplicit)
+ argss = if (hasImplicitParams) argss.dropRight(1) :+ (tags ++ argss.last) else argss :+ tags
+
+ // transforms argss taking into account varargness of paramss
+ // not all argument lists in argss map to macroDef.paramss, so we need to apply extra care
+ // namely:
+ // 1) the first argument list represents (c: Context) in macroImpl, so it doesn't have correspondence in macroDef
+ // 2) typetag context bounds are only declared on macroImpls, so this optional arglist also doesn't match macroDef
+ // nb! varargs can apply to any parameter section, not necessarily to the last one
+ mapWithIndex(argss)((as, i_argss) => {
+ val i_paramss = i_argss - 1
+ val mapsToParamss = 0 <= i_paramss && i_paramss < macroDef.paramss.length
+ if (mapsToParamss) {
+ val ps = macroDef.paramss(i_paramss)
+ if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1)
+ else as
+ } else as
})
- val tags = paramss.last takeWhile (_.isType) map (resolved(_)) map (tpe => if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe))
- if (paramss.lastOption map (params => !params.isEmpty && params.forall(_.isType)) getOrElse false) argss = argss :+ Nil
- argss = argss.dropRight(1) :+ (tags ++ argss.last) // todo. add support for context bounds in argss
-
- assert(argss.length == paramss.length, "argss: %s, paramss: %s".format(argss, paramss))
- val rawArgss = for ((as, ps) <- argss zip paramss) yield {
- if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1)
- else as
- }
- rawArgss
}
val rawArgs = rawArgss.flatten
macroTraceVerbose("rawArgs: ")(rawArgs)
@@ -996,12 +1048,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
return Cancel(typer.infer.setError(expandee))
}
- macroRuntime(expandee.symbol) match {
- case Some(runtime) =>
- macroExpandWithRuntime(typer, expandee, runtime)
- case None =>
- macroExpandWithoutRuntime(typer, expandee)
- }
+ val runtime = macroRuntime(expandee.symbol)
+ if (runtime != null) macroExpandWithRuntime(typer, expandee, runtime)
+ else macroExpandWithoutRuntime(typer, expandee)
}
/** Expands a macro when a runtime (i.e. the macro implementation) can be successfully loaded
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index b817ec7b5e..fc9cb02d37 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -556,7 +556,7 @@ trait Namers extends MethodSynthesis {
// via "x$lzy" as can be seen in test #3927.
val sym = (
if (owner.isClass) createFieldSymbol(tree)
- else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, (tree.mods.flags | HIDDEN) & ~IMPLICIT)
+ else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, (tree.mods.flags | ARTIFACT) & ~IMPLICIT)
)
enterValSymbol(tree, sym setFlag MUTABLE setLazyAccessor lazyAccessor)
}
@@ -577,7 +577,7 @@ trait Namers extends MethodSynthesis {
case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) =>
assignAndEnterFinishedSymbol(tree)
case DefDef(mods, name, tparams, _, _, _) =>
- val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | HIDDEN else 0
+ val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0
val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag
if (name == nme.copy && sym.isSynthetic)
@@ -988,6 +988,15 @@ trait Namers extends MethodSynthesis {
// (either "macro ???" as they used to or just "???" to maximally simplify their compilation)
if (fastTrack contains ddef.symbol) ddef.symbol setFlag MACRO
+ // macro defs need to be typechecked in advance
+ // because @macroImpl annotation only gets assigned during typechecking
+ // otherwise macro defs wouldn't be able to robustly coexist with their clients
+ // because a client could be typechecked before a macro def that it uses
+ if (ddef.symbol.isTermMacro) {
+ val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
+ typer.computeMacroDefType(ddef, pt)
+ }
+
thisMethodType({
val rt = (
if (!tpt.isEmpty) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 3bae4d8a46..74acaba74a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -164,7 +164,7 @@ trait NamesDefaults { self: Analyzer =>
// never used for constructor calls, they always have a stable qualifier
def blockWithQualifier(qual: Tree, selected: Name) = {
- val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = HIDDEN) setInfo qual.tpe
+ val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo qual.tpe
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
// it stays in Vegas: SI-5720, SI-5727
@@ -281,7 +281,7 @@ trait NamesDefaults { self: Analyzer =>
}
else arg.tpe
).widen // have to widen or types inferred from literal defaults will be singletons
- val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = HIDDEN) setInfo (
+ val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo (
if (byName) functionType(Nil, argTpe) else argTpe
)
(context.scope.enter(s), byName, repeated)
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 1e5f8cb604..b11b327648 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc
package typechecker
import symtab._
-import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC, HIDDEN}
+import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC, ARTIFACT}
import language.postfixOps
import scala.tools.nsc.transform.TypingTransformers
import scala.tools.nsc.transform.Transform
@@ -67,10 +67,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
object exceeded extends Exception {
val advice = s"(The analysis required more space than allowed. Please try with scalac -Dscalac.patmat.analysisBudget=${AnalysisBudget.max*2} or -Dscalac.patmat.analysisBudget=off.)"
}
-
- object stackOverflow extends Exception {
- val advice = "(There was a stack overflow. Please try increasing the stack available to the compiler using e.g., -Xss2m.)"
- }
}
def newTransformer(unit: CompilationUnit): Transformer =
@@ -521,7 +517,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// case Star(_) | ArrayValue => error("stone age pattern relics encountered!")
case _ =>
- error("unsupported pattern: "+ patTree +"(a "+ patTree.getClass +")")
+ typer.context.unit.error(patTree.pos, s"unsupported pattern: $patTree (a ${patTree.getClass}).\n This is a scalac bug. Tree diagnostics: ${asCompactDebugString(patTree)}.")
noFurtherSubPats()
}
@@ -1147,7 +1143,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix`
// if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor?
- val outer = expectedTp.typeSymbol.newMethod(vpmName.outer) setInfo expectedTp.prefix setFlag SYNTHETIC | HIDDEN
+ val outer = expectedTp.typeSymbol.newMethod(vpmName.outer) setInfo expectedTp.prefix setFlag SYNTHETIC | ARTIFACT
(Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter
}
@@ -2056,21 +2052,29 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def Lit(sym: Sym, pos: Boolean = true): Lit
// throws an AnalysisBudget.Exception when the prop results in a CNF that's too big
+ // TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding)
def eqFreePropToSolvable(p: Prop): Formula = {
- // TODO: for now, reusing the normalization from DPLL
- def negationNormalForm(p: Prop): Prop = p match {
- case And(a, b) => And(negationNormalForm(a), negationNormalForm(b))
- case Or(a, b) => Or(negationNormalForm(a), negationNormalForm(b))
- case Not(And(a, b)) => negationNormalForm(Or(Not(a), Not(b)))
- case Not(Or(a, b)) => negationNormalForm(And(Not(a), Not(b)))
- case Not(Not(p)) => negationNormalForm(p)
- case Not(True) => False
- case Not(False) => True
- case True
- | False
- | (_ : Sym)
- | Not(_ : Sym) => p
- }
+ def negationNormalFormNot(p: Prop, budget: Int = AnalysisBudget.max): Prop =
+ if (budget <= 0) throw AnalysisBudget.exceeded
+ else p match {
+ case And(a, b) => Or(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1))
+ case Or(a, b) => And(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1))
+ case Not(p) => negationNormalForm(p, budget - 1)
+ case True => False
+ case False => True
+ case s: Sym => Not(s)
+ }
+
+ def negationNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Prop =
+ if (budget <= 0) throw AnalysisBudget.exceeded
+ else p match {
+ case And(a, b) => And(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1))
+ case Or(a, b) => Or(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1))
+ case Not(negated) => negationNormalFormNot(negated, budget - 1)
+ case True
+ | False
+ | (_ : Sym) => p
+ }
val TrueF = formula()
val FalseF = formula(clause())
@@ -2113,12 +2117,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
val start = Statistics.startTimer(patmatCNF)
- val res =
- try {
- conjunctiveNormalForm(negationNormalForm(p))
- } catch { case ex : StackOverflowError =>
- throw AnalysisBudget.stackOverflow
- }
+ val res = conjunctiveNormalForm(negationNormalForm(p))
Statistics.stopTimer(patmatCNF, start)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index d0fbc7043e..3507bc4e09 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -172,7 +172,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe)
- val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE | HIDDEN) setPos clazz.pos
+ val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE | ARTIFACT) setPos clazz.pos
bridge.setInfo(bridgetpe.cloneInfo(bridge))
clazz.info.decls enter bridge
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 5e511591f3..2a71295690 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -61,7 +61,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val supername = nme.superName(name)
val superAcc = clazz.info.decl(supername).suchThat(_.alias == sym) orElse {
debuglog(s"add super acc ${sym.fullLocationString} to $clazz")
- val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | HIDDEN) setAlias sym
+ val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | ARTIFACT) setAlias sym
val tpe = clazz.thisType memberType sym match {
case t if sym.isModule && !sym.isMethod => NullaryMethodType(t)
case t => t
@@ -387,7 +387,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
val protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s)) orElse {
- val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = HIDDEN)
+ val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = ARTIFACT)
newAcc setInfoAndEnter accType(newAcc)
val code = DefDef(newAcc, {
@@ -449,7 +449,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
val accName = nme.protSetterName(field.originalName)
val protectedAccessor = clazz.info decl accName orElse {
- val protAcc = clazz.newMethod(accName, field.pos, newFlags = HIDDEN)
+ val protAcc = clazz.newMethod(accName, field.pos, newFlags = ARTIFACT)
val paramTypes = List(clazz.typeOfThis, field.tpe)
val params = protAcc newSyntheticValueParams paramTypes
val accessorType = MethodType(params, UnitClass.tpe)
diff --git a/src/ensime/.ensime.SAMPLE b/src/ensime/.ensime.SAMPLE
new file mode 100644
index 0000000000..10801816b7
--- /dev/null
+++ b/src/ensime/.ensime.SAMPLE
@@ -0,0 +1,17 @@
+(
+ :disable-source-load-on-startup t
+ :disable-scala-jars-on-classpath t
+ :root-dir "c:/Projects/Kepler"
+ :sources (
+ "c:/Projects/Kepler/src/library"
+ "c:/Projects/Kepler/src/reflect"
+ "c:/Projects/Kepler/src/compiler"
+ )
+ :compile-deps (
+ "c:/Projects/Kepler/build/asm/classes"
+ "c:/Projects/Kepler/build/locker/classes/library"
+ "c:/Projects/Kepler/build/locker/classes/reflect"
+ "c:/Projects/Kepler/build/locker/classes/compiler"
+ )
+ :target "c:/Projects/Kepler/build/classes"
+) \ No newline at end of file
diff --git a/src/ensime/README.md b/src/ensime/README.md
new file mode 100644
index 0000000000..302d47b8a7
--- /dev/null
+++ b/src/ensime/README.md
@@ -0,0 +1,11 @@
+Ensime project files
+=====================
+
+Rename .ensime.SAMPLE to .ensime and replace sample paths with real paths to your sources and build results.
+After that you're good to go with one of the ENSIME-enabled text editors.
+
+Editors that know how to talk to ENSIME servers:
+1) Emacs via https://github.com/aemoncannon/ensime
+2) jEdit via https://github.com/djspiewak/ensime-sidekick
+3) TextMate via https://github.com/mads379/ensime.tmbundle
+4) Sublime Text 2 via https://github.com/sublimescala/sublime-ensime
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 81db2d583a..3388d584db 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -92,6 +92,8 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
i - len
}
+ override /*IterableLike*/ def isEmpty: Boolean = lengthCompare(0) == 0
+
/** The size of this $coll, equivalent to `length`.
*
* $willNotTerminateInf
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index fda76c7b95..3415b0fa10 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -67,6 +67,11 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isSynthetic: Boolean
+ /** Does this symbol represent an implementation artifact that isn't meant for public use?
+ * Examples of such artifacts are erasure bridges and $outer fields.
+ */
+ def isImplementationArtifact: Boolean
+
/** Does this symbol represent a local declaration or definition?
*
* If yes, either `isPrivate` or `isProtected` are guaranteed to be true.
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index 0a848f8d67..906dfb95fb 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -342,7 +342,7 @@ object ClassfileConstants {
case JAVA_ACC_PRIVATE => PRIVATE
case JAVA_ACC_PROTECTED => PROTECTED
case JAVA_ACC_FINAL => FINAL
- case JAVA_ACC_SYNTHETIC => SYNTHETIC | HIDDEN // maybe should be just hidden?
+ case JAVA_ACC_SYNTHETIC => SYNTHETIC | ARTIFACT // maybe should be just artifact?
case JAVA_ACC_STATIC => STATIC
case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED
case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT
@@ -372,7 +372,7 @@ object ClassfileConstants {
}
def methodFlags(jflags: Int): Long = {
initFields(jflags)
- translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | HIDDEN else 0)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0)
}
}
object FlagTranslation extends FlagTranslation { }
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 86355bbb7f..f01247d918 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -852,8 +852,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL)
lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL)
lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL)
- lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | HIDDEN)(_ => booltype)
- lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC | HIDDEN)(_.typeConstructor)
+ lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_ => booltype)
+ lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_.typeConstructor)
lazy val Object_synchronized = newPolyMethod(1, ObjectClass, nme.synchronized_, FINAL)(tps =>
(Some(List(tps.head.typeConstructor)), tps.head.typeConstructor)
)
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 3f4f24a9f4..f021a9eebd 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -116,9 +116,9 @@ class ModifierFlags {
final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer
final val PRESUPER = 1L << 37 // value is evaluated before super call
final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit
- final val HIDDEN = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode
+ final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode
- /** Symbols which are marked HIDDEN. (Expand this list?)
+ /** Symbols which are marked ARTIFACT. (Expand this list?)
*
* - $outer fields and accessors
* - super accessors
@@ -128,7 +128,7 @@ class ModifierFlags {
* - default argument getters
* - evaluation-order preserving locals for right-associative and out-of-order named arguments
* - catch-expression storing vals
- * - anything else which feels a setFlag(HIDDEN)
+ * - anything else which feels a setFlag(ARTIFACT)
*/
// Overridden.
@@ -149,7 +149,7 @@ class Flags extends ModifierFlags {
final val CAPTURED = 1 << 16 // variable is accessed from nested function. Set by LambdaLift.
final val LABEL = 1 << 17 // method symbol is a label. Set by TailCall
final val INCONSTRUCTOR = 1 << 17 // class symbol is defined in this/superclass constructor.
- final val SYNTHETIC = 1 << 21 // symbol is compiler-generated (compare with HIDDEN)
+ final val SYNTHETIC = 1 << 21 // symbol is compiler-generated (compare with ARTIFACT)
final val STABLE = 1 << 22 // functions that are assumed to be stable
// (typically, access methods for valdefs)
// or classes that do not contain abstract types.
@@ -231,7 +231,7 @@ class Flags extends ModifierFlags {
/** To be a little clearer to people who aren't habitual bit twiddlers.
*/
final val AllFlags = -1L
-
+
/** These flags can be set when class or module symbol is first created.
* They are the only flags to survive a call to resetFlags().
*/
@@ -261,7 +261,7 @@ class Flags extends ModifierFlags {
/** These modifiers appear in TreePrinter output. */
final val PrintableFlags =
ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
- ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | HIDDEN
+ ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | ARTIFACT
/** When a symbol for a field is created, only these flags survive
* from Modifiers. Others which may be applied at creation time are:
@@ -301,11 +301,11 @@ class Flags extends ModifierFlags {
/** These flags are not pickled */
final val FlagsNotPickled = IS_ERROR | OVERLOADED | LIFTED | TRANS_FLAG | LOCKED | TRIEDCOOKING
-
+
// A precaution against future additions to FlagsNotPickled turning out
// to be overloaded flags thus not-pickling more than intended.
assert((OverloadedFlagsMask & FlagsNotPickled) == 0, flagsToString(OverloadedFlagsMask & FlagsNotPickled))
-
+
/** These flags are pickled */
final val PickledFlags = InitialFlags & ~FlagsNotPickled
@@ -352,13 +352,13 @@ class Flags extends ModifierFlags {
(SEALED, SEALED_PKL),
(ABSTRACT, ABSTRACT_PKL)
)
-
+
private val mappedRawFlags = rawPickledCorrespondence map (_._1)
private val mappedPickledFlags = rawPickledCorrespondence map (_._2)
-
+
private class MapFlags(from: Array[Long], to: Array[Long]) extends (Long => Long) {
val fromSet = (0L /: from) (_ | _)
-
+
def apply(flags: Long): Long = {
var result = flags & ~fromSet
var tobeMapped = flags & fromSet
@@ -373,7 +373,7 @@ class Flags extends ModifierFlags {
result
}
}
-
+
val rawToPickledFlags: Long => Long = new MapFlags(mappedRawFlags, mappedPickledFlags)
val pickledToRawFlags: Long => Long = new MapFlags(mappedPickledFlags, mappedRawFlags)
@@ -427,7 +427,7 @@ class Flags extends ModifierFlags {
case VARARGS => "<varargs>" // (1L << 43)
case TRIEDCOOKING => "<triedcooking>" // (1L << 44)
case SYNCHRONIZED => "<synchronized>" // (1L << 45)
- case HIDDEN => "<hidden>" // (1L << 46)
+ case ARTIFACT => "<artifact>" // (1L << 46)
case 0x800000000000L => "" // (1L << 47)
case 0x1000000000000L => "" // (1L << 48)
case 0x2000000000000L => "" // (1L << 49)
@@ -447,7 +447,7 @@ class Flags extends ModifierFlags {
case 0x8000000000000000L => "" // (1L << 63)
case _ => ""
}
-
+
private def accessString(flags: Long, privateWithin: String)= (
if (privateWithin == "") {
if ((flags & PrivateLocal) == PrivateLocal) "private[this]"
@@ -459,7 +459,7 @@ class Flags extends ModifierFlags {
else if ((flags & PROTECTED) != 0) "protected[" + privateWithin + "]"
else "private[" + privateWithin + "]"
)
-
+
@deprecated("Use flagString on the flag-carrying member", "2.10.0")
def flagsToString(flags: Long, privateWithin: String): String = {
val access = accessString(flags, privateWithin)
diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala
index 7ead9d6a1b..62c8ed702b 100644
--- a/src/reflect/scala/reflect/internal/HasFlags.scala
+++ b/src/reflect/scala/reflect/internal/HasFlags.scala
@@ -66,7 +66,7 @@ trait HasFlags {
*/
def flagString: String = flagString(flagMask)
def flagString(mask: Long): String = calculateFlagString(flags & mask)
-
+
/** The default mask determining which flags to display.
*/
def flagMask: Long = AllFlags
@@ -92,7 +92,7 @@ trait HasFlags {
def isCaseAccessor = hasFlag(CASEACCESSOR)
def isDeferred = hasFlag(DEFERRED)
def isFinal = hasFlag(FINAL)
- def isHidden = hasFlag(HIDDEN)
+ def isArtifact = hasFlag(ARTIFACT)
def isImplicit = hasFlag(IMPLICIT)
def isInterface = hasFlag(INTERFACE)
def isJavaDefined = hasFlag(JAVA)
@@ -136,7 +136,7 @@ trait HasFlags {
def accessString: String = {
val pw = if (hasAccessBoundary) privateWithin.toString else ""
-
+
if (pw == "") {
if (hasAllFlags(PrivateLocal)) "private[this]"
else if (hasAllFlags(ProtectedLocal)) "protected[this]"
@@ -150,7 +150,7 @@ trait HasFlags {
protected def calculateFlagString(basis: Long): String = {
val access = accessString
val nonAccess = flagBitsToString(basis & ~AccessFlags)
-
+
if (access == "") nonAccess
else if (nonAccess == "") access
else nonAccess + " " + access
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index e8a011d4f9..5e83f638a2 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -66,6 +66,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isExistential: Boolean = this.isExistentiallyBound
def isParamWithDefault: Boolean = this.hasDefault
def isByNameParam: Boolean = this.isValueParameter && (this hasFlag BYNAMEPARAM)
+ def isImplementationArtifact: Boolean = (this hasFlag BRIDGE) || (this hasFlag VBRIDGE) || (this hasFlag ARTIFACT)
def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match {
case n: TermName => newTermSymbol(n, pos, newFlags)
@@ -698,13 +699,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this symbol an accessor method for outer? */
final def isOuterAccessor = {
- hasFlag(STABLE | HIDDEN) &&
+ hasFlag(STABLE | ARTIFACT) &&
originalName == nme.OUTER
}
/** Is this symbol an accessor method for outer? */
final def isOuterField = {
- hasFlag(HIDDEN) &&
+ hasFlag(ARTIFACT) &&
originalName == nme.OUTER_LOCAL
}
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 51dc2567f8..fa4a35cfe9 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -372,6 +372,13 @@ abstract class TreeInfo {
case _ => EmptyTree
}
+ /** If this tree represents a type application the type arguments. Otherwise Nil.
+ */
+ def typeArguments(tree: Tree): List[Tree] = tree match {
+ case TypeApply(_, targs) => targs
+ case _ => Nil
+ }
+
/** If this tree has type parameters, those. Otherwise Nil.
*/
def typeParameters(tree: Tree): List[TypeDef] = tree match {