diff options
143 files changed, 2408 insertions, 1566 deletions
diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 8b8b6978b8..0000000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.jar -*.obj -*.log -*~ -target/ diff --git a/gitignore.SAMPLE b/gitignore.SAMPLE index ac50f91b2f..3c15a5de9e 100644 --- a/gitignore.SAMPLE +++ b/gitignore.SAMPLE @@ -2,22 +2,29 @@ /.gitignore /test/files/.gitignore -# "a" and "a/" to get both file (i.e. symlink) and folder -/build -/build/ -/target +*.jar +*~ + +#sbt +/project/target/ +/project/project/target + /target/ +/src/jline/target/ + +# target directories for ant build +/build/ /dists/ + +# other /out/ /bin/ - /sandbox/ +# eclipse, intellij /.classpath - +/.project /src/intellij/*.iml /src/intellij/*.ipr /src/intellij/*.iws -/project/boot/ -/project/build/target/ diff --git a/.project.SAMPLE b/project.SAMPLE index b1f7386a4a..b1f7386a4a 100644 --- a/.project.SAMPLE +++ b/project.SAMPLE diff --git a/src/compiler/scala/reflect/internal/Constants.scala b/src/compiler/scala/reflect/internal/Constants.scala index 2edb0d1fe6..9c4b2b2245 100644 --- a/src/compiler/scala/reflect/internal/Constants.scala +++ b/src/compiler/scala/reflect/internal/Constants.scala @@ -217,7 +217,7 @@ trait Constants extends api.Constants { } def escapedStringValue: String = { - def escape(text: String): String = (text map escapedChar) mkString "" + def escape(text: String): String = text flatMap escapedChar tag match { case NullTag => "null" case StringTag => "\"" + escape(stringValue) + "\"" diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 54c1153f81..d3af8e2623 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -6,6 +6,7 @@ package scala.reflect package internal +import annotation.{ switch } import scala.collection.{ mutable, immutable } import Flags._ import PartialFunction._ @@ -60,8 +61,8 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val numericWeight = symbolsMapFilt(ScalaValueClasses, nameToWeight.keySet, nameToWeight) lazy val boxedModule = classesMap(x => getModule(boxedName(x))) lazy val boxedClass = classesMap(x => getClass(boxedName(x))) - lazy val refClass = classesMap(x => getClass("scala.runtime." + x + "Ref")) - lazy val volatileRefClass = classesMap(x => getClass("scala.runtime.Volatile" + x + "Ref")) + lazy val refClass = classesMap(x => getRequiredClass("scala.runtime." + x + "Ref")) + lazy val volatileRefClass = classesMap(x => getRequiredClass("scala.runtime.Volatile" + x + "Ref")) lazy val boxMethod = classesMap(x => valueModuleMethod(x, nme.box)) lazy val unboxMethod = classesMap(x => valueModuleMethod(x, nme.unbox)) @@ -85,12 +86,6 @@ trait Definitions extends reflect.api.StandardDefinitions { def isGetClass(sym: Symbol) = (sym.name == nme.getClass_) && (sym.paramss.isEmpty || sym.paramss.head.isEmpty) - private[Definitions] def fullNameStrings: List[String] = nme.ScalaValueNames map ("scala." + _) - private[Definitions] lazy val fullValueName: Set[Name] = { - val values = nme.ScalaValueNames flatMap (x => List(newTypeName("scala." + x), newTermName("scala." + x))) - values.toSet + newTypeName("scala.AnyVal") - } - lazy val AnyValClass = valueCache(tpnme.AnyVal) lazy val UnitClass = valueCache(tpnme.Unit) lazy val ByteClass = valueCache(tpnme.Byte) @@ -101,9 +96,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val FloatClass = valueCache(tpnme.Float) lazy val DoubleClass = valueCache(tpnme.Double) lazy val BooleanClass = valueCache(tpnme.Boolean) - def Boolean_and = getMember(BooleanClass, nme.ZAND) - def Boolean_or = getMember(BooleanClass, nme.ZOR) - def Boolean_not = getMember(BooleanClass, nme.UNARY_!) + lazy val Boolean_and = getMember(BooleanClass, nme.ZAND) + lazy val Boolean_or = getMember(BooleanClass, nme.ZOR) + lazy val Boolean_not = getMember(BooleanClass, nme.UNARY_!) def ScalaValueClassesNoUnit = ScalaValueClasses filterNot (_ eq UnitClass) def ScalaValueClasses: List[Symbol] = List( @@ -151,8 +146,10 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val ScalaPackage = getModule(nme.scala_) lazy val ScalaPackageClass = ScalaPackage.moduleClass - lazy val RuntimePackage = getModule("scala.runtime") + lazy val RuntimePackage = getRequiredModule("scala.runtime") lazy val RuntimePackageClass = RuntimePackage.moduleClass + + lazy val JavaLangEnumClass = getRequiredClass("java.lang.Enum") // convenient one-argument parameter lists lazy val anyparam = List(AnyClass.typeConstructor) @@ -163,17 +160,45 @@ trait Definitions extends reflect.api.StandardDefinitions { private def booltype = BooleanClass.typeConstructor private def inttype = IntClass.typeConstructor private def stringtype = StringClass.typeConstructor + + // Java types + def javaTypeName(jclazz: Class[_]): TypeName = newTypeName(jclazz.getName) + + def javaTypeToValueClass(jtype: Class[_]): Symbol = jtype match { + case java.lang.Void.TYPE => UnitClass + case java.lang.Byte.TYPE => ByteClass + case java.lang.Character.TYPE => CharClass + case java.lang.Short.TYPE => ShortClass + case java.lang.Integer.TYPE => IntClass + case java.lang.Long.TYPE => LongClass + case java.lang.Float.TYPE => FloatClass + case java.lang.Double.TYPE => DoubleClass + case java.lang.Boolean.TYPE => BooleanClass + case _ => NoSymbol + } + def valueClassToJavaType(sym: Symbol): Class[_] = sym match { + case UnitClass => java.lang.Void.TYPE + case ByteClass => java.lang.Byte.TYPE + case CharClass => java.lang.Character.TYPE + case ShortClass => java.lang.Short.TYPE + case IntClass => java.lang.Integer.TYPE + case LongClass => java.lang.Long.TYPE + case FloatClass => java.lang.Float.TYPE + case DoubleClass => java.lang.Double.TYPE + case BooleanClass => java.lang.Boolean.TYPE + case _ => null + } // top types lazy val AnyClass = newClass(ScalaPackageClass, tpnme.Any, Nil) setFlag (ABSTRACT) lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.typeConstructor) lazy val ObjectClass = getClass(sn.Object) - lazy val AnyCompanionClass = getClass("scala.AnyCompanion") setFlag (SEALED | ABSTRACT | TRAIT) - lazy val AnyValCompanionClass = getClass("scala.AnyValCompanion") setFlag (SEALED | ABSTRACT | TRAIT) + lazy val AnyCompanionClass = getRequiredClass("scala.AnyCompanion") setFlag (SEALED | ABSTRACT | TRAIT) + lazy val AnyValCompanionClass = getRequiredClass("scala.AnyValCompanion") setFlag (SEALED | ABSTRACT | TRAIT) // bottom types - lazy val RuntimeNothingClass = getClass(ClassfileConstants.SCALA_NOTHING) - lazy val RuntimeNullClass = getClass(ClassfileConstants.SCALA_NULL) + lazy val RuntimeNothingClass = getClass(fulltpnme.RuntimeNothing) + lazy val RuntimeNullClass = getClass(fulltpnme.RuntimeNull) sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) { locally { @@ -194,25 +219,25 @@ trait Definitions extends reflect.api.StandardDefinitions { } // exceptions and other throwables - lazy val ClassCastExceptionClass = getClass("java.lang.ClassCastException") + lazy val ClassCastExceptionClass = getRequiredClass("java.lang.ClassCastException") lazy val IndexOutOfBoundsExceptionClass = getClass(sn.IOOBException) lazy val InvocationTargetExceptionClass = getClass(sn.InvTargetException) - lazy val MatchErrorClass = getClass("scala.MatchError") - lazy val NonLocalReturnControlClass = getClass("scala.runtime.NonLocalReturnControl") + lazy val MatchErrorClass = getRequiredClass("scala.MatchError") + lazy val NonLocalReturnControlClass = getRequiredClass("scala.runtime.NonLocalReturnControl") lazy val NullPointerExceptionClass = getClass(sn.NPException) lazy val ThrowableClass = getClass(sn.Throwable) - lazy val UninitializedErrorClass = getClass("scala.UninitializedFieldError") + lazy val UninitializedErrorClass = getRequiredClass("scala.UninitializedFieldError") // fundamental reference classes lazy val ScalaObjectClass = getMember(ScalaPackageClass, tpnme.ScalaObject) - lazy val PartialFunctionClass = getClass("scala.PartialFunction") - lazy val AbstractPartialFunctionClass = getClass("scala.runtime.AbstractPartialFunction") - lazy val SymbolClass = getClass("scala.Symbol") + lazy val PartialFunctionClass = getRequiredClass("scala.PartialFunction") + lazy val AbstractPartialFunctionClass = getRequiredClass("scala.runtime.AbstractPartialFunction") + lazy val SymbolClass = getRequiredClass("scala.Symbol") lazy val StringClass = getClass(sn.String) lazy val StringModule = StringClass.linkedClassOfClass lazy val ClassClass = getClass(sn.Class) def Class_getMethod = getMember(ClassClass, nme.getMethod_) - lazy val DynamicClass = getClass("scala.Dynamic") + lazy val DynamicClass = getRequiredClass("scala.Dynamic") // fundamental modules lazy val SysPackage = getPackageObject("scala.sys") @@ -223,7 +248,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Those modules and their module classes lazy val UnqualifiedOwners = UnqualifiedModules.toSet ++ UnqualifiedModules.map(_.moduleClass) - lazy val PredefModule: Symbol = getModule("scala.Predef") + lazy val PredefModule: Symbol = getRequiredModule("scala.Predef") lazy val PredefModuleClass = PredefModule.moduleClass // Note: this is not the type alias AnyRef, it's a val defined in Predef // used by the @specialize annotation. @@ -242,26 +267,27 @@ trait Definitions extends reflect.api.StandardDefinitions { (sym.name == name) && (sym.owner == PredefModule.moduleClass) ) - lazy val ConsoleModule: Symbol = getModule("scala.Console") - lazy val ScalaRunTimeModule: Symbol = getModule("scala.runtime.ScalaRunTime") - lazy val SymbolModule: Symbol = getModule("scala.Symbol") - lazy val Symbol_apply = getMember(SymbolModule, nme.apply) + lazy val ConsoleModule: Symbol = getRequiredModule("scala.Console") + lazy val ScalaRunTimeModule: Symbol = getRequiredModule("scala.runtime.ScalaRunTime") + lazy val SymbolModule: Symbol = getRequiredModule("scala.Symbol") + lazy val Symbol_apply = SymbolModule.info decl nme.apply + def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) - def arrayApplyMethod = getMember(ScalaRunTimeModule, "array_apply") - def arrayUpdateMethod = getMember(ScalaRunTimeModule, "array_update") - def arrayLengthMethod = getMember(ScalaRunTimeModule, "array_length") - def arrayCloneMethod = getMember(ScalaRunTimeModule, "array_clone") - def ensureAccessibleMethod = getMember(ScalaRunTimeModule, "ensureAccessible") + def arrayApplyMethod = getMember(ScalaRunTimeModule, nme.array_apply) + def arrayUpdateMethod = getMember(ScalaRunTimeModule, nme.array_update) + def arrayLengthMethod = getMember(ScalaRunTimeModule, nme.array_length) + def arrayCloneMethod = getMember(ScalaRunTimeModule, nme.array_clone) + def ensureAccessibleMethod = getMember(ScalaRunTimeModule, nme.ensureAccessible) def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements) // classes with special meanings - lazy val StringAddClass = getClass("scala.runtime.StringAdd") - lazy val ArrowAssocClass = getClass("scala.Predef.ArrowAssoc") + lazy val StringAddClass = getRequiredClass("scala.runtime.StringAdd") + lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc") lazy val StringAdd_+ = getMember(StringAddClass, nme.PLUS) - lazy val NotNullClass = getClass("scala.NotNull") - lazy val ScalaNumberClass = getClass("scala.math.ScalaNumber") - lazy val TraitSetterAnnotationClass = getClass("scala.runtime.TraitSetter") - lazy val DelayedInitClass = getClass("scala.DelayedInit") + lazy val NotNullClass = getRequiredClass("scala.NotNull") + lazy val ScalaNumberClass = getRequiredClass("scala.math.ScalaNumber") + lazy val TraitSetterAnnotationClass = getRequiredClass("scala.runtime.TraitSetter") + lazy val DelayedInitClass = getRequiredClass("scala.DelayedInit") def delayedInitMethod = getMember(DelayedInitClass, nme.delayedInit) // a dummy value that communicates that a delayedInit call is compiler-generated // from phase UnCurry to phase Constructors @@ -269,14 +295,14 @@ trait Definitions extends reflect.api.StandardDefinitions { // def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg) // .setInfo(UnitClass.tpe) - lazy val TypeConstraintClass = getClass("scala.annotation.TypeConstraint") + lazy val TypeConstraintClass = getRequiredClass("scala.annotation.TypeConstraint") lazy val SingletonClass = newClass(ScalaPackageClass, tpnme.Singleton, anyparam) setFlag (ABSTRACT | TRAIT | FINAL) - lazy val SerializableClass = getClass("scala.Serializable") + lazy val SerializableClass = getRequiredClass("scala.Serializable") lazy val JavaSerializableClass = getClass(sn.JavaSerializable) - lazy val ComparableClass = getClass("java.lang.Comparable") - lazy val JavaCloneableClass = getClass("java.lang.Cloneable") - lazy val RemoteInterfaceClass = getClass("java.rmi.Remote") - lazy val RemoteExceptionClass = getClass("java.rmi.RemoteException") + lazy val ComparableClass = getRequiredClass("java.lang.Comparable") + lazy val JavaCloneableClass = getRequiredClass("java.lang.Cloneable") + lazy val RemoteInterfaceClass = getRequiredClass("java.rmi.Remote") + lazy val RemoteExceptionClass = getRequiredClass("java.rmi.RemoteException") lazy val RepeatedParamClass = newCovariantPolyClass( ScalaPackageClass, @@ -326,66 +352,68 @@ trait Definitions extends reflect.api.StandardDefinitions { val clazz = newClass(ScalaPackageClass, tpnme.EQUALS_PATTERN_NAME, Nil) clazz setInfo polyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz)) } + lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy") // collections classes - lazy val ConsClass = getClass("scala.collection.immutable.$colon$colon") - lazy val IterableClass = getClass("scala.collection.Iterable") - lazy val IteratorClass = getClass("scala.collection.Iterator") - lazy val ListClass = getClass("scala.collection.immutable.List") - lazy val SeqClass = getClass("scala.collection.Seq") - lazy val StringBuilderClass = getClass("scala.collection.mutable.StringBuilder") - lazy val TraversableClass = getClass("scala.collection.Traversable") - - lazy val ListModule = getModule("scala.collection.immutable.List") + lazy val ConsClass = getRequiredClass("scala.collection.immutable.$colon$colon") + lazy val IterableClass = getRequiredClass("scala.collection.Iterable") + lazy val IteratorClass = getRequiredClass("scala.collection.Iterator") + lazy val ListClass = getRequiredClass("scala.collection.immutable.List") + lazy val SeqClass = getRequiredClass("scala.collection.Seq") + lazy val StringBuilderClass = getRequiredClass("scala.collection.mutable.StringBuilder") + lazy val TraversableClass = getRequiredClass("scala.collection.Traversable") + + lazy val ListModule = getRequiredModule("scala.collection.immutable.List") lazy val List_apply = getMember(ListModule, nme.apply) - lazy val NilModule = getModule("scala.collection.immutable.Nil") - lazy val SeqModule = getModule("scala.collection.Seq") + lazy val NilModule = getRequiredModule("scala.collection.immutable.Nil") + lazy val SeqModule = getRequiredModule("scala.collection.Seq") + lazy val IteratorModule = getRequiredModule("scala.collection.Iterator") + lazy val Iterator_apply = getMember(IteratorModule, nme.apply) // arrays and their members - lazy val ArrayModule = getModule("scala.Array") - def ArrayModule_overloadedApply = getMember(ArrayModule, nme.apply) - lazy val ArrayClass = getClass("scala.Array") - def Array_apply = getMember(ArrayClass, nme.apply) - def Array_update = getMember(ArrayClass, nme.update) - def Array_length = getMember(ArrayClass, nme.length) - lazy val Array_clone = getMember(ArrayClass, nme.clone_) + lazy val ArrayModule = getRequiredModule("scala.Array") + lazy val ArrayModule_overloadedApply = getMember(ArrayModule, nme.apply) + lazy val ArrayClass = getRequiredClass("scala.Array") + lazy val Array_apply = getMember(ArrayClass, nme.apply) + lazy val Array_update = getMember(ArrayClass, nme.update) + lazy val Array_length = getMember(ArrayClass, nme.length) + lazy val Array_clone = getMember(ArrayClass, nme.clone_) // reflection / structural types - lazy val SoftReferenceClass = getClass("java.lang.ref.SoftReference") - lazy val WeakReferenceClass = getClass("java.lang.ref.WeakReference") + lazy val SoftReferenceClass = getRequiredClass("java.lang.ref.SoftReference") + lazy val WeakReferenceClass = getRequiredClass("java.lang.ref.WeakReference") lazy val MethodClass = getClass(sn.MethodAsObject) def methodClass_setAccessible = getMember(MethodClass, nme.setAccessible) - lazy val EmptyMethodCacheClass = getClass("scala.runtime.EmptyMethodCache") - lazy val MethodCacheClass = getClass("scala.runtime.MethodCache") + lazy val EmptyMethodCacheClass = getRequiredClass("scala.runtime.EmptyMethodCache") + lazy val MethodCacheClass = getRequiredClass("scala.runtime.MethodCache") def methodCache_find = getMember(MethodCacheClass, nme.find_) def methodCache_add = getMember(MethodCacheClass, nme.add_) // scala.reflect - lazy val ReflectApiUniverse = getClass("scala.reflect.api.Universe") - lazy val ReflectRuntimeMirror = getModule("scala.reflect.runtime.Mirror") - def freeValueMethod = getMember(ReflectRuntimeMirror, "freeValue") + lazy val ReflectApiUniverse = getRequiredClass("scala.reflect.api.Universe") + lazy val ReflectRuntimeMirror = getRequiredModule("scala.reflect.runtime.Mirror") + def freeValueMethod = getMember(ReflectRuntimeMirror, nme.freeValue) lazy val ReflectPackage = getPackageObject("scala.reflect") - def Reflect_mirror = getMember(ReflectPackage, "mirror") - - - lazy val PartialManifestClass = getClass("scala.reflect.ClassManifest") - lazy val PartialManifestModule = getModule("scala.reflect.ClassManifest") - lazy val FullManifestClass = getClass("scala.reflect.Manifest") - lazy val FullManifestModule = getModule("scala.reflect.Manifest") - lazy val OptManifestClass = getClass("scala.reflect.OptManifest") - lazy val NoManifest = getModule("scala.reflect.NoManifest") + def Reflect_mirror = getMember(ReflectPackage, nme.mirror) + + lazy val PartialManifestClass = getRequiredClass("scala.reflect.ClassManifest") + lazy val PartialManifestModule = getRequiredModule("scala.reflect.ClassManifest") + lazy val FullManifestClass = getRequiredClass("scala.reflect.Manifest") + lazy val FullManifestModule = getRequiredModule("scala.reflect.Manifest") + lazy val OptManifestClass = getRequiredClass("scala.reflect.OptManifest") + lazy val NoManifest = getRequiredModule("scala.reflect.NoManifest") lazy val CodeClass = getClass(sn.Code) lazy val CodeModule = getModule(sn.Code) - def Code_lift = getMember(CodeModule, nme.lift_) + lazy val Code_lift = getMember(CodeModule, nme.lift_) - lazy val ScalaSignatureAnnotation = getClass("scala.reflect.ScalaSignature") - lazy val ScalaLongSignatureAnnotation = getClass("scala.reflect.ScalaLongSignature") + lazy val ScalaSignatureAnnotation = getRequiredClass("scala.reflect.ScalaSignature") + lazy val ScalaLongSignatureAnnotation = getRequiredClass("scala.reflect.ScalaLongSignature") // Option classes - lazy val OptionClass: Symbol = getClass("scala.Option") - lazy val SomeClass: Symbol = getClass("scala.Some") - lazy val NoneModule: Symbol = getModule("scala.None") - lazy val SomeModule: Symbol = getModule("scala.Some") + lazy val OptionClass: Symbol = getRequiredClass("scala.Option") + lazy val SomeClass: Symbol = getRequiredClass("scala.Some") + lazy val NoneModule: Symbol = getRequiredModule("scala.None") + lazy val SomeModule: Symbol = getRequiredModule("scala.Some") /** Note: don't use this manifest/type function for anything important, * as it is incomplete. Would love to have things like existential types @@ -441,7 +469,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Product, Tuple, Function private def mkArityArray(name: String, arity: Int, countFrom: Int = 1): Array[Symbol] = { - val list = countFrom to arity map (i => getClass("scala." + name + i)) + val list = countFrom to arity map (i => getRequiredClass("scala." + name + i)) if (countFrom == 0) list.toArray else (NoSymbol +: list).toArray } @@ -457,10 +485,24 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) lazy val isProductNClass = ProductClass.toSet + def wrapArrayMethodName(elemtp: Type): TermName = elemtp.typeSymbol match { + case ByteClass => nme.wrapByteArray + case ShortClass => nme.wrapShortArray + case CharClass => nme.wrapCharArray + case IntClass => nme.wrapIntArray + case LongClass => nme.wrapLongArray + case FloatClass => nme.wrapFloatArray + case DoubleClass => nme.wrapDoubleArray + case BooleanClass => nme.wrapBooleanArray + case UnitClass => nme.wrapUnitArray + case _ => + if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(elemtp.typeSymbol)) nme.wrapRefArray + else nme.genericWrapArray + } - def tupleField(n: Int, j: Int) = getMember(TupleClass(n), "_" + j) - def isTupleType(tp: Type): Boolean = isTupleType(tp, false) - def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp, true) + def tupleField(n: Int, j: Int) = getMember(TupleClass(n), nme.productAccessorName(j)) + def isTupleType(tp: Type): Boolean = isTupleType(tp, false) + def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp, true) private def isTupleType(tp: Type, subtypeOK: Boolean) = tp.normalize match { case TypeRef(_, sym, args) if args.nonEmpty => val len = args.length @@ -479,7 +521,7 @@ trait Definitions extends reflect.api.StandardDefinitions { } else NoType } - lazy val ProductRootClass: Symbol = getClass("scala.Product") + lazy val ProductRootClass: Symbol = getRequiredClass("scala.Product") def Product_productArity = getMember(ProductRootClass, nme.productArity) def Product_productElement = getMember(ProductRootClass, nme.productElement) // def Product_productElementName = getMember(ProductRootClass, nme.productElementName) @@ -548,9 +590,10 @@ trait Definitions extends reflect.api.StandardDefinitions { case _ => NoType } - def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg)) - def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg)) - def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg)) + def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg)) + def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg)) + def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg)) + def iteratorOfType(tp: Type) = appliedType(IteratorClass.typeConstructor, List(tp)) def ClassType(arg: Type) = if (phase.erasedTypes || forMSIL) ClassClass.tpe @@ -560,7 +603,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // .NET backend // - lazy val ComparatorClass = getClass("scala.runtime.Comparator") + lazy val ComparatorClass = getRequiredClass("scala.runtime.Comparator") // System.ValueType lazy val ValueTypeClass: Symbol = getClass(sn.ValueType) // System.MulticastDelegate @@ -605,10 +648,10 @@ trait Definitions extends reflect.api.StandardDefinitions { var Object_## : Symbol = _ var Object_synchronized: Symbol = _ lazy val Object_isInstanceOf = newPolyMethod( - ObjectClass, "$isInstanceOf", + ObjectClass, newTermName("$isInstanceOf"), tparam => MethodType(List(), booltype)) setFlag (FINAL | SYNTHETIC) lazy val Object_asInstanceOf = newPolyMethod( - ObjectClass, "$asInstanceOf", + ObjectClass, newTermName("$asInstanceOf"), tparam => MethodType(List(), tparam.typeConstructor)) setFlag (FINAL | SYNTHETIC) def Object_getClass = getMember(ObjectClass, nme.getClass_) @@ -623,57 +666,57 @@ trait Definitions extends reflect.api.StandardDefinitions { var String_+ : Symbol = _ // boxed classes - lazy val ObjectRefClass = getClass("scala.runtime.ObjectRef") - lazy val VolatileObjectRefClass = getClass("scala.runtime.VolatileObjectRef") - lazy val BoxesRunTimeClass = getModule("scala.runtime.BoxesRunTime") + lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef") + lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef") + lazy val BoxesRunTimeClass = getRequiredModule("scala.runtime.BoxesRunTime") lazy val BoxedNumberClass = getClass(sn.BoxedNumber) lazy val BoxedCharacterClass = getClass(sn.BoxedCharacter) lazy val BoxedBooleanClass = getClass(sn.BoxedBoolean) - lazy val BoxedByteClass = getClass("java.lang.Byte") - lazy val BoxedShortClass = getClass("java.lang.Short") - lazy val BoxedIntClass = getClass("java.lang.Integer") - lazy val BoxedLongClass = getClass("java.lang.Long") - lazy val BoxedFloatClass = getClass("java.lang.Float") - lazy val BoxedDoubleClass = getClass("java.lang.Double") - - lazy val BoxedUnitClass = getClass("scala.runtime.BoxedUnit") - lazy val BoxedUnitModule = getModule("scala.runtime.BoxedUnit") - def BoxedUnit_UNIT = getMember(BoxedUnitModule, "UNIT") - def BoxedUnit_TYPE = getMember(BoxedUnitModule, "TYPE") + lazy val BoxedByteClass = getRequiredClass("java.lang.Byte") + lazy val BoxedShortClass = getRequiredClass("java.lang.Short") + lazy val BoxedIntClass = getRequiredClass("java.lang.Integer") + lazy val BoxedLongClass = getRequiredClass("java.lang.Long") + lazy val BoxedFloatClass = getRequiredClass("java.lang.Float") + lazy val BoxedDoubleClass = getRequiredClass("java.lang.Double") + + lazy val BoxedUnitClass = getRequiredClass("scala.runtime.BoxedUnit") + lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit") + def BoxedUnit_UNIT = getMember(BoxedUnitModule, nme.UNIT) + def BoxedUnit_TYPE = getMember(BoxedUnitModule, nme.TYPE_) // Annotation base classes - lazy val AnnotationClass = getClass("scala.annotation.Annotation") - lazy val ClassfileAnnotationClass = getClass("scala.annotation.ClassfileAnnotation") - lazy val StaticAnnotationClass = getClass("scala.annotation.StaticAnnotation") + lazy val AnnotationClass = getRequiredClass("scala.annotation.Annotation") + lazy val ClassfileAnnotationClass = getRequiredClass("scala.annotation.ClassfileAnnotation") + lazy val StaticAnnotationClass = getRequiredClass("scala.annotation.StaticAnnotation") // Annotations - lazy val BridgeClass = getClass("scala.annotation.bridge") - lazy val ElidableMethodClass = getClass("scala.annotation.elidable") - lazy val ImplicitNotFoundClass = getClass("scala.annotation.implicitNotFound") - lazy val MigrationAnnotationClass = getClass("scala.annotation.migration") - lazy val ScalaStrictFPAttr = getClass("scala.annotation.strictfp") - lazy val SerializableAttr = getClass("scala.annotation.serializable") // @serializable is deprecated - lazy val SwitchClass = getClass("scala.annotation.switch") - lazy val TailrecClass = getClass("scala.annotation.tailrec") - lazy val VarargsClass = getClass("scala.annotation.varargs") - lazy val uncheckedStableClass = getClass("scala.annotation.unchecked.uncheckedStable") - lazy val uncheckedVarianceClass = getClass("scala.annotation.unchecked.uncheckedVariance") - - lazy val BeanPropertyAttr = getClass("scala.beans.BeanProperty") - lazy val BooleanBeanPropertyAttr = getClass("scala.beans.BooleanBeanProperty") - lazy val CloneableAttr = getClass("scala.cloneable") - lazy val DeprecatedAttr = getClass("scala.deprecated") - lazy val DeprecatedNameAttr = getClass("scala.deprecatedName") - lazy val NativeAttr = getClass("scala.native") - lazy val RemoteAttr = getClass("scala.remote") - lazy val ScalaInlineClass = getClass("scala.inline") - lazy val ScalaNoInlineClass = getClass("scala.noinline") - lazy val SerialVersionUIDAttr = getClass("scala.SerialVersionUID") - lazy val SpecializedClass = getClass("scala.specialized") - lazy val ThrowsClass = getClass("scala.throws") - lazy val TransientAttr = getClass("scala.transient") - lazy val UncheckedClass = getClass("scala.unchecked") - lazy val VolatileAttr = getClass("scala.volatile") + lazy val BridgeClass = getRequiredClass("scala.annotation.bridge") + lazy val ElidableMethodClass = getRequiredClass("scala.annotation.elidable") + lazy val ImplicitNotFoundClass = getRequiredClass("scala.annotation.implicitNotFound") + lazy val MigrationAnnotationClass = getRequiredClass("scala.annotation.migration") + lazy val ScalaStrictFPAttr = getRequiredClass("scala.annotation.strictfp") + lazy val SerializableAttr = getRequiredClass("scala.annotation.serializable") // @serializable is deprecated + lazy val SwitchClass = getRequiredClass("scala.annotation.switch") + lazy val TailrecClass = getRequiredClass("scala.annotation.tailrec") + lazy val VarargsClass = getRequiredClass("scala.annotation.varargs") + lazy val uncheckedStableClass = getRequiredClass("scala.annotation.unchecked.uncheckedStable") + lazy val uncheckedVarianceClass = getRequiredClass("scala.annotation.unchecked.uncheckedVariance") + + lazy val BeanPropertyAttr = getRequiredClass("scala.beans.BeanProperty") + lazy val BooleanBeanPropertyAttr = getRequiredClass("scala.beans.BooleanBeanProperty") + lazy val CloneableAttr = getRequiredClass("scala.cloneable") + lazy val DeprecatedAttr = getRequiredClass("scala.deprecated") + lazy val DeprecatedNameAttr = getRequiredClass("scala.deprecatedName") + lazy val NativeAttr = getRequiredClass("scala.native") + lazy val RemoteAttr = getRequiredClass("scala.remote") + lazy val ScalaInlineClass = getRequiredClass("scala.inline") + lazy val ScalaNoInlineClass = getRequiredClass("scala.noinline") + lazy val SerialVersionUIDAttr = getRequiredClass("scala.SerialVersionUID") + lazy val SpecializedClass = getRequiredClass("scala.specialized") + lazy val ThrowsClass = getRequiredClass("scala.throws") + lazy val TransientAttr = getRequiredClass("scala.transient") + lazy val UncheckedClass = getRequiredClass("scala.unchecked") + lazy val VolatileAttr = getRequiredClass("scala.volatile") // Meta-annotations lazy val BeanGetterTargetClass = getMetaAnnotation("beanGetter") @@ -684,7 +727,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val SetterTargetClass = getMetaAnnotation("setter") // TODO: module, moduleClass? package, packageObject? - private def getMetaAnnotation(name: String) = getClass("scala.annotation.meta." + name) + private def getMetaAnnotation(name: String) = getRequiredClass("scala.annotation.meta." + name) def isMetaAnnotation(sym: Symbol): Boolean = metaAnnotations(sym) || ( // Trying to allow for deprecated locations sym.isAliasType && isMetaAnnotation(sym.info.typeSymbol) @@ -702,11 +745,11 @@ trait Definitions extends reflect.api.StandardDefinitions { attr } - def getPackageObjectClass(fullname: Name): Symbol = + def getPackageObjectClass(fullname: String): Symbol = getPackageObject(fullname).companionClass - def getPackageObject(fullname: Name): Symbol = - getModule(fullname).info member nme.PACKAGE + def getPackageObject(fullname: String): Symbol = + getModule(newTermName(fullname)).info member nme.PACKAGE def getModule(fullname: Name): Symbol = getModuleOrClass(fullname.toTermName) @@ -716,6 +759,11 @@ trait Definitions extends reflect.api.StandardDefinitions { while (result.isAliasType) result = result.info.typeSymbol result } + + def getRequiredModule(fullname: String): Symbol = + getModule(newTermNameCached(fullname)) + def getRequiredClass(fullname: String): Symbol = + getClass(newTypeNameCached(fullname)) def getClassIfDefined(fullname: String): Symbol = getClassIfDefined(newTypeName(fullname)) @@ -953,8 +1001,7 @@ trait Definitions extends reflect.api.StandardDefinitions { ObjectClass, nme.synchronized_, tparam => msym => MethodType(msym.newSyntheticValueParams(List(tparam.typeConstructor)), tparam.typeConstructor)) setFlag FINAL - String_+ = newMethod( - StringClass, "+", anyparam, stringtype) setFlag FINAL + String_+ = newMethod(StringClass, nme.raw.PLUS, anyparam, stringtype) setFlag FINAL val forced = List( // force initialization of every symbol that is entered as a side effect AnnotationDefaultAttr, // #2264 @@ -987,7 +1034,7 @@ trait Definitions extends reflect.api.StandardDefinitions { assert(forMSIL, "scalaCallers can only be created if target is .NET") // object: reference to object on which to call (scala-)method val paramTypes: List[Type] = List(ObjectClass.tpe) - val name: String = "$scalaCaller$$" + nbScalaCallers + val name = newTermName("$scalaCaller$$" + nbScalaCallers) // tparam => resultType, which is the resultType of PolyType, i.e. the result type after applying the // type parameter =-> a MethodType in this case // TODO: set type bounds manually (-> MulticastDelegate), see newTypeParam diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index a4af4bf8f3..38f808cef9 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -20,8 +20,8 @@ trait Importers { self: SymbolTable => def importSymbol(sym: from.Symbol): Symbol = { def doImport(sym: from.Symbol): Symbol = { val myowner = importSymbol(sym.owner) - val mypos = importPosition(sym.pos) - val myname = importName(sym.name) + val mypos = importPosition(sym.pos) + val myname = importName(sym.name).toTermName def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { symMap(x) = mysym mysym.referenced = op(x.referenced) @@ -33,7 +33,7 @@ trait Importers { self: SymbolTable => case x: from.ModuleSymbol => linkReferenced(new ModuleSymbol(myowner, mypos, myname), x, doImport) case x: from.FreeVar => - new FreeVar(importName(x.name), importType(x.tpe), x.value) + new FreeVar(importName(x.name).toTermName, importType(x.tpe), x.value) case x: from.TermSymbol => linkReferenced(new TermSymbol(myowner, mypos, myname), x, importSymbol) case x: from.TypeSkolem => @@ -167,7 +167,7 @@ trait Importers { self: SymbolTable => case from.AntiPolyType(pre, targs) => AntiPolyType(importType(pre), targs map importType) case x: from.TypeVar => - new TypeVar(importType(x.origin), importTypeConstraint(x.constr0), x.typeArgs map importType, x.params map importSymbol) + TypeVar(importType(x.origin), importTypeConstraint(x.constr0), x.typeArgs map importType, x.params map importSymbol) case from.NotNullType(tpe) => NotNullType(importType(tpe)) case from.AnnotatedType(annots, tpe, selfsym) => diff --git a/src/compiler/scala/reflect/internal/Kinds.scala b/src/compiler/scala/reflect/internal/Kinds.scala index 15fcb5f94d..e675be43dc 100644 --- a/src/compiler/scala/reflect/internal/Kinds.scala +++ b/src/compiler/scala/reflect/internal/Kinds.scala @@ -110,10 +110,7 @@ trait Kinds { ): List[(Type, Symbol, KindErrors)] = { // instantiate type params that come from outside the abstract type we're currently checking - def transform(tp: Type, clazz: Symbol): Type = - tp.asSeenFrom(pre, clazz) - def transformedBounds(p: Symbol, o: Symbol) = - transform(p.info.instantiateTypeParams(tparams, targs).bounds, o) + def transform(tp: Type, clazz: Symbol): Type = tp.asSeenFrom(pre, clazz) // check that the type parameters hkargs to a higher-kinded type conform to the // expected params hkparams @@ -131,6 +128,7 @@ trait Kinds { // @M sometimes hkargs != arg.typeParams, the symbol and the type may // have very different type parameters val hkparams = param.typeParams + def kindCheck(cond: Boolean, f: KindErrors => KindErrors) { if (!cond) kindErrors = f(kindErrors) @@ -160,8 +158,8 @@ trait Kinds { // conceptually the same. Could also replace the types by // polytypes, but can't just strip the symbols, as ordering // is lost then. - val declaredBounds = transformedBounds(hkparam, paramowner) - val declaredBoundsInst = bindHKParams(declaredBounds) + val declaredBounds = transform(hkparam.info.instantiateTypeParams(tparams, targs).bounds, paramowner) + val declaredBoundsInst = transform(bindHKParams(declaredBounds), owner) val argumentBounds = transform(hkarg.info.bounds, owner) kindCheck(declaredBoundsInst <:< argumentBounds, _ strictnessError (hkarg -> hkparam)) diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index d4aa6339ff..ef092f16bb 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -23,8 +23,8 @@ trait NameManglers { val MODULE_SUFFIX_STRING = NameTransformer.MODULE_SUFFIX_STRING val NAME_JOIN_STRING = NameTransformer.NAME_JOIN_STRING - val MODULE_SUFFIX_NAME: TermName = MODULE_SUFFIX_STRING - val NAME_JOIN_NAME: TermName = NAME_JOIN_STRING + val MODULE_SUFFIX_NAME: TermName = newTermName(MODULE_SUFFIX_STRING) + val NAME_JOIN_NAME: TermName = newTermName(NAME_JOIN_STRING) def flattenedName(segments: Name*): NameType = compactedString(segments mkString NAME_JOIN_STRING) @@ -75,12 +75,12 @@ trait NameManglers { val LOCALDUMMY_PREFIX = "<local " // owner of local blocks val PROTECTED_PREFIX = "protected$" val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set" - val SETTER_SUFFIX = encode("_=") val SINGLETON_SUFFIX = ".type" val SPECIALIZED_SUFFIX_STRING = "$sp" val SUPER_PREFIX_STRING = "super$" val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" + val SETTER_SUFFIX: TermName = encode("_=") val SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX_STRING def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR @@ -124,6 +124,11 @@ trait NameManglers { name.subName(0, name.lastIndexOf('m') - 1) else name ) + + def macroMethodName(name: Name) = { + val base = if (name.isTypeName) nme.TYPEkw else nme.DEFkw + base append nme.MACRO append name + } /** Return the original name and the types on which this name * is specialized. For example, @@ -136,7 +141,7 @@ trait NameManglers { */ def splitSpecializedName(name: Name): (Name, String, String) = if (name endsWith SPECIALIZED_SUFFIX_NAME) { - val name1 = name stripEnd SPECIALIZED_SUFFIX_NAME + val name1 = name dropRight SPECIALIZED_SUFFIX_NAME.length val idxC = name1 lastIndexOf 'c' val idxM = name1 lastIndexOf 'm' @@ -147,18 +152,18 @@ trait NameManglers { (name, "", "") def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name - def getterToLocal(name: TermName): TermName = name.toTermName append LOCAL_SUFFIX_STRING - def getterToSetter(name: TermName): TermName = name.toTermName append SETTER_SUFFIX - def localToGetter(name: TermName): TermName = name stripEnd LOCAL_SUFFIX_STRING toTermName + def getterToLocal(name: TermName): TermName = name append LOCAL_SUFFIX_STRING + def getterToSetter(name: TermName): TermName = name append SETTER_SUFFIX + def localToGetter(name: TermName): TermName = name dropRight LOCAL_SUFFIX_STRING.length def dropLocalSuffix(name: Name): Name = if (name endsWith ' ') name dropRight 1 else name def setterToGetter(name: TermName): TermName = { val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING) if (p < name.length) - setterToGetter(name.subName(p + TRAIT_SETTER_SEPARATOR_STRING.length, name.length)) + setterToGetter(name drop (p + TRAIT_SETTER_SEPARATOR_STRING.length)) else - name stripEnd SETTER_SUFFIX toTermName + name.subName(0, name.length - SETTER_SUFFIX.length) } def defaultGetterName(name: Name, pos: Int): TermName = { @@ -167,8 +172,8 @@ trait NameManglers { } def defaultGetterToMethod(name: Name): TermName = { val p = name.pos(DEFAULT_GETTER_STRING) - if (p < name.length) name.subName(0, p) - else name + if (p < name.length) name.toTermName.subName(0, p) + else name.toTermName } /** !!! I'm putting this logic in place because I can witness @@ -192,18 +197,14 @@ trait NameManglers { } def stripModuleSuffix(name: Name): Name = ( - if (isModuleName(name)) name stripEnd MODULE_SUFFIX_STRING else name + if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name ) - /** Note that for performance reasons, stripEnd does not verify that the - * suffix is actually the suffix specified. - */ - def dropSingletonName(name: Name): TypeName = name stripEnd SINGLETON_SUFFIX toTypeName + def dropSingletonName(name: Name): TypeName = name dropRight SINGLETON_SUFFIX.length toTypeName def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName - def interfaceName(implname: Name): TypeName = implname stripEnd IMPL_CLASS_SUFFIX toTypeName + def interfaceName(implname: Name): TypeName = implname dropRight IMPL_CLASS_SUFFIX.length toTypeName def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">") - def productAccessorName(i: Int): TermName = newTermName("_" + i) def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name) /** The name of an accessor for protected symbols. */ diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/compiler/scala/reflect/internal/Names.scala index 8453b1e758..b960695f51 100644 --- a/src/compiler/scala/reflect/internal/Names.scala +++ b/src/compiler/scala/reflect/internal/Names.scala @@ -71,25 +71,38 @@ trait Names extends api.Names { } /** Create a term name from the characters in cs[offset..offset+len-1]. */ - def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = { + def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = + newTermName(cs, offset, len, cachedString = null) + + def newTermName(cs: Array[Char]): TermName = newTermName(cs, 0, cs.length) + def newTypeName(cs: Array[Char]): TypeName = newTypeName(cs, 0, cs.length) + + /** Create a term name from the characters in cs[offset..offset+len-1]. */ + protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = { val h = hashValue(cs, offset, len) & HASH_MASK var n = termHashtable(h) while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len))) n = n.next - if (n eq null) { + + if (n ne null) n + else { // The logic order here is future-proofing against the possibility // that name.toString will become an eager val, in which case the call // to enterChars cannot follow the construction of the TermName. val ncStart = nc enterChars(cs, offset, len) - n = new TermName(ncStart, len, h) + if (cachedString ne null) new TermName_S(ncStart, len, h, cachedString) + else new TermName_R(ncStart, len, h) } - n } + protected def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName = + newTermName(cs, offset, len, cachedString).toTypeName /** Create a term name from string. */ - def newTermName(s: String): TermName = - newTermName(s.toCharArray(), 0, s.length()) + def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null) + + /** Create a type name from string. */ + def newTypeName(s: String): TypeName = newTermName(s).toTypeName /** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. */ def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName = { @@ -97,13 +110,15 @@ trait Names extends api.Names { newTermName(chars, 0, chars.length) } + def newTermNameCached(s: String): TermName = + newTermName(s.toCharArray(), 0, s.length(), cachedString = s) + + def newTypeNameCached(s: String): TypeName = + newTypeName(s.toCharArray(), 0, s.length(), cachedString = s) + /** Create a type name from the characters in cs[offset..offset+len-1]. */ def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName = - newTermName(cs, offset, len).toTypeName - - /** Create a type name from string. */ - def newTypeName(s: String): TypeName = - newTermName(s).toTypeName + newTermName(cs, offset, len, cachedString = null).toTypeName /** Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1]. */ def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName = @@ -114,19 +129,27 @@ trait Names extends api.Names { // Classes ---------------------------------------------------------------------- - /** The name class. */ + /** The name class. + * TODO - resolve schizophrenia regarding whether to treat Names as Strings + * or Strings as Names. Give names the key functions the absence of which + * make people want Strings all the time. + */ sealed abstract class Name(protected val index: Int, protected val len: Int) extends AbsName with Function1[Int, Char] { + type ThisNameType <: Name + protected[this] def thisName: ThisNameType + /** Index into name table */ def start: Int = index /** The next name in the same hash bucket. */ - def next: Name + def next: ThisNameType /** The length of this name. */ final def length: Int = len final def isEmpty = length == 0 final def nonEmpty = !isEmpty + def nameKind: String def isTermName: Boolean def isTypeName: Boolean def toTermName: TermName @@ -134,6 +157,15 @@ trait Names extends api.Names { def companionName: Name def bothNames: List[Name] = List(toTermName, toTypeName) + /** Return the subname with characters from from to to-1. */ + def subName(from: Int, to: Int): ThisNameType + + /** Return a new name of the same variety. */ + def newName(str: String): ThisNameType + + /** Return a new name based on string transformation. */ + def mapName(f: String => String): ThisNameType = newName(f(toString)) + /** Copy bytes of this name to buffer cs, starting at position `offset`. */ final def copyChars(cs: Array[Char], offset: Int) = compat.Platform.arraycopy(chrs, index, cs, offset, len) @@ -145,21 +177,13 @@ trait Names extends api.Names { cs } - /** @return the string representation of this name */ - final override def toString(): String = new String(chrs, index, len) - // Should we opt to make toString into a val to avoid the creation - // of 750,000 copies of x$1, here's the line. - // final override val toString = new String(chrs, index, len) - - def debugString() = NameTransformer.decode(toString) + (if (isTypeName) "!" else "") - /** Write to UTF8 representation of this name to given character array. * Start copying to index `to`. Return index of next free byte in array. * Array must have enough remaining space for all bytes * (i.e. maximally 3*length bytes). */ final def copyUTF8(bs: Array[Byte], offset: Int): Int = { - val bytes = Codec toUTF8 chrs.slice(index, index + len) + val bytes = Codec.toUTF8(chrs, index, len) compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length) offset + bytes.length } @@ -326,17 +350,20 @@ trait Names extends api.Names { final def startsWith(name: String): Boolean = startsWith(newTermName(name)) final def endsWith(char: Char): Boolean = len > 0 && endChar == char final def endsWith(name: String): Boolean = endsWith(newTermName(name)) - final def stripStart(prefix: Name): Name = subName(prefix.length, len) - final def stripStart(prefix: String): Name = subName(prefix.length, len) - final def stripEnd(suffix: Name): Name = subName(0, len - suffix.length) - final def stripEnd(suffix: String): Name = subName(0, len - suffix.length) - - def dropRight(n: Int) = subName(0, len - n) - - def lastIndexOf(ch: Char) = toChars lastIndexOf ch - /** Return the subname with characters from from to to-1. */ - def subName(from: Int, to: Int): Name + def dropRight(n: Int) = subName(0, len - n) + def drop(n: Int) = subName(n, len) + + def indexOf(ch: Char) = { + val idx = pos(ch) + if (idx == length) -1 else idx + } + def indexOf(ch: Char, fromIndex: Int) = { + val idx = pos(ch, fromIndex) + if (idx == length) -1 else idx + } + def lastIndexOf(ch: Char) = lastPos(ch) + def lastIndexOf(ch: Char, fromIndex: Int) = lastPos(ch, fromIndex) /** Replace all occurrences of `from` by `to` in * name; result is always a term name. @@ -351,31 +378,79 @@ trait Names extends api.Names { } newTermName(cs, 0, len) } + + /** TODO - reconcile/fix that encode returns a Name but + * decode returns a String. + */ /** Replace operator symbols by corresponding $op_name. */ - def encode: Name = { + def encode: ThisNameType = { val str = toString val res = NameTransformer.encode(str) - if (res == str) this - else if (isTypeName) newTypeName(res) - else newTermName(res) + if (res == str) thisName else newName(res) } - def append(ch: Char): Name - def append(suffix: String): Name - def append(suffix: Name): Name - /** Replace $op_name by corresponding operator symbol. */ - def decode: String = ( - NameTransformer.decode(toString) + - (if (nameDebug && isTypeName) "!" else ""))//debug + def decode: String = { + if (this containsChar '$') { + val str = toString + val res = NameTransformer.decode(str) + if (res == str) str + else res + } + else toString + } + /** TODO - find some efficiency. */ + def append(ch: Char) = newName("" + this + ch) + def append(suffix: String) = newName("" + this + suffix) + def append(suffix: Name) = newName("" + this + suffix) + def prepend(ch: Char) = newName("" + ch + this) + def prepend(prefix: String) = newName("" + prefix + this) + def prepend(prefix: Name) = newName("" + prefix + this) + + def decodedName: ThisNameType = newName(decode) def isOperatorName: Boolean = decode != toString - def nameKind: String = if (isTypeName) "type" else "term" - def longString: String = nameKind + " " + NameTransformer.decode(toString) + def longString: String = nameKind + " " + decode + def debugString = { val s = decode ; if (isTypeName) s + "!" else s } + } + + /** A name that contains no operator chars nor dollar signs. + * TODO - see if it's any faster to do something along these lines. + */ + trait AlphaNumName extends Name { + final override def encode = thisName + final override def decodedName = thisName + final override def decode = toString + final override def isOperatorName = false + } + + /** TermName_S and TypeName_S have fields containing the string version of the name. + * TermName_R and TypeName_R recreate it each time toString is called. + */ + private class TermName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TermName(index0, len0, hash) { + protected def createCompanionName(h: Int): TypeName = new TypeName_S(index, len, h, toString) + override def newName(str: String): TermName = newTermNameCached(str) + } + private class TypeName_S(index0: Int, len0: Int, hash: Int, override val toString: String) extends TypeName(index0, len0, hash) { + protected def createCompanionName(h: Int): TermName = new TermName_S(index, len, h, toString) + override def newName(str: String): TypeName = newTypeNameCached(str) + } + + private class TermName_R(index0: Int, len0: Int, hash: Int) extends TermName(index0, len0, hash) { + protected def createCompanionName(h: Int): TypeName = new TypeName_R(index, len, h) + override def toString = new String(chrs, index, len) } - final class TermName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) { + private class TypeName_R(index0: Int, len0: Int, hash: Int) extends TypeName(index0, len0, hash) { + protected def createCompanionName(h: Int): TermName = new TermName_R(index, len, h) + override def toString = new String(chrs, index, len) + } + + sealed abstract class TermName(index0: Int, len0: Int, hash: Int) extends Name(index0, len0) { + type ThisNameType = TermName + protected[this] def thisName: TermName = this + var next: TermName = termHashtable(hash) termHashtable(hash) = this def isTermName: Boolean = true @@ -385,20 +460,24 @@ trait Names extends api.Names { val h = hashValue(chrs, index, len) & HASH_MASK var n = typeHashtable(h) while ((n ne null) && n.start != index) - n = n.next; - if (n eq null) - n = new TypeName(index, len, h); - n + n = n.next + + if (n ne null) n + else createCompanionName(h) } - def append(ch: Char): TermName = append("" + ch) - def append(suffix: String): TermName = newTermName(this + suffix) - def append(suffix: Name): TermName = append(suffix.toString) + def newName(str: String): TermName = newTermName(str) def companionName: TypeName = toTypeName def subName(from: Int, to: Int): TermName = newTermName(chrs, start + from, to - from) + + def nameKind = "term" + protected def createCompanionName(h: Int): TypeName } - final class TypeName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) { + sealed abstract class TypeName(index0: Int, len0: Int, hash: Int) extends Name(index0, len0) { + type ThisNameType = TypeName + protected[this] def thisName: TypeName = this + var next: TypeName = typeHashtable(hash) typeHashtable(hash) = this def isTermName: Boolean = false @@ -407,18 +486,19 @@ trait Names extends api.Names { val h = hashValue(chrs, index, len) & HASH_MASK var n = termHashtable(h) while ((n ne null) && n.start != index) - n = n.next; - if (n eq null) - n = new TermName(index, len, h); - n + n = n.next + + if (n ne null) n + else createCompanionName(h) } def toTypeName: TypeName = this - - def append(ch: Char): TypeName = append("" + ch) - def append(suffix: String): TypeName = newTypeName(this + suffix) - def append(suffix: Name): TypeName = append(suffix.toString) + def newName(str: String): TypeName = newTypeName(str) def companionName: TermName = toTermName def subName(from: Int, to: Int): TypeName = newTypeName(chrs, start + from, to - from) + + def nameKind = "type" + override def decode = if (nameDebug) super.decode + "!" else super.decode + protected def createCompanionName(h: Int): TermName } } diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index 8afe276514..ea5565c581 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -8,18 +8,21 @@ package internal import scala.collection.immutable import NameTransformer.MODULE_SUFFIX_STRING +import annotation.switch -trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: SymbolTable => +trait StdNames extends NameManglers { self: SymbolTable => - def encode(str: String): TermName = newTermName(NameTransformer.encode(str)) + def encode(str: String): TermName = newTermNameCached(NameTransformer.encode(str)) + + implicit def lowerTermNames(n: TermName): String = "" + n - implicit def stringToTermName(s: String): TermName = newTermName(s) + // implicit def stringToTermName(s: String): TermName = newTermName(s) /** This should be the first trait in the linearization. */ trait Keywords { private var kws: Set[TermName] = Set() private def kw(s: String): TermName = { - val result = newTermName(s) + val result = newTermNameCached(s) kws = kws + result result } @@ -87,7 +90,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy trait CommonNames /*extends LibraryCommonNames*/ { type NameType <: Name - implicit def createNameType(name: String): NameType + protected implicit def createNameType(name: String): NameType val EMPTY: NameType = "" val ANON_FUN_NAME: NameType = "$anonfun" @@ -146,6 +149,10 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy final val String: NameType = "String" final val Throwable: NameType = "Throwable" + final val Annotation: NameType = "Annotation" + final val ClassfileAnnotation: NameType = "ClassfileAnnotation" + final val Enum: NameType = "Enum" + // Annotation simple names, used in Namer final val BeanPropertyAnnot: NameType = "BeanProperty" final val BooleanBeanPropertyAnnot: NameType = "BooleanBeanProperty" @@ -172,123 +179,191 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy final val SyntheticATTR: NameType = "Synthetic" } - trait TermNames extends Keywords with CommonNames { // Compiler internal names + val EXPAND_SEPARATOR_STRING = "$$" + val ANYNAME: NameType = "<anyname>" val CONSTRUCTOR: NameType = "<init>" val FAKE_LOCAL_THIS: NameType = "this$" val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something? + val LAZY_LOCAL: NameType = "$lzy" + val LOCAL_SUFFIX_STRING = " " + val MACRO: NameType = "macro$" + val MIRROR_PREFIX: NameType = "$mr." + val MIRROR_SHORT: NameType = "$mr" val MIXIN_CONSTRUCTOR: NameType = "$init$" val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" val OUTER: NameType = "$outer" - val OUTER_LOCAL: NameType = "$outer " // note the space + val OUTER_LOCAL: NameType = OUTER + LOCAL_SUFFIX_STRING // "$outer ", note the space val OUTER_SYNTH: NameType = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter + val SELECTOR_DUMMY: NameType = "<unapply-selector>" val SELF: NameType = "$this" val SPECIALIZED_INSTANCE: NameType = "specInstance$" val STAR: NameType = "*" val THIS: NameType = "_$this" - val SELECTOR_DUMMY: NameType = "<unapply-selector>" final val Nil: NameType = "Nil" final val Predef: NameType = "Predef" final val ScalaRunTime: NameType = "ScalaRunTime" final val Some: NameType = "Some" + + val _1 : NameType = "_1" + val _2 : NameType = "_2" + val _3 : NameType = "_3" + val _4 : NameType = "_4" + val _5 : NameType = "_5" + val _6 : NameType = "_6" + val _7 : NameType = "_7" + val _8 : NameType = "_8" + val _9 : NameType = "_9" + val _10 : NameType = "_10" + val _11 : NameType = "_11" + val _12 : NameType = "_12" + val _13 : NameType = "_13" + val _14 : NameType = "_14" + val _15 : NameType = "_15" + val _16 : NameType = "_16" + val _17 : NameType = "_17" + val _18 : NameType = "_18" + val _19 : NameType = "_19" + val _20 : NameType = "_20" + val _21 : NameType = "_21" + val _22 : NameType = "_22" + + val wrapRefArray: NameType = "wrapRefArray" + val wrapByteArray: NameType = "wrapByteArray" + val wrapShortArray: NameType = "wrapShortArray" + val wrapCharArray: NameType = "wrapCharArray" + val wrapIntArray: NameType = "wrapIntArray" + val wrapLongArray: NameType = "wrapLongArray" + val wrapFloatArray: NameType = "wrapFloatArray" + val wrapDoubleArray: NameType = "wrapDoubleArray" + val wrapBooleanArray: NameType = "wrapBooleanArray" + val wrapUnitArray: NameType = "wrapUnitArray" + val genericWrapArray: NameType = "genericWrapArray" // Compiler utilized names // val productElementName: NameType = "productElementName" - val TYPE_ : NameType = "TYPE" - val add_ : NameType = "add" - val anyValClass: NameType = "anyValClass" - val append: NameType = "append" - val apply: NameType = "apply" - val arrayValue: NameType = "arrayValue" - val arraycopy: NameType = "arraycopy" - val asInstanceOf_ : NameType = "asInstanceOf" - val assert_ : NameType = "assert" - val assume_ : NameType = "assume" - val box: NameType = "box" - val bytes: NameType = "bytes" - val canEqual_ : NameType = "canEqual" - val checkInitialized: NameType = "checkInitialized" - val classOf: NameType = "classOf" - val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure - val conforms: NameType = "conforms" - val copy: NameType = "copy" - val delayedInit: NameType = "delayedInit" - val delayedInitArg: NameType = "delayedInit$body" - val drop: NameType = "drop" - val elem: NameType = "elem" - val eq: NameType = "eq" - val equals_ : NameType = if (forMSIL) "Equals" else "equals" - val error: NameType = "error" - val ex: NameType = "ex" - val false_ : NameType = "false" - val filter: NameType = "filter" - val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize" - val find_ : NameType = "find" - val flatMap: NameType = "flatMap" - val foreach: NameType = "foreach" - val formatted: NameType = "formatted" - val genericArrayOps: NameType = "genericArrayOps" - val get: NameType = "get" - val hasNext: NameType = "hasNext" - val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode" - val hash_ : NameType = "hash" - val head: NameType = "head" - val identity: NameType = "identity" - val inlinedEquals: NameType = "inlinedEquals" - val applyDynamic: NameType = "applyDynamic" - val isArray: NameType = "isArray" - val isDefinedAt: NameType = "isDefinedAt" - val _isDefinedAt: NameType = "_isDefinedAt" - val isEmpty: NameType = "isEmpty" - val isInstanceOf_ : NameType = "isInstanceOf" - val java: NameType = "java" - val lang: NameType = "lang" - val length: NameType = "length" - val lengthCompare: NameType = "lengthCompare" - val lift_ : NameType = "lift" - val macro_ : NameType = "macro" - val main: NameType = "main" - val map: NameType = "map" - val missingCase: NameType = "missingCase" - val ne: NameType = "ne" - val newArray: NameType = "newArray" - val next: NameType = "next" - val notifyAll_ : NameType = "notifyAll" - val notify_ : NameType = "notify" - val null_ : NameType = "null" - val ofDim: NameType = "ofDim" - val productArity: NameType = "productArity" - val productElement: NameType = "productElement" - val productIterator: NameType = "productIterator" - val productPrefix: NameType = "productPrefix" - val readResolve: NameType = "readResolve" - val runOrElse: NameType = "runOrElse" - val sameElements: NameType = "sameElements" - val scala_ : NameType = "scala" - val self: NameType = "self" - val setAccessible: NameType = "setAccessible" - val synchronized_ : NameType = "synchronized" - val tail: NameType = "tail" - val this_ : NameType = "this" - val throw_ : NameType = "throw" - val toArray: NameType = "toArray" - val toList: NameType = "toList" - val toSeq: NameType = "toSeq" - val toString_ : NameType = if (forMSIL) "ToString" else "toString" - val true_ : NameType = "true" - val unapply: NameType = "unapply" - val unapplySeq: NameType = "unapplySeq" - val unbox: NameType = "unbox" - val update: NameType = "update" - val value: NameType = "value" - val view_ : NameType = "view" - val wait_ : NameType = "wait" - val withFilter: NameType = "withFilter" - val wrapRefArray: NameType = "wrapRefArray" - val zip: NameType = "zip" + val Ident: NameType = "Ident" + val TYPE_ : NameType = "TYPE" + val TypeTree: NameType = "TypeTree" + val UNIT : NameType = "UNIT" + val _isDefinedAt: NameType = "_isDefinedAt" + val add_ : NameType = "add" + val annotation: NameType = "annotation" + val anyValClass: NameType = "anyValClass" + val append: NameType = "append" + val apply: NameType = "apply" + val applyDynamic: NameType = "applyDynamic" + val args : NameType = "args" + val argv : NameType = "argv" + val arrayValue: NameType = "arrayValue" + val array_apply : NameType = "array_apply" + val array_clone : NameType = "array_clone" + val array_length : NameType = "array_length" + val array_update : NameType = "array_update" + val arraycopy: NameType = "arraycopy" + val asInstanceOf_ : NameType = "asInstanceOf" + val asTypeConstructor: NameType = "asTypeConstructor" + val assert_ : NameType = "assert" + val assume_ : NameType = "assume" + val box: NameType = "box" + val bytes: NameType = "bytes" + val canEqual_ : NameType = "canEqual" + val checkInitialized: NameType = "checkInitialized" + val classOf: NameType = "classOf" + val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure + val conforms: NameType = "conforms" + val copy: NameType = "copy" + val delayedInit: NameType = "delayedInit" + val delayedInitArg: NameType = "delayedInit$body" + val drop: NameType = "drop" + val elem: NameType = "elem" + val emptyValDef: NameType = "emptyValDef" + val ensureAccessible : NameType = "ensureAccessible" + val eq: NameType = "eq" + val equalsNumChar : NameType = "equalsNumChar" + val equalsNumNum : NameType = "equalsNumNum" + val equalsNumObject : NameType = "equalsNumObject" + val equals_ : NameType = if (forMSIL) "Equals" else "equals" + val error: NameType = "error" + val ex: NameType = "ex" + val false_ : NameType = "false" + val filter: NameType = "filter" + val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize" + val find_ : NameType = "find" + val flatMap: NameType = "flatMap" + val foreach: NameType = "foreach" + val formatted: NameType = "formatted" + val freeValue : NameType = "freeValue" + val genericArrayOps: NameType = "genericArrayOps" + val get: NameType = "get" + val glob : NameType = "glob" + val hasNext: NameType = "hasNext" + val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode" + val hash_ : NameType = "hash" + val head: NameType = "head" + val identity: NameType = "identity" + val inlinedEquals: NameType = "inlinedEquals" + val isArray: NameType = "isArray" + val isDefinedAt: NameType = "isDefinedAt" + val isEmpty: NameType = "isEmpty" + val isInstanceOf_ : NameType = "isInstanceOf" + val java: NameType = "java" + val lang: NameType = "lang" + val length: NameType = "length" + val lengthCompare: NameType = "lengthCompare" + val lift_ : NameType = "lift" + val macro_ : NameType = "macro" + val main: NameType = "main" + val map: NameType = "map" + val mirror : NameType = "mirror" + val missingCase: NameType = "missingCase" + val ne: NameType = "ne" + val newArray: NameType = "newArray" + val newScopeWith: NameType = "newScopeWith" + val next: NameType = "next" + val notifyAll_ : NameType = "notifyAll" + val notify_ : NameType = "notify" + val null_ : NameType = "null" + val ofDim: NameType = "ofDim" + val productArity: NameType = "productArity" + val productElement: NameType = "productElement" + val productIterator: NameType = "productIterator" + val productPrefix: NameType = "productPrefix" + val readResolve: NameType = "readResolve" + val runOrElse: NameType = "runOrElse" + val runtime: NameType = "runtime" + val sameElements: NameType = "sameElements" + val scala_ : NameType = "scala" + val self: NameType = "self" + val setAccessible: NameType = "setAccessible" + val setAnnotations: NameType = "setAnnotations" + val setTypeSig: NameType = "setTypeSig" + val synchronized_ : NameType = "synchronized" + val tail: NameType = "tail" + val thisModuleType: NameType = "thisModuleType" + val this_ : NameType = "this" + val throw_ : NameType = "throw" + val toArray: NameType = "toArray" + val toList: NameType = "toList" + val toObjectArray : NameType = "toObjectArray" + val toSeq: NameType = "toSeq" + val toString_ : NameType = if (forMSIL) "ToString" else "toString" + val true_ : NameType = "true" + val typedProductIterator: NameType = "typedProductIterator" + val unapply: NameType = "unapply" + val unapplySeq: NameType = "unapplySeq" + val unbox: NameType = "unbox" + val update: NameType = "update" + val value: NameType = "value" + val valueOf : NameType = "valueOf" + val values : NameType = "values" + val view_ : NameType = "view" + val wait_ : NameType = "wait" + val withFilter: NameType = "withFilter" + val zip: NameType = "zip" // unencoded operators object raw { @@ -316,21 +391,53 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val toLong: NameType = "toLong" val toFloat: NameType = "toFloat" val toDouble: NameType = "toDouble" + + // primitive operation methods for structual types mostly + // overlap with the above, but not for these two. + val toCharacter: NameType = "toCharacter" + val toInteger: NameType = "toInteger" } object tpnme extends TypeNames /*with LibraryTypeNames*/ with TypeNameMangling { type NameType = TypeName - implicit def createNameType(name: String): TypeName = newTypeName(name) + protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) val REFINE_CLASS_NAME: NameType = "<refinement>" val ANON_CLASS_NAME: NameType = "$anon" } + + /** For fully qualified type names. + */ + object fulltpnme extends TypeNames { + type NameType = TypeName + protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) + + val RuntimeNothing: NameType = "scala.runtime.Nothing$" + val RuntimeNull: NameType = "scala.runtime.Null$" + val JavaLangEnum: NameType = "java.lang.Enum" + } + + /** Java binary names, like scala/runtime/Nothing$. + */ + object binarynme { + def toBinary(name: Name) = name mapName (_.replace('.', '/')) + + val RuntimeNothing = toBinary(fulltpnme.RuntimeNothing).toTypeName + val RuntimeNull = toBinary(fulltpnme.RuntimeNull).toTypeName + } + + object fullnme extends TermNames { + type NameType = TermName + protected implicit def createNameType(name: String): TermName = newTermNameCached(name) + + val MirrorPackage: NameType = "scala.reflect.mirror" + } val javanme = nme.javaKeywords object nme extends TermNames /*with LibraryTermNames*/ with TermNameMangling { type NameType = TermName - def createNameType(name: String): TermName = newTermName(name) + protected implicit def createNameType(name: String): TermName = newTermNameCached(name) /** Translate a String into a list of simple TypeNames and TermNames. * In all segments before the last, type/term is determined by whether @@ -363,7 +470,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy case -1 => if (name == "") scala.Nil else scala.List(mkName(name, assumeTerm)) // otherwise, we can tell based on whether '#' or '.' is the following char. case idx => - val (simple, div, rest) = (name take idx, name charAt idx, name drop (idx + 1)) + val (simple, div, rest) = (name take idx, name charAt idx, newTermName(name) drop (idx + 1)) mkName(simple, div == '.') :: segments(rest, assumeTerm) } } @@ -380,26 +487,27 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy /** The expanded name of `name` relative to this class `base` with given `separator` */ def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName = - newTermName(base.fullName('$') + separator + name) + newTermNameCached(base.fullName('$') + separator + name) - def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_VAR_SUFFIX) - - val EXPAND_SEPARATOR_STRING = "$$" - val LOCAL_SUFFIX_STRING = " " + def moduleVarName(name: TermName): TermName = + newTermNameCached("" + name + MODULE_VAR_SUFFIX) + val ROOTPKG: TermName = "_root_" /** Base strings from which synthetic names are derived. */ - val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$" - val DEFAULT_GETTER_STRING = "$default$" - val DO_WHILE_PREFIX = "doWhile$" - val EQEQ_LOCAL_VAR = "eqEqTemp$" - val EVIDENCE_PARAM_PREFIX = "evidence$" - val EXCEPTION_RESULT_PREFIX = "exceptionResult" - val INTERPRETER_IMPORT_WRAPPER = "$iw" - val INTERPRETER_LINE_PREFIX = "line" - val INTERPRETER_VAR_PREFIX = "res" - val INTERPRETER_WRAPPER_SUFFIX = "$object" - val WHILE_PREFIX = "while$" + val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$" + val DEFAULT_GETTER_STRING = "$default$" + val DO_WHILE_PREFIX = "doWhile$" + val EQEQ_LOCAL_VAR_STRING = "eqEqTemp$" + val EVIDENCE_PARAM_PREFIX = "evidence$" + val EXCEPTION_RESULT_PREFIX = "exceptionResult" + val INTERPRETER_IMPORT_WRAPPER = "$iw" + val INTERPRETER_LINE_PREFIX = "line" + val INTERPRETER_VAR_PREFIX = "res" + val INTERPRETER_WRAPPER_SUFFIX = "$object" + val WHILE_PREFIX = "while$" + + val EQEQ_LOCAL_VAR: TermName = newTermName(EQEQ_LOCAL_VAR_STRING) def getCause = sn.GetCause def getClass_ = sn.GetClass @@ -424,8 +532,8 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val MUL = encode("*") val NE = encode("!=") val OR = encode("|") - val PLUS = encode("+") - val SUB = encode("-") + val PLUS = ADD // technically redundant, but ADD looks funny with MINUS + val SUB = MINUS // ... as does SUB with PLUS val XOR = encode("^") val ZAND = encode("&&") val ZOR = encode("||") @@ -435,10 +543,138 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val UNARY_+ = encode("unary_+") val UNARY_- = encode("unary_-") val UNARY_! = encode("unary_!") + + // Grouped here so Cleanup knows what tests to perform. + val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) + val ConversionNames = Set[Name](toByte, toChar, toDouble, toFloat, toInt, toLong, toShort) + val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames + val NumberOpNames = ( + Set[Name](ADD, SUB, MUL, DIV, MOD, LSL, LSR, ASR, LT, LE, GE, GT) + ++ Set(UNARY_+, UNARY_-, UNARY_!) + ++ ConversionNames + ++ CommonOpNames + ) + + val add: NameType = "add" + val complement: NameType = "complement" + val divide: NameType = "divide" + val multiply: NameType = "multiply" + val negate: NameType = "negate" + val positive: NameType = "positive" + val shiftLogicalRight: NameType = "shiftLogicalRight" + val shiftSignedLeft: NameType = "shiftSignedLeft" + val shiftSignedRight: NameType = "shiftSignedRight" + val subtract: NameType = "subtract" + val takeAnd: NameType = "takeAnd" + val takeConditionalAnd: NameType = "takeConditionalAnd" + val takeConditionalOr: NameType = "takeConditionalOr" + val takeModulo: NameType = "takeModulo" + val takeNot: NameType = "takeNot" + val takeOr: NameType = "takeOr" + val takeXor: NameType = "takeXor" + val testEqual: NameType = "testEqual" + val testGreaterOrEqualThan: NameType = "testGreaterOrEqualThan" + val testGreaterThan: NameType = "testGreaterThan" + val testLessOrEqualThan: NameType = "testLessOrEqualThan" + val testLessThan: NameType = "testLessThan" + val testNotEqual: NameType = "testNotEqual" + + val isBoxedNumberOrBoolean: NameType = "isBoxedNumberOrBoolean" + val isBoxedNumber: NameType = "isBoxedNumber" + + def toUnaryName(name: TermName): TermName = name match { + case raw.MINUS => UNARY_- + case raw.PLUS => UNARY_+ + case raw.TILDE => UNARY_~ + case raw.BANG => UNARY_! + case _ => name + } + /** The name of a method which stands in for a primitive operation + * during structural type dispatch. + */ + def primitiveInfixMethodName(name: Name): TermName = name match { + case OR => takeOr + case XOR => takeXor + case AND => takeAnd + case EQ => testEqual + case NE => testNotEqual + case ADD => add + case SUB => subtract + case MUL => multiply + case DIV => divide + case MOD => takeModulo + case LSL => shiftSignedLeft + case LSR => shiftLogicalRight + case ASR => shiftSignedRight + case LT => testLessThan + case LE => testLessOrEqualThan + case GE => testGreaterOrEqualThan + case GT => testGreaterThan + case ZOR => takeConditionalOr + case ZAND => takeConditionalAnd + case _ => NO_NAME + } + /** Postfix/prefix, really. + */ + def primitivePostfixMethodName(name: Name): TermName = name match { + case UNARY_! => takeNot + case UNARY_+ => positive + case UNARY_- => negate + case UNARY_~ => complement + case `toByte` => toByte + case `toShort` => toShort + case `toChar` => toCharacter + case `toInt` => toInteger + case `toLong` => toLong + case `toFloat` => toFloat + case `toDouble` => toDouble + case _ => NO_NAME + } + + val reflPolyCacheName: NameType = "reflPoly$Cache" + val reflClassCacheName: NameType = "reflClass$Cache" + val reflParamsCacheName: NameType = "reflParams$Cache" + val reflMethodCacheName: NameType = "reflMethod$Cache" + val reflMethodName: NameType = "reflMethod$Method" + + private val reflectionCacheNames = Set[NameType]( + reflPolyCacheName, + reflClassCacheName, + reflParamsCacheName, + reflMethodCacheName, + reflMethodName + ) + def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) + + @switch def productAccessorName(j: Int): TermName = j match { + case 1 => nme._1 + case 2 => nme._2 + case 3 => nme._3 + case 4 => nme._4 + case 5 => nme._5 + case 6 => nme._6 + case 7 => nme._7 + case 8 => nme._8 + case 9 => nme._9 + case 10 => nme._10 + case 11 => nme._11 + case 12 => nme._12 + case 13 => nme._13 + case 14 => nme._14 + case 15 => nme._15 + case 16 => nme._16 + case 17 => nme._17 + case 18 => nme._18 + case 19 => nme._19 + case 20 => nme._20 + case 21 => nme._21 + case 22 => nme._22 + case _ => newTermName("_" + j) + } } abstract class SymbolNames { - protected implicit def stringToTypeName(s: String): TypeName = newTypeName(s) + protected implicit def createNameType(s: String): TypeName = newTypeNameCached(s) val BeanProperty : TypeName val BooleanBeanProperty : TypeName @@ -471,7 +707,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy class JavaKeywords { private var kws: Set[TermName] = Set() private def kw(s: String): TermName = { - val result = newTermName(s) + val result = newTermNameCached(s) kws = kws + result result } @@ -555,12 +791,12 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy final val Throwable: TypeName = "java.lang.Throwable" final val ValueType: TypeName = tpnme.NO_NAME - final val ForName: TermName = "forName" - final val GetCause: TermName = "getCause" - final val GetClass: TermName = "getClass" - final val GetMethod: TermName = "getMethod" - final val Invoke: TermName = "invoke" - final val JavaLang: TermName = "java.lang" + final val ForName: TermName = newTermName("forName") + final val GetCause: TermName = newTermName("getCause") + final val GetClass: TermName = newTermName("getClass") + final val GetMethod: TermName = newTermName("getMethod") + final val Invoke: TermName = newTermName("invoke") + final val JavaLang: TermName = newTermName("java.lang") val Boxed = immutable.Map[TypeName, TypeName]( tpnme.Boolean -> BoxedBoolean, @@ -593,12 +829,12 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy final val Throwable: TypeName = "System.Exception" final val ValueType: TypeName = "System.ValueType" - final val ForName: TermName = "GetType" - final val GetCause: TermName = "InnerException" /* System.Reflection.TargetInvocationException.InnerException */ - final val GetClass: TermName = "GetType" - final val GetMethod: TermName = "GetMethod" - final val Invoke: TermName = "Invoke" - final val JavaLang: TermName = "System" + final val ForName: TermName = newTermName("GetType") + final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */ + final val GetClass: TermName = newTermName("GetType") + final val GetMethod: TermName = newTermName("GetMethod") + final val Invoke: TermName = newTermName("Invoke") + final val JavaLang: TermName = newTermName("System") val Boxed = immutable.Map[TypeName, TypeName]( tpnme.Boolean -> "System.Boolean", diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 0c57f0c43a..6ee061392c 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -264,7 +264,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Create a new getter for current symbol (which must be a field) */ final def newGetter: Symbol = ( - owner.newMethod(focusPos(pos), nme.getterName(name)) + owner.newMethod(focusPos(pos), nme.getterName(name.toTermName)) setFlag getterFlags(flags) setPrivateWithin privateWithin setInfo MethodType(Nil, tpe) @@ -409,7 +409,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isError = hasFlag(IS_ERROR) final def isErroneous = isError || isInitialized && tpe.isErroneous final def isTypeParameterOrSkolem = isType && hasFlag(PARAM) - final def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem + final def isHigherOrderTypeParameter = (this ne NoSymbol) && owner.isTypeParameterOrSkolem final def isTypeSkolem = isSkolem && hasFlag(PARAM) // a type symbol bound by an existential type, for instance the T in // List[T] forSome { type T } @@ -430,7 +430,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isDefinedInPackage = effectiveOwner.isPackageClass final def isJavaInterface = isJavaDefined && isTrait - final def needsFlatClasses: Boolean = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass + final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass // In java.lang, Predef, or scala package/package object def isInDefaultNamespace = UnqualifiedOwners(effectiveOwner) @@ -699,16 +699,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => rawowner = owner } - private[Symbols] def flattenName(): Name = { - // This assertion caused me no end of trouble in the interpeter in situations - // where everything proceeds smoothly if there's no assert. I don't think calling "name" - // on a symbol is the right place to throw fatal exceptions if things don't look right. - // It really hampers exploration. Finally I gave up and disabled it, and tickets like - // SI-4874 instantly start working. - // assert(rawowner.isClass, "fatal: %s has non-class owner %s after flatten.".format(rawname + idString, rawowner)) - - nme.flattenedName(rawowner.name, rawname) - } def ownerChain: List[Symbol] = this :: owner.ownerChain def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain @@ -793,7 +783,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * Never adds id. * Drops package objects. */ - final def fullName(separator: Char): String = nme.dropLocalSuffix(fullNameInternal(separator)).toString + final def fullName(separator: Char): String = fullNameAsName(separator).toString /** Doesn't drop package objects, for those situations (e.g. classloading) * where the true path is needed. @@ -801,8 +791,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def fullNameInternal(separator: Char): Name = ( if (isRoot || isRootPackage || this == NoSymbol) name else if (owner.isEffectiveRoot) name - else effectiveOwner.enclClass.fullName(separator) append separator append name + else effectiveOwner.enclClass.fullNameAsName(separator) append separator append name ) + + def fullNameAsName(separator: Char): Name = nme.dropLocalSuffix(fullNameInternal(separator)) /** The encoded full path name of this symbol, where outer names and inner names * are separated by periods. @@ -1244,12 +1236,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def isNestedIn(that: Symbol): Boolean = owner == that || owner != NoSymbol && (owner isNestedIn that) - - /** Is this class symbol a subclass of that symbol? */ - final def isNonBottomSubClass(that: Symbol): Boolean = ( - (this eq that) || this.isError || that.isError || - info.baseTypeIndex(that) >= 0 - ) + + /** Is this class symbol a subclass of that symbol, + * and is this class symbol also different from Null or Nothing? */ + def isNonBottomSubClass(that: Symbol): Boolean = false /** Overridden in NullClass and NothingClass for custom behavior. */ @@ -1371,7 +1361,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** The symbol accessed by this accessor function, but with given owner type. */ final def accessed(ownerTp: Type): Symbol = { assert(hasAccessorFlag, this) - ownerTp decl nme.getterToLocal(getterName) + ownerTp decl nme.getterToLocal(getterName.toTermName) } /** The module corresponding to this module class (note that this @@ -1704,17 +1694,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def getter(base: Symbol): Symbol = base.info.decl(getterName) filter (_.hasAccessorFlag) - def getterName: Name = ( - if (isSetter) nme.setterToGetter(name) - else if (nme.isLocalName(name)) nme.localToGetter(name) - else name + def getterName: TermName = ( + if (isSetter) nme.setterToGetter(name.toTermName) + else if (nme.isLocalName(name)) nme.localToGetter(name.toTermName) + else name.toTermName ) /** The setter of this value or getter definition, or NoSymbol if none exists */ final def setter(base: Symbol): Symbol = setter(base, false) final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = { - var sname = nme.getterToSetter(nme.getterName(name)) + var sname = nme.getterToSetter(nme.getterName(name.toTermName)) if (hasExpandedName) sname = nme.expandedSetterName(sname, base) base.info.decl(sname) filter (_.hasAccessorFlag) } @@ -1769,7 +1759,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => getter(owner).expandName(base) setter(owner).expandName(base) } - name = nme.expandedName(name, base) + name = nme.expandedName(name.toTermName, base) if (isType) name = name } } @@ -2003,7 +1993,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => extends Symbol(initOwner, initPos, initName) { final override def isTerm = true - override def name: TermName = super.name + override def name: TermName = rawname.toTermName privateWithin = NoSymbol var referenced: Symbol = NoSymbol @@ -2090,20 +2080,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => class ModuleSymbol(initOwner: Symbol, initPos: Position, initName: TermName) extends TermSymbol(initOwner, initPos, initName) { private var flatname: TermName = null - // This method could use a better name from someone clearer on what the condition expresses. - private def isFlatAdjusted = !isMethod && needsFlatClasses - override def owner: Symbol = - if (isFlatAdjusted) rawowner.owner + override def owner = ( + if (!isMethod && needsFlatClasses) rawowner.owner else rawowner - - override def name: TermName = - if (isFlatAdjusted) { - if (flatname == null) - flatname = flattenName().toTermName - + ) + override def name: TermName = ( + if (!isMethod && needsFlatClasses) { + if (flatname eq null) + flatname = nme.flattenedName(rawowner.name, rawname) + flatname - } else rawname + } + else rawname.toTermName + ) override def cloneSymbolImpl(owner: Symbol): Symbol = new ModuleSymbol(owner, pos, name).copyAttrsFrom(this) @@ -2226,6 +2216,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => super.info_=(tp) } + final override def isNonBottomSubClass(that: Symbol): Boolean = ( + (this eq that) || this.isError || that.isError || + info.baseTypeIndex(that) >= 0 + ) + override def reset(completer: Type) { super.reset(completer) tpePeriod = NoPeriod @@ -2297,7 +2292,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** A class for class symbols */ class ClassSymbol(initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { - + private var flatname: TypeName = null private var source: AbstractFileType = null private var thissym: Symbol = this @@ -2316,20 +2311,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => thissym = this } - private var flatname: TypeName = null - - override def owner: Symbol = - if (needsFlatClasses) rawowner.owner - else rawowner - - override def name: TypeName = - if (needsFlatClasses) { - if (flatname == null) - flatname = flattenName().toTypeName - flatname - } - else rawname.asInstanceOf[TypeName] - private var thisTypeCache: Type = _ private var thisTypePeriod = NoPeriod @@ -2345,7 +2326,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => } thisTypeCache } - + + override def owner: Symbol = + if (needsFlatClasses) rawowner.owner else rawowner + override def name: TypeName = ( + if (needsFlatClasses) { + if (flatname eq null) + flatname = nme.flattenedName(rawowner.name, rawname).toTypeName + + flatname + } + else rawname.toTypeName + ) + /** A symbol carrying the self type of the class as its type */ override def thisSym: Symbol = thissym @@ -2416,7 +2409,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def sourceModule_=(module: Symbol) { this.module = module } } - class FreeVar(name: TermName, tpe: Type, val value: Any) extends TermSymbol(definitions.RootClass, NoPosition, name) { + class FreeVar(name0: TermName, tpe: Type, val value: Any) extends TermSymbol(definitions.RootClass, NoPosition, name0) { setInfo(tpe) override def hashCode = value.hashCode @@ -2520,6 +2513,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => val syms1 = cloneSymbolsAtOwner(syms, owner) creator(syms1, tpe.substSym(syms, syms1)) } + + /** A deep map on a symbol's paramss. + */ + def mapParamss[T](sym: Symbol)(f: Symbol => T): List[List[T]] = mmap(sym.info.paramss)(f) /** Create a new existential type skolem with the given owner and origin. */ diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index 14bf36fb47..e3ee39d2a0 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -192,7 +192,7 @@ abstract class TreeInfo { def isVariableOrGetter(tree: Tree) = { def sym = tree.symbol def isVar = sym.isVariable - def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(nme.getterToSetter(sym.name)) != NoSymbol + def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(nme.getterToSetter(sym.name.toTermName)) != NoSymbol tree match { case Ident(_) => isVar diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 566ee0e9cf..96f2c5cc45 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -160,12 +160,12 @@ trait Trees extends api.Trees { self: SymbolTable => */ def ModuleDef(sym: Symbol, impl: Template): ModuleDef = atPos(sym.pos) { - ModuleDef(Modifiers(sym.flags), sym.name, impl) setSymbol sym + ModuleDef(Modifiers(sym.flags), sym.name.toTermName, impl) setSymbol sym } def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) { - ValDef(Modifiers(sym.flags), sym.name, + ValDef(Modifiers(sym.flags), sym.name.toTermName, TypeTree(sym.tpe) setPos focusPos(sym.pos), rhs) setSymbol sym } @@ -182,7 +182,7 @@ trait Trees extends api.Trees { self: SymbolTable => atPos(sym.pos) { assert(sym != NoSymbol) DefDef(Modifiers(sym.flags), - sym.name, + sym.name.toTermName, sym.typeParams map TypeDef, vparamss, TypeTree(sym.tpe.finalResultType) setPos focusPos(sym.pos), @@ -193,7 +193,7 @@ trait Trees extends api.Trees { self: SymbolTable => DefDef(sym, Modifiers(sym.flags), vparamss, rhs) def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef = - DefDef(sym, mods, sym.paramss map (_.map(ValDef)), rhs) + DefDef(sym, mods, mapParamss(sym)(ValDef), rhs) def DefDef(sym: Symbol, rhs: Tree): DefDef = DefDef(sym, Modifiers(sym.flags), rhs) @@ -214,7 +214,7 @@ trait Trees extends api.Trees { self: SymbolTable => def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = atPos(sym.pos) { - LabelDef(sym.name, params map Ident, rhs) setSymbol sym + LabelDef(sym.name.toTermName, params map Ident, rhs) setSymbol sym } @@ -248,10 +248,13 @@ trait Trees extends api.Trees { self: SymbolTable => /** Block factory that flattens directly nested blocks. */ - def Block(stats: Tree*): Block = stats match { - case Seq(b @ Block(_, _)) => b - case Seq(stat) => Block(stats.toList, Literal(Constant(()))) - case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) + def Block(stats: Tree*): Block = { + if (stats.isEmpty) Block(Nil, Literal(Constant(()))) + else stats match { + case Seq(b @ Block(_, _)) => b + case Seq(stat) => Block(stats.toList, Literal(Constant(()))) + case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) + } } // --- specific traversers and transformers diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a644baf9f9..4630733db4 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -87,8 +87,13 @@ trait Types extends api.Types { self: SymbolTable => private final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1 private final val printLubs = sys.props contains "scalac.debug.lub" + private final val traceTypeVars = sys.props contains "scalac.debug.tvar" /** In case anyone wants to turn off lub verification without reverting anything. */ private final val verifyLubs = true + /** In case anyone wants to turn off type parameter bounds being used + * to seed type constraints. + */ + private final val propagateParameterBoundsToTypeVars = sys.props contains "scalac.debug.prop-constraints" protected val enableTypeVarExperimentals = settings.Xexperimental.value @@ -499,6 +504,9 @@ trait Types extends api.Types { self: SymbolTable => * Alternatives of overloaded symbol appear in the order they are declared. */ def decl(name: Name): Symbol = findDecl(name, 0) + + /** A list of all non-private members defined or declared in this type. */ + def nonPrivateDecls: List[Symbol] = decls filter (x => !x.isPrivate) toList /** The non-private defined or declared members with name `name` in this type; * an OverloadedSymbol if several exist, NoSymbol if none exist. @@ -537,6 +545,16 @@ trait Types extends api.Types { self: SymbolTable => */ def nonPrivateMember(name: Name): Symbol = memberBasedOnName(name, BridgeAndPrivateFlags) + + /** All members with the given flags, excluding bridges. + */ + def membersWithFlags(requiredFlags: Long): List[Symbol] = + membersBasedOnFlags(BridgeFlags, requiredFlags) + + /** All non-private members with the given flags, excluding bridges. + */ + def nonPrivateMembersWithFlags(requiredFlags: Long): List[Symbol] = + membersBasedOnFlags(BridgeAndPrivateFlags, requiredFlags) /** The non-private member with given name, admitting members with given flags `admit`. * "Admitting" refers to the fact that members with a PRIVATE, BRIDGE, or VBRIDGE @@ -552,7 +570,10 @@ trait Types extends api.Types { self: SymbolTable => * an OverloadedSymbol if several exist, NoSymbol if none exist */ def nonLocalMember(name: Name): Symbol = memberBasedOnName(name, BridgeFlags | LOCAL) - + + /** Members excluding and requiring the given flags. + * Note: unfortunately it doesn't work to exclude DEFERRED this way. + */ def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] = findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives @@ -1017,7 +1038,6 @@ trait Types extends api.Types { self: SymbolTable => baseClasses.head.newOverloaded(this, members.toList) } } - /** The existential skolems and existentially quantified variables which are free in this type */ def existentialSkolems: List[Symbol] = { var boundSyms: List[Symbol] = List() @@ -1298,6 +1318,7 @@ trait Types extends api.Types { self: SymbolTable => case TypeBounds(_, _) => that <:< this case _ => lo <:< that && that <:< hi } + def isEmptyBounds = (lo.typeSymbolDirect eq NothingClass) && (hi.typeSymbolDirect eq AnyClass) // override def isNullable: Boolean = NullClass.tpe <:< lo; override def safeToString = ">: " + lo + " <: " + hi override def kind = "TypeBoundsType" @@ -2416,31 +2437,54 @@ A type's typeSymbol should never be inspected directly. // but pattern-matching returned the original constr0 (a bug) // now, pattern-matching returns the most recent constr object TypeVar { - // encapsulate suspension so we can automatically link the suspension of cloned - // typevars to their original if this turns out to be necessary -/* - def Suspension = new Suspension - class Suspension { - private val suspended = mutable.HashSet[TypeVar]() - def suspend(tv: TypeVar): Unit = { - tv.suspended = true - suspended += tv - } - def resumeAll(): Unit = { - for (tv <- suspended) { - tv.suspended = false + @inline final def trace[T](action: String, msg: => String)(value: T): T = { + if (traceTypeVars) { + val s = msg match { + case "" => "" + case str => "( " + str + " )" } - suspended.clear() + Console.err.println("[%10s] %-25s%s".format(action, value, s)) } + value + } + + /** Create a new TypeConstraint based on the given symbol. + */ + private def deriveConstraint(tparam: Symbol): TypeConstraint = { + /** Must force the type parameter's info at this point + * or things don't end well for higher-order type params. + * See SI-5359. + */ + val bounds = tparam.info.bounds + /** We can seed the type constraint with the type parameter + * bounds as long as the types are concrete. This should lower + * the complexity of the search even if it doesn't improve + * any results. + */ + if (propagateParameterBoundsToTypeVars) { + val exclude = bounds.isEmptyBounds || bounds.exists(_.typeSymbolDirect.isNonClassType) + + if (exclude) new TypeConstraint + else TypeVar.trace("constraint", "For " + tparam.fullLocationString)(new TypeConstraint(bounds)) + } + else new TypeConstraint + } + def unapply(tv: TypeVar): Some[(Type, TypeConstraint)] = Some((tv.origin, tv.constr)) + def apply(origin: Type, constr: TypeConstraint): TypeVar = apply(origin, constr, Nil, Nil) + def apply(tparam: Symbol): TypeVar = apply(tparam.tpeHK, deriveConstraint(tparam), Nil, tparam.typeParams) + + /** This is the only place TypeVars should be instantiated. + */ + def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]): TypeVar = { + val tv = ( + if (args.isEmpty && params.isEmpty) new TypeVar(origin, constr) + else if (args.size == params.size) new AppliedTypeVar(origin, constr, params zip args) + else if (args.isEmpty) new HKTypeVar(origin, constr, params) + else throw new TypeError("Invalid TypeVar construction: " + ((origin, constr, args, params))) + ) + + trace("create", "In " + tv.originLocation)(tv) } -*/ - def unapply(tv: TypeVar): Some[(Type, TypeConstraint)] = Some((tv.origin, tv.constr)) - def apply(origin: Type, constr: TypeConstraint) = new TypeVar(origin, constr, List(), List()) - // TODO why not initialise TypeConstraint with bounds of tparam? - // @PP: I tried that, didn't work out so well for me. - def apply(tparam: Symbol) = new TypeVar(tparam.tpeHK, new TypeConstraint, List(), tparam.typeParams) - def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]) = - new TypeVar(origin, constr, args, params) } // TODO: I don't really know why this happens -- maybe because @@ -2467,23 +2511,53 @@ A type's typeSymbol should never be inspected directly. tp.typeSymbol ) + /** Precondition: params.nonEmpty. (args.nonEmpty enforced structurally.) + */ + class HKTypeVar( + _origin: Type, + _constr: TypeConstraint, + override val params: List[Symbol] + ) extends TypeVar(_origin, _constr) { + + require(params.nonEmpty, this) + override def isHigherKinded = true + override protected def typeVarString = params.map(_.name).mkString("[", ", ", "]=>" + originName) + } + + /** Precondition: zipped params/args nonEmpty. (Size equivalence enforced structurally.) + */ + class AppliedTypeVar( + _origin: Type, + _constr: TypeConstraint, + zippedArgs: List[(Symbol, Type)] + ) extends TypeVar(_origin, _constr) { + + require(zippedArgs.nonEmpty, this) + + override def params: List[Symbol] = zippedArgs map (_._1) + override def typeArgs: List[Type] = zippedArgs map (_._2) + + override protected def typeVarString = ( + zippedArgs map { case (p, a) => p.name + "=" + a } mkString (origin + "[", ", ", "]") + ) + } + /** A class representing a type variable: not used after phase `typer`. * * A higher-kinded TypeVar has params (Symbols) and typeArgs (Types). * A TypeVar with nonEmpty typeArgs can only be instantiated by a higher-kinded * type that can be applied to those args. A TypeVar is much like a TypeRef, * except it has special logic for equality and subtyping. + * + * Precondition for this class, enforced structurally: args.isEmpty && params.isEmpty. */ class TypeVar( val origin: Type, - val constr0: TypeConstraint, - override val typeArgs: List[Type], - override val params: List[Symbol] + val constr0: TypeConstraint ) extends Type { - private val numArgs = typeArgs.length - // params are needed to keep track of variance (see mapOverArgs in SubstMap) - assert(typeArgs.isEmpty || sameLength(typeArgs, params)) - // var tid = { tidCount += 1; tidCount } //DEBUG + override def params: List[Symbol] = Nil + override def typeArgs: List[Type] = Nil + override def isHigherKinded = false /** The constraint associated with the variable */ var constr = constr0 @@ -2491,7 +2565,38 @@ A type's typeSymbol should never be inspected directly. /** The variable's skolemization level */ val level = skolemizationLevel - + + /** Two occurrences of a higher-kinded typevar, e.g. `?CC[Int]` and `?CC[String]`, correspond to + * ''two instances'' of `TypeVar` that share the ''same'' `TypeConstraint`. + * + * `constr` for `?CC` only tracks type constructors anyway, + * so when `?CC[Int] <:< List[Int]` and `?CC[String] <:< Iterable[String]` + * `?CC's` hibounds contains List and Iterable. + */ + def applyArgs(newArgs: List[Type]): TypeVar = ( + if (newArgs.isEmpty && typeArgs.isEmpty) + this + else if (newArgs.size == params.size) { + val tv = TypeVar(origin, constr, newArgs, params) + TypeVar.trace("applyArgs", "In " + originLocation + ", apply args " + newArgs.mkString(", ") + " to " + originName)(tv) + } + else + throw new TypeError("Invalid type application in TypeVar: " + params + ", " + newArgs) + ) + // newArgs.length may differ from args.length (could've been empty before) + // + // !!! @PP - I need an example of this, since this exception never triggers + // even though I am requiring the size match. + // + // example: when making new typevars, you start out with C[A], then you replace C by ?C, which should yield ?C[A], then A by ?A, ?C[?A] + // we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver) + // TypeVars get applied to different arguments over time (in asSeenFrom) + // -- see pos/tcpoly_infer_implicit_tuplewrapper.scala + // thus: make new TypeVar's for every application of a TV to args, + // inference may generate several TypeVar's for a single type parameter that must be inferred, + // only one of them is in the set of tvars that need to be solved, but + // they share the same TypeConstraint instance + // When comparing to types containing skolems, remember the highest level // of skolemization. If that highest level is higher than our initial // skolemizationLevel, we can't re-use those skolems as the solution of this @@ -2502,26 +2607,6 @@ A type's typeSymbol should never be inspected directly. private var encounteredHigherLevel = false private def shouldRepackType = enableTypeVarExperimentals && encounteredHigherLevel - /** Two occurrences of a higher-kinded typevar, e.g. `?CC[Int]` and `?CC[String]`, correspond to - * ''two instances'' of `TypeVar` that share the ''same'' `TypeConstraint`. - * - * `constr` for `?CC` only tracks type constructors anyway, - * so when `?CC[Int] <:< List[Int]` and `?CC[String] <:< Iterable[String]` - * `?CC's` hibounds contains List and Iterable. - */ - def applyArgs(newArgs: List[Type]): TypeVar = - if (newArgs.isEmpty) this // SubstMap relies on this (though this check is redundant when called from appliedType...) - else TypeVar(origin, constr, newArgs, params) // @M TODO: interaction with undoLog?? - // newArgs.length may differ from args.length (could've been empty before) - // example: when making new typevars, you start out with C[A], then you replace C by ?C, which should yield ?C[A], then A by ?A, ?C[?A] - // we need to track a TypeVar's arguments, and map over them (see TypeMap::mapOver) - // TypeVars get applied to different arguments over time (in asSeenFrom) - // -- see pos/tcpoly_infer_implicit_tuplewrapper.scala - // thus: make new TypeVar's for every application of a TV to args, - // inference may generate several TypeVar's for a single type parameter that must be inferred, - // only one of them is in the set of tvars that need to be solved, but - // they share the same TypeConstraint instance - // <region name="constraint mutators + undoLog"> // invariant: before mutating constr, save old state in undoLog // (undoLog is used to reset constraints to avoid piling up unrelated ones) @@ -2530,7 +2615,8 @@ A type's typeSymbol should never be inspected directly. undoLog record this // if we were compared against later typeskolems, repack the existential, // because skolems are only compatible if they were created at the same level - constr.inst = if (shouldRepackType) repackExistential(tp) else tp + val res = if (shouldRepackType) repackExistential(tp) else tp + constr.inst = TypeVar.trace("setInst", "In " + originLocation + ", " + originName + "=" + res)(res) } def addLoBound(tp: Type, isNumericBound: Boolean = false) { @@ -2607,11 +2693,10 @@ A type's typeSymbol should never be inspected directly. * type parameter we're trying to infer (the result will be sanity-checked later). */ def unifyFull(tpe: Type) = { - // Since the alias/widen variations are often no-ops, this - // keenly collects them in a Set to avoid redundant tests. + // The alias/widen variations are often no-ops. val tpes = ( - if (isLowerBound) Set(tpe, tpe.widen, tpe.dealias, tpe.widen.dealias) - else Set(tpe) + if (isLowerBound) List(tpe, tpe.widen, tpe.dealias, tpe.widen.dealias).distinct + else List(tpe) ) tpes exists { tp => val lhs = if (isLowerBound) tp.typeArgs else typeArgs @@ -2711,32 +2796,56 @@ A type's typeSymbol should never be inspected directly. || !containsSkolemAboveLevel(tp) // side-effects tracking boolean || enableTypeVarExperimentals // -Xexperimental: always say we're relatable, track consequences ) - override val isHigherKinded = typeArgs.isEmpty && params.nonEmpty - override def normalize: Type = + override def normalize: Type = ( if (constr.instValid) constr.inst // get here when checking higher-order subtyping of the typevar by itself // TODO: check whether this ever happens? else if (isHigherKinded) typeFun(params, applyArgs(params map (_.typeConstructor))) else super.normalize - + ) override def typeSymbol = origin.typeSymbol override def isStable = origin.isStable override def isVolatile = origin.isVolatile - private def levelString = if (settings.explaintypes.value) level else "" - override def safeToString = constr.inst match { - case null => "<null " + origin + ">" - case NoType => "?" + levelString + origin + typeArgsString(this) - case x => "" + x + private def tparamsOfSym(sym: Symbol) = sym.info match { + case PolyType(tparams, _) if tparams.nonEmpty => + tparams map (_.defString) mkString("[", ",", "]") + case _ => "" + } + def originName = { + val name = origin.typeSymbolDirect.decodedName + if (name contains "_$") origin.typeSymbolDirect.decodedName else name } + def originLocation = { + val sym = origin.typeSymbolDirect + val encl = sym.owner.logicallyEnclosingMember + + // This should display somewhere between one and three + // things which enclose the origin: at most, a class, a + // a method, and a term. At least, a class. + List( + Some(encl.enclClass), + if (encl.isMethod) Some(encl) else None, + if (sym.owner.isTerm && (sym.owner != encl)) Some(sym.owner) else None + ).flatten map (s => s.decodedName + tparamsOfSym(s)) mkString "#" + } + private def levelString = if (settings.explaintypes.value) level else "" + protected def typeVarString = originName + override def safeToString = ( + if ((constr eq null) || (constr.inst eq null)) "TVar<" + originName + "=null>" + else if (constr.inst ne NoType) "" + constr.inst + else "?" + levelString + originName + ) override def kind = "TypeVar" def cloneInternal = { // cloning a suspended type variable when it's suspended will cause the clone // to never be resumed with the current implementation - assert(!suspended) - TypeVar(origin, constr cloneInternal, typeArgs, params) // @M TODO: clone args/params? + assert(!suspended, this) + TypeVar.trace("clone", originLocation)( + TypeVar(origin, constr cloneInternal, typeArgs, params) // @M TODO: clone args/params? + ) } } @@ -2993,6 +3102,9 @@ A type's typeSymbol should never be inspected directly. /** A creator for intersection type where intersections of a single type are * replaced by the type itself, and repeated parent classes are merged. + * + * !!! Repeated parent classes are not merged - is this a bug in the + * comment or in the code? */ def intersectionType(tps: List[Type], owner: Symbol): Type = tps match { case List(tp) => @@ -3187,7 +3299,7 @@ A type's typeSymbol should never be inspected directly. val isType = pnames.head.isTypeName val newParams = for (name <- pnames) yield if (isType) owner.newTypeParameter(NoPosition, name.toTypeName) - else owner.newValueParameter(NoPosition, name) + else owner.newValueParameter(NoPosition, name.toTermName) paramStack = newParams :: paramStack try { (newParams, ptypes).zipped foreach ((p, t) => p setInfo this(t)) @@ -3230,10 +3342,15 @@ A type's typeSymbol should never be inspected directly. */ class TypeConstraint(lo0: List[Type], hi0: List[Type], numlo0: Type, numhi0: Type, avoidWidening0: Boolean = false) { def this(lo0: List[Type], hi0: List[Type]) = this(lo0, hi0, NoType, NoType) + def this(bounds: TypeBounds) = this(List(bounds.lo), List(bounds.hi)) def this() = this(List(), List()) - private var lobounds = lo0 - private var hibounds = hi0 + /** Guard these lists against AnyClass and NothingClass appearing, + * else loBounds.isEmpty will have different results for an empty + * constraint and one with Nothing as a lower bound. + */ + private var lobounds = lo0 filterNot (_.typeSymbolDirect eq NothingClass) + private var hibounds = hi0 filterNot (_.typeSymbolDirect eq AnyClass) private var numlo = numlo0 private var numhi = numhi0 private var avoidWidening = avoidWidening0 @@ -3249,7 +3366,8 @@ A type's typeSymbol should never be inspected directly. else if (!isNumericSubType(tp, numlo)) numlo = numericLoBound } - else lobounds ::= tp + else if (tp.typeSymbolDirect ne NothingClass) + lobounds ::= tp } def checkWidening(tp: Type) { @@ -3268,7 +3386,8 @@ A type's typeSymbol should never be inspected directly. else if (!isNumericSubType(numhi, tp)) numhi = numericHiBound } - else hibounds ::= tp + else if (tp.typeSymbolDirect ne AnyClass) + hibounds ::= tp } def isWithinBounds(tp: Type): Boolean = @@ -3287,10 +3406,18 @@ A type's typeSymbol should never be inspected directly. tc } - override def toString = - (loBounds map (_.safeToString)).mkString("[ _>:(", ",", ") ") + - (hiBounds map (_.safeToString)).mkString("| _<:(", ",", ") ] _= ") + - inst.safeToString + override def toString = { + val boundsStr = ( + if (loBounds.isEmpty && hiBounds.isEmpty) "[]" + else { + val lostr = if (loBounds.isEmpty) "" else loBounds map (_.safeToString) mkString("_>:(", ", ", ")") + val histr = if (hiBounds.isEmpty) "" else hiBounds map (_.safeToString) mkString("_<:(", ", ", ")") + List(lostr, histr) filterNot (_ == "") mkString ("[", " | ", "]") + } + ) + if (inst eq NoType) boundsStr + else boundsStr + " _= " + inst.safeToString + } } trait AnnotationFilter extends TypeMap { @@ -4141,7 +4268,7 @@ A type's typeSymbol should never be inspected directly. case WildcardType => TypeVar(tp, new TypeConstraint) case BoundedWildcardType(bounds) => - TypeVar(tp, new TypeConstraint(List(bounds.lo), List(bounds.hi))) + TypeVar(tp, new TypeConstraint(bounds)) case _ => mapOver(tp) } @@ -5455,6 +5582,23 @@ A type's typeSymbol should never be inspected directly. val formatted = tableDef.table(transposed) println("** Depth is " + depth + "\n" + formatted) } + + /** From a list of types, find any which take type parameters + * where the type parameter bounds contain references to other + * any types in the list (including itself.) + * + * @return List of symbol pairs holding the recursive type + * parameter and the parameter which references it. + */ + def findRecursiveBounds(ts: List[Type]): List[(Symbol, Symbol)] = { + if (ts.isEmpty) Nil + else { + val sym = ts.head.typeSymbol + require(ts.tail forall (_.typeSymbol == sym), ts) + for (p <- sym.typeParams ; in <- sym.typeParams ; if in.info.bounds contains p) yield + p -> in + } + } /** Given a matrix `tsBts` whose columns are basetype sequences (and the symbols `tsParams` that should be interpreted as type parameters in this matrix), * compute its least sorted upwards closed upper bound relative to the following ordering <= between lists of types: @@ -5501,6 +5645,19 @@ A type's typeSymbol should never be inspected directly. // merging, strip targs that refer to bound tparams (when we're computing the lub of type // constructors.) Also filter out all types that are a subtype of some other type. if (isUniformFrontier) { + if (settings.debug.value || printLubs) { + val fbounds = findRecursiveBounds(ts0) + if (fbounds.nonEmpty) { + println("Encountered " + fbounds.size + " recursive bounds while lubbing " + ts0.size + " types.") + for ((p0, p1) <- fbounds) { + val desc = if (p0 == p1) "its own bounds" else "the bounds of " + p1 + + println(" " + p0.fullLocationString + " appears in " + desc) + println(" " + p1 + " " + p1.info.bounds) + } + println("") + } + } val tails = tsBts map (_.tail) mergePrefixAndArgs(elimSub(ts0 map elimHigherOrderTypeParam, depth), 1, depth) match { case Some(tp) => tp :: loop(tails) @@ -5526,7 +5683,7 @@ A type's typeSymbol should never be inspected directly. } } - val initialBTSes = ts map (_.baseTypeSeq.toList) + val initialBTSes = ts map (_.baseTypeSeq.toList filter (_.typeSymbol.isPublic)) if (printLubs) printLubMatrix(ts zip initialBTSes toMap, depth) @@ -5719,9 +5876,16 @@ A type's typeSymbol should never be inspected directly. val lubType = if (phase.erasedTypes || depth == 0) lubBase else { - val lubRefined = refinedType(lubParents, lubOwner) + val lubRefined = refinedType(lubParents, lubOwner) val lubThisType = lubRefined.typeSymbol.thisType - val narrowts = ts map (_.narrow) + val narrowts = ts map (_.narrow) + def excludeFromLub(sym: Symbol) = ( + sym.isClass + || sym.isConstructor + || !sym.isPublic + || isGetClass(sym) + || narrowts.exists(t => !refines(t, sym)) + ) def lubsym(proto: Symbol): Symbol = { val prototp = lubThisType.memberInfo(proto) val syms = narrowts map (t => @@ -5750,16 +5914,15 @@ A type's typeSymbol should never be inspected directly. // efficiency. alt != sym && !specializesSym(lubThisType, sym, tp, alt))) } - for (sym <- lubBase.nonPrivateMembers) { - // add a refinement symbol for all non-class members of lubBase - // which are refined by every type in ts. - if (!sym.isClass && !sym.isConstructor && !isGetClass(sym) && (narrowts forall (t => refines(t, sym)))) - try { - val lsym = lubsym(sym) - if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lubsym(sym)) - } catch { - case ex: NoCommonType => - } + // add a refinement symbol for all non-class members of lubBase + // which are refined by every type in ts. + for (sym <- lubBase.nonPrivateMembers ; if !excludeFromLub(sym)) { + try { + val lsym = lubsym(sym) + if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lsym) + } catch { + case ex: NoCommonType => + } } if (lubRefined.decls.isEmpty) lubBase else if (!verifyLubs) lubRefined @@ -5977,7 +6140,7 @@ A type's typeSymbol should never be inspected directly. // conforming to bounds. val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass) if (bounds0.isEmpty) AnyClass.tpe - else intersectionType(bounds0) + else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym))) } else if (tparam.variance == -variance) NothingClass.tpe else NoType diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 9927560c8c..0789f9c774 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -184,6 +184,8 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { case _ => errorBadSignature("bad name tag: " + tag) } } + protected def readTermName(): TermName = readName().toTermName + protected def readTypeName(): TypeName = readName().toTypeName /** Read a symbol */ protected def readSymbol(): Symbol = { @@ -211,7 +213,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { return NoSymbol if (tag == EXTMODCLASSref) { - val moduleVar = owner.info.decl(nme.moduleVarName(name)) + val moduleVar = owner.info.decl(nme.moduleVarName(name.toTermName)) if (moduleVar.isLazyAccessor) return moduleVar.lazyAccessor.lazyAccessor } @@ -223,7 +225,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { // (2) Try with expanded name. Can happen if references to private // symbols are read from outside: for instance when checking the children // of a class. See #1722. - fromName(nme.expandedName(name, owner)) orElse { + fromName(nme.expandedName(name.toTermName, owner)) orElse { // (3) Try as a nested object symbol. nestedObjectSymbol orElse { // (4) Otherwise, fail. @@ -296,14 +298,14 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... () if (isModuleRoot) moduleRoot else { - val m = owner.newModule(name, clazz) + val m = owner.newModule(name.toTermName, clazz) clazz.sourceModule = m m } case VALsym => if (isModuleRoot) { assert(false); NoSymbol } - else if (isMethodFlag) owner.newMethod(name) - else owner.newValue(name) + else if (isMethodFlag) owner.newMethod(name.toTermName) + else owner.newValue(name.toTermName) case _ => errorBadSignature("bad symbol tag: " + tag) @@ -549,13 +551,13 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { case MODULEtree => setSymModsName() - ModuleDef(mods, name, readTemplateRef()) + ModuleDef(mods, name.toTermName, readTemplateRef()) case VALDEFtree => setSymModsName() val tpt = readTreeRef() val rhs = readTreeRef() - ValDef(mods, name, tpt, rhs) + ValDef(mods, name.toTermName, tpt, rhs) case DEFDEFtree => setSymModsName() @@ -563,7 +565,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { val vparamss = times(readNat(), () => times(readNat(), readValDefRef)) val tpt = readTreeRef() val rhs = readTreeRef() - DefDef(mods, name, tparams, vparamss, tpt, rhs) + DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs) case TYPEDEFtree => setSymModsName() @@ -575,7 +577,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { setSymName() val rhs = readTreeRef() val params = until(end, readIdentRef) - LabelDef(name, params, rhs) + LabelDef(name.toTermName, params, rhs) case IMPORTtree => setSym() diff --git a/src/compiler/scala/reflect/internal/util/Collections.scala b/src/compiler/scala/reflect/internal/util/Collections.scala index 28a17c7821..94672097c4 100644 --- a/src/compiler/scala/reflect/internal/util/Collections.scala +++ b/src/compiler/scala/reflect/internal/util/Collections.scala @@ -21,6 +21,23 @@ trait Collections { else !xs2.isEmpty && !xs3.isEmpty && f(xs1.head, xs2.head, xs3.head) && corresponds3(xs1.tail, xs2.tail, xs3.tail)(f) ) + /** All these mm methods are "deep map" style methods for + * mapping etc. on a list of lists. + */ + final def mexists[A](xss: List[List[A]])(p: A => Boolean) = + xss exists (_ exists p) + final def mmap[A, B](xss: List[List[A]])(f: A => B) = + xss map (_ map f) + final def mforeach[A](xss: List[List[A]])(f: A => Unit) = + xss foreach (_ foreach f) + final def mfind[A](xss: List[List[A]])(p: A => Boolean): Option[A] = { + for (xs <- xss; x <- xs) + if (p(x)) return Some(x) + None + } + final def mfilter[A](xss: List[List[A]])(p: A => Boolean) = + for (xs <- xss; x <- xs; if p(x)) yield x + final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = { val lb = new ListBuffer[C] var ys1 = xs1 @@ -136,3 +153,6 @@ trait Collections { true } } + +object Collections extends Collections { } + diff --git a/src/compiler/scala/tools/nsc/util/Origins.scala b/src/compiler/scala/reflect/internal/util/Origins.scala index f8ba34ae3c..b9985c8f50 100644 --- a/src/compiler/scala/tools/nsc/util/Origins.scala +++ b/src/compiler/scala/reflect/internal/util/Origins.scala @@ -3,10 +3,12 @@ * @author Paul Phillips */ -package scala.tools.nsc -package util +package scala.reflect +package internal.util -import scala.reflect.NameTransformer._ +import NameTransformer._ +import scala.collection.{ mutable, immutable } +import Origins._ /** A debugging class for logging from whence a method is being called. * Say you wanted to discover who was calling phase_= in SymbolTable. @@ -33,10 +35,6 @@ import scala.reflect.NameTransformer._ }}} * */ - -import scala.collection.{ mutable, immutable } -import Origins._ - abstract class Origins { type Rep def newRep(xs: StackSlice): Rep @@ -94,7 +92,9 @@ object Origins { def apply(tag: String, clazz: Class[_]): Origins = apply(tag, new OneLine(clazz)) def apply(tag: String, orElse: => Origins): Origins = { counters find (_.tag == tag) getOrElse { - returning(orElse setTag tag)(counters += _) + val res = orElse setTag tag + counters += res + res } } diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index aa0572aceb..9da75bf2b0 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -272,7 +272,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => */ private def approximateMatch(sym: Symbol, jstr: String): Boolean = (sym.name.toString == jstr) || - sym.isPrivate && nme.expandedName(sym.name, sym.owner).toString == jstr + sym.isPrivate && nme.expandedName(sym.name.toTermName, sym.owner).toString == jstr /** * Find declarations or definition in class `clazz` that maps to a Java @@ -353,32 +353,28 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => * not available, wrapped from the Java reflection info. */ def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) { - if (jclazz.isMemberClass && !nme.isImplClassName(jclazz.getName)) { - val sym = sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)) + val jname = javaTypeName(jclazz) + def lookup = sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)) + + if (jclazz.isMemberClass && !nme.isImplClassName(jname)) { + val sym = lookup assert(sym.isType, sym+"/"+jclazz+"/"+sOwner(jclazz)+"/"+jclazz.getSimpleName) sym.asInstanceOf[ClassSymbol] - } else if (jclazz.isLocalClass || invalidClassName(jclazz.getName)) { + } + else if (jclazz.isLocalClass || invalidClassName(jname)) { // local classes and implementation classes not preserved by unpickling - treat as Java jclassAsScala(jclazz) - } else if (jclazz.isArray) { + } + else if (jclazz.isArray) { ArrayClass - } else jclazz match { - case java.lang.Void.TYPE => UnitClass - case java.lang.Byte.TYPE => ByteClass - case java.lang.Character.TYPE => CharClass - case java.lang.Short.TYPE => ShortClass - case java.lang.Integer.TYPE => IntClass - case java.lang.Long.TYPE => LongClass - case java.lang.Float.TYPE => FloatClass - case java.lang.Double.TYPE => DoubleClass - case java.lang.Boolean.TYPE => BooleanClass - case _ => - // jclazz is top-level - get signature - sOwner(jclazz).info decl newTypeName(jclazz.getSimpleName) -// val (clazz, module) = createClassModule( -// sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _)) -// classCache enter (jclazz, clazz) -// clazz + } + else javaTypeToValueClass(jclazz) orElse { + // jclazz is top-level - get signature + lookup + // val (clazz, module) = createClassModule( + // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _)) + // classCache enter (jclazz, clazz) + // clazz } } diff --git a/src/compiler/scala/reflect/runtime/ScalaToJava.scala b/src/compiler/scala/reflect/runtime/ScalaToJava.scala index b1e4d6224c..405a00de8d 100644 --- a/src/compiler/scala/reflect/runtime/ScalaToJava.scala +++ b/src/compiler/scala/reflect/runtime/ScalaToJava.scala @@ -29,17 +29,7 @@ trait ScalaToJava extends ConversionUtil { self: SymbolTable => def noClass = throw new ClassNotFoundException("no Java class corresponding to "+clazz+" found") //println("classToJava "+clazz+" "+clazz.owner+" "+clazz.owner.isPackageClass)//debug if (clazz.isValueClass) - clazz match { - case UnitClass => java.lang.Void.TYPE - case ByteClass => java.lang.Byte.TYPE - case CharClass => java.lang.Character.TYPE - case ShortClass => java.lang.Short.TYPE - case IntClass => java.lang.Integer.TYPE - case LongClass => java.lang.Long.TYPE - case FloatClass => java.lang.Float.TYPE - case DoubleClass => java.lang.Double.TYPE - case BooleanClass => java.lang.Boolean.TYPE - } + valueClassToJavaType(clazz) else if (clazz == ArrayClass) noClass else if (clazz.owner.isPackageClass) @@ -54,7 +44,7 @@ trait ScalaToJava extends ConversionUtil { self: SymbolTable => } private def expandedName(sym: Symbol): String = - if (sym.isPrivate) nme.expandedName(sym.name, sym.owner).toString + if (sym.isPrivate) nme.expandedName(sym.name.toTermName, sym.owner).toString else sym.name.toString def fieldToJava(fld: Symbol): jField = fieldCache.toJava(fld) { diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 9f44e2047a..231bcdbc0e 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -33,7 +33,7 @@ trait ToolBoxes extends { self: Universe => private def nextWrapperModuleName() = { wrapCount += 1 - "__wrapper$" + wrapCount + newTermName("__wrapper$" + wrapCount) } private def moduleFileName(className: String) = className + "$" @@ -57,8 +57,8 @@ trait ToolBoxes extends { self: Universe => val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), new Scope, obj.moduleClass) obj.moduleClass setInfo minfo obj setInfo obj.moduleClass.tpe - val meth = obj.moduleClass.newMethod(NoPosition, wrapperMethodName) - def makeParam(fv: Symbol) = meth.newValueParameter(NoPosition, fv.name) setInfo fv.tpe + val meth = obj.moduleClass.newMethod(NoPosition, newTermName(wrapperMethodName)) + def makeParam(fv: Symbol) = meth.newValueParameter(NoPosition, fv.name.toTermName) setInfo fv.tpe meth setInfo MethodType(fvs map makeParam, expr.tpe) minfo.decls enter meth trace("wrapping ")(defOwner(expr) -> meth) diff --git a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala index 8c9e6a2565..9d66ca6c6e 100644 --- a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala +++ b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala @@ -3,11 +3,9 @@ package runtime trait TreeBuildUtil extends Universe with api.TreeBuildUtil { - def staticClass(fullname: String): Symbol = definitions.getClass(newTypeName(fullname)) - def staticModule(fullname: String): Symbol = definitions.getModule(newTermName(fullname)) - - def thisModuleType(fullname: String) = - definitions.getModule(fullname).moduleClass.thisType + def staticClass(fullname: String): Symbol = definitions.getRequiredClass(fullname) + def staticModule(fullname: String): Symbol = definitions.getRequiredModule(fullname) + def thisModuleType(fullname: String) = staticModule(fullname).moduleClass.thisType /** Selects type symbol with given name from the defined members of prefix type */ @@ -41,7 +39,7 @@ trait TreeBuildUtil extends Universe with api.TreeBuildUtil { selectIn(owner.info, idx) } - def freeVar(name: String, info: Type, value: Any) = new FreeVar(name, info, value) + def freeVar(name: String, info: Type, value: Any) = new FreeVar(newTermName(name), info, value) def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers = Modifiers(flags, privateWithin, annotations) diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 470207fd35..940d115b2f 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -74,6 +74,9 @@ trait CompilationUnits { self: Global => * It is empty up to phase 'icode'. */ val icode: LinkedHashSet[icodes.IClass] = new LinkedHashSet + + def echo(pos: Position, msg: String) = + reporter.echo(pos, msg) def error(pos: Position, msg: String) = reporter.error(pos, msg) diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index b10ac78ac7..6393ade146 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -136,9 +136,9 @@ class StandardCompileServer extends SocketServer { } if (command.shouldStopWithInfo) - reporter.info(null, command.getInfoMessage(newGlobal(newSettings, reporter)), true) + reporter.echo(command.getInfoMessage(newGlobal(newSettings, reporter))) else if (command.files.isEmpty) - reporter.info(null, command.usageMsg, true) + reporter.echo(command.usageMsg) else { if (isCompilerReusable) { info("[Reusing existing Global instance.]") diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index db95c1442b..0c52954a0b 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -24,8 +24,8 @@ abstract class Driver { protected def doCompile(compiler: Global) { if (command.files.isEmpty) { - reporter.info(null, command.usageMsg, true) - reporter.info(null, compiler.pluginOptionsHelp, true) + reporter.echo(command.usageMsg) + reporter.echo(compiler.pluginOptionsHelp) } else { val run = new compiler.Run() run compile command.files @@ -40,14 +40,14 @@ abstract class Driver { settings = command.settings if (settings.version.value) { - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) } else if (processSettingsHook()) { val compiler = newCompiler() try { if (reporter.hasErrors) reporter.flush() else if (command.shouldStopWithInfo) - reporter.info(null, command.getInfoMessage(compiler), true) + reporter.echo(command.getInfoMessage(compiler)) else doCompile(compiler) } catch { diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 2dd32e355b..c388a62644 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -159,7 +159,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb // nearly every trait really must go. For now using globalError. def error(msg: String) = globalError(msg) def globalError(msg: String) = reporter.error(NoPosition, msg) - def inform(msg: String) = reporter.info(NoPosition, msg, true) + def inform(msg: String) = reporter.echo(msg) def warning(msg: String) = if (opt.fatalWarnings) globalError(msg) else reporter.warning(NoPosition, msg) diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala index a9330b053b..4fa2cc71e5 100644 --- a/src/compiler/scala/tools/nsc/ScalaDoc.scala +++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala @@ -30,17 +30,17 @@ class ScalaDoc { def hasFiles = command.files.nonEmpty || docSettings.uncompilableFiles.nonEmpty if (docSettings.version.value) - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) else if (docSettings.Xhelp.value) - reporter.info(null, command.xusageMsg, true) + reporter.echo(command.xusageMsg) else if (docSettings.Yhelp.value) - reporter.info(null, command.yusageMsg, true) + reporter.echo(command.yusageMsg) else if (docSettings.showPlugins.value) reporter.warning(null, "Plugins are not available when using Scaladoc") else if (docSettings.showPhases.value) reporter.warning(null, "Phases are restricted when using Scaladoc") else if (docSettings.help.value || !hasFiles) - reporter.info(null, command.usageMsg, true) + reporter.echo(command.usageMsg) else try { if (docSettings.target.value == "msil") msilLibPath foreach (x => docSettings.assemrefs.value += (pathSeparator + x)) diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index f9c818daf0..6a6379cca2 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -220,8 +220,8 @@ trait DocComments { self: Global => else site.info.baseClasses searchList collectFirst { case x if defs(x) contains vble => defs(x)(vble) } match { - case Some(str) if str startsWith '$' => lookupVariable(str.tail, site) - case res => res orElse lookupVariable(vble, site.owner) + case Some(str) if str startsWith "$" => lookupVariable(str.tail, site) + case res => res orElse lookupVariable(vble, site.owner) } } @@ -397,7 +397,7 @@ trait DocComments { self: Global => if (tpe != NoType) tpe else { val alias1 = alias.cloneSymbol(definitions.RootClass) - alias1.name = repl.toTypeName + alias1.name = newTypeName(repl) typeRef(NoPrefix, alias1, Nil) } case None => diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 752e3c6699..7b5de1f3dd 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -360,7 +360,7 @@ abstract class TreeBrowsers { ("Program", EMPTY) case UnitTree(unit) => - ("CompilationUnit", unit.toString) + ("CompilationUnit", newTermName("" + unit)) case DocDef(comment, definition) => ("DocDef", EMPTY) @@ -441,7 +441,7 @@ abstract class TreeBrowsers { ("Apply", EMPTY) case Super(qualif, mix) => - ("Super", "mix: " + mix) + ("Super", newTermName("mix: " + mix)) case This(qualifier) => ("This", qualifier) diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index efc64dbbc5..2cfd21ecc8 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -202,7 +202,7 @@ trait TreeDSL { class DefSymStart(val sym: Symbol) extends SymVODDStart with DefCreator { def symType = sym.tpe.finalResultType def tparams = sym.typeParams map TypeDef - def vparamss = sym.paramss map (xs => xs map ValDef) + def vparamss = mapParamss(sym)(ValDef) } class ValSymStart(val sym: Symbol) extends SymVODDStart with ValCreator { def symType = sym.tpe diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 0dc3b1fffd..e69c463e71 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -128,7 +128,7 @@ abstract class TreeGen extends reflect.internal.TreeGen { def mkManifestFactoryCall(full: Boolean, constructor: String, tparg: Type, args: List[Tree]): Tree = mkMethodCall( if (full) FullManifestModule else PartialManifestModule, - constructor, + newTermName(constructor), List(tparg), args ) @@ -161,16 +161,10 @@ abstract class TreeGen extends reflect.internal.TreeGen { * apply the element type directly. */ def mkWrapArray(tree: Tree, elemtp: Type) = { - val sym = elemtp.typeSymbol - val meth: Name = - if (isValueClass(sym)) "wrap"+sym.name+"Array" - else if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(sym)) "wrapRefArray" - else "genericWrapArray" - mkMethodCall( PredefModule, - meth, - if (isValueClass(sym)) Nil else List(elemtp), + wrapArrayMethodName(elemtp), + if (isScalaValueType(elemtp)) Nil else List(elemtp), List(tree) ) } @@ -179,8 +173,8 @@ abstract class TreeGen extends reflect.internal.TreeGen { * elem type elemtp to expected type pt. */ def mkCastArray(tree: Tree, elemtp: Type, pt: Type) = - if (elemtp.typeSymbol == AnyClass && isValueClass(tree.tpe.typeArgs.head.typeSymbol)) - mkCast(mkRuntimeCall("toObjectArray", List(tree)), pt) + if (elemtp.typeSymbol == AnyClass && isScalaValueType(tree.tpe.typeArgs.head)) + mkCast(mkRuntimeCall(nme.toObjectArray, List(tree)), pt) else mkCast(tree, pt) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 00ac3976a9..d7bfcfc314 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -314,7 +314,7 @@ self => val stmts = templateStatSeq(false)._2 accept(EOF) - def mainModuleName = settings.script.value + def mainModuleName = newTermName(settings.script.value) /** If there is only a single object template in the file and it has a * suitable main method, we will use it rather than building another object * around it. Since objects are loaded lazily the whole script would have @@ -343,7 +343,7 @@ self => * whole additional parse. So instead, if the actual object's name differs from * what the script is expecting, we transform it to match. */ - if (name.toString == mainModuleName) md + if (name == mainModuleName) md else treeCopy.ModuleDef(md, mods, mainModuleName, template) case _ => /** If we see anything but the above, fail. */ @@ -352,7 +352,7 @@ self => Some(makePackaging(0, emptyPkg, newStmts)) } - if (mainModuleName == ScriptRunner.defaultScriptMain) + if (mainModuleName == newTermName(ScriptRunner.defaultScriptMain)) searchForMain() foreach { return _ } /** Here we are building an AST representing the following source fiction, @@ -384,13 +384,13 @@ self => // def main def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String))) - def mainParameter = List(ValDef(Modifiers(Flags.PARAM), "argv", mainParamType, EmptyTree)) - def mainSetArgv = List(ValDef(NoMods, "args", TypeTree(), Ident("argv"))) + def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree)) + def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv))) def mainNew = makeNew(Nil, emptyValDef, stmts, List(Nil), NoPosition, NoPosition) def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, mainNew)) // object Main - def moduleName = ScriptRunner scriptMain settings + def moduleName = newTermName(ScriptRunner scriptMain settings) def moduleBody = Template(List(scalaScalaObjectConstr), emptyValDef, List(emptyInit, mainDef)) def moduleDef = ModuleDef(NoMods, moduleName, moduleBody) @@ -980,6 +980,7 @@ self => nme.ERROR } def ident(): Name = ident(true) + def rawIdent(): Name = try in.name finally in.nextToken() /** For when it's known already to be a type name. */ def identForType(): TypeName = ident().toTypeName @@ -1117,7 +1118,7 @@ self => case LONGLIT => in.intVal(isNegated) case FLOATLIT => in.floatVal(isNegated).toFloat case DOUBLELIT => in.floatVal(isNegated) - case STRINGLIT => in.strVal + case STRINGLIT => in.strVal.intern() case TRUE => true case FALSE => false case NULL => null @@ -1465,8 +1466,9 @@ self => def prefixExpr(): Tree = { if (isUnaryOp) { atPos(in.offset) { - val name: Name = "unary_" + ident() - if (in.name == raw.MINUS && isNumericLit) simpleExprRest(atPos(in.offset)(literal(true)), true) + val name = nme.toUnaryName(rawIdent()) + // val name = nme.toUnaryName(ident()) // val name: Name = "unary_" + ident() + if (name == nme.UNARY_- && isNumericLit) simpleExprRest(atPos(in.offset)(literal(true)), true) else Select(stripParens(simpleExpr()), name) } } @@ -1533,12 +1535,12 @@ self => case LBRACKET => val t1 = stripParens(t) t1 match { - case Ident(_) | Select(_, _) => - var tapp: Tree = t1 + case Ident(_) | Select(_, _) | Apply(_, _) => + var app: Tree = t1 while (in.token == LBRACKET) - tapp = atPos(tapp.pos.startOrPoint, in.offset)(TypeApply(tapp, exprTypeArgs())) + app = atPos(app.pos.startOrPoint, in.offset)(TypeApply(app, exprTypeArgs())) - simpleExprRest(tapp, true) + simpleExprRest(app, true) case _ => t1 } @@ -1743,11 +1745,16 @@ self => * }}} */ def pattern1(): Tree = pattern2() match { - case p @ Ident(name) if treeInfo.isVarPattern(p) && in.token == COLON => - atPos(p.pos.startOrPoint, in.skipToken()) { Typed(p, compoundType()) } - case p => - p + case p @ Ident(name) if in.token == COLON => + if (treeInfo.isVarPattern(p)) + atPos(p.pos.startOrPoint, in.skipToken())(Typed(p, compoundType())) + else { + syntaxError(in.offset, "Pattern variables must start with a lower-case letter. (SLS 8.1.1.)") + p + } + case p => p } + /** {{{ * Pattern2 ::= varid [ @ Pattern3 ] * | Pattern3 diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index b8fa55447a..ffe65aec63 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -58,11 +58,11 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { private object xmltypes extends XMLTypeNames { type NameType = TypeName - implicit def createNameType(name: String): TypeName = newTypeName(name) + implicit def createNameType(name: String): TypeName = newTypeNameCached(name) } private object xmlterms extends XMLTermNames { type NameType = TermName - implicit def createNameType(name: String): TermName = newTermName(name) + implicit def createNameType(name: String): TermName = newTermNameCached(name) } import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer, diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index d80a1c4f34..27df45b563 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -39,9 +39,9 @@ trait JavaPlatform extends Platform { ) ++ depAnalysisPhase lazy val externalEquals = getMember(BoxesRunTimeClass, nme.equals_) - lazy val externalEqualsNumNum = getMember(BoxesRunTimeClass, "equalsNumNum") - lazy val externalEqualsNumChar = getMember(BoxesRunTimeClass, "equalsNumChar") - lazy val externalEqualsNumObject = getMember(BoxesRunTimeClass, "equalsNumObject") + lazy val externalEqualsNumNum = getMember(BoxesRunTimeClass, nme.equalsNumNum) + lazy val externalEqualsNumChar = getMember(BoxesRunTimeClass, nme.equalsNumChar) + lazy val externalEqualsNumObject = getMember(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/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 56e05cdc04..4ab0eb0129 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -3,13 +3,12 @@ * @author Martin Odersky */ - package scala.tools.nsc package backend package icode import scala.collection.{ mutable, immutable } -import mutable.{ ArrayBuffer } +import mutable.{ ListBuffer, ArrayBuffer } import util.{ Position, NoPosition } import backend.icode.analysis.ProgramPoint @@ -17,23 +16,83 @@ trait BasicBlocks { self: ICodes => import opcodes._ - import global.{ settings, log, nme } + import global.{ ifDebug, settings, log, nme } import nme.isExceptionResultName + + object NoBasicBlock extends BasicBlock(-1, null) /** This class represents a basic block. Each * basic block contains a list of instructions that are * either executed all, or none. No jumps * to/from the "middle" of the basic block are allowed (modulo exceptions). */ - class BasicBlock(val label: Int, val method: IMethod) - extends AnyRef - with ProgramPoint[BasicBlock] - with Seq[Instruction] { + class BasicBlock(val label: Int, val method: IMethod) extends ProgramPoint[BasicBlock] { + outer => import BBFlags._ def code = method.code + private final class SuccessorList() { + private var successors: List[BasicBlock] = Nil + private def updateConserve() { + var lb: ListBuffer[BasicBlock] = null + var matches = 0 + var remaining = successors + + def addBlock(bb: BasicBlock) { + if (matches < 0) + lb += bb + else if (remaining.isEmpty || bb != remaining.head) { + lb = ListBuffer[BasicBlock]() ++= (successors take matches) += bb + matches = -1 + } + else { + matches += 1 + remaining = remaining.tail + } + } + + // exceptionSuccessors + method.exh foreach { handler => + if (handler covers outer) + addBlock(handler.startBlock) + } + // directSuccessors + val direct = directSuccessors + direct foreach addBlock + + /** Return a list of successors for 'b' that come from exception handlers + * covering b's (non-exceptional) successors. These exception handlers + * might not cover 'b' itself. This situation corresponds to an + * exception being thrown as the first thing of one of b's successors. + */ + method.exh foreach { handler => + direct foreach { block => + if (handler covers block) + addBlock(handler.startBlock) + } + } + // Blocks did not align: create a new list. + if (matches < 0) + successors = lb.toList + // Blocks aligned, but more blocks remain. Take a prefix of the list. + else if (remaining.nonEmpty) + successors = successors take matches + // Otherwise the list is unchanged, leave it alone. + } + + /** This is called millions of times: it is performance sensitive. */ + def updateSuccs() { + if (isEmpty) { + if (successors.nonEmpty) + successors = Nil + } + else updateConserve() + } + def toList = successors + } + /** Flags of this basic block. */ private var flags: Int = 0 @@ -76,20 +135,23 @@ trait BasicBlocks { setFlag(DIRTYSUCCS | DIRTYPREDS) /** Cached predecessors. */ - var preds: List[BasicBlock] = null + var preds: List[BasicBlock] = Nil /** Local variables that are in scope at entry of this basic block. Used * for debugging information. */ - var varsInScope: mutable.Set[Local] = new mutable.LinkedHashSet() + val varsInScope: mutable.Set[Local] = new mutable.LinkedHashSet() /** ICode instructions, used as temporary storage while emitting code. * Once closed is called, only the `instrs` array should be used. */ private var instructionList: List[Instruction] = Nil - private var instrs: Array[Instruction] = _ - override def toList: List[Instruction] = + + def take(n: Int): Seq[Instruction] = + if (closed) instrs take n else instructionList takeRight n reverse + + def toList: List[Instruction] = if (closed) instrs.toList else instructionList.reverse /** Return an iterator over the instructions in this basic block. */ @@ -117,17 +179,37 @@ trait BasicBlocks { } /** Apply a function to all the instructions of the block. */ - override def foreach[U](f: Instruction => U) = { - // !!! This appears to change behavior if I try to avoid the implicit - // conversion and traverse the array directly, which presumably means it - // is dependent on some mutation which is taking place during traversal. - // Please eliminate this if humanly possible. + final def foreach[U](f: Instruction => U) = { if (!closed) dumpMethodAndAbort(method, this) else instrs foreach f + + // !!! If I replace "instrs foreach f" with the following: + // var i = 0 + // val len = instrs.length + // while (i < len) { + // f(instrs(i)) + // i += 1 + // } + // + // Then when compiling under -optimise, quick.plugins fails as follows: + // + // quick.plugins: + // [mkdir] Created dir: /scratch/trunk6/build/quick/classes/continuations-plugin + // [scalacfork] Compiling 5 files to /scratch/trunk6/build/quick/classes/continuations-plugin + // [scalacfork] error: java.lang.VerifyError: (class: scala/tools/nsc/typechecker/Implicits$ImplicitSearch, method: typedImplicit0 signature: (Lscala/tools/nsc/typechecker/Implicits$ImplicitInfo;Z)Lscala/tools/nsc/typechecker/Implicits$SearchResult;) Incompatible object argument for function call + // [scalacfork] at scala.tools.nsc.typechecker.Implicits$class.inferImplicit(Implicits.scala:67) + // [scalacfork] at scala.tools.nsc.Global$$anon$1.inferImplicit(Global.scala:419) + // [scalacfork] at scala.tools.nsc.typechecker.Typers$Typer.wrapImplicit$1(Typers.scala:170) + // [scalacfork] at scala.tools.nsc.typechecker.Typers$Typer.inferView(Typers.scala:174) + // [scalacfork] at scala.tools.nsc.typechecker.Typers$Typer.adapt(Typers.scala:963) + // [scalacfork] at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4378) + // + // This is bad and should be understood/eliminated. } /** The number of instructions in this basic block so far. */ def length = if (closed) instrs.length else instructionList.length + def size = length /** Return the n-th instruction. */ def apply(n: Int): Instruction = @@ -208,7 +290,7 @@ trait BasicBlocks { */ def removeLastInstruction() { if (closed) - removeInstructionsAt(size) + removeInstructionsAt(length) else { instructionList = instructionList.tail code.touched = true @@ -321,10 +403,11 @@ trait BasicBlocks { def clear() { instructionList = Nil instrs = null - preds = null + preds = Nil } - override def isEmpty = instructionList.isEmpty + final def isEmpty = instructionList.isEmpty + final def nonEmpty = !isEmpty /** Enter ignore mode: new 'emit'ted instructions will not be * added to this basic block. It makes the generation of THROW @@ -341,33 +424,33 @@ trait BasicBlocks { /** Return the last instruction of this basic block. */ def lastInstruction = - if (closed) instrs.last + if (closed) instrs(instrs.length - 1) else instructionList.head def firstInstruction = if (closed) instrs(0) else instructionList.last + def exceptionSuccessors: List[BasicBlock] = + exceptionSuccessorsForBlock(this) + def exceptionSuccessorsForBlock(block: BasicBlock): List[BasicBlock] = method.exh collect { case x if x covers block => x.startBlock } /** Cached value of successors. Must be recomputed whenever a block in the current method is changed. */ - private var succs: List[BasicBlock] = Nil - private def updateSuccs() { - resetFlag(DIRTYSUCCS) - succs = - if (isEmpty) Nil - else exceptionSuccessors ++ directSuccessors ++ indirectExceptionSuccessors - } + private val succs = new SuccessorList - def successors : List[BasicBlock] = { - if (touched) updateSuccs() - succs + def successors: List[BasicBlock] = { + if (touched) { + succs.updateSuccs() + resetFlag(DIRTYSUCCS) + } + succs.toList } def directSuccessors: List[BasicBlock] = if (isEmpty) Nil else lastInstruction match { - case JUMP(whereto) => List(whereto) + case JUMP(whereto) => whereto :: Nil case CJUMP(succ, fail, _, _) => fail :: succ :: Nil case CZJUMP(succ, fail, _, _) => fail :: succ :: Nil case SWITCH(_, labels) => labels @@ -379,17 +462,6 @@ trait BasicBlocks { else Nil } - def exceptionSuccessors: List[BasicBlock] = - exceptionSuccessorsForBlock(this) - - /** Return a list of successors for 'b' that come from exception handlers - * covering b's (non-exceptional) successors. These exception handlers - * might not cover 'b' itself. This situation corresponds to an - * exception being thrown as the first thing of one of b's successors. - */ - def indirectExceptionSuccessors: List[BasicBlock] = - directSuccessors flatMap exceptionSuccessorsForBlock distinct - /** Returns the predecessors of this block. */ def predecessors: List[BasicBlock] = { if (hasFlag(DIRTYPREDS)) { diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala index 1880bdc52c..ffc6640743 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala @@ -3,13 +3,11 @@ * @author Martin Odersky */ - package scala.tools.nsc package backend package icode -import scala.collection.{ mutable, immutable, generic } -import util.{ Position, NoPosition } +import scala.collection.{ mutable, immutable } /** * Exception handlers are pieces of code that `handle` exceptions on @@ -21,10 +19,10 @@ import util.{ Position, NoPosition } trait ExceptionHandlers { self: ICodes => - import global.{ definitions, Symbol, NoSymbol } + import global._ import definitions.{ ThrowableClass } - class ExceptionHandler(val method: IMethod, val label: String, val cls: Symbol, val pos: Position) { + class ExceptionHandler(val method: IMethod, val label: TermName, val cls: Symbol, val pos: Position) { def loadExceptionClass = if (cls == NoSymbol) ThrowableClass else cls private var _startBlock: BasicBlock = _; var finalizer: Finalizer = _; @@ -69,12 +67,12 @@ trait ExceptionHandlers { def dup: ExceptionHandler = new ExceptionHandler(this) } - class Finalizer(method: IMethod, label: String, pos: Position) extends ExceptionHandler(method, label, NoSymbol, pos) { + class Finalizer(method: IMethod, label: TermName, pos: Position) extends ExceptionHandler(method, label, NoSymbol, pos) { override def toString() = "finalizer_" + label override def dup: Finalizer = new Finalizer(method, label, pos) } - object NoFinalizer extends Finalizer(null, "<no finalizer>", NoPosition) { + object NoFinalizer extends Finalizer(null, newTermNameCached("<no finalizer>"), NoPosition) { override def startBlock: BasicBlock = sys.error("NoFinalizer cannot have a start block."); override def setStartBlock(b: BasicBlock): Unit = sys.error("NoFinalizer cannot have a start block."); override def dup = this diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 3f0a0fac1a..803bd05031 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -102,7 +102,7 @@ abstract class GenICode extends SubComponent { case DefDef(mods, name, tparams, vparamss, tpt, rhs) => debuglog("Entering method " + name) val m = new IMethod(tree.symbol) - m.sourceFile = unit.source.toString() + m.sourceFile = unit.source m.returnType = if (tree.symbol.isConstructor) UNIT else toTypeKind(tree.symbol.info.resultType) ctx.clazz.addMethod(m) @@ -1293,7 +1293,7 @@ abstract class GenICode extends SubComponent { /** The Object => String overload. */ - private lazy val String_valueOf: Symbol = getMember(StringModule, "valueOf") filter (sym => + private lazy val String_valueOf: Symbol = getMember(StringModule, nme.valueOf) filter (sym => sym.info.paramTypes match { case List(pt) => pt.typeSymbol == ObjectClass case _ => false @@ -1305,7 +1305,7 @@ abstract class GenICode extends SubComponent { // case we want to get more precise. // // private def valueOfForType(tp: Type): Symbol = { - // val xs = getMember(StringModule, "valueOf") filter (sym => + // val xs = getMember(StringModule, nme.valueOf) filter (sym => // // We always exclude the Array[Char] overload because java throws an NPE if // // you pass it a null. It will instead find the Object one, which doesn't. // sym.info.paramTypes match { @@ -1352,7 +1352,7 @@ abstract class GenICode extends SubComponent { def genScalaHash(tree: Tree, ctx: Context): Context = { val hashMethod = { ctx.bb.emit(LOAD_MODULE(ScalaRunTimeModule)) - getMember(ScalaRunTimeModule, "hash") + getMember(ScalaRunTimeModule, nme.hash_) } val ctx1 = genLoad(tree, ctx, ObjectReference) @@ -1716,7 +1716,7 @@ abstract class GenICode extends SubComponent { do { changed = false n += 1 - method.code.blocks foreach prune0 + method.blocks foreach prune0 } while (changed) debuglog("Prune fixpoint reached in " + n + " iterations."); @@ -1924,7 +1924,7 @@ abstract class GenICode extends SubComponent { val ctx1 = new Context(this) setMethod(m) ctx1.labels = mutable.HashMap() ctx1.method.code = new Code(m) - ctx1.bb = ctx1.method.code.startBlock + ctx1.bb = ctx1.method.startBlock ctx1.defdef = d ctx1.scope = EmptyScope ctx1.enterScope @@ -1932,11 +1932,12 @@ abstract class GenICode extends SubComponent { } /** Return a new context for a new basic block. */ - def newBlock: Context = { + def newBlock(): Context = { val block = method.code.newBlock handlers foreach (_ addCoveredBlock block) currentExceptionHandlers foreach (_ addBlock block) - block.varsInScope = mutable.HashSet() ++= scope.varsInScope + block.varsInScope.clear() + block.varsInScope ++= scope.varsInScope new Context(this) setBasicBlock block } @@ -1958,7 +1959,7 @@ abstract class GenICode extends SubComponent { */ private def newExceptionHandler(cls: Symbol, resultKind: TypeKind, pos: Position): ExceptionHandler = { handlerCount += 1 - val exh = new ExceptionHandler(method, "" + handlerCount, cls, pos) + val exh = new ExceptionHandler(method, newTermNameCached("" + handlerCount), cls, pos) exh.resultKind = resultKind method.addHandler(exh) handlers = exh :: handlers diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 7a0017944b..631b71d83a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -84,15 +84,16 @@ abstract class ICodes extends AnyRef def checkValid(m: IMethod) { // always slightly dicey to iterate over mutable structures - val bs = m.code.blocks.toList - for (b <- bs ; if !b.closed) { - // Something is leaving open/empty blocks around (see SI-4840) so - // let's not kill the deal unless it's nonempty. - if (b.isEmpty) { - log("!!! Found open but empty block while inlining " + m + ": removing from block list.") - m.code removeBlock b + m foreachBlock { b => + if (!b.closed) { + // Something is leaving open/empty blocks around (see SI-4840) so + // let's not kill the deal unless it's nonempty. + if (b.isEmpty) { + log("!!! Found open but empty block while inlining " + m + ": removing from block list.") + m.code removeBlock b + } + else dumpMethodAndAbort(m, b) } - else dumpMethodAndAbort(m, b) } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index 1978a23d90..f71c8de449 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -36,7 +36,7 @@ trait Linearizers { var blocks: List[BasicBlock] = Nil def linearize(m: IMethod): List[BasicBlock] = { - val b = m.code.startBlock; + val b = m.startBlock; blocks = Nil; run { @@ -106,7 +106,7 @@ trait Linearizers { def linearize(m: IMethod): List[BasicBlock] = { blocks = Nil; - dfs(m.code.startBlock); + dfs(m.startBlock); m.exh foreach (b => dfs(b.startBlock)); blocks.reverse @@ -150,14 +150,14 @@ trait Linearizers { added.clear; m.exh foreach (b => rpo(b.startBlock)); - rpo(m.code.startBlock); + rpo(m.startBlock); // if the start block has predecessors, it won't be the first one // in the linearization, so we need to enforce it here - if (m.code.startBlock.predecessors eq Nil) + if (m.startBlock.predecessors eq Nil) blocks else - m.code.startBlock :: (blocks.filterNot(_ == m.code.startBlock)) + m.startBlock :: (blocks.filterNot(_ == m.startBlock)) } def linearizeAt(m: IMethod, start: BasicBlock): List[BasicBlock] = { @@ -195,7 +195,7 @@ trait Linearizers { * the last instruction being a jump). */ class DumpLinearizer extends Linearizer { - def linearize(m: IMethod): List[BasicBlock] = m.code.blocks.toList + def linearize(m: IMethod): List[BasicBlock] = m.blocks def linearizeAt(m: IMethod, start: BasicBlock): List[BasicBlock] = sys.error("not implemented") } @@ -250,7 +250,7 @@ trait Linearizers { * @param frozen blocks can't be moved (fist block of a method, blocks directly following a try-catch) */ def groupBlocks(method: IMethod, blocks: List[BasicBlock], handlers: List[ExceptionHandler], frozen: mutable.HashSet[BasicBlock]) = { - assert(blocks.head == method.code.startBlock, method) + assert(blocks.head == method.startBlock, method) // blocks before the try, and blocks for the try val beforeAndTry = new ListBuffer[BasicBlock]() diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index b2cc4cdd5b..2668e7f29f 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -3,13 +3,13 @@ * @author Martin Odersky */ - package scala.tools.nsc package backend package icode import java.io.PrintWriter import scala.collection.{ mutable, immutable } +import util.{ SourceFile, NoSourceFile } import symtab.Flags.{ DEFERRED } trait ReferenceEquality { @@ -17,29 +17,34 @@ trait ReferenceEquality { override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] } -trait Members { self: ICodes => +trait Members { + self: ICodes => + import global._ + + object NoCode extends Code(null, "NoCode") { + override def blocksList: List[BasicBlock] = Nil + } /** * This class represents the intermediate code of a method or * other multi-block piece of code, like exception handlers. */ - class Code(method: IMethod) { - private[this] val name = method.symbol.decodedName.toString.intern + class Code(method: IMethod, name: String) { + def this(method: IMethod) = this(method, method.symbol.decodedName.toString.intern) /** The set of all blocks */ val blocks = mutable.ListBuffer[BasicBlock]() /** The start block of the method */ - var startBlock: BasicBlock = null - - /** The stack produced by this method */ - var producedStack: TypeStack = null + var startBlock: BasicBlock = NoBasicBlock private var currentLabel: Int = 0 private var _touched = false - def blockCount = blocks.size - def instructionCount = blocks map (_.length) sum + def blocksList: List[BasicBlock] = blocks.toList + def instructions = blocksList flatMap (_.iterator) + def blockCount = blocks.size + def instructionCount = blocks map (_.length) sum def touched = _touched def touched_=(b: Boolean): Unit = { @@ -82,7 +87,7 @@ trait Members { self: ICodes => /* Create a new block and append it to the list */ - def newBlock: BasicBlock = { + def newBlock(): BasicBlock = { touched = true val block = new BasicBlock(nextLabel, method); blocks += block; @@ -133,6 +138,8 @@ trait Members { self: ICodes => /** Represent a field in ICode */ class IField(val symbol: Symbol) extends IMember { } + + object NoIMethod extends IMethod(NoSymbol) { } /** * Represents a method in ICode. Local variables contain @@ -145,14 +152,23 @@ trait Members { self: ICodes => * finished (GenICode does that). */ class IMethod(val symbol: Symbol) extends IMember { - var code: Code = null + var code: Code = NoCode + + def newBlock() = code.newBlock + def startBlock = code.startBlock + def lastBlock = blocks.last + def blocks = code.blocksList + def linearizedBlocks(lin: Linearizer = self.linearizer): List[BasicBlock] = lin linearize this + + def foreachBlock[U](f: BasicBlock => U): Unit = blocks foreach f + def foreachInstr[U](f: Instruction => U): Unit = foreachBlock(_.toList foreach f) + var native = false /** The list of exception handlers, ordered from innermost to outermost. */ var exh: List[ExceptionHandler] = Nil - var sourceFile: String = _ + var sourceFile: SourceFile = NoSourceFile var returnType: TypeKind = _ - var recursive: Boolean = false /** local variables and method parameters */ @@ -161,7 +177,8 @@ trait Members { self: ICodes => /** method parameters */ var params: List[Local] = Nil - def hasCode = code != null + // TODO - see how null is stil arriving here + def hasCode = (code ne NoCode) && (code ne null) def setCode(code: Code): IMethod = { this.code = code; this @@ -199,12 +216,14 @@ trait Members { self: ICodes => import opcodes._ def checkLocals(): Unit = { - def localsSet = code.blocks.flatten collect { - case LOAD_LOCAL(l) => l - case STORE_LOCAL(l) => l - } toSet + def localsSet = (code.blocks flatMap { bb => + bb.iterator collect { + case LOAD_LOCAL(l) => l + case STORE_LOCAL(l) => l + } + }).toSet - if (code != null) { + if (hasCode) { log("[checking locals of " + this + "]") locals filterNot localsSet foreach { l => log("Local " + l + " is not declared in " + this) @@ -218,7 +237,7 @@ trait Members { self: ICodes => * * This method should be most effective after heavy inlining. */ - def normalize(): Unit = if (this.code ne null) { + def normalize(): Unit = if (this.hasCode) { val nextBlock: mutable.Map[BasicBlock, BasicBlock] = mutable.HashMap.empty for (b <- code.blocks.toList if b.successors.length == 1; diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala index ff4abbb757..4ea253d29d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala @@ -82,7 +82,7 @@ trait Printers { self: ICodes => if (!m.isAbstractMethod) { println(" {") println("locals: " + m.locals.mkString("", ", ", "")) - println("startBlock: " + m.code.startBlock) + println("startBlock: " + m.startBlock) println("blocks: " + m.code.blocks.mkString("[", ",", "]")) println lin.linearize(m) foreach printBlock diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala index 45ab7ae43c..ba4b250303 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala @@ -21,6 +21,8 @@ trait TypeStacks { * stack of the ICode. */ type Rep = List[TypeKind] + + object NoTypeStack extends TypeStack(Nil) { } class TypeStack(var types: Rep) { if (types.nonEmpty) 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 5af5b05682..229bbceb36 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -194,9 +194,9 @@ abstract class CopyPropagation { this.method = m init { - worklist += m.code.startBlock + worklist += m.startBlock worklist ++= (m.exh map (_.startBlock)) - m.code.blocks.foreach { b => + m foreachBlock { b => in(b) = lattice.bottom out(b) = lattice.bottom assert(out.contains(b)) @@ -207,21 +207,21 @@ abstract class CopyPropagation { } // first block is special: it's not bottom, but a precisely defined state with no bindings - in(m.code.startBlock) = new lattice.State(lattice.emptyBinding, Nil); + in(m.startBlock) = new lattice.State(lattice.emptyBinding, Nil); } } override def run() { forwardAnalysis(blockTransfer) if (settings.debug.value) { - linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) + linearizer.linearize(method).foreach(b => if (b != method.startBlock) assert(in(b) != lattice.bottom, "Block " + b + " in " + this.method + " has input equal to bottom -- not visited?")); } } def blockTransfer(b: BasicBlock, in: lattice.Elem): lattice.Elem = - b.foldLeft(in)(interpret) + b.iterator.foldLeft(in)(interpret) import opcodes._ @@ -520,8 +520,8 @@ abstract class CopyPropagation { */ private def getBindingsForPrimaryCtor(in: copyLattice.State, ctor: Symbol): mutable.Map[Symbol, Value] = { val paramAccessors = ctor.owner.constrParamAccessors; - var values = in.stack.take(1 + ctor.info.paramTypes.length).reverse.drop(1); - val bindings = mutable.HashMap[Symbol, Value]() + var values = in.stack.take(1 + ctor.info.paramTypes.length).reverse.drop(1); + val bindings = mutable.HashMap[Symbol, Value]() debuglog("getBindings for: " + ctor + " acc: " + paramAccessors) @@ -562,13 +562,12 @@ abstract class CopyPropagation { final def isPureMethod(m: Symbol): Boolean = m.isGetter // abstract getters are still pure, as we 'know' - final override def toString(): String = { - var res = "" - for (b <- this.method.code.blocks.toList) - res = (res + "\nIN(" + b.label + "):\t Bindings: " + in(b).bindings + - "\nIN(" + b.label +"):\t Stack: " + in(b).stack) + "\n"; - res - } + final override def toString() = ( + method.blocks map { b => + "\nIN(%s):\t Bindings: %s".format(b.label, in(b).bindings) + + "\nIN(%s):\t Stack: %s".format(b.label, in(b).stack) + } mkString + ) } /* class CopyAnalysis */ } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala index c656219dc8..49f5b51d51 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala @@ -33,10 +33,9 @@ abstract class Liveness { final class LivenessAnalysis extends DataFlowAnalysis[livenessLattice.type] { type P = BasicBlock - val lattice = livenessLattice - var method: IMethod = _ - - val gen: mutable.Map[BasicBlock, Set[Local]] = perRunCaches.newMap() + val lattice = livenessLattice + var method: IMethod = _ + val gen: mutable.Map[BasicBlock, Set[Local]] = perRunCaches.newMap() val kill: mutable.Map[BasicBlock, Set[Local]] = perRunCaches.newMap() def init(m: IMethod) { @@ -44,14 +43,15 @@ abstract class Liveness { gen.clear() kill.clear() - for (b <- m.code.blocks; (g, k) = genAndKill(b)) { + m foreachBlock { b => + val (g, k) = genAndKill(b) gen += (b -> g) kill += (b -> k) } init { - worklist ++= m.code.blocks.toList - m.code.blocks.foreach { b => + m foreachBlock { b => + worklist += b in(b) = lattice.bottom out(b) = lattice.bottom } @@ -75,7 +75,7 @@ abstract class Liveness { override def run() { backwardAnalysis(blockTransfer) if (settings.debug.value) { - linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) + linearizer.linearize(method).foreach(b => if (b != method.startBlock) assert(lattice.bottom != in(b), "Block " + b + " in " + this.method + " has input equal to bottom -- not visited?")); } @@ -89,29 +89,14 @@ abstract class Liveness { * liveness *before* the given instruction `i`. */ def interpret(out: lattice.Elem, i: Instruction): lattice.Elem = { - var in = out - - if (settings.debug.value) { - log("- " + i) - log("out: " + out) - log("\n") - } - + debuglog("- " + i + "\nout: " + out + "\n") i match { - case LOAD_LOCAL(l) => in += l - case STORE_LOCAL(l) => in -= l - case _ => - () - } - in - } /* def interpret */ - - override def toString(): String = { - val buf = new StringBuilder() - for (b <- method.code.blocks.toList) { - buf.append("\nlive-in(" + b + ")=" + in(b) + "\nlive-out(" + b + ")=" + out(b)); + case LOAD_LOCAL(l) => out + l + case STORE_LOCAL(l) => out - l + case _ => out } - buf.toString() } + override def toString() = + method.blocks map (b => "\nlive-in(%s)=%s\nlive-out(%s)=%s".format(b, in(b), b, out(b))) mkString } /* Liveness analysis */ } diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala index eac714f999..c06bd2e097 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala @@ -78,7 +78,10 @@ abstract class ReachingDefinitions { drops.clear() outStack.clear() - for (b <- m.code.blocks.toList; (g, k) = genAndKill(b); (d, st) = dropsAndGen(b)) { + m foreachBlock { b => + val (g, k) = genAndKill(b) + val (d, st) = dropsAndGen(b) + gen += (b -> g) kill += (b -> k) drops += (b -> d) @@ -86,8 +89,8 @@ abstract class ReachingDefinitions { } init { - worklist ++= m.code.blocks.toList - m.code.blocks.foreach { b => + m foreachBlock { b => + worklist += b in(b) = lattice.bottom out(b) = lattice.bottom } @@ -141,7 +144,7 @@ abstract class ReachingDefinitions { override def run() { forwardAnalysis(blockTransfer) if (settings.debug.value) { - linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) + linearizer.linearize(method).foreach(b => if (b != method.startBlock) assert(lattice.bottom != in(b), "Block " + b + " in " + this.method + " has input equal to bottom -- not visited? " + in(b) + ": bot: " + lattice.bottom diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index a34d269cc9..937b0bdc3d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -110,16 +110,16 @@ abstract class TypeFlowAnalysis { this.method = m //typeFlowLattice.lubs = 0 init { - worklist += m.code.startBlock + worklist += m.startBlock worklist ++= (m.exh map (_.startBlock)) - m.code.blocks.foreach { b => + m foreachBlock { b => in(b) = typeFlowLattice.bottom out(b) = typeFlowLattice.bottom } // start block has var bindings for each of its parameters val entryBindings = new VarBinding ++= (m.params map (p => ((p, p.kind)))) - in(m.code.startBlock) = lattice.IState(entryBindings, typeStackLattice.bottom) + in(m.startBlock) = lattice.IState(entryBindings, typeStackLattice.bottom) m.exh foreach { e => in(e.startBlock) = lattice.IState(in(e.startBlock).vars, typeStackLattice.exceptionHandlerStack) @@ -132,16 +132,18 @@ abstract class TypeFlowAnalysis { if (this.method == null || this.method.symbol != m.symbol) init(m) else reinit { - for (b <- m.code.blocks; if !in.isDefinedAt(b)) { - for (p <- b.predecessors) { - if (out.isDefinedAt(p)) { - in(b) = out(p) - worklist += p - } -/* else - in(b) = typeFlowLattice.bottom -*/ } - out(b) = typeFlowLattice.bottom + m foreachBlock { b => + if (!in.contains(b)) { + for (p <- b.predecessors) { + if (out.isDefinedAt(p)) { + in(b) = out(p) + worklist += p + } + /* else + in(b) = typeFlowLattice.bottom + */ } + out(b) = typeFlowLattice.bottom + } } for (handler <- m.exh) { val start = handler.startBlock @@ -164,7 +166,7 @@ abstract class TypeFlowAnalysis { forwardAnalysis(blockTransfer) val t = timer.stop if (settings.debug.value) { - linearizer.linearize(method).foreach(b => if (b != method.code.startBlock) + linearizer.linearize(method).foreach(b => if (b != method.startBlock) assert(visited.contains(b), "Block " + b + " in " + this.method + " has input equal to bottom -- not visited? .." + visited)); } @@ -174,7 +176,7 @@ abstract class TypeFlowAnalysis { } def blockTransfer(b: BasicBlock, in: lattice.Elem): lattice.Elem = { - b.foldLeft(in)(interpret) + b.iterator.foldLeft(in)(interpret) } /** The flow function of a given basic block. */ /* var flowFun: immutable.Map[BasicBlock, TransferFunction] = new immutable.HashMap */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala index 301dbd18d6..e7cf716add 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenAndroid.scala @@ -23,15 +23,10 @@ trait GenAndroid { * `Parcelable` interface must also have a static field called `CREATOR`, * which is an object implementing the `Parcelable.Creator` interface. */ - private val fieldName = "CREATOR" + private val fieldName = newTermName("CREATOR") - private lazy val AndroidParcelableInterface = - try definitions.getClass("android.os.Parcelable") - catch { case _: FatalError => NoSymbol } - - private lazy val AndroidCreatorClass = - if (AndroidParcelableInterface == NoSymbol) NoSymbol - else definitions.getClass("android.os.Parcelable$Creator") + private lazy val AndroidParcelableInterface = definitions.getClassIfDefined("android.os.Parcelable") + private lazy val AndroidCreatorClass = definitions.getClassIfDefined("android.os.Parcelable$Creator") def isAndroidParcelableClass(sym: Symbol) = (AndroidParcelableInterface != NoSymbol) && diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index a2c4f16bf1..03d1bc3ad2 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -3,7 +3,6 @@ * @author Iulian Dragos */ - package scala.tools.nsc package backend.jvm @@ -13,6 +12,7 @@ import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer } import scala.tools.reflect.SigParser import scala.tools.nsc.symtab._ +import scala.tools.nsc.util.{ SourceFile, NoSourceFile } import scala.reflect.internal.ClassfileConstants._ import ch.epfl.lamp.fjbg._ import JAccessFlags._ @@ -183,10 +183,15 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val MethodHandleType = new JObjectType("java.dyn.MethodHandle") // Scala attributes - val BeanInfoAttr = definitions.getClass("scala.beans.BeanInfo") - val BeanInfoSkipAttr = definitions.getClass("scala.beans.BeanInfoSkip") - val BeanDisplayNameAttr = definitions.getClass("scala.beans.BeanDisplayName") - val BeanDescriptionAttr = definitions.getClass("scala.beans.BeanDescription") + val BeanInfoAttr = definitions.getRequiredClass("scala.beans.BeanInfo") + val BeanInfoSkipAttr = definitions.getRequiredClass("scala.beans.BeanInfoSkip") + val BeanDisplayNameAttr = definitions.getRequiredClass("scala.beans.BeanDisplayName") + val BeanDescriptionAttr = definitions.getRequiredClass("scala.beans.BeanDescription") + + final val ExcludedForwarderFlags = { + import Flags._ + ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | BridgeAndPrivateFlags ) + } // Additional interface parents based on annotations and other cues def newParentForAttr(attr: Symbol): Option[Type] = attr match { @@ -291,7 +296,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with */ def scalaSignatureAddingMarker(jclass: JClass, sym: Symbol): Option[AnnotationInfo] = currentRun.symData get sym match { - case Some(pickle) if !nme.isModuleName(jclass.getName()) => + case Some(pickle) if !nme.isModuleName(newTermName(jclass.getName)) => val scalaAttr = fjbgContext.JOtherAttribute(jclass, jclass, tpnme.ScalaSignatureATTR.toString, versionPickle.bytes, versionPickle.writeIndex) @@ -355,7 +360,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (isTopLevelModule(c.symbol)) { if (c.symbol.companionClass == NoSymbol) - generateMirrorClass(c.symbol, c.cunit.source.toString) + generateMirrorClass(c.symbol, c.cunit.source) else log("No mirror class for module with linked class: " + c.symbol.fullName) @@ -754,7 +759,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with null else { val outerName = javaName(innerSym.rawowner) - if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(outerName) + if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(newTermName(outerName)) else outerName } } @@ -925,8 +930,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with mopt match { case Some(m) => - val oldLastBlock = m.code.blocks.last - val lastBlock = m.code.newBlock + val oldLastBlock = m.lastBlock + val lastBlock = m.newBlock() oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock)) if (isStaticModule(clasz.symbol)) { @@ -1044,32 +1049,20 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val className = jclass.getName val linkedClass = moduleClass.companionClass val linkedModule = linkedClass.companionSymbol + lazy val conflictingNames: Set[Name] = { + linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet + } + debuglog("Potentially conflicting names for forwarders: " + conflictingNames) - /** There was a bit of a gordian logic knot here regarding forwarders. - * All we really have to do is exclude certain categories of symbols and - * then all matching names. - */ - def memberNames(sym: Symbol) = sym.info.members map (_.name.toString) toSet - lazy val membersInCommon = - memberNames(linkedModule) intersect memberNames(linkedClass) - - /** Should method `m` get a forwarder in the mirror class? */ - def shouldForward(m: Symbol): Boolean = ( - m.owner != ObjectClass - && m.isMethod - && m.isPublic - && !m.hasFlag(Flags.CASE | Flags.DEFERRED | Flags.SPECIALIZED | Flags.LIFTED) - && !m.isConstructor - && !m.isStaticMember - && !membersInCommon(m.name.toString) - ) - - for (m <- moduleClass.info.nonPrivateMembers) { - if (shouldForward(m)) { + 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)) + else if (conflictingNames(m.name)) + log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name)) + else { log("Adding static forwarder for '%s' from %s to '%s'".format(m, className, moduleClass)) addForwarder(jclass, moduleClass, m) } - else debuglog("No forwarder for '%s' from %s to '%s'".format(m, className, moduleClass)) } } @@ -1079,7 +1072,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with * generated if there is no companion class: if there is, an attempt will * instead be made to add the forwarder methods to the companion class. */ - def generateMirrorClass(clasz: Symbol, sourceFile: String) { + def generateMirrorClass(clasz: Symbol, sourceFile: SourceFile) { import JAccessFlags._ val moduleName = javaName(clasz) // + "$" val mirrorName = moduleName.substring(0, moduleName.length() - 1) @@ -1087,7 +1080,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with mirrorName, JAVA_LANG_OBJECT.getName, JClass.NO_INTERFACES, - sourceFile) + "" + sourceFile) log("Dumping mirror class for '%s'".format(mirrorClass.getName)) addForwarders(mirrorClass, clasz) @@ -1199,7 +1192,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with hostSymbol.info ; methodOwner.info def isInterfaceCall(sym: Symbol) = ( - sym.isInterface + sym.isInterface && methodOwner != ObjectClass || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass) ) // whether to reference the type of the receiver or @@ -1901,7 +1894,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with if (sym.isInterface) ACC_INTERFACE else 0, if (finalFlag) ACC_FINAL else 0, if (sym.isStaticMember) ACC_STATIC else 0, - if (sym.isBridge || sym.hasFlag(Flags.MIXEDIN) && sym.isMethod) ACC_BRIDGE else 0, + if (sym.isBridge) ACC_BRIDGE else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0 ) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala index acaf1f6cc2..93d3d19ac8 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala @@ -33,11 +33,11 @@ trait GenJVMUtil { ) // Don't put this in per run caches. - private val javaNameCache = new mutable.WeakHashMap[Symbol, String]() ++= List( - NothingClass -> RuntimeNothingClass.fullName('/'), - RuntimeNothingClass -> RuntimeNothingClass.fullName('/'), - NullClass -> RuntimeNullClass.fullName('/'), - RuntimeNullClass -> RuntimeNullClass.fullName('/') + private val javaNameCache = new mutable.WeakHashMap[Symbol, Name]() ++= List( + NothingClass -> binarynme.RuntimeNothing, + RuntimeNothingClass -> binarynme.RuntimeNothing, + NullClass -> binarynme.RuntimeNull, + RuntimeNullClass -> binarynme.RuntimeNull ) /** This trait may be used by tools who need access to @@ -70,7 +70,6 @@ trait GenJVMUtil { def mkArray(xs: Traversable[JType]): Array[JType] = { val a = new Array[JType](xs.size); xs.copyToArray(a); a } def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a } - /** Return the a name of this symbol that can be used on the Java * platform. It removes spaces from names. * @@ -86,11 +85,13 @@ trait GenJVMUtil { */ def javaName(sym: Symbol): String = javaNameCache.getOrElseUpdate(sym, { - if (sym.isClass || (sym.isModule && !sym.isMethod)) - sym.javaBinaryName - else - sym.javaSimpleName - }) + sym.name.newName( + if (sym.isClass || (sym.isModule && !sym.isMethod)) + sym.javaBinaryName + else + sym.javaSimpleName + ) + }).toString def javaType(t: TypeKind): JType = (t: @unchecked) match { case UNIT => JType.VOID diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index e208f5a8da..d2e54ff3f1 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -124,8 +124,8 @@ abstract class GenMSIL extends SubComponent { // Scala attributes // symtab.Definitions -> object (singleton..) val SerializableAttr = definitions.SerializableAttr.tpe - val CloneableAttr = definitions.getClass("scala.cloneable").tpe - val TransientAtt = definitions.getClass("scala.transient").tpe + val CloneableAttr = definitions.CloneableAttr.tpe + val TransientAtt = definitions.TransientAttr.tpe // remoting: the architectures are too different, no mapping (no portable code // possible) @@ -1898,8 +1898,8 @@ abstract class GenMSIL extends SubComponent { val sc = iclass.lookupStaticCtor if (sc.isDefined) { val m = sc.get - val oldLastBlock = m.code.blocks.last - val lastBlock = m.code.newBlock + val oldLastBlock = m.lastBlock + val lastBlock = m.newBlock() oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock)) // call object's private ctor from static ctor lastBlock.emit(CIL_NEWOBJ(iclass.symbol.primaryConstructor)) diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala index 3e921cf472..e8abee7d06 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala @@ -94,12 +94,12 @@ abstract class ClosureElimination extends SubComponent { import copyPropagation._ /* Some embryonic copy propagation. */ - def analyzeMethod(m: IMethod): Unit = try {if (m.code ne null) { + def analyzeMethod(m: IMethod): Unit = try {if (m.hasCode) { log("Analyzing " + m) cpp.init(m) cpp.run - for (bb <- linearizer.linearize(m)) { + m.linearizedBlocks() foreach { bb => var info = cpp.in(bb) debuglog("Cpp info at entry to block " + bb + ": " + info) @@ -201,28 +201,25 @@ abstract class ClosureElimination extends SubComponent { /** Peephole optimization. */ abstract class PeepholeOpt { - private var method: IMethod = null + private var method: IMethod = NoIMethod /** Concrete implementations will perform their optimizations here */ def peep(bb: BasicBlock, i1: Instruction, i2: Instruction): Option[List[Instruction]] var liveness: global.icodes.liveness.LivenessAnalysis = null - def apply(m: IMethod): Unit = if (m.code ne null) { + def apply(m: IMethod): Unit = if (m.hasCode) { method = m liveness = new global.icodes.liveness.LivenessAnalysis liveness.init(m) liveness.run - for (b <- m.code.blocks) - transformBlock(b) + m foreachBlock transformBlock } def transformBlock(b: BasicBlock): Unit = if (b.size >= 2) { - var newInstructions: List[Instruction] = Nil - - newInstructions = b.toList - + var newInstructions: List[Instruction] = b.toList var redo = false + do { var h = newInstructions.head var t = newInstructions.tail diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index 64df3b4636..5fc7329955 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -72,7 +72,7 @@ abstract class DeadCodeElimination extends SubComponent { val dropOf: mutable.Map[(BasicBlock, Int), List[(BasicBlock, Int)]] = perRunCaches.newMap() def dieCodeDie(m: IMethod) { - if (m.code ne null) { + if (m.hasCode) { log("dead code elimination on " + m); dropOf.clear() m.code.blocks.clear() @@ -90,12 +90,12 @@ abstract class DeadCodeElimination extends SubComponent { } /** collect reaching definitions and initial useful instructions for this method. */ - def collectRDef(m: IMethod): Unit = if (m.code ne null) { + def collectRDef(m: IMethod): Unit = if (m.hasCode) { defs = immutable.HashMap.empty; worklist.clear(); useful.clear(); rdef.init(m); rdef.run; - for (bb <- m.code.blocks.toList) { + m foreachBlock { bb => useful(bb) = new mutable.BitSet(bb.size) var rd = rdef.in(bb); for (Pair(i, idx) <- bb.toList.zipWithIndex) { @@ -184,7 +184,7 @@ abstract class DeadCodeElimination extends SubComponent { def sweep(m: IMethod) { val compensations = computeCompensations(m) - for (bb <- m.code.blocks.toList) { + m foreachBlock { bb => // Console.println("** Sweeping block " + bb + " **") val oldInstr = bb.toList bb.open @@ -223,7 +223,7 @@ abstract class DeadCodeElimination extends SubComponent { private def computeCompensations(m: IMethod): mutable.Map[(BasicBlock, Int), List[Instruction]] = { val compensations: mutable.Map[(BasicBlock, Int), List[Instruction]] = new mutable.HashMap - for (bb <- m.code.blocks) { + m foreachBlock { bb => assert(bb.closed, "Open block in computeCompensations") for ((i, idx) <- bb.toList.zipWithIndex) { if (!useful(bb)(idx)) { diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala index 1d971beae4..a37a3406a8 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala @@ -79,7 +79,7 @@ abstract class InlineExceptionHandlers extends SubComponent { /* Type Flow Analysis */ private val tfa: analysis.MethodTFA = new analysis.MethodTFA() private var tfaCache: Map[Int, tfa.lattice.Elem] = Map.empty - private var analyzedMethod: IMethod = null + private var analyzedMethod: IMethod = NoIMethod /* Blocks that need to be analyzed */ private var todoBlocks: List[BasicBlock] = Nil @@ -110,7 +110,7 @@ abstract class InlineExceptionHandlers extends SubComponent { * inlined blocks, so worst case scenario we double the size of the code */ private def applyMethod(method: IMethod): Unit = { - if (method.code ne null) { + if (method.hasCode) { // create the list of starting blocks todoBlocks = global.icodes.linearizer.linearize(method) @@ -127,7 +127,7 @@ abstract class InlineExceptionHandlers extends SubComponent { todoBlocks = Nil // Type flow analysis cleanup - analyzedMethod = null + analyzedMethod = NoIMethod tfaCache = Map.empty //TODO: Need a way to clear tfa structures } @@ -151,7 +151,7 @@ abstract class InlineExceptionHandlers extends SubComponent { * - we change the THROW exception to the new Clear stack + JUMP code */ for { - (instr @ THROW(clazz), index) <- bblock.zipWithIndex + (instr @ THROW(clazz), index) <- bblock.iterator.zipWithIndex // Decide if any handler fits this exception // If not, then nothing to do, we cannot determine statically which handler will catch the exception (handler, caughtException) <- findExceptionHandler(toTypeKind(clazz.tpe), bblock.exceptionSuccessors) @@ -181,7 +181,7 @@ abstract class InlineExceptionHandlers extends SubComponent { if (!canReplaceHandler) { currentClass.cunit.warning(NoPosition, "Unable to inline the exception handler inside incorrect" + - " block:\n" + bblock.mkString("\n") + "\nwith stack: " + typeInfo + " just " + + " block:\n" + bblock.iterator.mkString("\n") + "\nwith stack: " + typeInfo + " just " + "before instruction index " + index) } else { @@ -261,13 +261,13 @@ abstract class InlineExceptionHandlers extends SubComponent { private def getTypesAtBlockEntry(bblock: BasicBlock): tfa.lattice.Elem = { // lazily perform tfa, because it's expensive // cache results by block label, as rewriting the code messes up the block's hashCode - if (analyzedMethod eq null) { + if (analyzedMethod eq NoIMethod) { analyzedMethod = bblock.method tfa.init(bblock.method) tfa.run log(" performed tfa on method: " + bblock.method) - for (block <- bblock.method.code.blocks.sortBy(_.label)) + for (block <- bblock.method.blocks.sortBy(_.label)) tfaCache += block.label -> tfa.in(block) } @@ -360,7 +360,7 @@ abstract class InlineExceptionHandlers extends SubComponent { val caughtException = toTypeKind(caughtClass.tpe) // copy the exception handler code once again, dropping the LOAD_EXCEPTION val copy = handler.code.newBlock - copy.emitOnly(handler drop dropCount: _*) + copy.emitOnly(handler.iterator drop dropCount toSeq: _*) // extend the handlers of the handler to the copy for (parentHandler <- handler.method.exh ; if parentHandler covers handler) { @@ -382,7 +382,7 @@ abstract class InlineExceptionHandlers extends SubComponent { case _ => currentClass.cunit.warning(NoPosition, "Unable to inline the exception handler due to incorrect format:\n" + - handler.mkString("\n")) + handler.iterator.mkString("\n")) None } } diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index d56a0740d9..e3d21011d1 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -9,6 +9,7 @@ package backend.opt import scala.collection.mutable import scala.tools.nsc.symtab._ +import scala.tools.nsc.util.{ NoSourceFile } /** * @author Iulian Dragos @@ -84,9 +85,9 @@ abstract class Inliners extends SubComponent { /* fresh name counter */ val fresh = perRunCaches.newMap[String, Int]() withDefaultValue 0 - def freshName(s: String) = { + def freshName(s: String): TermName = { fresh(s) += 1 - s + fresh(s) + newTermName(s + fresh(s)) } private def hasInline(sym: Symbol) = sym hasAnnotation ScalaInlineClass @@ -111,8 +112,8 @@ abstract class Inliners extends SubComponent { private val inlinedMethodCount = perRunCaches.newMap[Symbol, Int]() withDefaultValue 0 def analyzeMethod(m: IMethod): Unit = { - var sizeBeforeInlining = if (m.code ne null) m.code.blockCount else 0 - var instrBeforeInlining = if (m.code ne null) m.code.instructionCount else 0 + var sizeBeforeInlining = if (m.hasCode) m.code.blockCount else 0 + var instrBeforeInlining = if (m.hasCode) m.code.instructionCount else 0 var retry = false var count = 0 fresh.clear() @@ -210,11 +211,11 @@ abstract class Inliners extends SubComponent { if (caller.inline) { log("Not inlining into " + caller.sym.originalName.decode + " because it is marked @inline.") } - else if (caller.hasCode) { + else if (caller.m.hasCode) { log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks") tfa init m tfa.run - caller.linearized foreach { bb => + caller.m.linearizedBlocks() foreach { bb => info = tfa in bb breakable { @@ -311,18 +312,16 @@ abstract class Inliners extends SubComponent { def isMonadic = isMonadicMethod(sym) def handlers = m.exh - def blocks = if (m.code eq null) sys.error("blocks = null + " + m) else m.code.blocks + def blocks = m.blocks def locals = m.locals def length = blocks.length def openBlocks = blocks filterNot (_.closed) - def instructions = blocks.flatten + def instructions = m.code.instructions def linearized = linearizer linearize m def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10 def isLarge = length > MAX_INLINE_SIZE def isRecursive = m.recursive - def hasCode = m.code != null - def hasSourceFile = m.sourceFile != null def hasHandlers = handlers.nonEmpty def hasNonFinalizerHandler = handlers exists { case _: Finalizer => true @@ -457,7 +456,7 @@ abstract class Inliners extends SubComponent { if (retVal ne null) caller addLocal retVal - inc.blocks foreach { b => + inc.m foreachBlock { b => inlinedBlock += (b -> newBlock()) inlinedBlock(b).varsInScope ++= (b.varsInScope map inlinedLocals) } @@ -475,11 +474,11 @@ abstract class Inliners extends SubComponent { blockEmit(STORE_LOCAL(inlinedThis)) // jump to the start block of the callee - blockEmit(JUMP(inlinedBlock(inc.m.code.startBlock))) + blockEmit(JUMP(inlinedBlock(inc.m.startBlock))) block.close // duplicate the other blocks in the callee - linearizer linearize inc.m foreach { bb => + inc.m.linearizedBlocks() foreach { bb => var info = a in bb def emitInlined(i: Instruction) = inlinedBlock(bb).emit(i, targetPos) def emitDrops(toDrop: Int) = info.stack.types drop toDrop foreach (t => emitInlined(DROP(t))) @@ -511,23 +510,23 @@ abstract class Inliners extends SubComponent { } def isStampedForInlining(stack: TypeStack) = - !sameSymbols && inc.hasCode && shouldInline && isSafeToInline(stack) + !sameSymbols && inc.m.hasCode && shouldInline && isSafeToInline(stack) def logFailure(stack: TypeStack) = log( """|inline failed for %s: | pair.sameSymbols: %s | inc.numInlined < 2: %s - | inc.hasCode: %s + | inc.m.hasCode: %s | isSafeToInline: %s | shouldInline: %s """.stripMargin.format( inc.m, sameSymbols, inc.numInlined < 2, - inc.hasCode, isSafeToInline(stack), shouldInline + inc.m.hasCode, isSafeToInline(stack), shouldInline ) ) def failureReason(stack: TypeStack) = - if (!inc.hasCode) "bytecode was unavailable" + if (!inc.m.hasCode) "bytecode was unavailable" else if (!isSafeToInline(stack)) "it is unsafe (target may reference private fields)" else "of a bug (run with -Ylog:inline -Ydebug for more information)" @@ -550,14 +549,14 @@ abstract class Inliners extends SubComponent { */ def isSafeToInline(stack: TypeStack): Boolean = { def makePublic(f: Symbol): Boolean = - inc.hasSourceFile && (f.isSynthetic || f.isParamAccessor) && { + (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && { debuglog("Making not-private symbol out of synthetic: " + f) f setNotFlag Flags.PRIVATE true } - if (!inc.hasCode || inc.isRecursive) + if (!inc.m.hasCode || inc.isRecursive) return false val accessNeeded = usesNonPublics.getOrElseUpdate(inc.m, { @@ -610,7 +609,7 @@ abstract class Inliners extends SubComponent { * - it's good to inline closures functions. * - it's bad (useless) to inline inside bridge methods */ - private def neverInline = caller.isBridge || !inc.hasCode || inc.noinline + private def neverInline = caller.isBridge || !inc.m.hasCode || inc.noinline private def alwaysInline = inc.inline def shouldInline: Boolean = !neverInline && (alwaysInline || { diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala index 4c7263ef69..089ef9cf35 100644 --- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala +++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala @@ -18,8 +18,8 @@ abstract class Changes { abstract class Change - private lazy val annotationsChecked = - List(definitions.getClass("scala.specialized")) // Any others that should be checked? + private lazy val annotationsChecked = + List(definitions.SpecializedClass) // Any others that should be checked? private val flagsToCheck = IMPLICIT | FINAL | PRIVATE | PROTECTED | SEALED | OVERRIDE | CASE | ABSTRACT | DEFERRED | METHOD | diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala index 5a510803ed..9a025b0d14 100644 --- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -96,7 +96,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor val documentError: PartialFunction[Throwable, Unit] = { case NoCompilerRunException => - reporter.info(NoPosition, "No documentation generated with unsucessful compiler run", false) + reporter.info(null, "No documentation generated with unsucessful compiler run", false) case _: ClassNotFoundException => () } diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index f900859f46..0fea0a2d92 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -818,7 +818,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") def add(sym: Symbol, pre: Type, implicitlyAdded: Boolean)(toMember: (Symbol, Type) => M) { if ((sym.isGetter || sym.isSetter) && sym.accessed != NoSymbol) { add(sym.accessed, pre, implicitlyAdded)(toMember) - } else if (!sym.name.decode.containsName(Dollar) && !sym.isSynthetic && sym.hasRawInfo) { + } else if (!sym.name.decodedName.containsName(Dollar) && !sym.isSynthetic && sym.hasRawInfo) { val symtpe = pre.memberType(sym) onTypeError ErrorType matching(sym, symtpe, this(sym.name)) match { case Some(m) => diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index 2b6e793c5c..b7a9c7329c 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -101,7 +101,7 @@ trait Picklers { self: Global => if (sym1.isOverloaded) { val index = sym1.alternatives.indexOf(sym) assert(index >= 0, sym1+" not found in alternatives "+sym1.alternatives) - buf += index.toString + buf += newTermName(index.toString) } } } diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index 81d4faa36e..1d78cc6e1c 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -37,7 +37,7 @@ object REPL { reporter = new ConsoleReporter(settings) val command = new CompilerCommand(args.toList, settings) if (command.settings.version.value) - reporter.info(null, versionMsg, true) + reporter.echo(versionMsg) else { try { object compiler extends Global(command.settings, reporter) { @@ -48,7 +48,7 @@ object REPL { return } if (command.shouldStopWithInfo) { - reporter.info(null, command.getInfoMessage(compiler), true) + reporter.echo(command.getInfoMessage(compiler)) } else { run(compiler) } diff --git a/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala b/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala index 2c556656ca..d889cadf47 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala @@ -12,6 +12,7 @@ trait Dossiers { import intp._ import intp.global._ + import definitions._ trait Dossier { def symbol: Symbol @@ -34,7 +35,7 @@ trait Dossiers { class TermDossier(val symbol: TermSymbol, val staticType: Type, val value: AnyRef) extends Dossier { def runtimeClass: JClass = value.getClass - def runtimeSymbol: Symbol = safeClass(runtimeClass.getName) getOrElse NoSymbol + def runtimeSymbol: Symbol = getClassIfDefined(runtimeClass.getName) def runtimeType: Type = runtimeSymbol.tpe def runtimeTypeString = TypeStrings.fromClazz(runtimeClass) diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala index 115cef7f00..9f5fde70d8 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala @@ -15,6 +15,7 @@ trait ExprTyper { import repl._ import replTokens.{ Tokenizer } import global.{ reporter => _, Import => _, _ } + import definitions._ import syntaxAnalyzer.{ UnitParser, UnitScanner, token2name } import naming.freshInternalVarName @@ -70,30 +71,29 @@ trait ExprTyper { // 2) A path loadable via getModule. // 3) Try interpreting it as an expression. private var typeOfExpressionDepth = 0 - def typeOfExpression(expr: String, silent: Boolean = true): Option[Type] = { + def typeOfExpression(expr: String, silent: Boolean = true): Type = { repltrace("typeOfExpression(" + expr + ")") if (typeOfExpressionDepth > 2) { repldbg("Terminating typeOfExpression recursion for expression: " + expr) - return None + return NoType } - def asQualifiedImport = { + def asQualifiedImport: Type = { val name = expr.takeWhile(_ != '.') - importedTermNamed(name) flatMap { sym => - typeOfExpression(sym.fullName + expr.drop(name.length), true) - } + typeOfExpression(importedTermNamed(name).fullName + expr.drop(name.length), true) } - def asModule = safeModule(expr) map (_.tpe) - def asExpr = { + def asModule: Type = getModuleIfDefined(expr).tpe + def asExpr: Type = { val lhs = freshInternalVarName() val line = "lazy val " + lhs + " =\n" + expr interpret(line, true) match { case IR.Success => typeOfExpression(lhs, true) - case _ => None + case _ => NoType } } - def evaluate() = { + + def evaluate(): Type = { typeOfExpressionDepth += 1 try typeOfTerm(expr) orElse asModule orElse asExpr orElse asQualifiedImport finally typeOfExpressionDepth -= 1 @@ -107,26 +107,27 @@ trait ExprTyper { if (!silent) evaluate() - None + NoType } } // Since people will be giving us ":t def foo = 5" even though that is not an // expression, we have a means of typing declarations too. - private def typeOfDeclaration(code: String): Option[Type] = { + private def typeOfDeclaration(code: String): Type = { repltrace("typeOfDeclaration(" + code + ")") val obname = freshInternalVarName() interpret("object " + obname + " {\n" + code + "\n}\n", true) match { case IR.Success => val sym = symbolOfTerm(obname) - if (sym == NoSymbol) None else { + if (sym == NoSymbol) NoType else { // TODO: bitmap$n is not marked synthetic. val decls = sym.tpe.decls.toList filterNot (x => x.isConstructor || x.isPrivate || (x.name.toString contains "$")) repltrace("decls: " + decls) - decls.lastOption map (decl => typeCleanser(sym, decl.name)) + if (decls.isEmpty) NoType + else typeCleanser(sym, decls.last.name) } case _ => - None + NoType } } // def compileAndTypeExpr(expr: String): Option[Typer] = { diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index 2159ecbb8a..0dc51d5eb0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -53,6 +53,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) def isAsync = !settings.Yreplsync.value lazy val power = new Power(intp, new StdReplVals(this)) + lazy val NoType = intp.global.NoType // TODO // object opt extends AestheticSettings @@ -436,9 +437,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // Still todo: modules. private def typeCommand(line: String): Result = { if (line.trim == "") ":type <expression>" - else intp.typeOfExpression(line, false) match { - case Some(tp) => intp.afterTyper(tp.toString) - case _ => "" // the error message was already printed + else { + val tp = intp.typeOfExpression(line, false) + if (tp == NoType) "" // the error message was already printed + else intp.afterTyper(tp.toString) } } private def warningsCommand(): Result = { @@ -485,13 +487,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } case wrapper :: Nil => intp.typeOfExpression(wrapper) match { - case Some(PolyType(List(targ), MethodType(List(arg), restpe))) => + case PolyType(List(targ), MethodType(List(arg), restpe)) => intp setExecutionWrapper intp.pathToTerm(wrapper) "Set wrapper to '" + wrapper + "'" - case Some(x) => - failMsg + "\nFound: " + x - case _ => - failMsg + "\nFound: <unknown>" + case tp => + failMsg + ( + if (tp == g.NoType) "\nFound: <unknown>" + else "\nFound: <unknown>" + ) } case _ => failMsg } diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 8e4ff8aa37..0f0ab69e6d 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -188,7 +188,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends import global._ import definitions.{ ScalaPackage, JavaLangPackage, PredefModule, RootClass, - getClassIfDefined, getModuleIfDefined + getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass } private implicit def privateTreeOps(t: Tree): List[Tree] = { @@ -196,6 +196,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def foreach[U](f: Tree => U): Unit = t foreach { x => f(x) ; () } }).toList } + + implicit def installReplTypeOps(tp: Type): ReplTypeOps = new ReplTypeOps(tp) + class ReplTypeOps(tp: Type) { + def orElse(other: => Type): Type = if (tp ne NoType) tp else other + def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp) + } // TODO: If we try to make naming a lazy val, we run into big time // scalac unhappiness with what look like cycles. It has not been easy to @@ -204,12 +210,13 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val global: imain.global.type = imain.global } with Naming { // make sure we don't overwrite their unwisely named res3 etc. - override def freshUserVarName(): String = { - val name = super.freshUserVarName() - if (definedNameMap contains name) freshUserVarName() + def freshUserTermName(): TermName = { + val name = newTermName(freshUserVarName()) + if (definedNameMap contains name) freshUserTermName() else name } - def isInternalVarName(name: Name): Boolean = isInternalVarName("" + name) + def isUserTermName(name: Name) = isUserVarName("" + name) + def isInternalTermName(name: Name) = isInternalVarName("" + name) } import naming._ @@ -359,7 +366,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private def mostRecentlyHandledTree: Option[Tree] = { prevRequests.reverse foreach { req => req.handlers.reverse foreach { - case x: MemberDefHandler if x.definesValue && !isInternalVarName(x.name) => return Some(x.member) + case x: MemberDefHandler if x.definesValue && !isInternalTermName(x.name) => return Some(x.member) case _ => () } } @@ -501,7 +508,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends trees.last match { case _:Assign => // we don't want to include assignments case _:TermTree | _:Ident | _:Select => // ... but do want other unnamed terms. - val varName = if (synthetic) freshInternalVarName() else freshUserVarName() + val varName = if (synthetic) freshInternalVarName() else ("" + freshUserTermName()) val rewrittenLine = ( // In theory this would come out the same without the 1-specific test, but // it's a cushion against any more sneaky parse-tree position vs. code mismatches: @@ -643,7 +650,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def directBind(name: String, boundType: String, value: Any): IR.Result = { val result = bind(name, boundType, value) if (result == IR.Success) - directlyBoundNames += name + directlyBoundNames += newTermName(name) result } def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value) @@ -651,7 +658,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def rebind(p: NamedParam): IR.Result = { val name = p.name - val oldType = typeOfTerm(name) getOrElse { return IR.Error } + val oldType = typeOfTerm(name) orElse { return IR.Error } val newType = p.tpe val tempName = freshInternalVarName() @@ -666,7 +673,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p)) def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) def bind[T: Manifest](name: String, value: T): IR.Result = bind((name, value)) - def bindValue(x: Any): IR.Result = bindValue(freshUserVarName(), x) + def bindValue(x: Any): IR.Result = bindValue("" + freshUserTermName(), x) def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x) /** Reset this interpreter, forgetting all user-specified requests. */ @@ -789,7 +796,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends * following accessPath into the outer one. */ def resolvePathToSymbol(accessPath: String): Symbol = { - val readRoot = definitions.getModule(readPath) // the outermost wrapper + val readRoot = getRequiredModule(readPath) // the outermost wrapper (accessPath split '.').foldLeft(readRoot) { (sym, name) => if (name == "") sym else lineAfterTyper(sym.info member newTermName(name)) @@ -1039,16 +1046,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def requestHistoryForName(name: Name): List[Request] = prevRequests.toList.reverse filter (_.definedNames contains name) - def safeClass(name: String): Option[Symbol] = { - try Some(definitions.getClass(newTypeName(name))) - catch { case _: MissingRequirementError => None } - } - - def safeModule(name: String): Option[Symbol] = { - try Some(definitions.getModule(newTermName(name))) - catch { case _: MissingRequirementError => None } - } - def definitionForName(name: Name): Option[MemberHandler] = requestForName(name) flatMap { req => req.handlers find (_.definedNames contains name) @@ -1060,34 +1057,32 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def classOfTerm(id: String): Option[JClass] = valueOfTerm(id) map (_.getClass) - def typeOfTerm(id: String): Option[Type] = newTermName(id) match { - case nme.ROOTPKG => Some(definitions.RootClass.tpe) - case name => requestForName(name) flatMap (_.compilerTypeOf get name) + def typeOfTerm(id: String): Type = newTermName(id) match { + case nme.ROOTPKG => definitions.RootClass.tpe + case name => requestForName(name) flatMap (_.compilerTypeOf get name) getOrElse NoType } def symbolOfTerm(id: String): Symbol = requestForIdent(id) flatMap (_.definedSymbols get newTermName(id)) getOrElse NoSymbol def runtimeClassAndTypeOfTerm(id: String): Option[(JClass, Type)] = { - for { - clazz <- classOfTerm(id) - tpe <- runtimeTypeOfTerm(id) - nonAnon <- clazz.supers find (!_.isScalaAnonymous) - } yield { - (nonAnon, tpe) + classOfTerm(id) flatMap { clazz => + clazz.supers find (!_.isScalaAnonymous) map { nonAnon => + (nonAnon, runtimeTypeOfTerm(id)) + } } } - def runtimeTypeOfTerm(id: String): Option[Type] = { - for { - tpe <- typeOfTerm(id) - clazz <- classOfTerm(id) - staticSym = tpe.typeSymbol - runtimeSym <- safeClass(clazz.getName) - if runtimeSym != staticSym - if runtimeSym isSubClass staticSym + def runtimeTypeOfTerm(id: String): Type = { + typeOfTerm(id) andAlso { tpe => + val clazz = classOfTerm(id) getOrElse { return NoType } + val staticSym = tpe.typeSymbol + val runtimeSym = getClassIfDefined(clazz.getName) + + if ((runtimeSym != NoSymbol) && (runtimeSym != staticSym) && (runtimeSym isSubClass staticSym)) + runtimeSym.info + else NoType } - yield runtimeSym.info } object replTokens extends { @@ -1099,16 +1094,16 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } with ExprTyper { } def parse(line: String): Option[List[Tree]] = exprTyper.parse(line) - def typeOfExpression(expr: String, silent: Boolean = true): Option[Type] = { + def typeOfExpression(expr: String, silent: Boolean = true): Type = exprTyper.typeOfExpression(expr, silent) - } + def prettyPrint(code: String) = replTokens.prettyPrint(exprTyper tokens code) protected def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x } protected def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x } - def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalVarName + def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName def definedTypes = onlyTypes(allDefinedNames) def definedSymbols = prevRequests.toSet flatMap ((x: Request) => x.definedSymbols.values) diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala index 10e3796404..d34ca8bbca 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala @@ -34,8 +34,9 @@ trait Imports { def languageWildcards: List[Type] = languageWildcardSyms map (_.tpe) def languageWildcardHandlers = languageWildcardSyms map makeWildcardImportHandler - def importedTerms = onlyTerms(importHandlers flatMap (_.importedNames)) - def importedTypes = onlyTypes(importHandlers flatMap (_.importedNames)) + def allImportedNames = importHandlers flatMap (_.importedNames) + def importedTerms = onlyTerms(allImportedNames) + def importedTypes = onlyTypes(allImportedNames) /** Types which have been wildcard imported, such as: * val x = "abc" ; import x._ // type java.lang.String @@ -49,10 +50,7 @@ trait Imports { * into the compiler scopes. */ def sessionWildcards: List[Type] = { - importHandlers flatMap { - case x if x.importsWildcard => x.targetType - case _ => None - } distinct + importHandlers filter (_.importsWildcard) map (_.targetType) distinct } def wildcardTypes = languageWildcards ++ sessionWildcards @@ -63,14 +61,15 @@ trait Imports { def importedTypeSymbols = importedSymbols collect { case x: TypeSymbol => x } def implicitSymbols = importedSymbols filter (_.isImplicit) - def importedTermNamed(name: String) = importedTermSymbols find (_.name.toString == name) + def importedTermNamed(name: String): Symbol = + importedTermSymbols find (_.name.toString == name) getOrElse NoSymbol /** Tuples of (source, imported symbols) in the order they were imported. */ def importedSymbolsBySource: List[(Symbol, List[Symbol])] = { val lang = languageWildcardSyms map (sym => (sym, membersAtPickler(sym))) - val session = importHandlers filter (_.targetType.isDefined) map { mh => - (mh.targetType.get.typeSymbol, mh.importedSymbols) + val session = importHandlers filter (_.targetType != NoType) map { mh => + (mh.targetType.typeSymbol, mh.importedSymbols) } lang ++ session diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala index 9c5299b633..d96e8b07fc 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -16,7 +16,7 @@ import collection.mutable.ListBuffer class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput { val global: intp.global.type = intp.global import global._ - import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage } + import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage, getModuleIfDefined } type ExecResult = Any import intp.{ debugging, afterTyper } @@ -24,14 +24,13 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput private var verbosity: Int = 0 def resetVerbosity() = verbosity = 0 - def getType(name: String, isModule: Boolean) = { - val f = if (isModule) definitions.getModule(_: Name) else definitions.getClass(_: Name) - try Some(f(name).tpe) - catch { case _: MissingRequirementError => None } - } - - def typeOf(name: String) = getType(name, false) - def moduleOf(name: String) = getType(name, true) + def getSymbol(name: String, isModule: Boolean) = ( + if (isModule) getModuleIfDefined(name) + else getModuleIfDefined(name) + ) + def getType(name: String, isModule: Boolean) = getSymbol(name, isModule).tpe + def typeOf(name: String) = getType(name, false) + def moduleOf(name: String) = getType(name, true) trait CompilerCompletion { def tp: Type @@ -46,9 +45,9 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput private def anyMembers = AnyClass.tpe.nonPrivateMembers def anyRefMethodsToShow = Set("isInstanceOf", "asInstanceOf", "toString") - def tos(sym: Symbol) = sym.name.decode.toString - def memberNamed(s: String) = members find (x => tos(x) == s) - def hasMethod(s: String) = methods exists (x => tos(x) == s) + def tos(sym: Symbol): String = sym.decodedName + def memberNamed(s: String) = afterTyper(effectiveTp member newTermName(s)) + def hasMethod(s: String) = memberNamed(s).isMethod // XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the // compiler to crash for reasons not yet known. @@ -62,6 +61,13 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput def packageNames = packages map tos def aliasNames = aliases map tos } + + object NoTypeCompletion extends TypeMemberCompletion(NoType) { + override def memberNamed(s: String) = NoSymbol + override def members = Nil + override def follow(s: String) = None + override def alternativesFor(id: String) = Nil + } object TypeMemberCompletion { def apply(tp: Type, runtimeType: Type, param: NamedParam): TypeMemberCompletion = { @@ -90,7 +96,8 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput } } def apply(tp: Type): TypeMemberCompletion = { - if (tp.typeSymbol.isPackageClass) new PackageCompletion(tp) + if (tp eq NoType) NoTypeCompletion + else if (tp.typeSymbol.isPackageClass) new PackageCompletion(tp) else new TypeMemberCompletion(tp) } def imported(tp: Type) = new ImportCompletion(tp) @@ -118,7 +125,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput debugging(tp + " completions ==> ")(filtered(memberNames)) override def follow(s: String): Option[CompletionAware] = - debugging(tp + " -> '" + s + "' ==> ")(memberNamed(s) map (x => TypeMemberCompletion(x.tpe))) + debugging(tp + " -> '" + s + "' ==> ")(Some(TypeMemberCompletion(memberNamed(s).tpe)) filterNot (_ eq NoTypeCompletion)) override def alternativesFor(id: String): List[String] = debugging(id + " alternatives ==> ") { @@ -155,28 +162,29 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput object ids extends CompletionAware { override def completions(verbosity: Int) = intp.unqualifiedIds ++ List("classOf") //, "_root_") // now we use the compiler for everything. - override def follow(id: String) = { - if (completions(0) contains id) { - intp typeOfExpression id map { tpe => - def default = TypeMemberCompletion(tpe) - - // only rebinding vals in power mode for now. - if (!isReplPower) default - else intp runtimeClassAndTypeOfTerm id match { - case Some((clazz, runtimeType)) => - val sym = intp.symbolOfTerm(id) - if (sym.isStable) { - val param = new NamedParam.Untyped(id, intp valueOfTerm id getOrElse null) - TypeMemberCompletion(tpe, runtimeType, param) - } - else default - case _ => - default + override def follow(id: String): Option[CompletionAware] = { + if (!completions(0).contains(id)) + return None + + val tpe = intp typeOfExpression id + if (tpe == NoType) + return None + + def default = Some(TypeMemberCompletion(tpe)) + + // only rebinding vals in power mode for now. + if (!isReplPower) default + else intp runtimeClassAndTypeOfTerm id match { + case Some((clazz, runtimeType)) => + val sym = intp.symbolOfTerm(id) + if (sym.isStable) { + val param = new NamedParam.Untyped(id, intp valueOfTerm id getOrElse null) + Some(TypeMemberCompletion(tpe, runtimeType, param)) } - } + else default + case _ => + default } - else - None } override def toString = "<repl ids> (%s)".format(completions(0).size) } diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index b64f14e929..c742ab89c0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -169,7 +169,7 @@ trait MemberHandlers { class ImportHandler(imp: Import) extends MemberHandler(imp) { val Import(expr, selectors) = imp - def targetType = intp.typeOfExpression("" + expr) + def targetType: Type = intp.typeOfExpression("" + expr) override def isLegalTopLevel = true def createImportForName(name: Name): String = { @@ -199,10 +199,10 @@ trait MemberHandlers { def importedSymbols = individualSymbols ++ wildcardSymbols lazy val individualSymbols: List[Symbol] = - atPickler(targetType.toList flatMap (tp => individualNames map (tp nonPrivateMember _))) + atPickler(individualNames map (targetType nonPrivateMember _)) lazy val wildcardSymbols: List[Symbol] = - if (importsWildcard) atPickler(targetType.toList flatMap (_.nonPrivateMembers)) + if (importsWildcard) atPickler(targetType.nonPrivateMembers) else Nil /** Complete list of names imported by a wildcard */ diff --git a/src/compiler/scala/tools/nsc/interpreter/Naming.scala b/src/compiler/scala/tools/nsc/interpreter/Naming.scala index 7377953263..8e215cf63b 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Naming.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Naming.scala @@ -84,7 +84,7 @@ trait Naming { var x = 0 () => { x += 1 ; x } } - def freshUserVarName() = userVar() + def freshUserVarName() = userVar() def freshInternalVarName() = internalVar() def resetAllCreators() { diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 82a466a7e5..b4a9b9b0e3 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -353,7 +353,7 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl def source(code: String) = new BatchSourceFile("<console>", code) def unit(code: String) = new CompilationUnit(source(code)) def trees(code: String) = parse(code) getOrElse Nil - def typeOf(id: String): Type = intp.typeOfExpression(id) getOrElse NoType + def typeOf(id: String) = intp.typeOfExpression(id) override def toString = """ |** Power mode status ** diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 742e9e03ca..0d7afdc4ec 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -547,7 +547,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { if (parentToken == AT && in.token == DEFAULT) { val annot = atPos(pos) { - New(Select(scalaDot(newTermName("runtime")), tpnme.AnnotationDefaultATTR), List(List())) + New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), List(List())) } mods1 = mods1 withAnnotations List(annot) skipTo(SEMI) @@ -794,9 +794,9 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { accept(INTERFACE) val pos = in.currentPos val name = identForType() - val parents = List(scalaDot(newTypeName("Annotation")), - Select(javaLangDot(newTermName("annotation")), newTypeName("Annotation")), - scalaDot(newTypeName("ClassfileAnnotation"))) + val parents = List(scalaDot(tpnme.Annotation), + Select(javaLangDot(nme.annotation), tpnme.Annotation), + scalaDot(tpnme.ClassfileAnnotation)) val (statics, body) = typeBody(AT, name) def getValueMethodType(tree: Tree) = tree match { case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate) @@ -838,18 +838,18 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { } val predefs = List( DefDef( - Modifiers(Flags.JAVA | Flags.STATIC), newTermName("values"), List(), + Modifiers(Flags.JAVA | Flags.STATIC), nme.values, List(), List(List()), arrayOf(enumType), blankExpr), DefDef( - Modifiers(Flags.JAVA | Flags.STATIC), newTermName("valueOf"), List(), + Modifiers(Flags.JAVA | Flags.STATIC), nme.valueOf, List(), List(List(makeParam("x", TypeTree(StringClass.tpe)))), enumType, blankExpr)) accept(RBRACE) val superclazz = - AppliedTypeTree(javaLangDot(newTypeName("Enum")), List(enumType)) + AppliedTypeTree(javaLangDot(tpnme.Enum), List(enumType)) addCompanionObject(consts ::: statics ::: predefs, atPos(pos) { ClassDef(mods, name, List(), makeTemplate(superclazz :: interfaces, body)) diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 420fba911b..e5748b7c23 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -36,6 +36,9 @@ trait Patterns extends ast.TreeDSL { // case _ => NoSymbol // } + private lazy val dummyMethod = + new TermSymbol(NoSymbol, NoPosition, newTermName("matching$dummy")) + // Fresh patterns def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern) def emptyTrees(i: Int): List[Tree] = List.fill(i)(EmptyTree) @@ -191,9 +194,9 @@ trait Patterns extends ast.TreeDSL { // As yet I can't testify this is doing any good relative to using // tpt.tpe, but it doesn't seem to hurt either. private lazy val packedType = global.typer.computeType(tpt, tpt.tpe) - private lazy val consRef = typeRef(NoPrefix, ConsClass, List(packedType)) - private lazy val listRef = typeRef(NoPrefix, ListClass, List(packedType)) - private lazy val seqRef = typeRef(NoPrefix, SeqClass, List(packedType)) + private lazy val consRef = appliedType(ConsClass.typeConstructor, List(packedType)) + private lazy val listRef = appliedType(ListClass.typeConstructor, List(packedType)) + private lazy val seqRef = appliedType(SeqClass.typeConstructor, List(packedType)) private def thisSeqRef = { val tc = (tree.tpe baseType SeqClass).typeConstructor @@ -205,7 +208,6 @@ trait Patterns extends ast.TreeDSL { private def listFolder(hd: Tree, tl: Tree): Tree = unbind(hd) match { case t @ Star(_) => moveBindings(hd, WILD(t.tpe)) case _ => - val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy") val consType = MethodType(dummyMethod newSyntheticValueParams List(packedType, listRef), consRef) Apply(TypeTree(consType), List(hd, tl)) setType consRef diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index 12306606e4..f19a285d7c 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -47,14 +47,23 @@ abstract class Reporter { finally incompleteHandler = saved } - var cancelled = false - def hasErrors = ERROR.count > 0 || cancelled - def hasWarnings = WARNING.count > 0 + var cancelled = false + def hasErrors = ERROR.count > 0 || cancelled + def hasWarnings = WARNING.count > 0 - def info(pos: Position, msg: String, force: Boolean) { info0(pos, msg, INFO, force) } - def warning(pos: Position, msg: String ) { withoutTruncating(info0(pos, msg, WARNING, false)) } - def error(pos: Position, msg: String ) { withoutTruncating(info0(pos, msg, ERROR, false)) } - def incompleteInputError(pos: Position, msg: String ) { + /** For sending a message which should not be labeled as a warning/error, + * but also shouldn't require -verbose to be visible. + */ + def echo(msg: String): Unit = info(NoPosition, msg, true) + def echo(pos: Position, msg: String): Unit = info(pos, msg, true) + + /** Informational messages, suppressed unless -verbose or force=true. */ + def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force) + + /** Warnings and errors. */ + def warning(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, WARNING, false)) + def error(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, ERROR, false)) + def incompleteInputError(pos: Position, msg: String): Unit = { if (incompleteHandled) incompleteHandler(pos, msg) else error(pos, msg) } diff --git a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala index 800af55861..f55d0684c8 100644 --- a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala +++ b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala @@ -13,8 +13,6 @@ import scala.tools.util.AbstractTimer * timings. */ class ReporterTimer(reporter: Reporter) extends AbstractTimer { - def issue(msg: String, duration: Long) = reporter.info(null, "[" + msg + " in " + duration + "ms]", false) - } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 7fcfb6fc6d..efd5323ce2 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -67,6 +67,8 @@ trait ScalaSettings extends AbsScalaSettings val future = BooleanSetting ("-Xfuture", "Turn on future language features.") val genPhaseGraph = StringSetting ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "") val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.") + val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.") + val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated") val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None) val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.") val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 94eb6d2afd..a158012f9f 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -439,19 +439,20 @@ abstract class ClassfileParser { /** Return the class symbol of the given name. */ def classNameToSymbol(name: Name): Symbol = { - def loadClassSymbol(name: Name) = { - val s = name.toString - val file = global.classPath findSourceFile s getOrElse { - MissingRequirementError.notFound("class " + s) + def loadClassSymbol(name: Name): Symbol = { + val file = global.classPath findSourceFile ("" +name) getOrElse { + warning("Class " + name + " not found - continuing with a stub.") + return NoSymbol.newClass(name.toTypeName) } - val completer = new global.loaders.ClassfileLoader(file) + val completer = new global.loaders.ClassfileLoader(file) var owner: Symbol = definitions.RootClass - var sym: Symbol = NoSymbol - var ss: String = null - var start = 0 - var end = s indexOf '.' + var sym: Symbol = NoSymbol + var ss: Name = null + var start = 0 + var end = name indexOf '.' + while (end > 0) { - ss = s.substring(start, end) + ss = name.subName(start, end) sym = owner.info.decls lookup ss if (sym == NoSymbol) { sym = owner.newPackage(NoPosition, ss) setInfo completer @@ -460,17 +461,16 @@ abstract class ClassfileParser { } owner = sym.moduleClass start = end + 1 - end = s.indexOf('.', start) + end = name.indexOf('.', start) } - ss = s substring start - sym = owner.info.decls lookup ss - if (sym == NoSymbol) { - sym = owner.newClass(NoPosition, newTypeName(ss)) setInfo completer - owner.info.decls enter sym - if (settings.debug.value && settings.verbose.value) + ss = name.subName(0, start) + owner.info.decls lookup ss orElse { + sym = owner.newClass(NoPosition, ss.toTypeName) setInfo completer + if (opt.verboseDebug) println("loaded "+sym+" from file "+file) + + owner.info.decls enter sym } - sym } def lookupClass(name: Name) = try { @@ -718,7 +718,12 @@ abstract class ClassfileParser { index += 1 val bounds = variance match { case '+' => TypeBounds.upper(objToAny(sig2type(tparams, skiptvs))) - case '-' => TypeBounds.lower(sig2type(tparams, skiptvs)) + case '-' => + val tp = sig2type(tparams, skiptvs) + // sig2type seems to return AnyClass regardless of the situation: + // we don't want Any as a LOWER bound. + if (tp.typeSymbol == definitions.AnyClass) TypeBounds.empty + else TypeBounds.lower(tp) case '*' => TypeBounds.empty } val newtparam = sym.newExistential(sym.pos, newTypeName("?"+i)) setInfo bounds diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index a203b8a78b..0b64a49a2c 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -25,10 +25,7 @@ abstract class ICodeReader extends ClassfileParser { var instanceCode: IClass = null // the ICode class for the current symbol var staticCode: IClass = null // the ICode class static members - var method: IMethod = _ // the current IMethod - - val nothingName = newTermName(SCALA_NOTHING) - val nullName = newTermName(SCALA_NULL) + var method: IMethod = NoIMethod // the current IMethod var isScalaModule = false /** Read back bytecode for the given class symbol. It returns @@ -182,9 +179,9 @@ abstract class ICodeReader extends ClassfileParser { } override def classNameToSymbol(name: Name) = { - val sym = if (name == nothingName) + val sym = if (name == fulltpnme.RuntimeNothing) definitions.NothingClass - else if (name == nullName) + else if (name == fulltpnme.RuntimeNull) definitions.NullClass else if (nme.isImplClassName(name)) { val iface = definitions.getClass(nme.interfaceName(name)) @@ -194,7 +191,7 @@ abstract class ICodeReader extends ClassfileParser { } else if (nme.isModuleName(name)) { val strippedName = nme.stripModuleSuffix(name) - val sym = forceMangledName(strippedName.decode, true) + val sym = forceMangledName(newTermName(strippedName.decode), true) if (sym == NoSymbol) definitions.getModule(strippedName) else sym @@ -629,7 +626,7 @@ abstract class ICodeReader extends ClassfileParser { skipAttributes() code.toBasicBlock - assert(method.code ne null) + assert(method.hasCode, method) // reverse parameters, as they were prepended during code generation method.params = method.params.reverse @@ -692,7 +689,7 @@ abstract class ICodeReader extends ClassfileParser { mutable.Map(jmpTargets.toSeq map (_ -> code.newBlock): _*) val blocks = makeBasicBlocks - var otherBlock: BasicBlock = null + var otherBlock: BasicBlock = NoBasicBlock var disableJmpTarget = false for ((pc, instr) <- instrs.iterator) { @@ -991,7 +988,7 @@ abstract class ICodeReader extends ClassfileParser { /** Return a fresh Local variable for the given index. */ private def freshLocal(idx: Int, kind: TypeKind, isArg: Boolean) = { - val sym = method.symbol.newVariable(NoPosition, "loc" + idx).setInfo(kind.toType); + val sym = method.symbol.newVariable(NoPosition, newTermName("loc" + idx)).setInfo(kind.toType); val l = new Local(sym, kind, isArg) method.addLocal(l) l @@ -1008,7 +1005,7 @@ abstract class ICodeReader extends ClassfileParser { /** add a method param with the given index. */ def enterParam(idx: Int, kind: TypeKind) = { - val sym = method.symbol.newVariable(NoPosition, "par" + idx).setInfo(kind.toType) + val sym = method.symbol.newVariable(NoPosition, newTermName("par" + idx)).setInfo(kind.toType) val l = new Local(sym, kind, true) assert(!locals.isDefinedAt(idx)) locals += (idx -> List((l, kind))) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala index 728593abe7..676c8f09da 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala @@ -49,7 +49,7 @@ abstract class MetaParser{ val sym = locals.lookup(newTypeName(str)) if (sym != NoSymbol) sym.tpe else { - val tp = definitions.getClass(str).tpe; + val tp = definitions.getRequiredClass(str).tpe; if (token != "[") tp else { val args = new ListBuffer[Type]; diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index 95ef799720..e0cb0848be 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -34,6 +34,8 @@ abstract class TypeParser { protected var busy: Boolean = false // lock to detect recursive reads + private implicit def stringToTermName(s: String): TermName = newTermName(s) + private object unpickler extends UnPickler { val global: TypeParser.this.global.type = TypeParser.this.global } @@ -153,8 +155,8 @@ abstract class TypeParser { val canBeTakenAddressOf = (typ.IsValueType || typ.IsEnum) && (typ.FullName != "System.Enum") if(canBeTakenAddressOf) { - clazzBoxed = clazz.owner.newClass(clazz.name.toTypeName append "Boxed") - clazzMgdPtr = clazz.owner.newClass(clazz.name.toTypeName append "MgdPtr") + clazzBoxed = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("Boxed")) + clazzMgdPtr = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("MgdPtr")) clrTypes.mdgptrcls4clssym(clazz) = clazzMgdPtr /* adding typMgdPtr to clrTypes.sym2type should happen early (before metadata for supertypes is parsed, before metadata for members are parsed) so that clazzMgdPtr can be found by getClRType. */ diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 98345dd01e..034628e95f 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -22,9 +22,35 @@ abstract class CleanUp extends Transform with ast.TreeDSL { new CleanUpTransformer(unit) class CleanUpTransformer(unit: CompilationUnit) extends Transformer { - private val newStaticMembers = mutable.Buffer.empty[Tree] - private val newStaticInits = mutable.Buffer.empty[Tree] + private val newStaticMembers = mutable.Buffer.empty[Tree] + private val newStaticInits = mutable.Buffer.empty[Tree] private val symbolsStoredAsStatic = mutable.Map.empty[String, Symbol] + private def clearStatics() { + newStaticMembers.clear() + newStaticInits.clear() + symbolsStoredAsStatic.clear() + } + private def savingStatics[T](body: => T): T = { + val savedNewStaticMembers : mutable.Buffer[Tree] = newStaticMembers.clone() + val savedNewStaticInits : mutable.Buffer[Tree] = newStaticInits.clone() + val savedSymbolsStoredAsStatic : mutable.Map[String, Symbol] = symbolsStoredAsStatic.clone() + val result = body + + clearStatics() + newStaticMembers ++= savedNewStaticMembers + newStaticInits ++= savedNewStaticInits + symbolsStoredAsStatic ++= savedSymbolsStoredAsStatic + + result + } + private def transformTemplate(tree: Tree) = { + val Template(parents, self, body) = tree + clearStatics() + val newBody = transformTrees(body) + val templ = treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) + try addStaticInits(templ) // postprocess to include static ctors + finally clearStatics() + } private def mkTerm(prefix: String): TermName = unit.freshTermName(prefix) /** Kludge to provide a safe fix for #4560: @@ -60,7 +86,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } private def typedWithPos(pos: Position)(tree: Tree) = - localTyper typed { atPos(pos)(tree) } + localTyper.typedPos(pos)(tree) /** A value class is defined to be only Java-compatible values: unit is * not part of it, as opposed to isValueClass in definitions. scala.Int is @@ -71,7 +97,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /** The boxed type if it's a primitive; identity otherwise. */ def toBoxedType(tp: Type) = if (isJavaValueType(tp)) boxedClass(tp.typeSymbol).tpe else tp - + override def transform(tree: Tree): Tree = tree match { /* Transforms dynamic calls (i.e. calls to methods that are undefined @@ -106,6 +132,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * refinement, where the refinement defines a parameter based on a * type variable. */ case ad@ApplyDynamic(qual0, params) => + if (settings.logReflectiveCalls.value) + unit.echo(ad.pos, "method invocation uses reflection") + val typedPos = typedWithPos(ad.pos) _ assert(ad.symbol.isPublic) @@ -113,11 +142,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### CREATING THE METHOD CACHE ### */ - def addStaticVariableToClass(forName: String, forType: Type, forInit: Tree, isFinal: Boolean): Symbol = { + def addStaticVariableToClass(forName: TermName, forType: Type, forInit: Tree, isFinal: Boolean): Symbol = { val varSym = ( - currentClass.newVariable(ad.pos, mkTerm(forName)) - setFlag (PRIVATE | STATIC | SYNTHETIC) - setInfo (forType) + currentClass.newVariable(ad.pos, mkTerm("" + forName)) + setFlag PRIVATE | STATIC | SYNTHETIC + setInfo forType ) if (isFinal) varSym setFlag FINAL else varSym.addAnnotation(VolatileAttr) @@ -165,9 +194,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) { + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => (REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym)) } @@ -194,18 +223,18 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) val reflMethodCacheSym: Symbol = - addStaticVariableToClass("reflMethod$Cache", MethodClass.tpe, NULL, false) + addStaticVariableToClass(nme.reflMethodCacheName, MethodClass.tpe, NULL, false) val reflClassCacheSym: Symbol = - addStaticVariableToClass("reflClass$Cache", SoftReferenceClass.tpe, NULL, false) + addStaticVariableToClass(nme.reflClassCacheName, SoftReferenceClass.tpe, NULL, false) def isCacheEmpty(receiver: Symbol): Tree = reflClassCacheSym.IS_NULL() OR (reflClassCacheSym.GET() OBJ_NE REF(receiver)) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) { + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => BLOCK( IF (isCacheEmpty(forReceiverSym)) THEN BLOCK( @@ -241,13 +270,15 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) def mkNewPolyCache = gen.mkSoftRef(NEW(TypeTree(EmptyMethodCacheClass.tpe))) - val reflPolyCacheSym: Symbol = addStaticVariableToClass("reflPoly$Cache", SoftReferenceClass.tpe, mkNewPolyCache, false) + val reflPolyCacheSym: Symbol = ( + addStaticVariableToClass(nme.reflPolyCacheName, SoftReferenceClass.tpe, mkNewPolyCache, false) + ) def getPolyCache = gen.mkCast(fn(safeREF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => val methodSym = reflMethodSym.newVariable(ad.pos, mkTerm("method")) setInfo MethodClass.tpe @@ -271,59 +302,14 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */ - val testForNumber: Tree => Tree = { - qual1 => (qual1 IS_OBJ BoxedNumberClass.tpe) OR (qual1 IS_OBJ BoxedCharacterClass.tpe) - } - val testForBoolean: Tree => Tree = { - qual1 => (qual1 IS_OBJ BoxedBooleanClass.tpe) - } - val testForNumberOrBoolean: Tree => Tree = { - qual1 => testForNumber(qual1) OR testForBoolean(qual1) - } - - def postfixTest(name: Name): Option[(String, Tree => Tree)] = { - var runtimeTest: Tree => Tree = testForNumber - val newName = name match { - case nme.UNARY_! => runtimeTest = testForBoolean ; "takeNot" - case nme.UNARY_+ => "positive" - case nme.UNARY_- => "negate" - case nme.UNARY_~ => "complement" - case nme.toByte => "toByte" - case nme.toShort => "toShort" - case nme.toChar => "toCharacter" - case nme.toInt => "toInteger" - case nme.toLong => "toLong" - case nme.toFloat => "toFloat" - case nme.toDouble => "toDouble" - case _ => return None - } - Some((newName, runtimeTest)) - } - def infixTest(name: Name): Option[(String, Tree => Tree)] = { - val (newName, runtimeTest) = name match { - case nme.OR => ("takeOr", testForNumberOrBoolean) - case nme.XOR => ("takeXor", testForNumberOrBoolean) - case nme.AND => ("takeAnd", testForNumberOrBoolean) - case nme.EQ => ("testEqual", testForNumberOrBoolean) - case nme.NE => ("testNotEqual", testForNumberOrBoolean) - case nme.ADD => ("add", testForNumber) - case nme.SUB => ("subtract", testForNumber) - case nme.MUL => ("multiply", testForNumber) - case nme.DIV => ("divide", testForNumber) - case nme.MOD => ("takeModulo", testForNumber) - case nme.LSL => ("shiftSignedLeft", testForNumber) - case nme.LSR => ("shiftLogicalRight", testForNumber) - case nme.ASR => ("shiftSignedRight", testForNumber) - case nme.LT => ("testLessThan", testForNumber) - case nme.LE => ("testLessOrEqualThan", testForNumber) - case nme.GE => ("testGreaterOrEqualThan", testForNumber) - case nme.GT => ("testGreaterThan", testForNumber) - case nme.ZOR => ("takeConditionalOr", testForBoolean) - case nme.ZAND => ("takeConditionalAnd", testForBoolean) - case _ => return None - } - Some((newName, runtimeTest)) - } + def testForName(name: Name): Tree => Tree = t => ( + if (nme.CommonOpNames(name)) + gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean), t :: Nil) + else if (nme.BooleanOpNames(name)) + t IS_OBJ BoxedBooleanClass.tpe + else + gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumber), t :: Nil) + ) /** The Tree => Tree function in the return is necessary to prevent the original qual * from being duplicated in the resulting code. It may be a side-effecting expression, @@ -332,12 +318,13 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * (If the compiler can verify qual is safe to inline, it will not create the block.) */ def getPrimitiveReplacementForStructuralCall(name: Name): Option[(Symbol, Tree => Tree)] = { - val opt = ( - if (params.isEmpty) postfixTest(name) - else if (params.tail.isEmpty) infixTest(name) - else None + val methodName = ( + if (params.isEmpty) nme.primitivePostfixMethodName(name) + else if (params.tail.isEmpty) nme.primitiveInfixMethodName(name) + else nme.NO_NAME ) - opt map { case (name, fn) => (getMember(BoxesRunTimeClass, name), fn) } + if (methodName == nme.NO_NAME) None + else Some((getMember(BoxesRunTimeClass, methodName), testForName(name))) } /* ### BOXING PARAMS & UNBOXING RESULTS ### */ @@ -502,7 +489,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * expected to be an AnyRef. */ val t: Tree = ad.symbol.tpe match { case MethodType(mparams, resType) => - assert(params.length == mparams.length) + assert(params.length == mparams.length, mparams) + typedPos { val sym = currentOwner.newValue(ad.pos, mkTerm("qual")) setInfo qual0.tpe qual = safeREF(sym) @@ -554,31 +542,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * constructor. */ case Template(parents, self, body) => localTyper = typer.atOwner(tree, currentClass) - var savedNewStaticMembers : mutable.Buffer[Tree] = null - var savedNewStaticInits : mutable.Buffer[Tree] = null - var savedSymbolsStoredAsStatic : mutable.Map[String, Symbol] = null - if(forMSIL) { - savedNewStaticMembers = newStaticMembers.clone - savedNewStaticInits = newStaticInits.clone - savedSymbolsStoredAsStatic = symbolsStoredAsStatic.clone - } - newStaticMembers.clear - newStaticInits.clear - symbolsStoredAsStatic.clear - val transformedTemplate: Template = { - var newBody = transformTrees(body) - treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) - } - val res = addStaticInits(transformedTemplate) // postprocess to include static ctors - newStaticMembers.clear - newStaticInits.clear - symbolsStoredAsStatic.clear - if(forMSIL) { - newStaticMembers ++= savedNewStaticMembers - newStaticInits ++= savedNewStaticInits - symbolsStoredAsStatic ++= savedSymbolsStoredAsStatic - } - res + if (forMSIL) savingStatics( transformTemplate(tree) ) + else transformTemplate(tree) case Literal(c) if (c.tag == ClassTag) && !forMSIL=> val tpe = c.typeValue @@ -641,15 +606,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * And, finally, be advised - scala symbol literal and the Symbol class of the compiler * have little in common. */ - case symapp @ Apply(Select(Select(a @ Ident(nme.scala_), b @ nme.Symbol), nme.apply), - List(Literal(Constant(symname: String)))) => + case Apply(fn, (arg @ Literal(Constant(symname: String))) :: Nil) if fn.symbol == Symbol_apply => // add the symbol name to a map if it's not there already - val rhs = gen.mkCast(Apply(gen.scalaDot(nme.Symbol), List(Literal(Constant(symname)))), symbolType) - val staticFieldSym = getSymbolStaticField(symapp.pos, symname, rhs, symapp) - + val rhs = gen.mkMethodCall(Symbol_apply, arg :: Nil) + val staticFieldSym = getSymbolStaticField(tree.pos, symname, rhs, tree) // create a reference to a static field - val ntree = typedWithPos(symapp.pos)(safeREF(staticFieldSym)) - + val ntree = typedWithPos(tree.pos)(safeREF(staticFieldSym)) super.transform(ntree) // This transform replaces Array(Predef.wrapArray(Array(...)), <manifest>) @@ -669,19 +631,21 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * If it doesn't exist, i.e. the symbol is encountered the first time, * it creates a new static field definition and initialization and returns it. */ - private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): Symbol = + private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): Symbol = { symbolsStoredAsStatic.getOrElseUpdate(symname, { val theTyper = typer.atOwner(tree, currentClass) // create a symbol for the static field - val stfieldSym = currentClass.newVariable(pos, mkTerm("symbol$")) - .setFlag(PRIVATE | STATIC | SYNTHETIC | FINAL) - .setInfo(symbolType) + val stfieldSym = ( + currentClass.newVariable(pos, mkTerm("symbol$")) + setFlag PRIVATE | STATIC | SYNTHETIC | FINAL + setInfo SymbolClass.tpe + ) currentClass.info.decls enter stfieldSym // create field definition and initialization - val stfieldDef = theTyper.typed { atPos(pos)(VAL(stfieldSym) === rhs) } - val stfieldInit = theTyper.typed { atPos(pos)(safeREF(stfieldSym) === rhs) } + val stfieldDef = theTyper.typedPos(pos)(VAL(stfieldSym) === rhs) + val stfieldInit = theTyper.typedPos(pos)(safeREF(stfieldSym) === rhs) // add field definition to new defs newStaticMembers append stfieldDef @@ -689,6 +653,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { stfieldSym }) + } /* finds the static ctor DefDef tree within the template if it exists. */ private def findStaticCtor(template: Template): Option[Tree] = @@ -700,7 +665,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* changes the template for the class so that it contains a static constructor with symbol fields inits, * augments an existing static ctor if one already existed. */ - private def addStaticInits(template: Template): Template = + private def addStaticInits(template: Template): Template = { if (newStaticInits.isEmpty) template else { @@ -722,11 +687,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // create new static ctor val staticCtorSym = currentClass.newStaticConstructor(template.pos) val rhs = Block(newStaticInits.toList, Literal(Constant())) - val staticCtorTree = DefDef(staticCtorSym, rhs) - localTyper.typed { atPos(template.pos)(staticCtorTree) } + + localTyper.typedPos(template.pos)(DefDef(staticCtorSym, rhs)) } treeCopy.Template(template, template.parents, template.self, newCtor :: template.body) } + } } // CleanUpTransformer diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 342c298e1d..4d4f4f4c27 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -254,26 +254,18 @@ abstract class Constructors extends Transform with ast.TreeDSL { for ((accSym, accBody) <- outerAccessors) if (mustbeKept(accSym)) accessTraverser.traverse(accBody) - // Conflicting symbol list from parents: see bug #1960. - // It would be better to mangle the constructor parameter name since - // it can only be used internally, but I think we need more robust name - // mangling before we introduce more of it. - val parentSymbols = Map((for { - p <- impl.parents - if p.symbol.isTrait - sym <- p.symbol.info.nonPrivateMembers - if sym.isGetter && !sym.isOuterField - } yield sym.name -> p): _*) - // Initialize all parameters fields that must be kept. - val paramInits = - for (acc <- paramAccessors if mustbeKept(acc)) yield { - if (parentSymbols contains acc.name) - unit.error(acc.pos, "parameter '%s' requires field but conflicts with %s in '%s'".format( - acc.name, acc.name, parentSymbols(acc.name))) - - copyParam(acc, parameter(acc)) - } + val paramInits = paramAccessors filter mustbeKept map { acc => + // Check for conflicting symbol amongst parents: see bug #1960. + // It would be better to mangle the constructor parameter name since + // it can only be used internally, but I think we need more robust name + // mangling before we introduce more of it. + val conflict = clazz.info.nonPrivateMember(acc.name) filter (s => s.isGetter && !s.isOuterField && s.enclClass.isTrait) + if (conflict ne NoSymbol) + unit.error(acc.pos, "parameter '%s' requires field but conflicts with %s".format(acc.name, conflict.fullLocationString)) + + copyParam(acc, parameter(acc)) + } /** Return a single list of statements, merging the generic class constructor with the * specialized stats. The original statements are retyped in the current class, and @@ -299,11 +291,10 @@ abstract class Constructors extends Transform with ast.TreeDSL { * be an error to pass it to array_update(.., .., Object). */ def rewriteArrayUpdate(tree: Tree): Tree = { - val array_update = definitions.ScalaRunTimeModule.info.member("array_update") val adapter = new Transformer { override def transform(t: Tree): Tree = t match { - case Apply(fun @ Select(receiver, method), List(xs, idx, v)) if fun.symbol == array_update => - localTyper.typed(Apply(gen.mkAttributedSelect(xs, definitions.Array_update), List(idx, v))) + case Apply(fun @ Select(receiver, method), List(xs, idx, v)) if fun.symbol == arrayUpdateMethod => + localTyper.typed(Apply(gen.mkAttributedSelect(xs, arrayUpdateMethod), List(idx, v))) case _ => super.transform(t) } } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 1a421eb82f..f3b1e77c8d 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -866,7 +866,7 @@ abstract class Erasure extends AddInterfaces unboundedGenericArrayLevel(arg.tpe) > 0) => val level = unboundedGenericArrayLevel(arg.tpe) def isArrayTest(arg: Tree) = - gen.mkRuntimeCall("isArray", List(arg, Literal(Constant(level)))) + gen.mkRuntimeCall(nme.isArray, List(arg, Literal(Constant(level)))) global.typer.typedPos(tree.pos) { if (level == 1) isArrayTest(qual) @@ -887,19 +887,30 @@ abstract class Erasure extends AddInterfaces fun.symbol != Object_isInstanceOf) => // leave all other type tests/type casts, remove all other type applications preErase(fun) - case Apply(fn @ Select(qual, name), args) if (fn.symbol.owner == ArrayClass) => - if (unboundedGenericArrayLevel(qual.tpe.widen) == 1) + case Apply(fn @ Select(qual, name), args) if fn.symbol.owner == ArrayClass => + // Have to also catch calls to abstract types which are bounded by Array. + if (unboundedGenericArrayLevel(qual.tpe.widen) == 1 || qual.tpe.typeSymbol.isAbstractType) { // convert calls to apply/update/length on generic arrays to // calls of ScalaRunTime.array_xxx method calls - global.typer.typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) } - else + global.typer.typedPos(tree.pos)({ + val arrayMethodName = name match { + case nme.apply => nme.array_apply + case nme.length => nme.array_length + case nme.update => nme.array_update + case nme.clone_ => nme.array_clone + case _ => unit.error(tree.pos, "Unexpected array member, no translation exists.") ; nme.NO_NAME + } + gen.mkRuntimeCall(arrayMethodName, qual :: args) + }) + } + else { // store exact array erasure in map to be retrieved later when we might // need to do the cast in adaptMember treeCopy.Apply( tree, SelectFromArray(qual, name, erasure(tree.symbol, qual.tpe)).copyAttrs(fn), args) - + } case Apply(fn @ Select(qual, _), Nil) if interceptedMethods(fn.symbol) => if (fn.symbol == Any_## || fn.symbol == Object_##) { // This is unattractive, but without it we crash here on ().## because after diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index fcc03a82d0..cf7d6c94fe 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -68,6 +68,8 @@ abstract class ExplicitOuter extends InfoTransform result } + + private val innerClassConstructorParamName: TermName = newTermName("arg" + nme.OUTER) class RemoveBindingsTransformer(toRemove: Set[Symbol]) extends Transformer { override def transform(tree: Tree) = tree match { @@ -134,7 +136,7 @@ abstract class ExplicitOuter extends InfoTransform } if (sym.owner.isTrait) sym setNotFlag PROTECTED // 6 if (sym.isClassConstructor && isInner(sym.owner)) { // 1 - val p = sym.newValueParameter(sym.pos, "arg" + nme.OUTER) + val p = sym.newValueParameter(sym.pos, innerClassConstructorParamName) .setInfo(sym.owner.outerClass.thisType) MethodType(p :: params, restpe) } else if (restpe ne restpe1) diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index 171d1df975..bc7d1754d4 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -165,9 +165,6 @@ abstract class LiftCode extends Transform with TypingTransformers { */ class Reifier() { - final val mirrorFullName = "scala.reflect.mirror" - final val mirrorShortName = "$mr" - final val mirrorPrefix = mirrorShortName + "." final val scalaPrefix = "scala." final val localPrefix = "$local" final val memoizerName = "$memo" @@ -217,16 +214,20 @@ abstract class LiftCode extends Transform with TypingTransformers { // helper methods - private def localName(sym: Symbol) = localPrefix + symIndex(sym) + private def localName(sym: Symbol): TermName = + newTermName(localPrefix + symIndex(sym)) private def call(fname: String, args: Tree*): Tree = Apply(termPath(fname), args.toList) private def mirrorSelect(name: String): Tree = - termPath(mirrorPrefix + name) + termPath(nme.MIRROR_PREFIX + name) + + private def mirrorCall(name: TermName, args: Tree*): Tree = + call("" + (nme.MIRROR_PREFIX append name), args: _*) private def mirrorCall(name: String, args: Tree*): Tree = - call(mirrorPrefix + name, args: _*) + call(nme.MIRROR_PREFIX + name, args: _*) private def mirrorFactoryCall(value: Product, args: Tree*): Tree = mirrorCall(value.productPrefix, args: _*) @@ -322,15 +323,15 @@ abstract class LiftCode extends Transform with TypingTransformers { * Generate code to add type and annotation info to a reified symbol */ private def fillInSymbol(sym: Symbol): Tree = { - val rset = Apply(Select(reifySymRef(sym), "setTypeSig"), List(reifyType(sym.info))) + val rset = Apply(Select(reifySymRef(sym), nme.setTypeSig), List(reifyType(sym.info))) if (sym.annotations.isEmpty) rset - else Apply(Select(rset, "setAnnotations"), List(reify(sym.annotations))) + else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations))) } /** Reify a scope */ private def reifyScope(scope: Scope): Tree = { scope foreach registerReifiableSymbol - mirrorCall("newScopeWith", scope.toList map reifySymRef: _*) + mirrorCall(nme.newScopeWith, scope.toList map reifySymRef: _*) } /** Reify a list of symbols that need to be created */ @@ -348,14 +349,14 @@ abstract class LiftCode extends Transform with TypingTransformers { val tpe = tpe0.normalize val tsym = tpe.typeSymbol if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) - Select(reifySymRef(tpe.typeSymbol), "asTypeConstructor") + Select(reifySymRef(tpe.typeSymbol), nme.asTypeConstructor) else tpe match { case t @ NoType => reifyMirrorObject(t) case t @ NoPrefix => reifyMirrorObject(t) case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => - mirrorCall("thisModuleType", reify(clazz.fullName)) + mirrorCall(nme.thisModuleType, reify(clazz.fullName)) case t @ RefinedType(parents, decls) => registerReifiableSymbol(tpe.typeSymbol) mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) @@ -387,13 +388,13 @@ abstract class LiftCode extends Transform with TypingTransformers { case tt: TypeTree if (tt.tpe != null) => if (!(boundSyms exists (tt.tpe contains _))) mirrorCall("TypeTree", reifyType(tt.tpe)) else if (tt.original != null) reify(tt.original) - else mirrorCall("TypeTree") + else mirrorCall(nme.TypeTree) case ta @ TypeApply(hk, ts) => val thereAreOnlyTTs = ts collect { case t if !t.isInstanceOf[TypeTree] => t } isEmpty; val ttsAreNotEssential = ts collect { case tt: TypeTree => tt } find { tt => tt.original != null } isEmpty; if (thereAreOnlyTTs && ttsAreNotEssential) reifyTree(hk) else reifyProduct(ta) case global.emptyValDef => - mirrorSelect("emptyValDef") + mirrorSelect(nme.emptyValDef) case _ => if (tree.isDef) boundSyms += tree.symbol @@ -403,8 +404,8 @@ abstract class LiftCode extends Transform with TypingTransformers { if (tree.isDef || tree.isInstanceOf[Function]) registerReifiableSymbol(tree.symbol) if (tree.hasSymbol) - rtree = Apply(Select(rtree, "setSymbol"), List(reifySymRef(tree.symbol))) - Apply(Select(rtree, "setType"), List(reifyType(tree.tpe))) + rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol))) + Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe))) */ } @@ -413,7 +414,7 @@ abstract class LiftCode extends Transform with TypingTransformers { * to a global value, or else a mirror Literal. */ private def reifyFree(tree: Tree): Tree = - mirrorCall("Ident", reifySymRef(tree.symbol)) + mirrorCall(nme.Ident, reifySymRef(tree.symbol)) // todo: consider whether we should also reify positions private def reifyPosition(pos: Position): Tree = @@ -443,7 +444,7 @@ abstract class LiftCode extends Transform with TypingTransformers { case sym: Symbol => reifySymRef(sym) case tpe: Type => reifyType(tpe) case xs: List[_] => reifyList(xs) - case xs: Array[_] => scalaFactoryCall("Array", xs map reify: _*) + case xs: Array[_] => scalaFactoryCall(nme.Array, xs map reify: _*) case scope: Scope => reifyScope(scope) case x: Name => reifyName(x) case x: Position => reifyPosition(x) @@ -475,7 +476,7 @@ abstract class LiftCode extends Transform with TypingTransformers { private def typePath(fullname: String): Tree = path(fullname, newTypeName) private def mirrorAlias = - ValDef(NoMods, mirrorShortName, TypeTree(), termPath(mirrorFullName)) + ValDef(NoMods, nme.MIRROR_SHORT, TypeTree(), termPath(fullnme.MirrorPackage)) /** * Generate code that generates a symbol table of all symbols registered in `reifiableSyms` diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index bbe803a3fb..99b0a82690 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -572,8 +572,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // resolved by the type checker. Later on, erasure re-typechecks everything and // chokes if it finds default parameters for specialized members, even though // they are never needed. - sym.info.paramss.flatten foreach (_.resetFlag(DEFAULTPARAM)) - + mapParamss(sym)(_ resetFlag DEFAULTPARAM) decls1.enter(subst(fullEnv)(sym)) } @@ -1235,7 +1234,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs)) body(tree.symbol) = rhs // body(tree.symbol) = tree // whole method - parameters(tree.symbol) = vparamss map (_ map (_.symbol)) + parameters(tree.symbol) = mmap(vparamss)(_.symbol) concreteSpecMethods -= tree.symbol } // no need to descend further down inside method bodies @@ -1609,7 +1608,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (m.isClassConstructor) { val origParamss = parameters(info(m).target) val vparams = ( - for ((tp, sym) <- m.info.paramTypes zip origParamss(0)) yield ( + map2(m.info.paramTypes, origParamss(0))((tp, sym) => m.newValue(sym.pos, specializedName(sym, typeEnv(cls))) .setInfo(tp) .setFlag(sym.flags) @@ -1625,7 +1624,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } // ctor - mbrs += atPos(m.pos)(DefDef(m, Modifiers(m.flags), List(vparams) map (_ map ValDef), EmptyTree)) + mbrs += atPos(m.pos)(DefDef(m, Modifiers(m.flags), mmap(List(vparams))(ValDef), EmptyTree)) } else { mbrs += atPos(m.pos)(DefDef(m, { paramss => EmptyTree })) } @@ -1671,7 +1670,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } private def forwardCall(pos: util.Position, receiver: Tree, paramss: List[List[ValDef]]): Tree = { - val argss = paramss map (_ map (x => Ident(x.symbol))) + val argss = mmap(paramss)(x => Ident(x.symbol)) atPos(pos) { (receiver /: argss) (Apply) } } @@ -1708,11 +1707,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { && clazz.info.decl(f.name).suchThat(_.isGetter) != NoSymbol ) - val argss = paramss map (_ map (x => + val argss = mmap(paramss)(x => if (initializesSpecializedField(x.symbol)) gen.mkAsInstanceOf(Literal(Constant(null)), x.symbol.tpe) else - Ident(x.symbol)) + Ident(x.symbol) ) atPos(pos) { (receiver /: argss) (Apply) } } diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index ca16e491e2..e2cd0a8402 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -128,7 +128,7 @@ abstract class TailCalls extends Transform { * the label field. */ this.label = { - val label = method.newLabel(method.pos, "_" + method.name) + val label = method.newLabel(method.pos, newTermName("_" + method.name)) val thisParam = method.newSyntheticValueParam(currentClass.typeOfThis) label setInfo MethodType(thisParam :: method.tpe.params, method.tpe.finalResultType) } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 13516037f5..adb408f7e4 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -357,7 +357,7 @@ abstract class UnCurry extends InfoTransform case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), args_scrut), args_pm) if opt.virtPatmat => object noOne extends Transformer { override val treeCopy = newStrictTreeCopier // must duplicate everything - val one = tgt.tpe member "one".toTermName + val one = tgt.tpe member newTermName("one") override def transform(tree: Tree): Tree = tree match { case Apply(fun, List(a)) if fun.symbol == one => // blow one's argument away since all we want to know is whether the match succeeds or not @@ -367,7 +367,7 @@ abstract class UnCurry extends InfoTransform super.transform(tree) } } - substTree(Apply(Apply(TypeApply(Select(tgt.duplicate, tgt.tpe.member("isSuccess".toTermName)), targs map (_.duplicate)), args_scrut map (_.duplicate)), args_pm map (noOne.transform))) + substTree(Apply(Apply(TypeApply(Select(tgt.duplicate, tgt.tpe.member(newTermName("isSuccess"))), targs map (_.duplicate)), args_scrut map (_.duplicate)), args_pm map (noOne.transform))) // for the optimized version of virtpatmat case Block((zero: ValDef) :: (x: ValDef) :: (matchRes: ValDef) :: (keepGoing: ValDef) :: stats, _) if opt.virtPatmat => dupVirtMatch(zero, x, matchRes, keepGoing, stats) @@ -452,7 +452,7 @@ abstract class UnCurry extends InfoTransform atPhase(phase.next) { if (isJava && isPrimitiveArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) { suffix = localTyper.typedPos(pos) { - gen.mkRuntimeCall("toObjectArray", List(suffix)) + gen.mkRuntimeCall(nme.toObjectArray, List(suffix)) } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index d54cb248cf..3b90eaeed7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -214,10 +214,10 @@ trait Implicits { /** An extractor for types of the form ? { name: (? >: argtpe <: Any*)restp } */ object HasMethodMatching { + val dummyMethod = new TermSymbol(NoSymbol, NoPosition, newTermName("typer$dummy")) + def templateArgType(argtpe: Type) = new BoundedWildcardType(TypeBounds.lower(argtpe)) + def apply(name: Name, argtpes: List[Type], restpe: Type): Type = { - def templateArgType(argtpe: Type) = - new BoundedWildcardType(TypeBounds(argtpe, AnyClass.tpe)) - val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "typer$dummy") val mtpe = MethodType(dummyMethod.newSyntheticValueParams(argtpes map templateArgType), restpe) memberWildcardType(name, mtpe) } @@ -816,7 +816,14 @@ trait Implicits { val newPending = undoLog undo { is filterNot (alt => alt == i || { try improves(i, alt) - catch { case e: CyclicReference => true } + catch { + case e: CyclicReference => + if (printInfers) { + println(i+" discarded because cyclic reference occurred") + e.printStackTrace() + } + true + } }) } rankImplicits(newPending, i :: acc) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 2bd307e31a..295b66b17f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1447,8 +1447,17 @@ trait Infer { /** A traverser to collect type parameters referred to in a type */ object freeTypeParamsOfTerms extends SymCollector { - protected def includeCondition(sym: Symbol): Boolean = - sym.isAbstractType && sym.owner.isTerm + // An inferred type which corresponds to an unknown type + // constructor creates a file/declaration order-dependent crasher + // situation, the behavior of which depends on the state at the + // time the typevar is created. Until we can deal with these + // properly, we can avoid it by ignoring type parameters which + // have type constructors amongst their bounds. See SI-4070. + protected def includeCondition(sym: Symbol) = ( + sym.isAbstractType + && sym.owner.isTerm + && !sym.info.bounds.exists(_.typeParams.nonEmpty) + ) } /** A traverser to collect type parameters referred to in a type diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 99ba0e0971..b9264aae55 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -7,13 +7,10 @@ trait Macros { self: Analyzer => import global._ import definitions._ - def macroMethName(name: Name) = - newTermName((if (name.isTypeName) "type" else "def") + "macro$" + name) - def macroMeth(mac: Symbol): Symbol = { var owner = mac.owner if (!owner.isModuleClass) owner = owner.companionModule.moduleClass - owner.info.decl(macroMethName(mac.name)) + owner.info.decl(nme.macroMethodName(mac.name)) } /** @@ -37,21 +34,21 @@ trait Macros { self: Analyzer => def macroMethDef(mdef: DefDef): Tree = { def paramDef(name: Name, tpt: Tree) = ValDef(Modifiers(PARAM), name, tpt, EmptyTree) val universeType = TypeTree(ReflectApiUniverse.tpe) - val globParamSec = List(paramDef("glob", universeType)) - def globSelect(name: Name) = Select(Ident("glob"), name) + val globParamSec = List(paramDef(nme.glob, universeType)) + def globSelect(name: Name) = Select(Ident(nme.glob), name) def globTree = globSelect(newTypeName("Tree")) def globType = globSelect(newTypeName("Type")) - val thisParamSec = if (mdef.symbol.owner.isModuleClass) List() else List(paramDef("_this", globTree)) + val thisParamSec = if (mdef.symbol.owner.isModuleClass) List() else List(paramDef(newTermName("_this"), globTree)) def tparamInMacro(tdef: TypeDef) = paramDef(tdef.name.toTermName, globType) def vparamInMacro(vdef: ValDef): ValDef = paramDef(vdef.name, globTree) def wrapImplicit(tree: Tree) = atPos(tree.pos) { - Block(List(ValDef(Modifiers(IMPLICIT), "$glob", universeType, Ident("glob"))), tree) + Block(List(ValDef(Modifiers(IMPLICIT), newTermName("$" + nme.glob), universeType, Ident(nme.glob))), tree) } atPos(mdef.pos) { new DefDef( // can't call DefDef here; need to find out why mods = mdef.mods &~ MACRO, - name = macroMethName(mdef.name), + name = nme.macroMethodName(mdef.name), tparams = List(), vparamss = globParamSec :: thisParamSec :: (mdef.tparams map tparamInMacro) :: (mdef.vparamss map (_ map vparamInMacro)), diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 7915a64e21..62393befd2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -9,22 +9,6 @@ import symtab.Flags._ import scala.collection.{ mutable, immutable } import scala.tools.util.StringOps.{ ojoin } -object listutil { - def mexists[T](xss: List[List[T]])(p: T => Boolean) = - xss exists (_ exists p) - def mmap[T, U](xss: List[List[T]])(f: T => U) = - xss map (_ map f) - def mforeach[T](xss: List[List[T]])(f: T => Unit) = - xss foreach (_ foreach f) - def mfind[T](xss: List[List[T]])(p: T => Boolean): Option[T] = { - for (xs <- xss; x <- xs) - if (p(x)) return Some(x) - None - } - def mfilter[T](xss: List[List[T]])(p: T => Boolean) = - for (xs <- xss; x <- xs; if p(x)) yield x -} - /** Logic related to method synthesis which involves cooperation between * Namer and Typer. */ @@ -264,7 +248,7 @@ trait MethodSynthesis { } sealed abstract class BeanAccessor(bean: String) extends DerivedFromValDef { - def name = bean + tree.name.toString.capitalize + val name = newTermName(bean + tree.name.toString.capitalize) def flagsMask = BeanPropertyFlags def flagsExtra = 0 override def derivedSym = enclClass.info decl name diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 364e887939..200191fa13 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -99,7 +99,7 @@ trait Namers extends MethodSynthesis { } def enterValueParams(vparamss: List[List[ValDef]]): List[List[Symbol]] = { - listutil.mmap(vparamss) { param => + mmap(vparamss) { param => val sym = assignSymbol(param, param.name, mask = ValueParameterFlags) setPrivateWithin(param, sym) enterInScope(sym) @@ -522,13 +522,13 @@ trait Namers extends MethodSynthesis { val vparamss = tree match { case x: DefDef => x.vparamss ; case _ => Nil } val cparamss = constructorType.paramss - for ((vparams, cparams) <- vparamss zip cparamss) { - for ((param, cparam) <- vparams zip cparams) { + map2(vparamss, cparamss)((vparams, cparams) => + map2(vparams, cparams)((param, cparam) => // need to clone the type cparam.tpe??? // problem is: we don't have the new owner yet (the new param symbol) param.tpt setType subst(cparam.tpe) - } - } + ) + ) } sym setInfo { mkTypeCompleter(tree) { copySym => @@ -579,7 +579,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.pos, tree.name + "$lzy") setFlag tree.mods.flags resetFlag IMPLICIT + else owner.newValue(tree.pos, tree.name append nme.LAZY_LOCAL) setFlag tree.mods.flags resetFlag IMPLICIT ) enterValSymbol(tree, sym setFlag MUTABLE setLazyAccessor lazyAccessor) } @@ -627,7 +627,7 @@ trait Namers extends MethodSynthesis { classOfModuleClass(m.moduleClass) = new WeakReference(tree) } val hasDefault = impl.body exists { - case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => listutil.mexists(vparamss)(_.mods.hasDefault) + case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => mexists(vparamss)(_.mods.hasDefault) case _ => false } if (hasDefault) { @@ -953,9 +953,9 @@ trait Namers extends MethodSynthesis { // def overriddenSymbol = meth.nextOverriddenSymbol // fill in result type and parameter types from overridden symbol if there is a unique one. - if (clazz.isClass && (tpt.isEmpty || listutil.mexists(vparamss)(_.tpt.isEmpty))) { + if (clazz.isClass && (tpt.isEmpty || mexists(vparamss)(_.tpt.isEmpty))) { // try to complete from matching definition in base type - listutil.mforeach(vparamss)(v => if (v.tpt.isEmpty) v.symbol setInfo WildcardType) + mforeach(vparamss)(v => if (v.tpt.isEmpty) v.symbol setInfo WildcardType) val overridden = overriddenSymbol if (overridden != NoSymbol && !overridden.isOverloaded) { overridden.cookJavaRawInfo() // #3404 xform java rawtypes into existentials @@ -993,7 +993,7 @@ trait Namers extends MethodSynthesis { _.info.isInstanceOf[MethodType])) { vparamSymss = List(List()) } - listutil.mforeach(vparamss) { vparam => + mforeach(vparamss) { vparam => if (vparam.tpt.isEmpty) { context.error(vparam.pos, "missing parameter type") vparam.tpt defineType ErrorType @@ -1073,7 +1073,7 @@ trait Namers extends MethodSynthesis { // Create trees for the defaultGetter. Uses tools from Unapplies.scala var deftParams = tparams map copyUntyped[TypeDef] - val defvParamss = listutil.mmap(previous) { p => + val defvParamss = mmap(previous) { p => // in the default getter, remove the default parameter val p1 = atPos(p.pos.focus) { ValDef(p.mods &~ DEFAULTPARAM, p.name, p.tpt.duplicate, EmptyTree) } UnTyper.traverse(p1) diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala index 75a5ad6f8a..440db4300c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala @@ -46,8 +46,6 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => import global._ import definitions._ - private lazy val matchingStrategyTycon = definitions.getClass("scala.MatchingStrategy").typeConstructor - class MatchTranslator(typer: Typer) extends MatchCodeGen { def typed(tree: Tree, mode: Int, pt: Type): Tree = typer.typed(tree, mode, pt) // for MatchCodeGen -- imports don't provide implementations for abstract members @@ -55,7 +53,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => import typeDebug.{ ptTree, ptBlock, ptLine } def solveContextBound(contextBoundTp: Type): (Tree, Type) = { - val solSym = NoSymbol.newTypeParameter(NoPosition, "SolveImplicit$".toTypeName) + val solSym = NoSymbol.newTypeParameter(NoPosition, newTypeName("SolveImplicit$")) val param = solSym.setInfo(contextBoundTp.typeSymbol.typeParams(0).info.cloneInfo(solSym)) // TypeBounds(NothingClass.typeConstructor, baseTp) val pt = appliedType(contextBoundTp, List(param.tpeHK)) val savedUndets = context.undetparams @@ -67,7 +65,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer => (result.tree, result.subst.to(result.subst.from indexOf param)) } - lazy val (matchingStrategy, matchingMonadType) = solveContextBound(matchingStrategyTycon) + lazy val (matchingStrategy, matchingMonadType) = solveContextBound(MatchingStrategyClass.typeConstructor) /** Implement a pattern match by turning its cases (including the implicit failure case) * into the corresponding (monadic) extractors, and combining them with the `orElse` combinator. @@ -1482,19 +1480,18 @@ defined class Foo */ } object vpmName { - val one = "one".toTermName - val drop = "drop".toTermName - val flatMap = "flatMap".toTermName - val get = "get".toTermName - val guard = "guard".toTermName - val isEmpty = "isEmpty".toTermName - val orElse = "orElse".toTermName - val outer = "<outer>".toTermName - val runOrElse = "runOrElse".toTermName - val zero = "zero".toTermName - - def counted(str: String, i: Int) = (str+i).toTermName - def tupleIndex(i: Int) = ("_"+i).toTermName + val one = newTermName("one") + val drop = newTermName("drop") + val flatMap = newTermName("flatMap") + val get = newTermName("get") + val guard = newTermName("guard") + val isEmpty = newTermName("isEmpty") + val orElse = newTermName("orElse") + val outer = newTermName("<outer>") + val runOrElse = newTermName("runOrElse") + val zero = newTermName("zero") + + def counted(str: String, i: Int) = newTermName(str+i) } @@ -1503,7 +1500,7 @@ defined class Foo */ trait CommonCodeGen extends AbsCodeGen { self: CommonCodeGen with MatchingStrategyGen with MonadInstGen => def fun(arg: Symbol, body: Tree): Tree = Function(List(ValDef(arg)), body) def genTypeApply(tfun: Tree, args: Type*): Tree = if(args contains NoType) tfun else TypeApply(tfun, args.toList map TypeTree) - def tupleSel(binder: Symbol)(i: Int): Tree = (REF(binder) DOT vpmName.tupleIndex(i)) // make tree that accesses the i'th component of the tuple referenced by binder + def tupleSel(binder: Symbol)(i: Int): Tree = (REF(binder) DOT nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder def index(tgt: Tree)(i: Int): Tree = tgt APPLY (LIT(i)) def drop(tgt: Tree)(n: Int): Tree = (tgt DOT vpmName.drop) (LIT(n)) def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index ace38bb4cb..8f9cd46611 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -154,7 +154,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def isJavaVarargsAncestor(clazz: Symbol) = ( clazz.isClass && clazz.isJavaDefined - && (clazz.info.nonPrivateMembers exists isJavaVarArgsMethod) + && (clazz.info.nonPrivateDecls exists isJavaVarArgsMethod) ) /** Add bridges for vararg methods that extend Java vararg methods @@ -1347,7 +1347,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R } // types of the value parameters - member.paramss.flatten foreach (p => checkAccessibilityOfType(p.tpe)) + mapParamss(member)(p => checkAccessibilityOfType(p.tpe)) // upper bounds of type parameters member.typeParams.map(_.info.bounds.hi.widen) foreach checkAccessibilityOfType } diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index a0ef2f5e2e..cde531adc1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -321,12 +321,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val code = DefDef(protAcc, { val (receiver :: _) :: tail = protAcc.paramss val base: Tree = Select(Ident(receiver), sym) - val allParamTypes = sym.tpe.paramss map (xs => xs map (_.tpe)) - - (tail zip allParamTypes).foldLeft(base) { - case (fn, (params, tpes)) => - Apply(fn, params zip tpes map { case (p, tp) => makeArg(p, receiver, tp) }) - } + val allParamTypes = mapParamss(sym)(_.tpe) + val args = map2(tail, allParamTypes)((params, tpes) => map2(params, tpes)(makeArg(_, receiver, _))) + args.foldLeft(base)(Apply(_, _)) }) debuglog("" + code) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 3d4f5e8724..92e4e257bf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -39,10 +39,6 @@ trait SyntheticMethods extends ast.TreeDSL { private object util { private type CM[T] = ClassManifest[T] - lazy val IteratorModule = getModule("scala.collection.Iterator") - lazy val Iterator_apply = getMember(IteratorModule, nme.apply) - def iteratorOfType(tp: Type) = appliedType(IteratorClass.typeConstructor, List(tp)) - def ValOrDefDef(sym: Symbol, body: Tree) = if (sym.isLazy) ValDef(sym, body) else DefDef(sym, body) @@ -76,11 +72,11 @@ trait SyntheticMethods extends ast.TreeDSL { } def manifestToSymbol(m: CM[_]): Symbol = m match { - case x: scala.reflect.AnyValManifest[_] => definitions.getClass("scala." + x) + case x: scala.reflect.AnyValManifest[_] => getMember(ScalaPackageClass, newTermName("" + x)) case _ => getClassIfDefined(m.erasure.getName) } def companionType[T](implicit m: CM[T]) = - getModule(m.erasure.getName).tpe + getRequiredModule(m.erasure.getName).tpe // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]` def applyType[M](implicit m1: CM[M]): Type = @@ -202,7 +198,7 @@ trait SyntheticMethods extends ast.TreeDSL { // in the original order. def accessors = clazz.caseFieldAccessors sortBy { acc => originalAccessors indexWhere { orig => - (acc.name == orig.name) || (acc.name startsWith (orig.name + "$").toTermName) + (acc.name == orig.name) || (acc.name startsWith (orig.name append "$")) } } val arity = accessors.size @@ -225,7 +221,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def forwardToRuntime(method: Symbol): Tree = - forwardMethod(method, getMember(ScalaRunTimeModule, "_" + method.name toTermName))(This(clazz) :: _) + forwardMethod(method, getMember(ScalaRunTimeModule, method.name prepend "_"))(This(clazz) :: _) // Any member, including private def hasConcreteImpl(name: Name) = @@ -238,14 +234,14 @@ trait SyntheticMethods extends ast.TreeDSL { } } def readConstantValue[T](name: String, default: T = null.asInstanceOf[T]): T = { - clazzMember(name.toTermName).info match { + clazzMember(newTermName(name)).info match { case NullaryMethodType(ConstantType(Constant(value))) => value.asInstanceOf[T] case _ => default } } def productIteratorMethod = { createMethod(nme.productIterator, iteratorOfType(accessorLub))(_ => - gen.mkMethodCall(ScalaRunTimeModule, "typedProductIterator", List(accessorLub), List(This(clazz))) + gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(This(clazz))) ) } def projectionMethod(accessor: Symbol, num: Int) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9991836344..5ccf27ded9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -969,7 +969,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { return typed(Select(tree, meth), mode, pt) } if (coercion != EmptyTree) { - debuglog("inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe) + def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe + if (settings.logImplicitConv.value) + unit.echo(tree.pos, msg) + + debuglog(msg) return newTyper(context.makeImplicit(context.reportAmbiguousErrors)).typed( new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt) } @@ -1056,7 +1060,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } inferView(qual, qual.tpe, searchTemplate, true) match { case EmptyTree => qual - case coercion => typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) + case coercion => + if (settings.logImplicitConv.value) + unit.echo(qual.pos, + "applied implicit conversion from %s to %s = %s".format( + qual.tpe, searchTemplate, coercion.symbol.defString)) + + typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) } } else qual @@ -3468,7 +3478,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case ex: TypeError => fun match { case Select(qual, name) - if !isPatternMode && nme.isOpAssignmentName(name.decode) => + if !isPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) => val qual1 = typedQualifier(qual) if (treeInfo.isVariableOrGetter(qual1)) { stopTimer(failedOpEqNanos, opeqStart) diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 4f7e6225e1..fd6f972ffc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -21,6 +21,8 @@ trait Unapplies extends ast.TreeDSL import CODE.{ CASE => _, _ } import treeInfo.{ isRepeatedParamType, isByNameParamType } + private val unapplyParamName = newTermName("x$0") + /** returns type list for return type of the extraction */ def unapplyTypeList(ufn: Symbol, ufntpe: Type) = { assert(ufn.isMethod) @@ -112,7 +114,7 @@ trait Unapplies extends ast.TreeDSL private def constrParamss(cdef: ClassDef): List[List[ValDef]] = { val DefDef(_, _, _, vparamss, _, _) = treeInfo firstConstructor cdef.impl.body - vparamss map (_ map copyUntyped[ValDef]) + mmap(vparamss)(copyUntyped[ValDef]) } /** The return value of an unapply method of a case class C[Ts] @@ -165,7 +167,7 @@ trait Unapplies extends ast.TreeDSL val cparamss = constrParamss(cdef) atPos(cdef.pos.focus)( DefDef(caseMods, nme.apply, tparams, cparamss, classType(cdef, tparams), - New(classType(cdef, tparams), cparamss map (_ map gen.paramToArg))) + New(classType(cdef, tparams), mmap(cparamss)(gen.paramToArg))) ) } @@ -173,14 +175,13 @@ trait Unapplies extends ast.TreeDSL */ def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = { val tparams = cdef.tparams map copyUntypedInvariant - val paramName = newTermName("x$0") val method = constrParamss(cdef) match { case xs :: _ if xs.nonEmpty && isRepeatedParamType(xs.last.tpt) => nme.unapplySeq case _ => nme.unapply } - val cparams = List(ValDef(Modifiers(PARAM | SYNTHETIC), paramName, classType(cdef, tparams), EmptyTree)) + val cparams = List(ValDef(Modifiers(PARAM | SYNTHETIC), unapplyParamName, classType(cdef, tparams), EmptyTree)) val ifNull = if (constrParamss(cdef).head.isEmpty) FALSE else REF(NoneModule) - val body = nullSafe({ case Ident(x) => caseClassUnapplyReturnValue(x, cdef.symbol) }, ifNull)(Ident(paramName)) + val body = nullSafe({ case Ident(x) => caseClassUnapplyReturnValue(x, cdef.symbol) }, ifNull)(Ident(unapplyParamName)) atPos(cdef.pos.focus)( DefDef(caseMods, method, tparams, List(cparams), TypeTree(), body) @@ -201,12 +202,12 @@ trait Unapplies extends ast.TreeDSL def paramWithDefault(vd: ValDef) = treeCopy.ValDef(vd, vd.mods | DEFAULTPARAM, vd.name, atPos(vd.pos.focus)(TypeTree() setOriginal vd.tpt), toIdent(vd)) - val paramss = cparamss map (_ map paramWithDefault) + val paramss = mmap(cparamss)(paramWithDefault) val classTpe = classType(cdef, tparams) Some(atPos(cdef.pos.focus)( DefDef(Modifiers(SYNTHETIC), nme.copy, tparams, paramss, classTpe, - New(classTpe, paramss map (_ map toIdent))) + New(classTpe, mmap(paramss)(toIdent))) )) } } diff --git a/src/compiler/scala/tools/nsc/util/ProxyReport.scala b/src/compiler/scala/tools/nsc/util/ProxyReport.scala index 86cf2006bb..2f4f029308 100644 --- a/src/compiler/scala/tools/nsc/util/ProxyReport.scala +++ b/src/compiler/scala/tools/nsc/util/ProxyReport.scala @@ -13,7 +13,7 @@ import scala.collection.{ mutable, immutable, generic } trait ProxyReport { val global: Global import global._ - import definitions.{ getClass => gc, _ } + import definitions._ private object classes { def isIgnorable(sym: Symbol) = sym :: sym.allOverriddenSymbols exists { s => @@ -26,13 +26,13 @@ trait ProxyReport { methods foreach (m => m.initialize.info.paramss.flatten foreach (_.initialize)) methods } - lazy val GlobalClass = gc(classOf[Global].getName) - lazy val GenericClass = getModule("scala.collection.generic").moduleClass - lazy val CollectionClass = getModule("scala.collection").moduleClass + lazy val GlobalClass = getRequiredClass(classOf[Global].getName) + lazy val GenericClass = getRequiredModule("scala.collection.generic").moduleClass + lazy val CollectionClass = getRequiredModule("scala.collection").moduleClass - def getType(name: String) = getMember(GlobalClass, name.toTypeName) - def getColl(name: String) = getMember(CollectionClass, name.toTypeName) - def getGeneric(name: String) = getMember(GenericClass, name.toTypeName) + def getType(name: String) = getMember(GlobalClass, newTypeName(name)) + def getColl(name: String) = getMember(CollectionClass, newTypeName(name)) + def getGeneric(name: String) = getMember(GenericClass, newTypeName(name)) // the following operations + those in RewrappingTypeProxy are all operations // in class Type that are overridden in some subclass diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index f4481b800e..8bbda5dd05 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -12,22 +12,37 @@ trait CPSUtils { var cpsEnabled = true val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true" def vprintln(x: =>Any): Unit = if (verbose) println(x) + + object cpsNames { + val catches = newTermName("$catches") + val ex = newTermName("$ex") + val flatMapCatch = newTermName("flatMapCatch") + val getTrivialValue = newTermName("getTrivialValue") + val isTrivial = newTermName("isTrivial") + val reify = newTermName("reify") + val reifyR = newTermName("reifyR") + val shift = newTermName("shift") + val shiftR = newTermName("shiftR") + val shiftSuffix = newTermName("$shift") + val shiftUnit = newTermName("shiftUnit") + val shiftUnitR = newTermName("shiftUnitR") + } - lazy val MarkerCPSSym = definitions.getClass("scala.util.continuations.cpsSym") - lazy val MarkerCPSTypes = definitions.getClass("scala.util.continuations.cpsParam") - lazy val MarkerCPSSynth = definitions.getClass("scala.util.continuations.cpsSynth") - lazy val MarkerCPSAdaptPlus = definitions.getClass("scala.util.continuations.cpsPlus") - lazy val MarkerCPSAdaptMinus = definitions.getClass("scala.util.continuations.cpsMinus") - - lazy val Context = definitions.getClass("scala.util.continuations.ControlContext") - lazy val ModCPS = definitions.getModule("scala.util.continuations") - - lazy val MethShiftUnit = definitions.getMember(ModCPS, "shiftUnit") - lazy val MethShiftUnitR = definitions.getMember(ModCPS, "shiftUnitR") - lazy val MethShift = definitions.getMember(ModCPS, "shift") - lazy val MethShiftR = definitions.getMember(ModCPS, "shiftR") - lazy val MethReify = definitions.getMember(ModCPS, "reify") - lazy val MethReifyR = definitions.getMember(ModCPS, "reifyR") + lazy val MarkerCPSSym = definitions.getRequiredClass("scala.util.continuations.cpsSym") + lazy val MarkerCPSTypes = definitions.getRequiredClass("scala.util.continuations.cpsParam") + lazy val MarkerCPSSynth = definitions.getRequiredClass("scala.util.continuations.cpsSynth") + lazy val MarkerCPSAdaptPlus = definitions.getRequiredClass("scala.util.continuations.cpsPlus") + lazy val MarkerCPSAdaptMinus = definitions.getRequiredClass("scala.util.continuations.cpsMinus") + + lazy val Context = definitions.getRequiredClass("scala.util.continuations.ControlContext") + lazy val ModCPS = definitions.getRequiredModule("scala.util.continuations") + + lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit) + lazy val MethShiftUnitR = definitions.getMember(ModCPS, cpsNames.shiftUnitR) + lazy val MethShift = definitions.getMember(ModCPS, cpsNames.shift) + lazy val MethShiftR = definitions.getMember(ModCPS, cpsNames.shiftR) + lazy val MethReify = definitions.getMember(ModCPS, cpsNames.reify) + lazy val MethReifyR = definitions.getMember(ModCPS, cpsNames.reifyR) lazy val allCPSAnnotations = List(MarkerCPSSym, MarkerCPSTypes, MarkerCPSSynth, MarkerCPSAdaptPlus, MarkerCPSAdaptMinus) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index b383227243..585dc3fbe8 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -355,7 +355,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with val valueTpe = removeAllCPSAnnotations(expr.tpe) - val sym = currentOwner.newValue(tree.pos, unit.fresh.newName("tmp")) + val sym = currentOwner.newValue(tree.pos, newTermName(unit.fresh.newName("tmp"))) .setInfo(valueTpe) .setFlag(Flags.SYNTHETIC) .setAnnotations(List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil))) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index f0c389bb11..960b27c52f 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -192,21 +192,21 @@ abstract class SelectiveCPSTransform extends PluginComponent with // val expr2 = if (catches.nonEmpty) { val pos = catches.head.pos - val argSym = currentOwner.newValueParameter(pos, "$ex").setInfo(ThrowableClass.tpe) + val argSym = currentOwner.newValueParameter(pos, cpsNames.ex).setInfo(ThrowableClass.tpe) val rhs = Match(Ident(argSym), catches1) val fun = Function(List(ValDef(argSym)), rhs) - val funSym = currentOwner.newValueParameter(pos, "$catches").setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp))) + val funSym = currentOwner.newValueParameter(pos, cpsNames.catches).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp))) val funDef = localTyper.typed(atPos(pos) { ValDef(funSym, fun) }) - val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member("flatMapCatch")), List(Ident(funSym))) }) + val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym))) }) argSym.owner = fun.symbol val chown = new ChangeOwnerTraverser(currentOwner, fun.symbol) chown.traverse(rhs) - val exSym = currentOwner.newValueParameter(pos, "$ex").setInfo(ThrowableClass.tpe) + val exSym = currentOwner.newValueParameter(pos, cpsNames.ex).setInfo(ThrowableClass.tpe) val catch2 = { localTyper.typedCases(tree, List( CaseDef(Bind(exSym, Typed(Ident("_"), TypeTree(ThrowableClass.tpe))), - Apply(Select(Ident(funSym), "isDefinedAt"), List(Ident(exSym))), + Apply(Select(Ident(funSym), nme.isDefinedAt), List(Ident(exSym))), Apply(Ident(funSym), List(Ident(exSym)))) ), ThrowableClass.tpe, targettp) } @@ -317,11 +317,11 @@ abstract class SelectiveCPSTransform extends PluginComponent with log("fun.tpe:"+fun.tpe) log("return type of fun:"+body1.tpe) - var methodName = "map" + var methodName = nme.map if (body1.tpe != null) { if (body1.tpe.typeSymbol == Context) - methodName = "flatMap" + methodName = nme.flatMap } else unit.error(rhs.pos, "cannot compute type for CPS-transformed function result") @@ -347,14 +347,14 @@ abstract class SelectiveCPSTransform extends PluginComponent with // val <lhs> = ctx.getTrivialValue; ... <--- TODO: try/catch ??? don't bother for the moment... // else // ctx.flatMap { <lhs> => ... } - val ctxSym = currentOwner.newValue(vd.symbol.name + "$shift").setInfo(rhs1.tpe) + val ctxSym = currentOwner.newValue(vd.symbol.name append cpsNames.shiftSuffix).setInfo(rhs1.tpe) val ctxDef = localTyper.typed(ValDef(ctxSym, rhs1)) def ctxRef = localTyper.typed(Ident(ctxSym)) val argSym = currentOwner.newValue(vd.symbol.name).setInfo(tpe) - val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member("getTrivialValue")))) + val argDef = localTyper.typed(ValDef(argSym, Select(ctxRef, ctxRef.tpe.member(cpsNames.getTrivialValue)))) val switchExpr = localTyper.typed(atPos(vd.symbol.pos) { val body2 = mkBlock(bodyStms, bodyExpr).duplicate // dup before typing! - If(Select(ctxRef, ctxSym.tpe.member("isTrivial")), + If(Select(ctxRef, ctxSym.tpe.member(cpsNames.isTrivial)), applyTrivial(argSym, mkBlock(argDef::bodyStms, bodyExpr)), applyCombinatorFun(ctxRef, body2)) }) diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index bd498de847..6db4904b93 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -192,6 +192,13 @@ sealed abstract class Option[+A] extends Product with Serializable { @inline final def exists(p: A => Boolean): Boolean = !isEmpty && p(this.get) + /** Returns true if this option is empty '''or''' the predicate + * $p returns true when applied to this $option's value. + * + * @param p the predicate to test + */ + @inline final def forall(p: A => Boolean): Boolean = isEmpty || p(this.get) + /** Apply the given procedure $f to the option's value, * if it is nonempty. Otherwise, do nothing. * diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala index 8a17ae87b0..8851f1ab91 100644 --- a/src/library/scala/Symbol.scala +++ b/src/library/scala/Symbol.scala @@ -31,8 +31,8 @@ final class Symbol private (val name: String) extends Serializable { override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] } -object Symbol extends UniquenessCache[String, Symbol] -{ +object Symbol extends UniquenessCache[String, Symbol] { + override def apply(name: String): Symbol = super.apply(name) protected def valueFromKey(name: String): Symbol = new Symbol(name) protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name) } diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala index 37065e32fc..31750b0b0d 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -190,7 +190,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr } else { // construct a normal table and fill it sequentially // TODO parallelize by keeping separate sizemaps and merging them - val table = new HashTable[K, DefaultEntry[K, V]] { + object table extends HashTable[K, DefaultEntry[K, V]] { def insertEntry(e: DefaultEntry[K, V]) = if (super.findEntry(e.key) eq null) super.addEntry(e) sizeMapInit(table.length) } @@ -201,8 +201,7 @@ extends collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntr } i += 1 } - val c = table.hashTableContents - new ParHashMap(c) + new ParHashMap(table.hashTableContents) } /* classes */ diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala index fa17f3eaeb..1a27df1c10 100644 --- a/src/library/scala/io/Codec.scala +++ b/src/library/scala/io/Codec.scala @@ -110,7 +110,15 @@ object Codec extends LowPriorityCodecImplicits { @migration("This method was previously misnamed `fromUTF8`. Converts from character sequence to Array[Byte].", "2.9.0") def toUTF8(cs: CharSequence): Array[Byte] = { - val cbuffer = java.nio.CharBuffer wrap cs + val cbuffer = java.nio.CharBuffer.wrap(cs, 0, cs.length) + val bbuffer = UTF8.charSet encode cbuffer + val bytes = new Array[Byte](bbuffer.remaining()) + bbuffer get bytes + + bytes + } + def toUTF8(chars: Array[Char], offset: Int, len: Int): Array[Byte] = { + val cbuffer = java.nio.CharBuffer.wrap(chars, offset, len) val bbuffer = UTF8.charSet encode cbuffer val bytes = new Array[Byte](bbuffer.remaining()) bbuffer get bytes diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala index acd28f04f5..466b57dea7 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifest.scala @@ -127,7 +127,7 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable { java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]] def arrayManifest: ClassManifest[Array[T]] = - ClassManifest.classType[Array[T]](arrayClass[T](erasure)) + ClassManifest.classType[Array[T]](arrayClass[T](erasure), this) def newArray(len: Int): Array[T] = java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]] @@ -220,7 +220,7 @@ object ClassManifest { new ClassTypeManifest[T](Some(prefix), clazz, args.toList) def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match { - case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] + case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest } diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala index df5f64cdf6..be08409636 100644 --- a/src/library/scala/reflect/Manifest.scala +++ b/src/library/scala/reflect/Manifest.scala @@ -44,7 +44,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { override def typeArguments: List[Manifest[_]] = Nil override def arrayManifest: Manifest[Array[T]] = - Manifest.classType[Array[T]](arrayClass[T](erasure)) + Manifest.classType[Array[T]](arrayClass[T](erasure), this) override def canEqual(that: Any): Boolean = that match { case _: Manifest[_] => true @@ -60,7 +60,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { override def hashCode = this.erasure.## } -trait AnyValManifest[T] extends Manifest[T] with Equals { +sealed abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal) override def canEqual(other: Any) = other match { @@ -68,7 +68,7 @@ trait AnyValManifest[T] extends Manifest[T] with Equals { case _ => false } override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) + override val hashCode = System.identityHashCode(this) } /** The object `Manifest` defines factory methods for manifests. @@ -76,127 +76,104 @@ trait AnyValManifest[T] extends Manifest[T] with Equals { * in client code. */ object Manifest { - private def ObjectClass = classOf[java.lang.Object] + def valueManifests: List[AnyValManifest[_]] = + List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) - val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte] { + val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") { def erasure = java.lang.Byte.TYPE - override def toString = "Byte" override def newArray(len: Int): Array[Byte] = new Array[Byte](len) override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len)) override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() private def readResolve(): Any = Manifest.Byte } - val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short] { + val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") { def erasure = java.lang.Short.TYPE - override def toString = "Short" override def newArray(len: Int): Array[Short] = new Array[Short](len) override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len)) override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() private def readResolve(): Any = Manifest.Short } - val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char] { + val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") { def erasure = java.lang.Character.TYPE - override def toString = "Char" override def newArray(len: Int): Array[Char] = new Array[Char](len) override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len)) override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() private def readResolve(): Any = Manifest.Char } - val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int] { + val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") { def erasure = java.lang.Integer.TYPE - override def toString = "Int" override def newArray(len: Int): Array[Int] = new Array[Int](len) override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len)) override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() private def readResolve(): Any = Manifest.Int } - val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long] { + val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") { def erasure = java.lang.Long.TYPE - override def toString = "Long" override def newArray(len: Int): Array[Long] = new Array[Long](len) override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len)) override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() private def readResolve(): Any = Manifest.Long } - val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float] { + val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") { def erasure = java.lang.Float.TYPE - override def toString = "Float" override def newArray(len: Int): Array[Float] = new Array[Float](len) override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len)) override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() private def readResolve(): Any = Manifest.Float } - val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double] { + val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") { def erasure = java.lang.Double.TYPE - override def toString = "Double" override def newArray(len: Int): Array[Double] = new Array[Double](len) override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len)) override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() private def readResolve(): Any = Manifest.Double } - val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean] { + val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") { def erasure = java.lang.Boolean.TYPE - override def toString = "Boolean" override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len)) override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() private def readResolve(): Any = Manifest.Boolean } - val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit] { + val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") { def erasure = java.lang.Void.TYPE - override def toString = "Unit" override def newArray(len: Int): Array[Unit] = new Array[Unit](len) override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len)) override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() private def readResolve(): Any = Manifest.Unit } - val Any: Manifest[Any] = new ClassTypeManifest[scala.Any](None, ObjectClass, Nil) { - override def toString = "Any" + val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Any } - val Object: Manifest[Object] = new ClassTypeManifest[java.lang.Object](None, ObjectClass, Nil) { - override def toString = "Object" + val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Object } - val AnyVal: Manifest[AnyVal] = new ClassTypeManifest[scala.AnyVal](None, ObjectClass, Nil) { - override def toString = "AnyVal" + val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") { override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.AnyVal } - val Null: Manifest[Null] = new ClassTypeManifest[scala.Null](None, ObjectClass, Nil) { - override def toString = "Null" + val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") { override def <:<(that: ClassManifest[_]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Null } - val Nothing: Manifest[Nothing] = new ClassTypeManifest[scala.Nothing](None, ObjectClass, Nil) { - override def toString = "Nothing" + val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") { override def <:<(that: ClassManifest[_]): Boolean = (that ne null) - override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] - override def hashCode = System.identityHashCode(this) private def readResolve(): Any = Manifest.Nothing } @@ -231,6 +208,11 @@ object Manifest { def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) + private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) { + override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + override val hashCode = System.identityHashCode(this) + } + /** Manifest for the class type `clazz[args]`, where `clazz` is * a top-level or static class. */ private class ClassTypeManifest[T](prefix: Option[Manifest[_]], diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index e5502acb20..2394925657 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -542,12 +542,18 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => case class Select(qualifier: Tree, name: Name) extends RefTree + def Select(qualifier: Tree, name: String): Select = + Select(qualifier, newTermName(name)) + def Select(qualifier: Tree, sym: Symbol): Select = Select(qualifier, sym.name) setSymbol sym /** Identifier <name> */ case class Ident(name: Name) extends RefTree { } + def Ident(name: String): Ident = + Ident(newTermName(name)) + def Ident(sym: Symbol): Ident = Ident(sym.name) setSymbol sym diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala index f48d99f5af..cbe778f09b 100644 --- a/src/library/scala/runtime/AbstractPartialFunction.scala +++ b/src/library/scala/runtime/AbstractPartialFunction.scala @@ -26,7 +26,7 @@ abstract class AbstractPartialFunction[-T1, +R] private var fallBackField: PartialFunction[T1 @uncheckedVariance, R @uncheckedVariance] = _ def fallBack: PartialFunction[T1, R] = synchronized { - if (fallBackField == null) fallBackField = PartialFunction.empty + if (fallBackField eq null) fallBackField = PartialFunction.empty fallBackField } @@ -38,7 +38,7 @@ abstract class AbstractPartialFunction[-T1, +R] override def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]) : PartialFunction[A1, B1] = { val result = this.clone.asInstanceOf[AbstractPartialFunction[A1, B1]] result.synchronized { - result.fallBackField = this.fallBackField orElse that + result.fallBackField = if (this.fallBackField eq null) that else this.fallBackField orElse that result } } diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index c726c56d0e..b19c8d086c 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -769,6 +769,24 @@ public final class BoxesRunTime } throw new NoSuchMethodException(); } + + public static boolean isBoxedNumberOrBoolean(Object arg) { + if (arg instanceof java.lang.Boolean) + return true; + else + return isBoxedNumber(arg); + } + public static boolean isBoxedNumber(Object arg) { + return ( + (arg instanceof java.lang.Integer) + || (arg instanceof java.lang.Long) + || (arg instanceof java.lang.Double) + || (arg instanceof java.lang.Float) + || (arg instanceof java.lang.Short) + || (arg instanceof java.lang.Character) + || (arg instanceof java.lang.Byte) + ); + } /** arg.toChar */ public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException { diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala index 127e6e0ab7..df52b34f87 100644 --- a/src/library/scala/xml/Elem.scala +++ b/src/library/scala/xml/Elem.scala @@ -41,7 +41,7 @@ object Elem { class Elem( override val prefix: String, val label: String, - override val attributes: MetaData, + attributes1: MetaData, override val scope: NamespaceBinding, val child: Node*) extends Node with Serializable @@ -49,6 +49,8 @@ extends Node with Serializable final override def doCollectNamespaces = true final override def doTransform = true + override val attributes = MetaData.normalize(attributes1, scope) + if (prefix == "") throw new IllegalArgumentException("prefix of zero length, use null instead") diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala index 98e863eb37..c516747bae 100644 --- a/src/library/scala/xml/MetaData.scala +++ b/src/library/scala/xml/MetaData.scala @@ -38,8 +38,8 @@ object MetaData { def iterate(md: MetaData, normalized_attribs: MetaData, set: Set[String]): MetaData = { lazy val key = getUniversalKey(md, scope) if (md eq Null) normalized_attribs - else if (set(key)) iterate(md.next, normalized_attribs, set) - else iterate(md.next, md copy normalized_attribs, set + key) + else if ((md.value eq null) || set(key)) iterate(md.next, normalized_attribs, set) + else md copy iterate(md.next, normalized_attribs, set + key) } iterate(attribs, Null, Set()) } diff --git a/src/library/scala/xml/PrefixedAttribute.scala b/src/library/scala/xml/PrefixedAttribute.scala index 436dfcda43..b80d6a1c73 100644 --- a/src/library/scala/xml/PrefixedAttribute.scala +++ b/src/library/scala/xml/PrefixedAttribute.scala @@ -13,22 +13,25 @@ package scala.xml * * @param pre ... * @param key ... - * @param value the attribute value, which may not be null + * @param value the attribute value * @param next ... */ class PrefixedAttribute( val pre: String, val key: String, val value: Seq[Node], - val next: MetaData) + val next1: MetaData) extends Attribute { - if (value eq null) - throw new UnsupportedOperationException("value is null") + val next = if (value ne null) next1 else next1.remove(key) - /** same as this(key, Utility.parseAttributeValue(value), next) */ + /** same as this(pre, key, Text(value), next), or no attribute if value is null */ def this(pre: String, key: String, value: String, next: MetaData) = - this(pre, key, Text(value), next) + this(pre, key, if (value ne null) Text(value) else null: NodeSeq, next) + + /** same as this(pre, key, value.get, next), or no attribute if value is None */ + def this(pre: String, key: String, value: Option[Seq[Node]], next: MetaData) = + this(pre, key, value.orNull, next) /** Returns a copy of this unprefixed attribute with the given * next field. diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala index c56fba1e6c..b6800d5ed1 100644 --- a/src/library/scala/xml/UnprefixedAttribute.scala +++ b/src/library/scala/xml/UnprefixedAttribute.scala @@ -22,7 +22,7 @@ extends Attribute final val pre = null val next = if (value ne null) next1 else next1.remove(key) - /** same as this(key, Text(value), next) */ + /** same as this(key, Text(value), next), or no attribute if value is null */ def this(key: String, value: String, next: MetaData) = this(key, if (value ne null) Text(value) else null: NodeSeq, next) diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala index 9b48f4e1bb..fc20b892b9 100644 --- a/src/library/scala/xml/Utility.scala +++ b/src/library/scala/xml/Utility.scala @@ -61,7 +61,7 @@ object Utility extends AnyRef with parsing.TokenTests { val key = md.key val smaller = sort(md.filter { m => m.key < key }) val greater = sort(md.filter { m => m.key > key }) - smaller.append( Null ).append(md.copy ( greater )) + smaller.copy(md.copy ( greater )) } /** Return the node with its attribute list sorted alphabetically diff --git a/src/scalap/scala/tools/scalap/JavaWriter.scala b/src/scalap/scala/tools/scalap/JavaWriter.scala index db9d6c5ed9..02b940ab16 100644 --- a/src/scalap/scala/tools/scalap/JavaWriter.scala +++ b/src/scalap/scala/tools/scalap/JavaWriter.scala @@ -9,7 +9,7 @@ package scala.tools.scalap import java.io._ - +import scala.reflect.NameTransformer class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer) { @@ -32,22 +32,22 @@ class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer } def nameToClass(str: String): String = { - val res = Names.decode(str.replace('/', '.')) + val res = NameTransformer.decode(str.replace('/', '.')) if (res == "java.lang.Object") "scala.Any" else res } def nameToClass0(str: String) = { - val res = Names.decode(str.replace('/', '.')) + val res = NameTransformer.decode(str.replace('/', '.')) if (res == "java.lang.Object") "scala.AnyRef" else res } def nameToSimpleClass(str: String) = - Names.decode(str.substring(str.lastIndexOf('/') + 1)) + NameTransformer.decode(str.substring(str.lastIndexOf('/') + 1)) def nameToPackage(str: String) = { val inx = str.lastIndexOf('/') val name = if (inx == -1) str else str.substring(0, inx).replace('/', '.') - Names.decode(name) + NameTransformer.decode(name) } def sigToType(str: String): String = @@ -119,9 +119,9 @@ class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer def printField(flags: Int, name: Int, tpe: Int, attribs: List[cf.Attribute]) { print(flagsToStr(false, flags)) if ((flags & 0x0010) != 0) - print("val " + Names.decode(getName(name))) + print("val " + NameTransformer.decode(getName(name))) else - print("final var " + Names.decode(getName(name))) + print("final var " + NameTransformer.decode(getName(name))) print(": " + getType(tpe) + ";").newline } @@ -139,20 +139,20 @@ class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer if (getName(name) == "<init>") { print("def this" + getType(tpe) + ";").newline } else { - print("def " + Names.decode(getName(name))) + print("def " + NameTransformer.decode(getName(name))) print(getType(tpe) + ";").newline } case Some(str) => if (getName(name) == "<init>") print("def this" + str + ";").newline else - print("def " + Names.decode(getName(name)) + str + ";").newline + print("def " + NameTransformer.decode(getName(name)) + str + ";").newline } case None => if (getName(name) == "<init>") { print("def this" + getType(tpe) + ";").newline } else { - print("def " + Names.decode(getName(name))) + print("def " + NameTransformer.decode(getName(name))) print(getType(tpe) + ";").newline } } diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 7254b00480..a8a9c65f63 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -8,6 +8,7 @@ package scala.tools.scalap import java.io.{ PrintStream, OutputStreamWriter, ByteArrayOutputStream } +import scala.reflect.NameTransformer import scalax.rules.scalasig._ import tools.nsc.util.{ ClassPath, JavaClassPath } import tools.util.PathResolver @@ -96,7 +97,7 @@ class Main { */ def process(args: Arguments, path: ClassPath[AbstractFile])(classname: String): Unit = { // find the classfile - val encName = Names.encode( + val encName = NameTransformer.encode( if (classname == "scala.AnyRef") "java.lang.Object" else classname) val cls = path.findClass(encName) diff --git a/src/scalap/scala/tools/scalap/Names.scala b/src/scalap/scala/tools/scalap/Names.scala deleted file mode 100644 index 1d66b31ce3..0000000000 --- a/src/scalap/scala/tools/scalap/Names.scala +++ /dev/null @@ -1,96 +0,0 @@ -/* ___ ____ ___ __ ___ ___ -** / _// __// _ | / / / _ | / _ \ Scala classfile decoder -** __\ \/ /__/ __ |/ /__/ __ |/ ___/ (c) 2003-2011, LAMP/EPFL -** /____/\___/_/ |_/____/_/ |_/_/ http://scala-lang.org/ -** -*/ - - -package scala.tools.scalap - - -object Names { - - val operatorName = new Array[String](128) - operatorName('$') = "$" - operatorName('~') = "$tilde" - operatorName('=') = "$eq" - operatorName('<') = "$less" - operatorName('>') = "$greater" - operatorName('!') = "$bang" - operatorName('#') = "$hash" - operatorName('%') = "$percent" - operatorName('^') = "$up" - operatorName('&') = "$amp" - operatorName('|') = "$bar" - operatorName('*') = "$times" - operatorName('/') = "$div" - operatorName('\\') = "$bslash" - operatorName('+') = "$plus" - operatorName('-') = "$minus" - operatorName(':') = "$colon" - - /** Replace operator symbols by corresponding "$op_name" in names. - */ - def encode(name: String): String = { - var i = 0 - val len = name.length() - val res = new StringBuffer() - while (i < len) { - val c = name.charAt(i) - if (c < 128) { - val nop = operatorName(c) - if (nop == null) - res.append(c) - else - res.append(nop) - } else - res.append(c) - i = i + 1 - } - res.toString() - } - - /** Replace "$op_name" by corresponding operator symbols in names. - */ - def decode(name: String): String = { - var i = 0 - val len = name.length() - val res = new StringBuffer() - while (i < len) { - val c = name.charAt(i) - if (c == '$') { - var j = len - while (j > i) { - val prefix = name.substring(i, j) - val c = lookup(prefix) - if (c != null) { - i = j - res.append(c) - } else - j = j - 1 - } - } else { - i = i + 1 - res.append(c) - } - } - res.toString() - } - - /** Looks up the array entry for the operator name. - */ - def lookup(string: String): String = { - var i = 0 - var res: String = null - while (i < 128) { - if (string.equals(operatorName(i))) { - res = String.valueOf(i.asInstanceOf[Char]) - i = 128 - } - i = i + 1 - } - res - } - -} diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala index df78bad25e..aa454934c1 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala @@ -13,9 +13,8 @@ package scalasig import java.io.{PrintStream, ByteArrayOutputStream} import java.util.regex.Pattern - import scala.tools.scalap.scalax.util.StringUtil -import reflect.NameTransformer +import scala.reflect.NameTransformer import java.lang.String class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { diff --git a/test/files/continuations-neg/t2949.check b/test/files/continuations-neg/t2949.check index dd9768807c..411aed1b5b 100644 --- a/test/files/continuations-neg/t2949.check +++ b/test/files/continuations-neg/t2949.check @@ -1,6 +1,6 @@ t2949.scala:13: error: type mismatch; found : Int - required: ? @scala.util.continuations.cpsParam[List[?],Any] + required: ? @scala.util.continuations.cpsParam[List[?],?] x * y ^ one error found diff --git a/test/files/jvm/xml03syntax.check b/test/files/jvm/xml03syntax.check index 75dc539137..9fbedc2ae6 100644 --- a/test/files/jvm/xml03syntax.check +++ b/test/files/jvm/xml03syntax.check @@ -23,4 +23,4 @@ true 4 node=<elem key="<b>hello</b>"></elem>, key=Some(<b>hello</b>) -node=<elem ></elem>, key=None +node=<elem></elem>, key=None diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check new file mode 100644 index 0000000000..d98422dacb --- /dev/null +++ b/test/files/neg/logImplicits.check @@ -0,0 +1,19 @@ +logImplicits.scala:2: applied implicit conversion from xs.type to ?{val size: ?} = implicit def byteArrayOps(xs: Array[Byte]): scala.collection.mutable.ArrayOps[Byte] + def f(xs: Array[Byte]) = xs.size + ^ +logImplicits.scala:7: applied implicit conversion from String("abc") to ?{val map: ?} = implicit def augmentString(x: String): scala.collection.immutable.StringOps + def f = "abc" map (_ + 1) + ^ +logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert:(p: String("abc"))Int + math.max(122, x: Int) + ^ +logImplicits.scala:19: applied implicit conversion from Int(1) to ?{val ->: ?} = implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] + def f = (1 -> 2) + "c" + ^ +logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{val +: ?} = implicit def any2stringadd(x: Any): scala.runtime.StringAdd + def f = (1 -> 2) + "c" + ^ +logImplicits.scala:22: error: class Un needs to be abstract, since method unimplemented is not defined +class Un { + ^ +one error found diff --git a/test/files/neg/logImplicits.flags b/test/files/neg/logImplicits.flags new file mode 100644 index 0000000000..97e5ae94ef --- /dev/null +++ b/test/files/neg/logImplicits.flags @@ -0,0 +1 @@ +-Xlog-implicit-conversions
\ No newline at end of file diff --git a/test/files/neg/logImplicits.scala b/test/files/neg/logImplicits.scala new file mode 100644 index 0000000000..fb5dd8a025 --- /dev/null +++ b/test/files/neg/logImplicits.scala @@ -0,0 +1,25 @@ +class A { + def f(xs: Array[Byte]) = xs.size + def g(xs: Array[Byte]) = xs.length +} + +class B { + def f = "abc" map (_ + 1) +} + +object C { + final val x = "abc" + + implicit def convert(p: x.type): Int = 123 + + math.max(122, x: Int) +} + +class D { + def f = (1 -> 2) + "c" +} + +class Un { + // forcing post-typer failure, since we're only interested in the output from the above + def unimplemented: Int +}
\ No newline at end of file diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index 01ef54e0ea..01bbe2de4e 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -83,7 +83,7 @@ names-defaults-neg.scala:76: error: no type parameters for method test4: (x: T[T --- because --- argument expression's type is not compatible with formal parameter type; found : List[Int] - required: ?T[?T[List[?T[X forSome { type X }]]]] + required: ?T Error occurred in an application involving default arguments. test4() ^ diff --git a/test/files/neg/t1960.check b/test/files/neg/t1960.check index dabf53f126..5238141c4e 100644 --- a/test/files/neg/t1960.check +++ b/test/files/neg/t1960.check @@ -1,4 +1,4 @@ -t1960.scala:5: error: parameter 'p' requires field but conflicts with p in 'TBase' +t1960.scala:5: error: parameter 'p' requires field but conflicts with method p in trait TBase class Aclass (p: Int) extends TBase { def g() { f(p) } } ^ one error found diff --git a/test/files/neg/t5354.check b/test/files/neg/t5354.check new file mode 100644 index 0000000000..e47cecb5fe --- /dev/null +++ b/test/files/neg/t5354.check @@ -0,0 +1,7 @@ +t5354.scala:9: error: ambiguous implicit values: + both method x123 in package foo of type => foo.Bippy + and method z of type => foo.Bippy + match expected type foo.Bippy + implicitly[Bippy] + ^ +one error found diff --git a/test/files/neg/t5354.scala b/test/files/neg/t5354.scala new file mode 100644 index 0000000000..99b5650155 --- /dev/null +++ b/test/files/neg/t5354.scala @@ -0,0 +1,15 @@ +package object foo { + implicit def x123: Bippy = new Bippy("x") +} +package foo { + class Bippy(override val toString: String){ } + class Dingus { + def f1 = { + implicit def z: Bippy = new Bippy("z") + implicitly[Bippy] + } + } + object Test extends App { + println(new Dingus().f1) + } +} diff --git a/test/files/neg/t5357.check b/test/files/neg/t5357.check new file mode 100644 index 0000000000..3385559071 --- /dev/null +++ b/test/files/neg/t5357.check @@ -0,0 +1,4 @@ +t5357.scala:5: error: Pattern variables must start with a lower-case letter. (SLS 8.1.1.) + case A: N => 1 + ^ +one error found diff --git a/test/files/neg/t5357.scala b/test/files/neg/t5357.scala new file mode 100644 index 0000000000..369a5568a4 --- /dev/null +++ b/test/files/neg/t5357.scala @@ -0,0 +1,9 @@ +trait M + +case class N() extends M { + def mytest(x: M) = x match { + case A: N => 1 + case _ => 0 + } +} + diff --git a/test/files/pos/t1459/App.scala b/test/files/pos/t1459/App.scala index 651b285b17..36e5022e94 100755 --- a/test/files/pos/t1459/App.scala +++ b/test/files/pos/t1459/App.scala @@ -1,7 +1,7 @@ package foo import base._ -object App extends Application { +object App extends scala.App { class Concrete extends AbstractBase { override def doStuff(params:java.lang.String*): Unit = println("doStuff invoked") } diff --git a/test/files/pos/t4070.scala b/test/files/pos/t4070.scala new file mode 100644 index 0000000000..29c8d16e30 --- /dev/null +++ b/test/files/pos/t4070.scala @@ -0,0 +1,37 @@ +package a { + // method before classes + trait Foo { + def crash(x: Dingus[_]): Unit = x match { case m: Bippy[tv] => () } + + class Dingus[T] + class Bippy[CC[X] <: Seq[X]]() extends Dingus[CC[Int]] + } +} + +package b { + // classes before method + trait Foo { + class Dingus[T] + class Bippy[CC[X] <: Seq[X]]() extends Dingus[CC[Int]] + + def crash(x: Dingus[_]): Unit = x match { case m: Bippy[tv] => () } + } +} + + +/* +// With crash below the clasess: +% scalac -Dscalac.debug.tvar ./a.scala +[ create] ?_$1 ( In Foo#crash ) +[ setInst] tv[Int] ( In Foo#crash, _$1=tv[Int] ) +[ create] tv[Int] ( In Foo#crash ) +[ clone] tv[Int] ( Foo#crash ) + +// With crash above the classes: +% scalac -Dscalac.debug.tvar ./a.scala +[ create] ?tv ( In Foo#crash ) +./a.scala:2: error: Invalid type application in TypeVar: List(), List(Int) + def crash(x: Dingus[_]): Unit = x match { case m: Bippy[tv] => () } + ^ +one error found +*/ diff --git a/test/files/pos/t4070b.scala b/test/files/pos/t4070b.scala new file mode 100644 index 0000000000..36d03de80c --- /dev/null +++ b/test/files/pos/t4070b.scala @@ -0,0 +1,35 @@ +package a { + abstract class DeliteOp[B] + abstract class DeliteCollection[A] + abstract class Exp[T] { def Type: T } + + trait DeliteOpMap[A,B,C[X] <: DeliteCollection[X]] extends DeliteOp[C[B]] { + val in: Exp[C[A]] + val func: Exp[B] + val alloc: Exp[C[B]] + } + + object Test { + def f(x: DeliteOp[_]) = x match { + case map: DeliteOpMap[_,_,_] => map.alloc.Type + } + } +} + +package b { + object Test { + def f(x: DeliteOp[_]) = x match { + case map: DeliteOpMap[_,_,_] => map.alloc.Type + } + } + + abstract class DeliteOp[B] + abstract class DeliteCollection[A] + abstract class Exp[T] { def Type: T } + + trait DeliteOpMap[A,B,C[X] <: DeliteCollection[X]] extends DeliteOp[C[B]] { + val in: Exp[C[A]] + val func: Exp[B] + val alloc: Exp[C[B]] + } +}
\ No newline at end of file diff --git a/test/files/pos/t5020.scala b/test/files/pos/t5020.scala new file mode 100644 index 0000000000..06f7723f9f --- /dev/null +++ b/test/files/pos/t5020.scala @@ -0,0 +1,19 @@ +package a { + sealed trait GenericList[U, M[_ <: U]] { + type Transformed[N[MMA <: U]] <: GenericList[U, N] + } + + trait GenericCons[U, M[_ <: U], T <: GenericList[U, M]] extends GenericList[U, M] { + type Transformed[N[MMB <: U]] = GenericCons[U, N, GenericList[U, M]#Transformed[N]] + } +} + +package b { + sealed trait GenericList[L, M[_ >: L]] { + type Transformed[N[MMA >: L]] <: GenericList[L, N] + } + + trait GenericCons[L, M[_ >: L], T <: GenericList[L, M]] extends GenericList[L, M] { + type Transformed[N[MMB >: L]] = GenericCons[L, N, T#Transformed[N]] + } +}
\ No newline at end of file diff --git a/test/files/pos/t5359.scala b/test/files/pos/t5359.scala new file mode 100644 index 0000000000..c22b2b1c76 --- /dev/null +++ b/test/files/pos/t5359.scala @@ -0,0 +1,17 @@ +// /scala/trac/5359/a.scala +// Thu Jan 5 13:31:05 PST 2012 + +object test { + trait Step[F[_]] { + // crash: typeConstructor inapplicable for <none> + this match { + case S1() => + } + } + case class S1[F[_]]() extends Step[F] + + // okay + (null: Step[Option]) match { + case S1() => + } +} diff --git a/test/files/run/array-existential-bound.check b/test/files/run/array-existential-bound.check new file mode 100644 index 0000000000..f5cca843e3 --- /dev/null +++ b/test/files/run/array-existential-bound.check @@ -0,0 +1,4 @@ +2 +1000 +1000 +26 diff --git a/test/files/run/array-existential-bound.scala b/test/files/run/array-existential-bound.scala new file mode 100644 index 0000000000..bc442d39f7 --- /dev/null +++ b/test/files/run/array-existential-bound.scala @@ -0,0 +1,17 @@ +trait Fooz[Q <: Array[_]] { + def f0(x: Q) = x.length +} + +object Test extends Fooz[Array[Int]] { + val f1 = new Fooz[Array[String]] { } + val f2 = new Fooz[Array[Int]] { } + val f3 = new Fooz[Array[Any]] { } + val f4 = new Fooz[Array[_]] { } + + def main(args: Array[String]): Unit = { + println(f1.f0(Array[String]("a", "b"))) + println(f2.f0(1 to 1000 toArray)) + println(f3.f0((1 to 1000).toArray[Any])) + println(f4.f0('a' to 'z' toArray)) + } +} diff --git a/test/files/run/mixin-bridge-methods.scala b/test/files/run/mixin-bridge-methods.scala new file mode 100644 index 0000000000..e0340ebb12 --- /dev/null +++ b/test/files/run/mixin-bridge-methods.scala @@ -0,0 +1,14 @@ +trait Foo { + def getFoo() = "foo" +} + +class Sub extends Foo { + def getBar() = "bar" +} + +object Test { + def main(args: Array[String]): Unit = { + val ms = classOf[Sub].getDeclaredMethods + assert(ms forall (x => !x.isBridge), ms mkString " ") + } +} diff --git a/test/files/run/origins.scala b/test/files/run/origins.scala index ab873bca89..9dc6071c7b 100644 --- a/test/files/run/origins.scala +++ b/test/files/run/origins.scala @@ -1,4 +1,4 @@ -import scala.tools.nsc.util.Origins +import scala.reflect.internal.util.Origins package goxbox { object Socks { diff --git a/test/files/run/t3758.scala b/test/files/run/t3758.scala new file mode 100644 index 0000000000..18750b0a9c --- /dev/null +++ b/test/files/run/t3758.scala @@ -0,0 +1,10 @@ +object Test { + def main(args: Array[String]): Unit = { + assert(classManifest[Array[String]].typeArguments contains classManifest[String]) + assert(classManifest[Array[Int]].typeArguments contains classManifest[Int]) + assert(classManifest[Array[Float]].typeArguments contains classManifest[Float]) + assert(manifest[Array[String]].typeArguments contains manifest[String]) + assert(manifest[Array[Int]].typeArguments contains manifest[Int]) + assert(manifest[Array[Float]].typeArguments contains manifest[Float]) + } +} diff --git a/test/files/run/t5300.scala b/test/files/run/t5300.scala new file mode 100644 index 0000000000..073b29604a --- /dev/null +++ b/test/files/run/t5300.scala @@ -0,0 +1,7 @@ +object Test { + val pf: PartialFunction[Any, Unit] = { case _ => () } + + def main(args: Array[String]): Unit = { + pf orElse pf + } +} diff --git a/test/files/run/t5356.check b/test/files/run/t5356.check new file mode 100644 index 0000000000..21c4aef07b --- /dev/null +++ b/test/files/run/t5356.check @@ -0,0 +1,6 @@ +1 scala.runtime.RichInt +1 scala.runtime.RichInt +1 scala.math.BigInt +1 scala.runtime.RichDouble +1 scala.runtime.RichFloat +1 diff --git a/test/files/run/t5356.scala b/test/files/run/t5356.scala new file mode 100644 index 0000000000..f7696c6088 --- /dev/null +++ b/test/files/run/t5356.scala @@ -0,0 +1,12 @@ +object Test { + def f(x: { def toInt: Int }) = println(x.toInt + " " + x.getClass.getName) + + def main(args: Array[String]): Unit = { + f(1) + f(1.toInt) + f(BigInt(1)) + f(1d) + f(1f) + println((1: { def toInt: Int }).toInt) + } +} diff --git a/test/files/run/type-currying.scala b/test/files/run/type-currying.scala index 717e0763a3..f9764c64f0 100644 --- a/test/files/run/type-currying.scala +++ b/test/files/run/type-currying.scala @@ -43,3 +43,16 @@ object Test { assert(n0 == n1) } } + +class A { + object Foo { + def apply[T] = Bar + } + object Bar { + def apply() = Foo + } + + def f() = Foo + def g = f()[Int]()[String]() + def h = Foo[Foo.type]()[Foo.type]() +} diff --git a/test/files/run/xml-attribute.scala b/test/files/run/xml-attribute.scala new file mode 100644 index 0000000000..8b261acc94 --- /dev/null +++ b/test/files/run/xml-attribute.scala @@ -0,0 +1,33 @@ +import xml.Node + +object Test { + def main(args: Array[String]): Unit = { + val noAttr = <t/> + val attrNull = <t a={ null: String }/> + val attrNone = <t a={ None: Option[Seq[Node]] }/> + val preAttrNull = <t p:a={ null: String }/> + val preAttrNone = <t p:a={ None: Option[Seq[Node]] }/> + assert(noAttr == attrNull) + assert(noAttr == attrNone) + assert(noAttr == preAttrNull) + assert(noAttr == preAttrNone) + + val noAttrStr = "<t></t>" + assert(noAttr.toString() == noAttrStr) + assert(attrNull.toString() == noAttrStr) + assert(attrNone.toString() == noAttrStr) + assert(preAttrNull.toString() == noAttrStr) + assert(preAttrNone.toString() == noAttrStr) + + val xml1 = <t b="1" d="2"/> + val xml2 = <t a={ null: String } p:a={ null: String } b="1" c={ null: String } d="2"/> + val xml3 = <t b="1" c={ null: String } d="2" a={ null: String } p:a={ null: String }/> + assert(xml1 == xml2) + assert(xml1 == xml3) + + val xml1Str = "<t d=\"2\" b=\"1\"></t>" + assert(xml1.toString() == xml1Str) + assert(xml2.toString() == xml1Str) + assert(xml3.toString() == xml1Str) + } +} |