From 0bea2ab5f6b211a83bbf14ea46fe57b8163c6334 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 28 Nov 2011 08:03:10 +0000 Subject: Fix for erroneous bytecode generation. A remedy for an IllegalAccessError where generated bytecode referred to an inaccessible type. Closes SI-1430. Bonus materials: - tore out all the invokedynamic support. The shipped jdk7 implementation shows limited resemblance to the one this was written against; the code mostly serves to distract. (I think I could get invokedynamic working pretty quickly, except that it would mean having a codebase for java7 and one for 5-6, which is not a yak I wish to shave today.) - gave NullClass and NothingClass objects of their own, which allowed a nice polymorphic simplification of isSubClass, plus a couple other streamlinings. --- .../scala/reflect/internal/Definitions.scala | 26 ++-- src/compiler/scala/reflect/internal/Symbols.scala | 19 +-- src/compiler/scala/reflect/internal/Types.scala | 3 +- .../scala/reflect/internal/transform/Erasure.scala | 2 +- .../scala/tools/nsc/backend/icode/GenICode.scala | 15 ++- .../scala/tools/nsc/backend/icode/Members.scala | 1 - .../scala/tools/nsc/backend/icode/Opcodes.scala | 4 - .../backend/icode/analysis/CopyPropagation.scala | 2 +- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 147 +++++++++------------ .../tools/nsc/interpreter/CompletionOutput.scala | 2 +- .../tools/nsc/matching/ParallelMatching.scala | 2 +- .../scala/tools/nsc/symtab/SymbolTrackers.scala | 2 +- .../nsc/symtab/classfile/ClassfileParser.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 9 +- 14 files changed, 110 insertions(+), 126 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 092c478bef..1cc3d580d9 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -172,11 +172,27 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val AnyValCompanionClass = getClass("scala.AnyValCompanion") setFlag (SEALED | ABSTRACT | TRAIT) // bottom types - lazy val NullClass = newClass(ScalaPackageClass, tpnme.Null, anyrefparam) setFlag (ABSTRACT | TRAIT | FINAL) - lazy val NothingClass = newClass(ScalaPackageClass, tpnme.Nothing, anyparam) setFlag (ABSTRACT | TRAIT | FINAL) lazy val RuntimeNothingClass = getClass(ClassfileConstants.SCALA_NOTHING) lazy val RuntimeNullClass = getClass(ClassfileConstants.SCALA_NULL) + sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) { + locally { + this setFlag ABSTRACT | TRAIT | FINAL + this setInfo ClassInfoType(List(parent.tpe), new Scope, this) + owner.info.decls enter this + } + final override def isBottomClass = true + } + final object NothingClass extends BottomClassSymbol(tpnme.Nothing, AnyClass) { + override def isSubClass(that: Symbol) = true + } + final object NullClass extends BottomClassSymbol(tpnme.Null, AnyRefClass) { + override def isSubClass(that: Symbol) = ( + (that eq AnyClass) + || (that ne NothingClass) && (that isSubClass ObjectClass) + ) + } + // exceptions and other throwables lazy val ClassCastExceptionClass = getClass("java.lang.ClassCastException") lazy val IndexOutOfBoundsExceptionClass = getClass(sn.IOOBException) @@ -351,12 +367,6 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val ScalaSignatureAnnotation = getClass("scala.reflect.ScalaSignature") lazy val ScalaLongSignatureAnnotation = getClass("scala.reflect.ScalaLongSignature") - // invoke dynamic support - lazy val LinkageModule = getModule("java.dyn.Linkage") - lazy val Linkage_invalidateCallerClass = getMember(LinkageModule, "invalidateCallerClass") - lazy val DynamicDispatchClass = getModule("scala.runtime.DynamicDispatch") - lazy val DynamicDispatch_DontSetTarget = getMember(DynamicDispatchClass, "DontSetTarget") - // Option classes lazy val OptionClass: Symbol = getClass("scala.Option") lazy val SomeClass: Symbol = getClass("scala.Some") diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 65b60bfa39..058108c285 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -334,6 +334,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isTerm = false // to be overridden def isType = false // to be overridden def isClass = false // to be overridden + def isBottomClass = false // to be overridden def isAliasType = false // to be overridden def isAbstractType = false // to be overridden private[scala] def isSkolem = false // to be overridden @@ -951,6 +952,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def hasRawInfo: Boolean = infos ne null + def hasCompleteInfo = hasRawInfo && rawInfo.isComplete /** Return info without checking for initialization or completing */ def rawInfo: Type = { @@ -1236,17 +1238,15 @@ trait Symbols extends api.Symbols { self: SymbolTable => owner == that || owner != NoSymbol && (owner isNestedIn that) /** Is this class symbol a subclass of that symbol? */ - final def isNonBottomSubClass(that: Symbol): Boolean = - this == that || this.isError || that.isError || + final def isNonBottomSubClass(that: Symbol): Boolean = ( + (this eq that) || this.isError || that.isError || info.baseTypeIndex(that) >= 0 - - final def isSubClass(that: Symbol): Boolean = ( - isNonBottomSubClass(that) || - this == NothingClass || - this == NullClass && - (that == AnyClass || - that != NothingClass && (that isSubClass ObjectClass)) ) + + /** Overridden in NullClass and NothingClass for custom behavior. + */ + def isSubClass(that: Symbol) = isNonBottomSubClass(that) + final def isNumericSubClass(that: Symbol): Boolean = definitions.isNumericSubClass(this, that) @@ -2425,6 +2425,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => unlock() validTo = currentPeriod } + override def isSubClass(that: Symbol) = false override def filter(cond: Symbol => Boolean) = this override def defString: String = toString override def locationString: String = "" diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a9dded3cd1..320fb949ff 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -3063,8 +3063,7 @@ A type's typeSymbol should never be inspected directly. case TypeRef(pre, sym, args) if (variance != 0) && (occurCount isDefinedAt sym) => val repl = if (variance == 1) dropSingletonType(tp1.bounds.hi) else tp1.bounds.lo //println("eliminate "+sym+"/"+repl+"/"+occurCount(sym)+"/"+(tparams exists (repl.contains)))//DEBUG - if (repl.typeSymbol != NothingClass && repl.typeSymbol != NullClass && - occurCount(sym) == 1 && !(tparams exists (repl.contains))) + if (!repl.typeSymbol.isBottomClass && occurCount(sym) == 1 && !(tparams exists (repl.contains))) repl else tp1 case _ => diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala index 9648befb49..c8cb6febfa 100644 --- a/src/compiler/scala/reflect/internal/transform/Erasure.scala +++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala @@ -75,7 +75,7 @@ trait Erasure { case TypeRef(pre, sym, args) => if (sym == ArrayClass) if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe - else if (args.head.typeSymbol == NothingClass || args.head.typeSymbol == NullClass) arrayType(ObjectClass.tpe) + else if (args.head.typeSymbol.isBottomClass) arrayType(ObjectClass.tpe) else typeRef(apply(pre), sym, args map this) else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass) else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 90e387d384..e26a0d59e8 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -24,7 +24,7 @@ abstract class GenICode extends SubComponent { import icodes._ import icodes.opcodes._ import definitions.{ - ArrayClass, ObjectClass, ThrowableClass, StringClass, StringModule, NothingClass, NullClass, AnyRefClass, + ArrayClass, ObjectClass, ThrowableClass, StringClass, StringModule, AnyRefClass, Object_equals, Object_isInstanceOf, Object_asInstanceOf, ScalaRunTimeModule, BoxedNumberClass, BoxedCharacterClass, getMember @@ -923,12 +923,13 @@ abstract class GenICode extends SubComponent { } case ApplyDynamic(qual, args) => - assert(!forMSIL) - ctx.clazz.bootstrapClass = Some("scala.runtime.DynamicDispatch") - val ctx1 = genLoad(qual, ctx, ObjectReference) - genLoadArguments(args, tree.symbol.info.paramTypes, ctx1) - ctx1.bb.emit(CALL_METHOD(tree.symbol, InvokeDynamic), tree.pos) - ctx1 + assert(!forMSIL, tree) + // TODO - this is where we'd catch dynamic applies for invokedynamic. + sys.error("No invokedynamic support yet.") + // val ctx1 = genLoad(qual, ctx, ObjectReference) + // genLoadArguments(args, tree.symbol.info.paramTypes, ctx1) + // ctx1.bb.emit(CALL_METHOD(tree.symbol, InvokeDynamic), tree.pos) + // ctx1 case This(qual) => assert(tree.symbol == ctx.clazz.symbol || tree.symbol.isModuleClass, diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 5aa76fad83..2f43d43bdd 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -106,7 +106,6 @@ trait Members { self: ICodes => var fields: List[IField] = Nil var methods: List[IMethod] = Nil var cunit: CompilationUnit = _ - var bootstrapClass: Option[String] = None def addField(f: IField): this.type = { fields = f :: fields; diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index ba33c425f2..2bcfb9d4a9 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -616,7 +616,6 @@ trait Opcodes { self: ICodes => /** Returns a string representation of this style. */ override def toString(): String = this match { case Dynamic => "dynamic" - case InvokeDynamic => "invoke-dynamic" case Static(false) => "static-class" case Static(true) => "static-instance" case SuperCall(mix) => "super(" + mix + ")" @@ -626,9 +625,6 @@ trait Opcodes { self: ICodes => /** Virtual calls */ case object Dynamic extends InvokeStyle - /** InvokeDynamic a la JSR 292 (experimental). */ - case object InvokeDynamic extends InvokeStyle - /** * Special invoke. Static(true) is used for calls to private * members. diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index 16cba38f9a..5af5b05682 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -321,7 +321,7 @@ abstract class CopyPropagation { out.stack = Unknown :: out.stack.drop(i.consumed) case CALL_METHOD(method, style) => style match { - case Dynamic | InvokeDynamic => + case Dynamic => out = simulateCall(in, method, false) case Static(onInstance) => diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 9d5cc9e0a6..3fe5b83515 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -31,7 +31,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with import icodes._ import icodes.opcodes._ import definitions.{ - NullClass, RuntimeNullClass, NothingClass, RuntimeNothingClass, AnyClass, ObjectClass, ThrowsClass, ThrowableClass, ClassfileAnnotationClass, SerializableClass, StringClass, ClassClass, FunctionClass, DeprecatedAttr, SerializableAttr, SerialVersionUIDAttr, VolatileAttr, @@ -332,8 +331,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ifaces, c.cunit.source.toString) - if (isStaticModule(c.symbol) || serialVUID != None || isParcelableClass || - clasz.bootstrapClass.isDefined) { + if (isStaticModule(c.symbol) || serialVUID != None || isParcelableClass) { if (isStaticModule(c.symbol)) addModuleInstanceField addStaticInit(jclass, c.lookupStaticCtor) @@ -375,9 +373,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } - if (clasz.bootstrapClass.isDefined) - jclass setBootstrapClass clasz.bootstrapClass.get - clasz.fields foreach genField clasz.methods foreach genMethod @@ -913,8 +908,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with mopt match { case Some(m) => - if (clasz.bootstrapClass.isDefined) legacyEmitBootstrapMethodInstall(clinit) - val oldLastBlock = m.code.blocks.last val lastBlock = m.code.newBlock oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock)) @@ -940,11 +933,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (isParcelableClass) addCreatorCode(BytecodeGenerator.this, lastBlock) - if (clasz.bootstrapClass.isDefined) { - // emit bootstrap method install - //emitBootstrapMethodInstall(block) - } - lastBlock emit RETURN(UNIT) lastBlock.close @@ -975,28 +963,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (isParcelableClass) legacyAddCreatorCode(BytecodeGenerator.this, clinit) - if (clasz.bootstrapClass.isDefined) - legacyEmitBootstrapMethodInstall(clinit) - clinit.emitRETURN() } - /** Emit code that installs a boostrap method for invoke dynamic. It - * installs the default method, found in scala.runtime.DynamicDispatch. - */ - def legacyEmitBootstrapMethodInstall(jcode: JExtendedCode) { - jcode emitPUSH jclass.getType.asInstanceOf[JReferenceType] - jcode emitPUSH new JObjectType("scala.runtime.DynamicDispatch") - jcode emitPUSH "bootstrapInvokeDynamic" - jcode.emitGETSTATIC("java.dyn.Linkage", "BOOTSTRAP_METHOD_TYPE", MethodTypeType) - jcode.emitDUP - jcode.emitINVOKESTATIC("scala.Console", "println", new JMethodType(JType.VOID, Array(JAVA_LANG_OBJECT))) - jcode.emitINVOKESTATIC("java.dyn.MethodHandles", "findStatic", - new JMethodType(MethodHandleType, Array(JavaLangClassType, JAVA_LANG_STRING, MethodTypeType))) - jcode.emitINVOKESTATIC("java.dyn.Linkage", "registerBootstrapMethod", - new JMethodType(JType.VOID, Array(JavaLangClassType, MethodHandleType))) - } - /** Add a forwarder for method m */ def addForwarder(jclass: JClass, module: Symbol, m: Symbol) { val moduleName = javaName(module) @@ -1197,6 +1166,68 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } + def isAccessibleFrom(target: Symbol, site: Symbol): Boolean = { + target.isPublic || target.isProtected && { + (site.enclClass isSubClass target.enclClass) || + (site.enclosingPackage == target.privateWithin) + } + } + + def genCallMethod(call: CALL_METHOD) { + val CALL_METHOD(method, style) = call + val siteSymbol = clasz.symbol + val hostSymbol = call.hostClass + val methodOwner = method.owner + // info calls so that types are up to date; erasure may add lateINTERFACE to traits + hostSymbol.info ; methodOwner.info + + def isInterfaceCall(sym: Symbol) = ( + sym.isInterface + || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass) + ) + // whether to reference the type of the receiver or + // the type of the method owner (if not an interface!) + val useMethodOwner = ( + style != Dynamic + || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol) + || hostSymbol.isBottomClass + ) + val receiver = if (useMethodOwner) methodOwner else hostSymbol + val jowner = javaName(receiver) + val jname = javaName(method) + val jtype = javaType(method).asInstanceOf[JMethodType] + + def emit(invoke: String) { + log("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype)) + invoke match { + case "invokeinterface" => jcode.emitINVOKEINTERFACE(jowner, jname, jtype) + case "invokevirtual" => jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) + case "invokespecial" => jcode.emitINVOKESPECIAL(jowner, jname, jtype) + case "invokestatic" => jcode.emitINVOKESTATIC(jowner, jname, jtype) + } + } + def initModule() { + // we initialize the MODULE$ field immediately after the super ctor + if (isStaticModule(siteSymbol) && !isModuleInitialized && + jmethod.getName() == JMethod.INSTANCE_CONSTRUCTOR_NAME && + jname == JMethod.INSTANCE_CONSTRUCTOR_NAME) { + isModuleInitialized = true + jcode.emitALOAD_0() + jcode.emitPUTSTATIC(jclass.getName(), + nme.MODULE_INSTANCE_FIELD.toString, + jclass.getType()) + } + } + + style match { + case Static(true) => emit("invokespecial") + case Static(false) => emit("invokestatic") + case Dynamic if isInterfaceCall(receiver) => emit("invokeinterface") + case Dynamic => emit("invokevirtual") + case SuperCall(_) => emit("invokespecial") ; initModule() + } + } + def genBlock(b: BasicBlock) { labels(b).anchorToNext() @@ -1276,43 +1307,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with jcode.emitINVOKEVIRTUAL(target, "clone", arrayCloneType) case call @ CALL_METHOD(method, style) => - val owner: String = javaName(method.owner) - // reference the type of the receiver instead of the method owner (if not an interface!) - val dynamicOwner = - if (needsInterfaceCall(call.hostClass)) owner - else javaName(call.hostClass) - val jname = javaName(method) - val jtype = javaType(method).asInstanceOf[JMethodType] - - style match { - case InvokeDynamic => - jcode.emitINVOKEINTERFACE("java.dyn.Dynamic", jname, jtype) - - case Dynamic => - if (needsInterfaceCall(method.owner)) - jcode.emitINVOKEINTERFACE(owner, jname, jtype) - else - jcode.emitINVOKEVIRTUAL(dynamicOwner, jname, jtype) - - case Static(instance) => - if (instance) - jcode.emitINVOKESPECIAL(owner, jname, jtype) - else - jcode.emitINVOKESTATIC(owner, jname, jtype) - - case SuperCall(_) => - jcode.emitINVOKESPECIAL(owner, jname, jtype) - // we initialize the MODULE$ field immediately after the super ctor - if (isStaticModule(clasz.symbol) && !isModuleInitialized && - jmethod.getName() == JMethod.INSTANCE_CONSTRUCTOR_NAME && - jname == JMethod.INSTANCE_CONSTRUCTOR_NAME) { - isModuleInitialized = true - jcode.emitALOAD_0() - jcode.emitPUTSTATIC(jclass.getName(), - nme.MODULE_INSTANCE_FIELD.toString, - jclass.getType()) - } - } + genCallMethod(call) case BOX(kind) => val boxedType = definitions.boxedClass(kind.toType.typeSymbol) @@ -1839,20 +1834,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ////////////////////// Utilities //////////////////////// - /** Calls to methods in 'sym' need invokeinterface? */ - def needsInterfaceCall(sym: Symbol): Boolean = { - debuglog("checking for interface call: " + sym.fullName) - // the following call to 'info' may cause certain symbols to fail loading - // because we're too late in the compilation chain (aliases to overloaded - // symbols will not be properly resolved, see scala.Range, method - // `super$++` that fails in UnPickler at LazyTypeRefAndAlias.complete - if (sym.isTrait) sym.info // needed so that the type is up to date - // (erasure may add lateINTERFACE to traits) - - sym.isInterface || - (sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass)) - } - /** Merge adjacent ranges. */ private def mergeEntries(ranges: List[(Int, Int)]): List[(Int, Int)] = (ranges.foldLeft(Nil: List[(Int, Int)]) { (collapsed: List[(Int, Int)], p: (Int, Int)) => (collapsed, p) match { diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala index 9c34565928..015dc2a7f1 100644 --- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala +++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala @@ -15,7 +15,7 @@ trait CompletionOutput { val global: Global import global._ - import definitions.{ NothingClass, AnyClass, isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType } + import definitions.{ isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType } /** Reducing fully qualified noise for some common packages. */ diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index c97d65c6bc..11d829eadb 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -25,7 +25,7 @@ trait ParallelMatching extends ast.TreeDSL import global.{ typer => _, _ } import definitions.{ - AnyRefClass, NothingClass, IntClass, BooleanClass, SomeClass, OptionClass, + AnyRefClass, IntClass, BooleanClass, SomeClass, OptionClass, getProductArgs, productProj, Object_eq, Any_asInstanceOf } import CODE._ diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala index 1f32355bf7..e62070a239 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala @@ -131,7 +131,7 @@ trait SymbolTrackers { else " (" + Flags.flagsToString(masked) + ")" } def symString(sym: Symbol) = ( - if (settings.debug.value && sym.hasRawInfo && sym.rawInfo.isComplete) { + if (settings.debug.value && sym.hasCompleteInfo) { val s = sym.defString take 240 if (s.length == 240) s + "..." else s } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index ef1bcdd739..e67ce90cfa 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1257,7 +1257,7 @@ abstract class ClassfileParser { protected def getScope(flags: Int): Scope = if (isStatic(flags)) staticDefs else instanceDefs - private def setPrivateWithin(sym: Symbol, jflags: Int) { + private def setPrivateWithin(sym: Symbol, jflags: Int) { if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0) // See ticket #1687 for an example of when topLevelClass is NoSymbol: it // apparently occurs when processing v45.3 bytecode. diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 054fb1c036..62ad78c64d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1033,8 +1033,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { && qual.isTerm && ((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) && !qtpe.isError - && qtpe.typeSymbol != NullClass - && qtpe.typeSymbol != NothingClass + && !qtpe.typeSymbol.isBottomClass && qtpe != WildcardType && !qual.isInstanceOf[ApplyImplicitView] // don't chain views && context.implicitsEnabled @@ -2190,10 +2189,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { * in an argument closure overlaps with an uninstantiated formal? */ def needsInstantiation(tparams: List[Symbol], formals: List[Type], args: List[Tree]) = { - def isLowerBounded(tparam: Symbol) = { - val losym = tparam.info.bounds.lo.typeSymbol - losym != NothingClass && losym != NullClass - } + def isLowerBounded(tparam: Symbol) = !tparam.info.bounds.lo.typeSymbol.isBottomClass + (formals, args).zipped exists { case (formal, Function(vparams, _)) => (vparams exists (_.tpt.isEmpty)) && -- cgit v1.2.3