summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-04-06 09:11:00 -0700
committerPaul Phillips <paulp@improving.org>2012-04-06 09:43:17 -0700
commit19bb1732646c77e58fd63490afdca066afd5ec15 (patch)
treece9280294f5aa13e4c6fcb2e37b9ffc4a099d3d4 /src/compiler
parentec1d28ee0dbd08f814984e95c3245c1d6fab79d8 (diff)
downloadscala-19bb1732646c77e58fd63490afdca066afd5ec15.tar.gz
scala-19bb1732646c77e58fd63490afdca066afd5ec15.tar.bz2
scala-19bb1732646c77e58fd63490afdca066afd5ec15.zip
Fix for SI-5644.
Don't let OverloadedTypes reach the backend. When you want a method from a particular symbol, avoid getMember, which may inflict upon you an OverloadedType if an inherited member has the same name. Instead, use the (just now appearing) definitions.getDecl.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala26
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/JavaPlatform.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala12
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala19
7 files changed, 59 insertions, 22 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 0224f9158e..e1740b621e 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -863,7 +863,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
// boxed classes
lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef")
lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef")
- lazy val BoxesRunTimeClass = getRequiredModule("scala.runtime.BoxesRunTime")
+ lazy val BoxesRunTimeModule = getRequiredModule("scala.runtime.BoxesRunTime")
+ lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass
lazy val BoxedNumberClass = getClass(sn.BoxedNumber)
lazy val BoxedCharacterClass = getClass(sn.BoxedCharacter)
lazy val BoxedBooleanClass = getClass(sn.BoxedBoolean)
@@ -874,6 +875,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val BoxedFloatClass = getRequiredClass("java.lang.Float")
lazy val BoxedDoubleClass = getRequiredClass("java.lang.Double")
+ lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean)
+ lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber)
+
lazy val BoxedUnitClass = getRequiredClass("scala.runtime.BoxedUnit")
lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit")
def BoxedUnit_UNIT = getMember(BoxedUnitModule, nme.UNIT)
@@ -990,12 +994,24 @@ trait Definitions extends reflect.api.StandardDefinitions {
else findNamedMember(segs.tail, root.info member segs.head)
def getMember(owner: Symbol, name: Name): Symbol = {
- if (owner == NoSymbol) NoSymbol
- else owner.info.nonPrivateMember(name) match {
- case NoSymbol => throw new FatalError(owner + " does not have a member " + name)
- case result => result
+ getMemberIfDefined(owner, name) orElse {
+ throw new FatalError(owner + " does not have a member " + name)
+ }
+ }
+ def getMemberIfDefined(owner: Symbol, name: Name): Symbol =
+ owner.info.nonPrivateMember(name)
+
+ /** Using getDecl rather than getMember may avoid issues with
+ * OverloadedTypes turning up when you don't want them, if you
+ * know the method in question is uniquely declared in the given owner.
+ */
+ def getDecl(owner: Symbol, name: Name): Symbol = {
+ getDeclIfDefined(owner, name) orElse {
+ throw new FatalError(owner + " does not have a decl " + name)
}
}
+ def getDeclIfDefined(owner: Symbol, name: Name): Symbol =
+ owner.info.nonPrivateDecl(name)
def packageExists(packageName: String): Boolean =
getModuleIfDefined(packageName).isPackage
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 8df687eca9..5e0c24d304 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1002,7 +1002,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** Set phase to a newly created syntaxAnalyzer and call definitions.init. */
val parserPhase: Phase = syntaxAnalyzer.newPhase(NoPhase)
phase = parserPhase
- definitions.init
+ definitions.init()
// Flush the cache in the terminal phase: the chain could have been built
// before without being used. (This happens in the interpreter.)
diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
index 27df45b563..314a3b45a0 100644
--- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
+++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
@@ -38,10 +38,10 @@ trait JavaPlatform extends Platform {
genJVM // generate .class files
) ++ depAnalysisPhase
- lazy val externalEquals = getMember(BoxesRunTimeClass, nme.equals_)
- lazy val externalEqualsNumNum = getMember(BoxesRunTimeClass, nme.equalsNumNum)
- lazy val externalEqualsNumChar = getMember(BoxesRunTimeClass, nme.equalsNumChar)
- lazy val externalEqualsNumObject = getMember(BoxesRunTimeClass, nme.equalsNumObject)
+ lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_)
+ lazy val externalEqualsNumNum = getDecl(BoxesRunTimeClass, nme.equalsNumNum)
+ lazy val externalEqualsNumChar = getDecl(BoxesRunTimeClass, nme.equalsNumChar)
+ lazy val externalEqualsNumObject = getDecl(BoxesRunTimeClass, nme.equalsNumObject)
/** We could get away with excluding BoxedBooleanClass for the
* purpose of equality testing since it need not compare equal
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 7b7135d180..18dc4aa56c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1281,7 +1281,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val jname = javaName(method)
val jtype = javaType(method).asInstanceOf[JMethodType]
- def debugMsg(invoke: String) {
+ def dbg(invoke: String) {
debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype))
}
@@ -1299,14 +1299,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
style match {
- case Static(true) => jcode.emitINVOKESPECIAL (jowner, jname, jtype) ; debugMsg("invokespecial")
- case Static(false) => jcode.emitINVOKESTATIC (jowner, jname, jtype) ; debugMsg("invokestatic")
- case Dynamic if isInterfaceCall(receiver) => jcode.emitINVOKEINTERFACE(jowner, jname, jtype) ; debugMsg("invokinterface")
- case Dynamic => jcode.emitINVOKEVIRTUAL (jowner, jname, jtype) ; debugMsg("invokevirtual")
+ case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype)
+ case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype)
+ case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype)
+ case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype)
case SuperCall(_) =>
+ dbg("invokespecial")
jcode.emitINVOKESPECIAL(jowner, jname, jtype)
initModule()
- debugMsg("invokespecial")
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 68af518d3a..775a7a9d38 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -625,11 +625,11 @@ abstract class ICodeReader extends ClassfileParser {
* such as Int.box(5).
*/
def isBox(m: Symbol): Boolean =
- (m.owner == definitions.BoxesRunTimeClass.moduleClass
+ (m.owner == definitions.BoxesRunTimeClass
&& m.name.startsWith("boxTo"))
def isUnbox(m: Symbol): Boolean =
- (m.owner == definitions.BoxesRunTimeClass.moduleClass
+ (m.owner == definitions.BoxesRunTimeClass
&& m.name.startsWith("unboxTo"))
/** Return the icode class that should include members with the given flags.
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index b21fa4bc83..e6f5dc5b5f 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -299,11 +299,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
def testForName(name: Name): Tree => Tree = t => (
if (nme.CommonOpNames(name))
- gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean), t :: Nil)
+ gen.mkMethodCall(definitions.Boxes_isNumberOrBool, t :: Nil)
else if (nme.BooleanOpNames(name))
t IS_OBJ BoxedBooleanClass.tpe
else
- gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumber), t :: Nil)
+ gen.mkMethodCall(definitions.Boxes_isNumber, t :: Nil)
)
/** The Tree => Tree function in the return is necessary to prevent the original qual
@@ -318,8 +318,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
else if (params.tail.isEmpty) nme.primitiveInfixMethodName(name)
else nme.NO_NAME
)
- if (methodName == nme.NO_NAME) None
- else Some((getMember(BoxesRunTimeClass, methodName), testForName(name)))
+ definitions.getDeclIfDefined(BoxesRunTimeClass, methodName) match {
+ case NoSymbol => None
+ case sym => assert(!sym.isOverloaded, sym) ; Some((sym, testForName(name)))
+ }
}
/* ### BOXING PARAMS & UNBOXING RESULTS ### */
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 105c2c0b98..8895905ca7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -14,6 +14,20 @@ import util.returning
abstract class TreeCheckers extends Analyzer {
import global._
+ private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]()
+ private val currentTrees = mutable.Map[Tree, (Symbol, Type)]()
+
+ if (settings.debug.value) {
+ sys addShutdownHook {
+ for ((ph, map) <- everything.toList) {
+ println("\n>>>> " + ph + "\n")
+ for ((tree, (sym, tpe)) <- map.toList.sortBy(_._1.summaryString)) {
+ println("%20s %20s %s".format(sym, tpe, ("" + tree) take 50))
+ }
+ }
+ }
+ }
+
private def classstr(x: AnyRef) = x.getClass.getName split """\\.|\\$""" last;
private def typestr(x: Type) = " (tpe = " + x + ")"
private def treestr(t: Tree) = t + " [" + classstr(t) + "]" + typestr(t.tpe)
@@ -92,11 +106,16 @@ abstract class TreeCheckers extends Analyzer {
if (maps.isEmpty || maps.last._1 != ph)
maps += ((ph, new PhaseMap))
+ currentTrees.clear()
traverse(unit.body)
+ everything += ((ph, currentTrees.toMap))
+
reportChanges()
}
override def traverse(tree: Tree): Unit = {
val sym = tree.symbol
+ currentTrees(tree) = ((sym, tree.tpe))
+
if (sym != null && sym != NoSymbol) {
record(sym, tree)
tree match {