summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala212
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala42
-rw-r--r--src/compiler/scala/tools/nsc/symtab/NameManglers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala30
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--test/files/neg/bug4302.check4
-rw-r--r--test/files/neg/bug4302.flags1
-rw-r--r--test/files/neg/bug4302.scala3
10 files changed, 116 insertions, 193 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index a934d569d5..076a59ce46 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -42,14 +42,19 @@ abstract class GenMSIL extends SubComponent {
//classes is ICodes.classes, a HashMap[Symbol, IClass]
classes.values foreach codeGenerator.findEntryPoint
+ if( opt.showClass.isDefined && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead
+ val entryclass = opt.showClass.get.toString
+ warning("Couldn't find entry class " + entryclass)
+ }
codeGenerator.initAssembly
- classes.values foreach codeGenerator.createTypeBuilder
- classes.values foreach codeGenerator.createClassMembers
+ val classesSorted = classes.values.toList.sortBy(c => c.symbol.id) // simplifies comparing cross-compiler vs. .exe output
+ classesSorted foreach codeGenerator.createTypeBuilder
+ classesSorted foreach codeGenerator.createClassMembers
try {
- classes.values foreach codeGenerator.genClass
+ classesSorted foreach codeGenerator.genClass
} finally {
codeGenerator.writeAssembly
}
@@ -68,7 +73,7 @@ abstract class GenMSIL extends SubComponent {
val MODULE_INSTANCE_NAME = "MODULE$"
- import clrTypes.{VOID => MVOID, BOOLEAN => MBOOL, UBYTE => MBYTE, SHORT => MSHORT,
+ import clrTypes.{VOID => MVOID, BOOLEAN => MBOOL, BYTE => MBYTE, SHORT => MSHORT,
CHAR => MCHAR, INT => MINT, LONG => MLONG, FLOAT => MFLOAT,
DOUBLE => MDOUBLE, OBJECT => MOBJECT, STRING => MSTRING,
STRING_ARRAY => MSTRING_ARRAY,
@@ -98,18 +103,16 @@ abstract class GenMSIL extends SubComponent {
val JOBJECT = definitions.ObjectClass
val JSTRING = definitions.StringClass
- var JSTRING_SUBSTRING_INT_INT: Symbol = _
-
val SystemConvert = clrTypes.getType("System.Convert")
val objParam = Array(MOBJECT)
// val toBool: MethodInfo = SystemConvert.GetMethod("ToBoolean", objParam)
- val toByte: MethodInfo = SystemConvert.GetMethod("ToByte", objParam)
- val toShort: MethodInfo = SystemConvert.GetMethod("ToInt16", objParam)
- val toChar: MethodInfo = SystemConvert.GetMethod("ToChar", objParam)
- val toInt: MethodInfo = SystemConvert.GetMethod("ToInt32", objParam)
- val toLong: MethodInfo = SystemConvert.GetMethod("ToInt64", objParam)
+ val toSByte: MethodInfo = SystemConvert.GetMethod("ToSByte", objParam)
+ val toShort: MethodInfo = SystemConvert.GetMethod("ToInt16", objParam)
+ val toChar: MethodInfo = SystemConvert.GetMethod("ToChar", objParam)
+ val toInt: MethodInfo = SystemConvert.GetMethod("ToInt32", objParam)
+ val toLong: MethodInfo = SystemConvert.GetMethod("ToInt64", objParam)
val toFloat: MethodInfo = SystemConvert.GetMethod("ToSingle", objParam)
val toDouble: MethodInfo = SystemConvert.GetMethod("ToDouble", objParam)
@@ -140,58 +143,6 @@ abstract class GenMSIL extends SubComponent {
mapType(definitions.NullClass, EXCEPTION)
mapType(definitions.NothingClass, EXCEPTION)
- val jEmpty = new Array[Type](0)
- val jString1 = Array(JSTRING.tpe)
- val jInt1 = Array(definitions.IntClass.tpe)
- val jInt2 = Array(definitions.IntClass.tpe, definitions.IntClass.tpe)
- val jLong1 = Array(definitions.LongClass.tpe)
- val jStringInt = Array(JSTRING.tpe, definitions.IntClass.tpe)
- val jChar2 = Array(definitions.CharClass.tpe, definitions.CharClass.tpe)
-
- val mObject1 = Array(MOBJECT)
- val mString1 = Array(MSTRING)
- val mString2 = Array(MSTRING, MSTRING)
- val mChar1 = Array(MCHAR)
- val mCharInt = Array(MCHAR, MINT)
-
- JSTRING_SUBSTRING_INT_INT = lookupMethod(JSTRING, "substring", jInt2)
-
- mapMethod(JOBJECT, "clone", MOBJECT, "MemberwiseClone")
- mapMethod(JOBJECT, nme.equals_, MOBJECT, "Equals")
- mapMethod(JOBJECT, nme.hashCode_, MOBJECT, "GetHashCode")
- mapMethod(JOBJECT, nme.toString_, MOBJECT, "ToString")
- mapMethod(JOBJECT, nme.finalize_, MOBJECT, "Finalize")
- mapMethod(JOBJECT, nme.wait_, jEmpty, MMONITOR, "Wait", mObject1)
- mapMethod(JOBJECT, nme.wait_, jLong1, MMONITOR, "Wait", Array(MOBJECT, MINT))
- mapMethod(JOBJECT, nme.notify_, jEmpty, MMONITOR, "Pulse", mObject1)
- mapMethod(JOBJECT, nme.notifyAll_, jEmpty, MMONITOR, "PulseAll", mObject1)
-
- mapMethod(JSTRING, "compareTo",MSTRING, "CompareTo")
- mapMethod(JSTRING, "length", MSTRING, "get_Length")
- mapMethod(JSTRING, "charAt", MSTRING, "get_Chars")
-
- mapMethod(JSTRING, "concat", jString1, MSTRING, "Concat", mString2)
- mapMethod(JSTRING, "indexOf", jInt1, MSTRING, "IndexOf", mChar1)
- mapMethod(JSTRING, "indexOf", jInt2, MSTRING, "IndexOf", mCharInt)
-
- mapMethod(JSTRING, "indexOf", jString1, MSTRING, "IndexOf")
- mapMethod(JSTRING, "indexOf", jStringInt, MSTRING, "IndexOf")
- mapMethod(JSTRING, "lastIndexOf", jInt1, MSTRING, "LastIndexOf", mChar1)
- mapMethod(JSTRING, "lastIndexOf", jInt2, MSTRING, "LastIndexOf", mCharInt)
- mapMethod(JSTRING, "lastIndexOf", jString1, MSTRING, "LastIndexOf")
- mapMethod(JSTRING, "lastIndexOf", jStringInt, MSTRING, "LastIndexOf")
-
- mapMethod(JSTRING, "toLowerCase", jEmpty, MSTRING, "ToLower")
- mapMethod(JSTRING, "toUpperCase", jEmpty, MSTRING, "ToUpper")
- mapMethod(JSTRING, "startsWith", jString1, MSTRING, "StartsWith")
- mapMethod(JSTRING, "endsWith", jString1, MSTRING, "EndsWith")
- mapMethod(JSTRING, "substring", jInt1, MSTRING, "Substring")
- mapMethod(JSTRING, "substring", jInt2, MSTRING, "Substring")
- mapMethod(JSTRING, "trim", jEmpty, MSTRING, "Trim")
- mapMethod(JSTRING, "intern", jEmpty, MSTRING, "Intern", mString1)
- mapMethod(JSTRING, "replace", jChar2, MSTRING, "Replace")
- mapMethod(JSTRING, "toCharArray", MSTRING, "ToCharArray")
-
mapType(definitions.BooleanClass, MBOOL)
mapType(definitions.ByteClass, MBYTE)
mapType(definitions.ShortClass, MSHORT)
@@ -457,14 +408,17 @@ abstract class GenMSIL extends SubComponent {
code.Emit(OpCodes.Ret)
}
createTypes()
- val filename = outDir.getPath()
- if (settings.debug.value)
- log("Output path: " + filename)
+ var outDirName: String = null
try {
- // massembly.Save(filename + "\\" + assemName + ".msil") /* use SingleFileILPrinterVisitor */
- massembly.Save(filename, srcPath.getPath()) /* use MultipleFilesILPrinterVisitor */
+ if (settings.Ygenjavap.isDefault) { // we reuse the JVM-sounding setting because it's conceptually similar
+ outDirName = outDir.getPath()
+ massembly.Save(outDirName + "\\" + assemName + ".msil") /* use SingleFileILPrinterVisitor */
+ } else {
+ outDirName = srcPath.getPath()
+ massembly.Save(settings.Ygenjavap.value, outDirName) /* use MultipleFilesILPrinterVisitor */
+ }
} catch {
- case e:IOException => abort("Could not write to " + filename + ": " + e.getMessage())
+ case e:IOException => abort("Could not write to " + outDirName + ": " + e.getMessage())
}
}
@@ -596,14 +550,19 @@ abstract class GenMSIL extends SubComponent {
labels.clear
- var linearization = if(m.exh != Nil) msilLinearizer.linearize(m)
+ var linearization = if(!m.exh.isEmpty) msilLinearizer.linearize(m)
else linearizer.linearize(m)
- if (m.exh != Nil)
+ if (!m.exh.isEmpty)
linearization = computeExceptionMaps(linearization, m)
makeLabels(linearization)
+ // debug val blocksInM = m.code.blocks.toList.sortBy(bb => bb.label)
+ // debug val blocksInL = linearization.sortBy(bb => bb.label)
+ // debug val MButNotL = (blocksInM.toSet) diff (blocksInL.toSet) // if non-empty, a jump to B fails to find a label for B (case CJUMP, case CZJUMP)
+ // debug if(!MButNotL.isEmpty) { }
+
genBlocks(linearization)
// RETURN inside exception blocks are replaced by Leave. The target of the
@@ -989,7 +948,7 @@ abstract class GenMSIL extends SubComponent {
case LOAD_ARRAY_ITEM(kind) =>
(kind: @unchecked) match {
case BOOL => mcode.Emit(OpCodes.Ldelem_I1)
- case BYTE => mcode.Emit(OpCodes.Ldelem_U1)
+ case BYTE => mcode.Emit(OpCodes.Ldelem_I1) // I1 for System.SByte, i.e. a scala.Byte
case SHORT => mcode.Emit(OpCodes.Ldelem_I2)
case CHAR => mcode.Emit(OpCodes.Ldelem_U2)
case INT => mcode.Emit(OpCodes.Ldelem_I4)
@@ -1113,17 +1072,6 @@ abstract class GenMSIL extends SubComponent {
}
} else {
- // java.lang.String.substring(int start_incl, int end_excl)
- // System.String.Substring(int start_incl, int length)
- if (msym == JSTRING_SUBSTRING_INT_INT) {
- val endLocal = mcode.DeclareLocal(MINT)
- endLocal.SetLocalSymInfo("$substring_end")
- mcode.Emit(OpCodes.Stloc, endLocal)
- mcode.Emit(OpCodes.Dup) // duplicate start_incl
- mcode.Emit(OpCodes.Neg)
- mcode.Emit(OpCodes.Ldloc, endLocal) // load end_excl
- mcode.Emit(OpCodes.Add) // compute length (-start + end)
- }
var doEmit = true
getTypeOpt(msym.owner) match {
@@ -1388,7 +1336,7 @@ abstract class GenMSIL extends SubComponent {
log("Converting from: " + src + " to: " + dst)
dst match {
- case BYTE => mcode.Emit(OpCodes.Conv_U1)
+ case BYTE => mcode.Emit(OpCodes.Conv_I1) // I1 for System.SByte, i.e. a scala.Byte
case SHORT => mcode.Emit(OpCodes.Conv_I2)
case CHAR => mcode.Emit(OpCodes.Conv_U2)
case INT => mcode.Emit(OpCodes.Conv_I4)
@@ -1745,6 +1693,7 @@ abstract class GenMSIL extends SubComponent {
val localBuilders: HashMap[Local, LocalBuilder] = new HashMap()
private[GenMSIL] def findEntryPoint(cls: IClass) {
+
def isEntryPoint(sym: Symbol):Boolean = {
if (isStaticModule(sym.owner) && msilName(sym) == "main")
if (sym.tpe.paramTypes.length == 1) {
@@ -1759,12 +1708,15 @@ abstract class GenMSIL extends SubComponent {
false
}
- for (m <- cls.methods) {
- if (isEntryPoint(m.symbol)) {
- if (entryPoint == null)
- entryPoint = m.symbol
+ if((entryPoint == null) && opt.showClass.isDefined) { // TODO introduce dedicated setting instead
+ val entryclass = opt.showClass.get.toString
+ val cfn = cls.symbol.fullName
+ if(cfn == entryclass) {
+ for (m <- cls.methods; if isEntryPoint(m.symbol)) { entryPoint = m.symbol }
+ if(entryPoint == null) { warning("Couldn't find main method in class " + cfn) }
}
}
+
if (firstSourceName == "")
if (cls.symbol.sourceFile != null) // is null for nested classes
firstSourceName = cls.symbol.sourceFile.name
@@ -1806,22 +1758,25 @@ abstract class GenMSIL extends SubComponent {
* Get an MSIL type from a symbol. First look in the clrTypes.types map, then
* lookup the name using clrTypes.getType
*/
- def getTypeOpt(sym: Symbol): Option[MsilType] = types.get(sym) match {
- case typ @ Some(_) => typ
- case None =>
- def typeString(sym: Symbol): String = {
- val s = if (sym.isNestedClass) typeString(sym.owner) +"+"+ sym.simpleName
- else sym.fullName
- if (sym.isModuleClass && !sym.isTrait) s + "$" else s
- }
- val name = typeString(sym)
- val typ = clrTypes.getType(name)
- if (typ == null)
- None
- else {
- types(sym) = typ
- Some(typ)
- }
+ def getTypeOpt(sym: Symbol): Option[MsilType] = {
+ val tmp = types.get(sym)
+ tmp match {
+ case typ @ Some(_) => typ
+ case None =>
+ def typeString(sym: Symbol): String = {
+ val s = if (sym.isNestedClass) typeString(sym.owner) +"+"+ sym.simpleName
+ else sym.fullName
+ if (sym.isModuleClass && !sym.isTrait) s + "$" else s
+ }
+ val name = typeString(sym)
+ val typ = clrTypes.getType(name)
+ if (typ == null)
+ None
+ else {
+ types(sym) = typ
+ Some(typ)
+ }
+ }
}
def mapType(sym: Symbol, mType: MsilType) {
@@ -1952,7 +1907,7 @@ abstract class GenMSIL extends SubComponent {
} else {
var resType = msilType(m.returnType)
val method =
- ownerType.DefineMethod(getMethodName(sym), attr, resType, paramTypes)
+ ownerType.DefineMethod(msilName(sym), attr, resType, paramTypes)
for (i <- 0.until(paramTypes.length)) {
method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
}
@@ -2106,7 +2061,7 @@ abstract class GenMSIL extends SubComponent {
paramNames(i) = "x_" + i
// CHECK: verify if getMethodName is better than msilName
- val mirrorMethod = mirrorTypeBuilder.DefineMethod(getMethodName(m),
+ val mirrorMethod = mirrorTypeBuilder.DefineMethod(msilName(m),
(MethodAttributes.Public |
MethodAttributes.Static).toShort,
msilType(m.tpe.resultType),
@@ -2198,25 +2153,29 @@ abstract class GenMSIL extends SubComponent {
case UNIT => code.Emit(OpCodes.Ldsfld, boxedUnit)
case BOOL | BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE =>
code.Emit(OpCodes.Box, msilType(boxType))
- case REFERENCE(cls) if (definitions.boxMethod.contains(cls)) =>
+ case REFERENCE(cls) if clrTypes.isValueType(cls) =>
code.Emit(OpCodes.Box, (msilType(boxType)))
- case REFERENCE(_) | ARRAY(_) => ()
+ case REFERENCE(_) | ARRAY(_) =>
+ warning("Tried to BOX a non-valuetype.")
+ ()
}
def emitUnbox(code: ILGenerator, boxType: TypeKind) = (boxType: @unchecked) match {
case UNIT => code.Emit(OpCodes.Pop)
case BOOL => code.Emit(OpCodes.Unbox, MBOOL); code.Emit(OpCodes.Ldind_I1)
- case BYTE => code.Emit(OpCodes.Call, toByte)
+ case BYTE => code.Emit(OpCodes.Call, toSByte)
case SHORT => code.Emit(OpCodes.Call, toShort)
case CHAR => code.Emit(OpCodes.Call, toChar)
case INT => code.Emit(OpCodes.Call, toInt)
case LONG => code.Emit(OpCodes.Call, toLong)
case FLOAT => code.Emit(OpCodes.Call, toFloat)
case DOUBLE => code.Emit(OpCodes.Call, toDouble)
- case REFERENCE(cls) if (definitions.unboxMethod.contains(cls)) =>
+ case REFERENCE(cls) if clrTypes.isValueType(cls) =>
code.Emit(OpCodes.Unbox, msilType(boxType))
code.Emit(OpCodes.Ldobj, msilType(boxType))
- case REFERENCE(_) | ARRAY(_) => ()
+ case REFERENCE(_) | ARRAY(_) =>
+ warning("Tried to UNBOX a non-valuetype.")
+ ()
}
// #####################################################################
@@ -2243,23 +2202,13 @@ abstract class GenMSIL extends SubComponent {
}
private def getMethod(sym: Symbol): MethodInfo = {
- //private def getMethod(sym: Symbol): MethodInfo = sym match {
-// case SRToInt => toInt
-// case SRToDouble => toDouble
-// case SRToLong => toLong
-// case SRToChar => toChar
-// case SRToFloat => toFloat
-// case SRToBool => toBool
-// case SRToByte => toByte
-// case SRToShort => toShort
-// case _ =>
methods.get(sym) match {
case Some(method) => method
case None =>
val mClass = getType(sym.owner)
try {
- val method = mClass.GetMethod(getMethodName(sym), msilParamTypes(sym),
+ val method = mClass.GetMethod(msilName(sym), msilParamTypes(sym),
msilType(sym.tpe.resultType))
if (method eq null) {
java.lang.System.out.println("Cannot find method " + sym.owner + "::" + msilName(sym))
@@ -2379,25 +2328,6 @@ abstract class GenMSIL extends SubComponent {
}
}
- def getMethodName(methodSym: Symbol): String = {
- val name = methodSym.name
- val params = methodSym.tpe.paramTypes
- if (name == nme.finalize_ && params.length == 0)
- "Finalize"
- else if (name == nme.toString_ && params.length == 0)
- "ToString"
- else if (name == nme.hashCode_ && params.length == 0)
- "GetHashCode"
- else if (name == nme.equals_ && params.length == 1 &&
- params(0) == definitions.ObjectClass.tpe)
- "Equals"
- // FIXME: why is there no nme.clone_ ?
- else if (name.toString() == "clone" && params.length == 0)
- "Clone"
- else
- msilName(methodSym)
- }
-
private def showsym(sym: Symbol): String = (sym.toString +
"\n symbol = " + Flags.flagsToString(sym.flags) + " " + sym +
"\n owner = " + Flags.flagsToString(sym.owner.flags) + " " + sym.owner
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 5f9a7d2816..118d650586 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -843,48 +843,6 @@ trait Definitions extends reflect.generic.StandardDefinitions {
setParents(sym, anyvalparam)
}
- if (forMSIL) {
- val intType = IntClass.typeConstructor
- val intParam = List(intType)
- val longType = LongClass.typeConstructor
- val charType = CharClass.typeConstructor
- val unitType = UnitClass.typeConstructor
- val stringType = StringClass.typeConstructor
- val stringParam = List(stringType)
-
- // additional methods of Object
- newMethod(ObjectClass, "clone", List(), AnyRefClass.typeConstructor)
- // wait in Java returns void, on .NET Wait returns boolean. by putting
- // `booltype` the compiler adds a `drop` after calling wait.
- newMethod(ObjectClass, "wait", List(), booltype)
- newMethod(ObjectClass, "wait", List(longType), booltype)
- newMethod(ObjectClass, "notify", List(), unitType)
- newMethod(ObjectClass, "notifyAll", List(), unitType)
-
- // additional methods of String
- newMethod(StringClass, "length", List(), intType)
- newMethod(StringClass, "compareTo", stringParam, intType)
- newMethod(StringClass, "charAt", intParam, charType)
- newMethod(StringClass, "concat", stringParam, stringType)
- newMethod(StringClass, "indexOf", intParam, intType)
- newMethod(StringClass, "indexOf", List(intType, intType), intType)
- newMethod(StringClass, "indexOf", stringParam, intType)
- newMethod(StringClass, "indexOf", List(stringType, intType), intType)
- newMethod(StringClass, "lastIndexOf", intParam, intType)
- newMethod(StringClass, "lastIndexOf", List(intType, intType), intType)
- newMethod(StringClass, "lastIndexOf", stringParam, intType)
- newMethod(StringClass, "lastIndexOf", List(stringType, intType), intType)
- newMethod(StringClass, "toLowerCase", List(), stringType)
- newMethod(StringClass, "toUpperCase", List(), stringType)
- newMethod(StringClass, "startsWith", stringParam, booltype)
- newMethod(StringClass, "endsWith", stringParam, booltype)
- newMethod(StringClass, "substring", intParam, stringType)
- newMethod(StringClass, "substring", List(intType, intType), stringType)
- newMethod(StringClass, "trim", List(), stringType)
- newMethod(StringClass, "intern", List(), stringType)
- newMethod(StringClass, "replace", List(charType, charType), stringType)
- newMethod(StringClass, "toCharArray", List(), arrayType(charType))
- }
isInitialized = true
} //init
diff --git a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
index dae07a29d5..ce372b6e50 100644
--- a/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/NameManglers.scala
@@ -38,7 +38,7 @@ trait NameManglers {
private final val marker = "$$$$"
private final val MaxNameLength = math.min(
settings.maxClassfileName.value - 6,
- 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32) + 6
+ 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32)
)
private lazy val md5 = MessageDigest.getInstance("MD5")
private def toMD5(s: String, edge: Int) = {
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index ec545fa4c6..8c2966e494 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -186,7 +186,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val canEqual_ : NameType = "canEqual"
val checkInitialized: NameType = "checkInitialized"
val classOf: NameType = "classOf"
- val clone_ : NameType = "clone"
+ val clone_ : NameType = sn.OClone
val conforms: NameType = "conforms"
val copy: NameType = "copy"
val delayedInit: NameType = "delayedInit"
@@ -195,19 +195,19 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val drop: NameType = "drop"
val elem: NameType = "elem"
val eq: NameType = "eq"
- val equals_ : NameType = "equals"
+ val equals_ : NameType = sn.OEquals
val error: NameType = "error"
val ex: NameType = "ex"
val false_ : NameType = "false"
val filter: NameType = "filter"
- val finalize_ : NameType = "finalize"
+ val finalize_ : NameType = sn.OFinalize
val find_ : NameType = "find"
val flatMap: NameType = "flatMap"
val foreach: NameType = "foreach"
val genericArrayOps: NameType = "genericArrayOps"
val get: NameType = "get"
val hasNext: NameType = "hasNext"
- val hashCode_ : NameType = "hashCode"
+ val hashCode_ : NameType = sn.OHashCode
val hash_ : NameType = "hash"
val head: NameType = "head"
val identity: NameType = "identity"
@@ -246,7 +246,7 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val toArray: NameType = "toArray"
val toList: NameType = "toList"
val toSeq: NameType = "toSeq"
- val toString_ : NameType = "toString"
+ val toString_ : NameType = sn.OToString
val true_ : NameType = "true"
val unapply: NameType = "unapply"
val unapplySeq: NameType = "unapplySeq"
@@ -430,6 +430,12 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
val Invoke : TermName
val JavaLang : TermName
+ val OClone : String
+ val OEquals : String
+ val OFinalize : String
+ val OHashCode : String
+ val OToString : String
+
val Boxed: immutable.Map[TypeName, TypeName]
}
@@ -527,6 +533,12 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val Invoke: TermName = "invoke"
final val JavaLang: TermName = "java.lang"
+ final val OClone = "clone"
+ final val OEquals = "equals"
+ final val OFinalize = "finalize"
+ final val OHashCode = "hashCode"
+ final val OToString = "toString"
+
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
tpnme.Byte -> BoxedByte,
@@ -565,9 +577,15 @@ trait StdNames extends reflect.generic.StdNames with NameManglers {
final val Invoke: TermName = "Invoke"
final val JavaLang: TermName = "System"
+ final val OClone = "MemberwiseClone"
+ final val OEquals = "Equals"
+ final val OFinalize = "Finalize"
+ final val OHashCode = "GetHashCode"
+ final val OToString = "ToString"
+
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> "System.Boolean",
- tpnme.Byte -> "System.Byte",
+ tpnme.Byte -> "System.SByte", // a scala.Byte is signed and a System.SByte too (unlike a System.Byte)
tpnme.Char -> "System.Char",
tpnme.Short -> "System.Int16",
tpnme.Int -> "System.Int32",
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
index c7b3a7a736..cf1f7f1db3 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala
@@ -66,8 +66,8 @@ abstract class CLRTypes {
def isAddressOf(msym : Symbol) = addressOfViews.contains(msym)
- def isNonEnumValuetype(clssym : Symbol) = {
- val msilTOpt = types.get(clssym)
+ def isNonEnumValuetype(cls: Symbol) = {
+ val msilTOpt = types.get(cls)
val res = msilTOpt.isDefined && {
val msilT = msilTOpt.get
msilT.IsValueType && !msilT.IsEnum
@@ -75,6 +75,11 @@ abstract class CLRTypes {
res
}
+ def isValueType(cls: Symbol): Boolean = {
+ val opt = types.get(cls)
+ opt.isDefined && opt.get.IsValueType
+ }
+
def init() = try { // initialize
// the MsilClasspath (nsc/util/Classpath.scala) initializes the msil-library by calling
// Assembly.LoadFrom("mscorlib.dll"), so this type should be found
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index e15c8fae66..296e555559 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1312,7 +1312,7 @@ trait Infer {
((bound contains sym) ||
sym.name == tpnme.WILDCARD || {
val e = context.scope.lookupEntry(sym.name)
- (e ne null) && e.sym == sym && e.owner == context.scope
+ (e ne null) && e.sym == sym && !e.sym.isTypeParameterOrSkolem && e.owner == context.scope
})
tp match {
case SingleType(pre, _) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index fb8b0058eb..d2d9257989 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4268,6 +4268,10 @@ trait Typers extends Modes {
val restpe = result.tpe.normalize // normalize to get rid of type aliases for the following check (#1241)
if (!phase.erasedTypes && restpe.isInstanceOf[TypeRef] && !restpe.prefix.isStable && !context.unit.isJava) {
+ // The isJava exception if OK only because the only type constructors scalac gets
+ // to see are those in the signatures. These do not need a unique object as a prefix.
+ // The situation is different for new's and super's, but scalac does not look deep
+ // enough to see those. See #3938
error(tree.pos, restpe.prefix+" is not a legal prefix for a constructor")
}
diff --git a/test/files/neg/bug4302.check b/test/files/neg/bug4302.check
new file mode 100644
index 0000000000..ca33748cfd
--- /dev/null
+++ b/test/files/neg/bug4302.check
@@ -0,0 +1,4 @@
+bug4302.scala:2: error: abstract type T in type T is unchecked since it is eliminated by erasure
+ def hasMatch[T](x: AnyRef) = x.isInstanceOf[T]
+ ^
+one error found
diff --git a/test/files/neg/bug4302.flags b/test/files/neg/bug4302.flags
new file mode 100644
index 0000000000..779916d58f
--- /dev/null
+++ b/test/files/neg/bug4302.flags
@@ -0,0 +1 @@
+-unchecked -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/bug4302.scala b/test/files/neg/bug4302.scala
new file mode 100644
index 0000000000..53565f05c2
--- /dev/null
+++ b/test/files/neg/bug4302.scala
@@ -0,0 +1,3 @@
+object Test {
+ def hasMatch[T](x: AnyRef) = x.isInstanceOf[T]
+}