diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala | 212 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 42 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/NameManglers.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 | ||||
-rw-r--r-- | test/files/neg/bug4302.check | 4 | ||||
-rw-r--r-- | test/files/neg/bug4302.flags | 1 | ||||
-rw-r--r-- | test/files/neg/bug4302.scala | 3 |
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] +} |