diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 4e32634ae274..8c8ec5f9270b 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -706,6 +706,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def isJavaEntryPoint: Boolean = CollectEntryPoints.isJavaEntryPoint(sym) def isClassConstructor: Boolean = toDenot(sym).isClassConstructor + def isSerializable: Boolean = toDenot(sym).isSerializable /** * True for module classes of modules that are top-level or owned only by objects. Module classes @@ -855,6 +856,9 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma def samMethod(): Symbol = toDenot(sym).info.abstractTermMembers.headOption.getOrElse(toDenot(sym).info.member(nme.apply)).symbol + + def isFunctionClass: Boolean = + defn.isFunctionClass(sym) } diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index daabf824cead..d94f82180c48 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -6,6 +6,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Phases.Phase import scala.collection.mutable +import scala.collection.JavaConverters._ import scala.tools.asm.CustomAttr import scala.tools.nsc.backend.jvm._ import dotty.tools.dotc.transform.SymUtils._ @@ -23,6 +24,7 @@ import java.io.DataOutputStream import scala.tools.asm +import scala.tools.asm.Handle import scala.tools.asm.tree._ import tpd._ import StdNames._ @@ -304,10 +306,98 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter class Worker2 { // lazy val localOpt = new LocalOpt(new Settings()) - def localOptimizations(classNode: ClassNode): Unit = { + private def localOptimizations(classNode: ClassNode): Unit = { // BackendStats.timed(BackendStats.methodOptTimer)(localOpt.methodOptimizations(classNode)) } + + /* Return an array of all serializable lambdas in this class */ + private def collectSerializableLambdas(classNode: ClassNode): Array[Handle] = { + val indyLambdaBodyMethods = new mutable.ArrayBuffer[Handle] + for (m <- classNode.methods.asScala) { + val iter = m.instructions.iterator + while (iter.hasNext) { + val insn = iter.next() + insn match { + case indy: InvokeDynamicInsnNode + // No need to check the exact bsmArgs because we only generate + // altMetafactory indy calls for serializable lambdas. + if indy.bsm == BCodeBodyBuilder.lambdaMetaFactoryAltMetafactoryHandle => + val implMethod = indy.bsmArgs(1).asInstanceOf[Handle] + indyLambdaBodyMethods += implMethod + case _ => + } + } + } + indyLambdaBodyMethods.toArray + } + + /* + * Add: + * + * private static Object $deserializeLambda$(SerializedLambda l) { + * try return indy[scala.runtime.LambdaDeserialize.bootstrap, targetMethodGroup$0](l) + * catch { + * case i: IllegalArgumentException => + * try return indy[scala.runtime.LambdaDeserialize.bootstrap, targetMethodGroup$1](l) + * catch { + * case i: IllegalArgumentException => + * ... + * return indy[scala.runtime.LambdaDeserialize.bootstrap, targetMethodGroup${NUM_GROUPS-1}](l) + * } + * + * We use invokedynamic here to enable caching within the deserializer without needing to + * host a static field in the enclosing class. This allows us to add this method to interfaces + * that define lambdas in default methods. + * + * SI-10232 we can't pass arbitrary number of method handles to the final varargs parameter of the bootstrap + * method due to a limitation in the JVM. Instead, we emit a separate invokedynamic bytecode for each group of target + * methods. + */ + private def addLambdaDeserialize(classNode: ClassNode, implMethodsArray: Array[Handle]): Unit = { + import asm.Opcodes._ + import BCodeBodyBuilder._ + import bTypes._ + import coreBTypes._ + + val cw = classNode + + // Make sure to reference the ClassBTypes of all types that are used in the code generated + // here (e.g. java/util/Map) are initialized. Initializing a ClassBType adds it to + // `classBTypeFromInternalNameMap`. When writing the classfile, the asm ClassWriter computes + // stack map frames and invokes the `getCommonSuperClass` method. This method expects all + // ClassBTypes mentioned in the source code to exist in the map. + + val serlamObjDesc = MethodBType(jliSerializedLambdaRef :: Nil, ObjectReference).descriptor + + val mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambda$", serlamObjDesc, null, null) + def emitLambdaDeserializeIndy(targetMethods: Seq[Handle]): Unit = { + mv.visitVarInsn(ALOAD, 0) + mv.visitInvokeDynamicInsn("lambdaDeserialize", serlamObjDesc, lambdaDeserializeBootstrapHandle, targetMethods: _*) + } + + val targetMethodGroupLimit = 255 - 1 - 3 // JVM limit. See See MAX_MH_ARITY in CallSite.java + val groups: Array[Array[Handle]] = implMethodsArray.grouped(targetMethodGroupLimit).toArray + val numGroups = groups.length + + import scala.tools.asm.Label + val initialLabels = Array.fill(numGroups - 1)(new Label()) + val terminalLabel = new Label + def nextLabel(i: Int) = if (i == numGroups - 2) terminalLabel else initialLabels(i + 1) + + for ((label, i) <- initialLabels.iterator.zipWithIndex) { + mv.visitTryCatchBlock(label, nextLabel(i), nextLabel(i), jlIllegalArgExceptionRef.internalName) + } + for ((label, i) <- initialLabels.iterator.zipWithIndex) { + mv.visitLabel(label) + emitLambdaDeserializeIndy(groups(i)) + mv.visitInsn(ARETURN) + } + mv.visitLabel(terminalLabel) + emitLambdaDeserializeIndy(groups(numGroups - 1)) + mv.visitInsn(ARETURN) + } + def run(): Unit = { while (true) { val item = q2.poll @@ -317,7 +407,11 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } else { try { - localOptimizations(item.plain.classNode) + val plainNode = item.plain.classNode + localOptimizations(plainNode) + val serializableLambdas = collectSerializableLambdas(plainNode) + if (serializableLambdas.nonEmpty) + addLambdaDeserialize(plainNode, serializableLambdas) addToQ3(item) } catch { case ex: Throwable => diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index df3809b64281..dd15a25031d5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -341,8 +341,9 @@ object desugar { case _ => false } - val isCaseClass = mods.is(Case) && !mods.is(Module) - val isCaseObject = mods.is(Case) && mods.is(Module) + val isObject = mods.is(Module) + val isCaseClass = mods.is(Case) && !isObject + val isCaseObject = mods.is(Case) && isObject val isImplicit = mods.is(Implicit) val isInstance = isImplicit && mods.mods.exists(_.isInstanceOf[Mod.Instance]) val isEnum = mods.isEnumClass && !mods.is(Module) @@ -527,13 +528,13 @@ object desugar { else Nil } - // Case classes and case objects get Product parents - // Enum cases get an inferred parent if no parents are given var parents1 = parents if (isEnumCase && parents.isEmpty) parents1 = enumClassTypeRef :: Nil if (isCaseClass | isCaseObject) parents1 = parents1 :+ scalaDot(str.Product.toTypeName) :+ scalaDot(nme.Serializable.toTypeName) + else if (isObject) + parents1 = parents1 :+ scalaDot(nme.Serializable.toTypeName) if (isEnum) parents1 = parents1 :+ ref(defn.EnumType) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 77922d677354..2332a9b8204e 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1001,6 +1001,7 @@ class Definitions { tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass) /** Is a function class. + * - FunctionXXL * - FunctionN for N >= 0 * - ImplicitFunctionN for N >= 0 * - ErasedFunctionN for N > 0 @@ -1020,15 +1021,21 @@ class Definitions { */ def isErasedFunctionClass(cls: Symbol): Boolean = scalaClassName(cls).isErasedFunction - /** Is a class that will be erased to FunctionXXL + /** Is either FunctionXXL or a class that will be erased to FunctionXXL + * - FunctionXXL * - FunctionN for N >= 22 * - ImplicitFunctionN for N >= 22 */ - def isXXLFunctionClass(cls: Symbol): Boolean = scalaClassName(cls).functionArity > MaxImplementedFunctionArity + def isXXLFunctionClass(cls: Symbol): Boolean = { + val name = scalaClassName(cls) + (name eq tpnme.FunctionXXL) || name.functionArity > MaxImplementedFunctionArity + } /** Is a synthetic function class * - FunctionN for N > 22 - * - ImplicitFunctionN for N > 0 + * - ImplicitFunctionN for N >= 0 + * - ErasedFunctionN for N > 0 + * - ErasedImplicitFunctionN for N > 0 */ def isSyntheticFunctionClass(cls: Symbol): Boolean = scalaClassName(cls).isSyntheticFunction diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 4b2d6f5ad216..7bb897c0d73b 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -183,9 +183,9 @@ object NameOps { if (n == 0) -1 else n } - /** Is a function name, i.e one of FunctionN, ImplicitFunctionN for N >= 0 or ErasedFunctionN, ErasedImplicitFunctionN for N > 0 + /** Is a function name, i.e one of FunctionXXL, FunctionN, ImplicitFunctionN for N >= 0 or ErasedFunctionN, ErasedImplicitFunctionN for N > 0 */ - def isFunction: Boolean = functionArity >= 0 + def isFunction: Boolean = (name eq tpnme.FunctionXXL) || functionArity >= 0 /** Is an implicit function name, i.e one of ImplicitFunctionN for N >= 0 or ErasedImplicitFunctionN for N > 0 */ diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index e702a47ce8eb..3d3da013af4b 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -205,6 +205,7 @@ object StdNames { final val Singleton: N = "Singleton" final val Throwable: N = "Throwable" final val IOOBException: N = "IndexOutOfBoundsException" + final val FunctionXXL: N = "FunctionXXL" final val ClassfileAnnotation: N = "ClassfileAnnotation" final val ClassManifest: N = "ClassManifest" diff --git a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala index bdd339482ab3..b465452f4bdf 100644 --- a/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala +++ b/compiler/src/dotty/tools/dotc/transform/GenericSignatures.scala @@ -123,6 +123,60 @@ object GenericSignatures { builder.append('L').append(name) } + def classSig(sym: Symbol, pre: Type = NoType, args: List[Type] = Nil): Unit = { + def argSig(tp: Type): Unit = + tp match { + case bounds: TypeBounds => + if (!(defn.AnyType <:< bounds.hi)) { + builder.append('+') + boxedSig(bounds.hi) + } + else if (!(bounds.lo <:< defn.NothingType)) { + builder.append('-') + boxedSig(bounds.lo) + } + else builder.append('*') + case PolyType(_, res) => + builder.append('*') // scala/bug#7932 + case _: HKTypeLambda => + fullNameInSig(tp.typeSymbol) + builder.append(';') + case _ => + boxedSig(tp) + } + + if (pre.exists) { + val preRebound = pre.baseType(sym.owner) // #2585 + if (needsJavaSig(preRebound, Nil)) { + val i = builder.length() + jsig(preRebound) + if (builder.charAt(i) == 'L') { + builder.delete(builder.length() - 1, builder.length())// delete ';' + // If the prefix is a module, drop the '$'. Classes (or modules) nested in modules + // are separated by a single '$' in the filename: `object o { object i }` is o$i$. + if (preRebound.typeSymbol.is(ModuleClass)) + builder.delete(builder.length() - 1, builder.length()) + + // Ensure every '.' in the generated signature immediately follows + // a close angle bracket '>'. Any which do not are replaced with '$'. + // This arises due to multiply nested classes in the face of the + // rewriting explained at rebindInnerClass. + + // TODO revisit this. Does it align with javac for code that can be expressed in both languages? + val delimiter = if (builder.charAt(builder.length() - 1) == '>') '.' else '$' + builder.append(delimiter).append(sanitizeName(sym.name.asSimpleName)) + } else fullNameInSig(sym) + } else fullNameInSig(sym) + } else fullNameInSig(sym) + + if (args.nonEmpty) { + builder.append('<') + args foreach argSig + builder.append('>') + } + builder.append(';') + } + @noinline def jsig(tp0: Type, toplevel: Boolean = false, primitiveOK: Boolean = true): Unit = { @@ -133,57 +187,6 @@ object GenericSignatures { typeParamSig(ref.paramName.lastPart) case RefOrAppliedType(sym, pre, args) => - def argSig(tp: Type): Unit = - tp match { - case bounds: TypeBounds => - if (!(defn.AnyType <:< bounds.hi)) { - builder.append('+') - boxedSig(bounds.hi) - } - else if (!(bounds.lo <:< defn.NothingType)) { - builder.append('-') - boxedSig(bounds.lo) - } - else builder.append('*') - case PolyType(_, res) => - builder.append('*') // scala/bug#7932 - case _: HKTypeLambda => - fullNameInSig(tp.typeSymbol) - builder.append(';') - case _ => - boxedSig(tp) - } - def classSig: Unit = { - val preRebound = pre.baseType(sym.owner) // #2585 - if (needsJavaSig(preRebound, Nil)) { - val i = builder.length() - jsig(preRebound) - if (builder.charAt(i) == 'L') { - builder.delete(builder.length() - 1, builder.length())// delete ';' - // If the prefix is a module, drop the '$'. Classes (or modules) nested in modules - // are separated by a single '$' in the filename: `object o { object i }` is o$i$. - if (preRebound.typeSymbol.is(ModuleClass)) - builder.delete(builder.length() - 1, builder.length()) - - // Ensure every '.' in the generated signature immediately follows - // a close angle bracket '>'. Any which do not are replaced with '$'. - // This arises due to multiply nested classes in the face of the - // rewriting explained at rebindInnerClass. - - // TODO revisit this. Does it align with javac for code that can be expressed in both languages? - val delimiter = if (builder.charAt(builder.length() - 1) == '>') '.' else '$' - builder.append(delimiter).append(sanitizeName(sym.name.asSimpleName)) - } else fullNameInSig(sym) - } else fullNameInSig(sym) - - if (args.nonEmpty) { - builder.append('<') - args foreach argSig - builder.append('>') - } - builder.append(';') - } - // If args isEmpty, Array is being used as a type constructor if (sym == defn.ArrayClass && args.nonEmpty) { if (unboundedGenericArrayLevel(tp) == 1) jsig(defn.ObjectType) @@ -215,14 +218,14 @@ object GenericSignatures { val unboxed = ValueClasses.valueClassUnbox(sym.asClass).info.finalResultType val unboxedSeen = tp.memberInfo(ValueClasses.valueClassUnbox(sym.asClass)).finalResultType if (unboxedSeen.isPrimitiveValueType && !primitiveOK) - classSig + classSig(sym, pre, args) else jsig(unboxedSeen, toplevel, primitiveOK) } else if (defn.isXXLFunctionClass(sym)) - jsig(defn.FunctionXXLType, toplevel, primitiveOK) + classSig(defn.FunctionXXLClass) else if (sym.isClass) - classSig + classSig(sym, pre, args) else jsig(erasure(tp), toplevel, primitiveOK) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 49236ad4c890..b557fde92235 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -361,6 +361,11 @@ class Typer extends Namer if (untpd.isVarPattern(tree) && name.isTermName) return typed(desugar.patternVar(tree), pt) } + // Shortcut for the root package, this is not just a performance + // optimization, it also avoids forcing imports thus potentially avoiding + // cyclic references. + if (name == nme.ROOTPKG) + return tree.withType(defn.RootPackage.termRef) val rawType = { val saved1 = unimported @@ -1606,6 +1611,11 @@ class Typer extends Namer var result = if (isTreeType(tree)) typedType(tree)(superCtx) else typedExpr(tree)(superCtx) val psym = result.tpe.dealias.typeSymbol if (seenParents.contains(psym) && !cls.isRefinementClass) { + // Desugaring can adds parents to classes, but we don't want to emit an + // error if the same parent was explicitly added in user code. + if (!tree.span.isSourceDerived) + return EmptyTree + if (!ctx.isAfterTyper) ctx.error(i"$psym is extended twice", tree.sourcePos) } else seenParents += psym @@ -1640,7 +1650,7 @@ class Typer extends Namer completeAnnotations(cdef, cls) val constr1 = typed(constr).asInstanceOf[DefDef] - val parentsWithClass = ensureFirstTreeIsClass(parents mapconserve typedParent, cdef.nameSpan) + val parentsWithClass = ensureFirstTreeIsClass(parents.mapconserve(typedParent).filterConserve(!_.isEmpty), cdef.nameSpan) val parents1 = ensureConstrCall(cls, parentsWithClass)(superCtx) var self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible diff --git a/library/src/scala/compat/java8/JFunction0.java b/library/src/scala/compat/java8/JFunction0.java index 4937d5578ea0..87a9e26f8b61 100644 --- a/library/src/scala/compat/java8/JFunction0.java +++ b/library/src/scala/compat/java8/JFunction0.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction0 extends scala.Function0 { +public interface JFunction0 extends scala.Function0, java.io.Serializable { default void $init$() { }; default void apply$mcV$sp() { diff --git a/library/src/scala/compat/java8/JFunction1.java b/library/src/scala/compat/java8/JFunction1.java index ed22c91eb96f..d1b526d5b5b8 100644 --- a/library/src/scala/compat/java8/JFunction1.java +++ b/library/src/scala/compat/java8/JFunction1.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction1 extends scala.Function1 { +public interface JFunction1 extends scala.Function1, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction10.java b/library/src/scala/compat/java8/JFunction10.java index 63e392a8e449..a31517e551fe 100644 --- a/library/src/scala/compat/java8/JFunction10.java +++ b/library/src/scala/compat/java8/JFunction10.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction10 extends scala.Function10 { +public interface JFunction10 extends scala.Function10, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction11.java b/library/src/scala/compat/java8/JFunction11.java index 0dd20546192b..123ae015361b 100644 --- a/library/src/scala/compat/java8/JFunction11.java +++ b/library/src/scala/compat/java8/JFunction11.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction11 extends scala.Function11 { +public interface JFunction11 extends scala.Function11, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction12.java b/library/src/scala/compat/java8/JFunction12.java index c992cc43f1b1..9da50de2edbd 100644 --- a/library/src/scala/compat/java8/JFunction12.java +++ b/library/src/scala/compat/java8/JFunction12.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction12 extends scala.Function12 { +public interface JFunction12 extends scala.Function12, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction13.java b/library/src/scala/compat/java8/JFunction13.java index cca43006f26c..76c78158ab44 100644 --- a/library/src/scala/compat/java8/JFunction13.java +++ b/library/src/scala/compat/java8/JFunction13.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction13 extends scala.Function13 { +public interface JFunction13 extends scala.Function13, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction14.java b/library/src/scala/compat/java8/JFunction14.java index 3e69530a603e..74c37e64571f 100644 --- a/library/src/scala/compat/java8/JFunction14.java +++ b/library/src/scala/compat/java8/JFunction14.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction14 extends scala.Function14 { +public interface JFunction14 extends scala.Function14, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction15.java b/library/src/scala/compat/java8/JFunction15.java index 76d70174c876..68dd9b7cfcc3 100644 --- a/library/src/scala/compat/java8/JFunction15.java +++ b/library/src/scala/compat/java8/JFunction15.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction15 extends scala.Function15 { +public interface JFunction15 extends scala.Function15, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction16.java b/library/src/scala/compat/java8/JFunction16.java index c11b461f5495..73aa9328b36e 100644 --- a/library/src/scala/compat/java8/JFunction16.java +++ b/library/src/scala/compat/java8/JFunction16.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction16 extends scala.Function16 { +public interface JFunction16 extends scala.Function16, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction17.java b/library/src/scala/compat/java8/JFunction17.java index c088f9dce7d6..fb225de5ed1a 100644 --- a/library/src/scala/compat/java8/JFunction17.java +++ b/library/src/scala/compat/java8/JFunction17.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction17 extends scala.Function17 { +public interface JFunction17 extends scala.Function17, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction18.java b/library/src/scala/compat/java8/JFunction18.java index 25600da3ffe1..a1f796df9030 100644 --- a/library/src/scala/compat/java8/JFunction18.java +++ b/library/src/scala/compat/java8/JFunction18.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction18 extends scala.Function18 { +public interface JFunction18 extends scala.Function18, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction19.java b/library/src/scala/compat/java8/JFunction19.java index cacc66d08e9e..c446f6c21815 100644 --- a/library/src/scala/compat/java8/JFunction19.java +++ b/library/src/scala/compat/java8/JFunction19.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction19 extends scala.Function19 { +public interface JFunction19 extends scala.Function19, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction2.java b/library/src/scala/compat/java8/JFunction2.java index 5ece8c62aea7..2984a9746335 100644 --- a/library/src/scala/compat/java8/JFunction2.java +++ b/library/src/scala/compat/java8/JFunction2.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction2 extends scala.Function2 { +public interface JFunction2 extends scala.Function2, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction20.java b/library/src/scala/compat/java8/JFunction20.java index f34574f7f77f..82fe356f57f3 100644 --- a/library/src/scala/compat/java8/JFunction20.java +++ b/library/src/scala/compat/java8/JFunction20.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction20 extends scala.Function20 { +public interface JFunction20 extends scala.Function20, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction21.java b/library/src/scala/compat/java8/JFunction21.java index 0af8db2db3b7..8b6b476da1d4 100644 --- a/library/src/scala/compat/java8/JFunction21.java +++ b/library/src/scala/compat/java8/JFunction21.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction21 extends scala.Function21 { +public interface JFunction21 extends scala.Function21, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction22.java b/library/src/scala/compat/java8/JFunction22.java index fcd83a05fefd..7e635391798f 100644 --- a/library/src/scala/compat/java8/JFunction22.java +++ b/library/src/scala/compat/java8/JFunction22.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction22 extends scala.Function22 { +public interface JFunction22 extends scala.Function22, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction3.java b/library/src/scala/compat/java8/JFunction3.java index 9122f68198c9..5147e73600d9 100644 --- a/library/src/scala/compat/java8/JFunction3.java +++ b/library/src/scala/compat/java8/JFunction3.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction3 extends scala.Function3 { +public interface JFunction3 extends scala.Function3, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction4.java b/library/src/scala/compat/java8/JFunction4.java index d7356a0f8f32..6d39a3a06cd4 100644 --- a/library/src/scala/compat/java8/JFunction4.java +++ b/library/src/scala/compat/java8/JFunction4.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction4 extends scala.Function4 { +public interface JFunction4 extends scala.Function4, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction5.java b/library/src/scala/compat/java8/JFunction5.java index 1e0414bc5dce..9a36af977387 100644 --- a/library/src/scala/compat/java8/JFunction5.java +++ b/library/src/scala/compat/java8/JFunction5.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction5 extends scala.Function5 { +public interface JFunction5 extends scala.Function5, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction6.java b/library/src/scala/compat/java8/JFunction6.java index 112c21cbe977..6cd79beaeb8f 100644 --- a/library/src/scala/compat/java8/JFunction6.java +++ b/library/src/scala/compat/java8/JFunction6.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction6 extends scala.Function6 { +public interface JFunction6 extends scala.Function6, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction7.java b/library/src/scala/compat/java8/JFunction7.java index 1f59bc7affd9..34f48cc31114 100644 --- a/library/src/scala/compat/java8/JFunction7.java +++ b/library/src/scala/compat/java8/JFunction7.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction7 extends scala.Function7 { +public interface JFunction7 extends scala.Function7, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction8.java b/library/src/scala/compat/java8/JFunction8.java index 10825347af38..af7d5a99bdf9 100644 --- a/library/src/scala/compat/java8/JFunction8.java +++ b/library/src/scala/compat/java8/JFunction8.java @@ -8,7 +8,7 @@ import scala.MatchError; @FunctionalInterface -public interface JFunction8 extends scala.Function8 { +public interface JFunction8 extends scala.Function8, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JFunction9.java b/library/src/scala/compat/java8/JFunction9.java index 02fe323c56c6..9157c23a80a3 100644 --- a/library/src/scala/compat/java8/JFunction9.java +++ b/library/src/scala/compat/java8/JFunction9.java @@ -6,7 +6,7 @@ package scala.compat.java8; @FunctionalInterface -public interface JFunction9 extends scala.Function9 { +public interface JFunction9 extends scala.Function9, java.io.Serializable { default void $init$() { }; diff --git a/library/src/scala/compat/java8/JProcedure0.java b/library/src/scala/compat/java8/JProcedure0.java index 8361252c63a1..1cb975e2a781 100644 --- a/library/src/scala/compat/java8/JProcedure0.java +++ b/library/src/scala/compat/java8/JProcedure0.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure0 extends JFunction0 { +public interface JProcedure0 extends JFunction0, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure1.java b/library/src/scala/compat/java8/JProcedure1.java index 189e451cd0d3..b524810614c3 100644 --- a/library/src/scala/compat/java8/JProcedure1.java +++ b/library/src/scala/compat/java8/JProcedure1.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure1 extends JFunction1 { +public interface JProcedure1 extends JFunction1, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure10.java b/library/src/scala/compat/java8/JProcedure10.java index 63a7543c5c0d..4a94f53951f7 100644 --- a/library/src/scala/compat/java8/JProcedure10.java +++ b/library/src/scala/compat/java8/JProcedure10.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure10 extends JFunction10 { +public interface JProcedure10 extends JFunction10, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure11.java b/library/src/scala/compat/java8/JProcedure11.java index 1f530fba9699..bdf09102062c 100644 --- a/library/src/scala/compat/java8/JProcedure11.java +++ b/library/src/scala/compat/java8/JProcedure11.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure11 extends JFunction11 { +public interface JProcedure11 extends JFunction11, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure12.java b/library/src/scala/compat/java8/JProcedure12.java index 454868e664a6..fc6033f593cc 100644 --- a/library/src/scala/compat/java8/JProcedure12.java +++ b/library/src/scala/compat/java8/JProcedure12.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure12 extends JFunction12 { +public interface JProcedure12 extends JFunction12, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure13.java b/library/src/scala/compat/java8/JProcedure13.java index 4db2cd866931..8db24920b21c 100644 --- a/library/src/scala/compat/java8/JProcedure13.java +++ b/library/src/scala/compat/java8/JProcedure13.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure13 extends JFunction13 { +public interface JProcedure13 extends JFunction13, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure14.java b/library/src/scala/compat/java8/JProcedure14.java index 9d1c4b89faa2..7cc807a87d9d 100644 --- a/library/src/scala/compat/java8/JProcedure14.java +++ b/library/src/scala/compat/java8/JProcedure14.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure14 extends JFunction14 { +public interface JProcedure14 extends JFunction14, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure15.java b/library/src/scala/compat/java8/JProcedure15.java index c49f042e7158..456671e5d004 100644 --- a/library/src/scala/compat/java8/JProcedure15.java +++ b/library/src/scala/compat/java8/JProcedure15.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure15 extends JFunction15 { +public interface JProcedure15 extends JFunction15, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure16.java b/library/src/scala/compat/java8/JProcedure16.java index aad602dfa972..cb06658e4c68 100644 --- a/library/src/scala/compat/java8/JProcedure16.java +++ b/library/src/scala/compat/java8/JProcedure16.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure16 extends JFunction16 { +public interface JProcedure16 extends JFunction16, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure17.java b/library/src/scala/compat/java8/JProcedure17.java index cdc30b9ee7a6..7924877ced54 100644 --- a/library/src/scala/compat/java8/JProcedure17.java +++ b/library/src/scala/compat/java8/JProcedure17.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure17 extends JFunction17 { +public interface JProcedure17 extends JFunction17, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure18.java b/library/src/scala/compat/java8/JProcedure18.java index 2e03d8f807de..dec8ee18382f 100644 --- a/library/src/scala/compat/java8/JProcedure18.java +++ b/library/src/scala/compat/java8/JProcedure18.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure18 extends JFunction18 { +public interface JProcedure18 extends JFunction18, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure19.java b/library/src/scala/compat/java8/JProcedure19.java index 5e4fcb9aa1e3..ce92050b67e6 100644 --- a/library/src/scala/compat/java8/JProcedure19.java +++ b/library/src/scala/compat/java8/JProcedure19.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure19 extends JFunction19 { +public interface JProcedure19 extends JFunction19, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure2.java b/library/src/scala/compat/java8/JProcedure2.java index 36e84d8ddd98..256cb0efa00e 100644 --- a/library/src/scala/compat/java8/JProcedure2.java +++ b/library/src/scala/compat/java8/JProcedure2.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure2 extends JFunction2 { +public interface JProcedure2 extends JFunction2, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure20.java b/library/src/scala/compat/java8/JProcedure20.java index d6598c312ab2..11dbda1b0712 100644 --- a/library/src/scala/compat/java8/JProcedure20.java +++ b/library/src/scala/compat/java8/JProcedure20.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure20 extends JFunction20 { +public interface JProcedure20 extends JFunction20, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure21.java b/library/src/scala/compat/java8/JProcedure21.java index c85cb540cef2..e59b6074768e 100644 --- a/library/src/scala/compat/java8/JProcedure21.java +++ b/library/src/scala/compat/java8/JProcedure21.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure21 extends JFunction21 { +public interface JProcedure21 extends JFunction21, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure22.java b/library/src/scala/compat/java8/JProcedure22.java index a1653ae61140..2a39864e1ef6 100644 --- a/library/src/scala/compat/java8/JProcedure22.java +++ b/library/src/scala/compat/java8/JProcedure22.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure22 extends JFunction22 { +public interface JProcedure22 extends JFunction22, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure3.java b/library/src/scala/compat/java8/JProcedure3.java index f2b1e498a565..ed13ae0d6b03 100644 --- a/library/src/scala/compat/java8/JProcedure3.java +++ b/library/src/scala/compat/java8/JProcedure3.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure3 extends JFunction3 { +public interface JProcedure3 extends JFunction3, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure4.java b/library/src/scala/compat/java8/JProcedure4.java index 7a3457b57069..d4840458fd99 100644 --- a/library/src/scala/compat/java8/JProcedure4.java +++ b/library/src/scala/compat/java8/JProcedure4.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure4 extends JFunction4 { +public interface JProcedure4 extends JFunction4, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure5.java b/library/src/scala/compat/java8/JProcedure5.java index e9d25854ae76..c8e9f7e1bd4a 100644 --- a/library/src/scala/compat/java8/JProcedure5.java +++ b/library/src/scala/compat/java8/JProcedure5.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure5 extends JFunction5 { +public interface JProcedure5 extends JFunction5, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure6.java b/library/src/scala/compat/java8/JProcedure6.java index d1675bd24410..15f0adf9f348 100644 --- a/library/src/scala/compat/java8/JProcedure6.java +++ b/library/src/scala/compat/java8/JProcedure6.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure6 extends JFunction6 { +public interface JProcedure6 extends JFunction6, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure7.java b/library/src/scala/compat/java8/JProcedure7.java index 1348e051bef3..f81ae878acf9 100644 --- a/library/src/scala/compat/java8/JProcedure7.java +++ b/library/src/scala/compat/java8/JProcedure7.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure7 extends JFunction7 { +public interface JProcedure7 extends JFunction7, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure8.java b/library/src/scala/compat/java8/JProcedure8.java index df944ca6e87a..77bfec22802e 100644 --- a/library/src/scala/compat/java8/JProcedure8.java +++ b/library/src/scala/compat/java8/JProcedure8.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure8 extends JFunction8 { +public interface JProcedure8 extends JFunction8, java.io.Serializable { default void $init$() { } diff --git a/library/src/scala/compat/java8/JProcedure9.java b/library/src/scala/compat/java8/JProcedure9.java index 47ad5d23425f..ebeb59f522ed 100644 --- a/library/src/scala/compat/java8/JProcedure9.java +++ b/library/src/scala/compat/java8/JProcedure9.java @@ -8,7 +8,7 @@ import scala.runtime.BoxedUnit; @FunctionalInterface -public interface JProcedure9 extends JFunction9 { +public interface JProcedure9 extends JFunction9, java.io.Serializable { default void $init$() { } diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index befe2dd433d3..9106d9f5304a 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -79,10 +79,10 @@ class ExtractUsedNamesSpecification { val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB, srcC, srcD) val scalaVersion = scala.util.Properties.versionNumberString val namesA = standardNames ++ Set("Nothing", "Any") - val namesAX = standardNames ++ Set("x", "T", "A", "Nothing", "Any") + val namesAX = standardNames ++ objectStandardNames ++ Set("x", "T", "A", "Nothing", "Any", "scala") val namesB = Set("A", "Int", "A;init;", "Unit") - val namesC = Set("B;init;", "B", "Unit") - val namesD = standardNames ++ Set("C", "X", "foo", "Int", "T") + val namesC = objectStandardNames ++ Set("B;init;", "B", "Unit") + val namesD = standardNames ++ objectStandardNames ++ Set("C", "X", "foo", "Int", "T") assertEquals(namesA, usedNames("A")) assertEquals(namesAX, usedNames("A.X")) assertEquals(namesB, usedNames("B")) @@ -130,23 +130,30 @@ class ExtractUsedNamesSpecification { |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(src1, src2) - val expectedNames_lista = standardNames ++ Set("B", "lista", "List", "A") - val expectedNames_at = standardNames ++ Set("B", "at", "A", "T", "X0", "X1") - val expectedNames_as = standardNames ++ Set("B", "as", "S", "Y") - val expectedNames_foo = standardNames ++ Set("B", - "foo", - "M", - "N", - "Predef", - "???", - "Nothing") - val expectedNames_bar = standardNames ++ Set("B", - "bar", - "P1", - "P0", - "Predef", - "???", - "Nothing") + val expectedNames_lista = + standardNames ++ objectStandardNames ++ Set("B", "lista", "List", "A") + val expectedNames_at = + standardNames ++ objectStandardNames ++ Set("B", "at", "A", "T", "X0", "X1") + val expectedNames_as = + standardNames ++ objectStandardNames ++ Set("B", "as", "S", "Y") + val expectedNames_foo = + standardNames ++ objectStandardNames ++ + Set("B", + "foo", + "M", + "N", + "Predef", + "???", + "Nothing") + val expectedNames_bar = + standardNames ++ objectStandardNames ++ + Set("B", + "bar", + "P1", + "P0", + "Predef", + "???", + "Nothing") assertEquals(expectedNames_lista, usedNames("Test_lista")) assertEquals(expectedNames_at, usedNames("Test_at")) assertEquals(expectedNames_as, usedNames("Test_as")) @@ -167,7 +174,7 @@ class ExtractUsedNamesSpecification { |""".stripMargin val compilerForTesting = new ScalaCompilerForUnitTesting val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcFoo, srcBar) - val expectedNames = standardNames ++ Set("Outer", "TypeInner", "Inner", "Int") + val expectedNames = standardNames ++ objectStandardNames ++ Set("Outer", "TypeInner", "Inner", "Int") assertEquals(expectedNames, usedNames("Bar")) } @@ -302,4 +309,9 @@ class ExtractUsedNamesSpecification { // the return type of the default constructor is Unit "Unit" ) + + private val objectStandardNames = Set( + // all Dotty objects extend scala.Serializable + "scala", "Serializable" + ) } diff --git a/scala-backend b/scala-backend index 9ef70dd9b9ee..1447a7fbbc5d 160000 --- a/scala-backend +++ b/scala-backend @@ -1 +1 @@ -Subproject commit 9ef70dd9b9eeec11cfb72dabb57c61198fa18a20 +Subproject commit 1447a7fbbc5dd51a5e561c57bc873576e1ba542c diff --git a/tests/neg/duplicate-parents.scala b/tests/neg/duplicate-parents.scala new file mode 100644 index 000000000000..810b7cdc669e --- /dev/null +++ b/tests/neg/duplicate-parents.scala @@ -0,0 +1,2 @@ +case class Foo1(x: Int) extends Serializable with Serializable // error +case class Foo2(x: Int) extends scala.Serializable with Serializable // error diff --git a/tests/pos/duplicate-parents.scala b/tests/pos/duplicate-parents.scala new file mode 100644 index 000000000000..1f4625cd40eb --- /dev/null +++ b/tests/pos/duplicate-parents.scala @@ -0,0 +1,14 @@ +case class Foo1(x: Int) extends Serializable +case class Foo2(x: Int) extends scala.Serializable +case class Foo3(x: Int) extends Product + +case object Foo4 extends Serializable + +object Scope { + class Serializable + case class Foo5(x: Int) extends Serializable + + val f = Foo5(1) + f: Scope.Serializable + f: scala.Serializable +} diff --git a/tests/run/inlineAddDeserializeLambda.scala b/tests/run/inlineAddDeserializeLambda.scala new file mode 100644 index 000000000000..0b97b2583ef0 --- /dev/null +++ b/tests/run/inlineAddDeserializeLambda.scala @@ -0,0 +1,20 @@ +class C { inline final def f: Int => Int = (x: Int) => x + 1 } + +object Test extends App { + import java.io._ + + def serialize(obj: AnyRef): Array[Byte] = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + buffer.toByteArray + } + def deserialize(a: Array[Byte]): AnyRef = { + val in = new ObjectInputStream(new ByteArrayInputStream(a)) + in.readObject + } + + def serializeDeserialize[T <: AnyRef](obj: T) = deserialize(serialize(obj)).asInstanceOf[T] + + assert(serializeDeserialize((new C).f).isInstanceOf[Function1[_, _]]) +} diff --git a/tests/run/lambda-serialization-gc.scala b/tests/run/lambda-serialization-gc.scala new file mode 100644 index 000000000000..4d156c421013 --- /dev/null +++ b/tests/run/lambda-serialization-gc.scala @@ -0,0 +1,40 @@ +import java.io._ + +import java.net.URLClassLoader + +class C { + def serializeDeserialize[T <: AnyRef](obj: T) = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } + + serializeDeserialize((c: String) => c.length) +} + +object Test { + def main(args: Array[String]): Unit = { + test() + } + + def test(): Unit = { + val loader = getClass.getClassLoader.asInstanceOf[URLClassLoader] + val loaderCClass = classOf[C] + def deserializedInThrowawayClassloader = { + val throwawayLoader: java.net.URLClassLoader = new java.net.URLClassLoader(loader.getURLs, ClassLoader.getSystemClassLoader) { + val maxMemory = Runtime.getRuntime.maxMemory() + val junk = new Array[Long]((maxMemory / 8 / 4).toInt) + } + val clazz = throwawayLoader.loadClass("C") + assert(clazz != loaderCClass) + clazz.newInstance() + } + (1 to 5) foreach { i => + // This would OOM by the fifth iteration if we leaked `throwawayLoader` during + // deserialization. + deserializedInThrowawayClassloader + } + } +} diff --git a/tests/run/lambda-serialization-others.scala b/tests/run/lambda-serialization-others.scala new file mode 100644 index 000000000000..38b63d499e7d --- /dev/null +++ b/tests/run/lambda-serialization-others.scala @@ -0,0 +1,67 @@ +import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream, PrintWriter, StringWriter} +import java.lang.invoke.{MethodHandleInfo, SerializedLambda} + +class C1 { + val xxlfun = ((x1: Int, + x2: String, + x3: Int, + x4: Int, + x5: Int, + x6: Int, + x7: Int, + x8: Int, + x9: Int, + x10: Int, + x11: Int, + x12: Int, + x13: Int, + x14: Int, + x15: Int, + x16: Int, + x17: Int, + x18: Int, + x19: Int, + x20: Int, + x21: Int, + x22: Int, + x23: Int, + x24: Int, + x25: Int, + x26: Int) => x2 + x1) + + val depfun: (x1: Int) => List[x1.type] = x1 => List(x1) + + val erasedfun: erased Int => Int = erased (x1) => 0 +} + +class C2 + extends Serializable /* Needed because of #5866 */ { + val impfun: given Int => Int = given x1 => x1 + + val impdepfun: given (x1: Int) => List[x1.type] = given x1 => List(x1) + + val erasedimpfun: given erased Int => Int = given erased (x1) => 0 +} + +object Test { + def main(args: Array[String]): Unit = { + val c1 = new C1 + serializeDeserialize(c1.xxlfun) + serializeDeserialize(c1.erasedfun) + + val c2 = new C2 + serializeDeserialize[given Int => Int](c2.impfun) + // Won't compile until #5841 is merged + // serializeDeserialize[given Int => Int](c2.impdepfun) + serializeDeserialize[given Int => Int](c2.erasedimpfun) + } + + def serializeDeserialize[T <: AnyRef](obj: T): Unit = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} + diff --git a/tests/run/lambda-serialization-security.scala b/tests/run/lambda-serialization-security.scala new file mode 100644 index 000000000000..08e235b1cb9b --- /dev/null +++ b/tests/run/lambda-serialization-security.scala @@ -0,0 +1,47 @@ +import java.io.{ByteArrayInputStream, ObjectInputStream, ObjectOutputStream, ByteArrayOutputStream} + +trait IntToString extends java.io.Serializable { def apply(i: Int): String } + +object Test { + def main(args: Array[String]): Unit = { + roundTrip() + roundTripIndySam() + } + + def roundTrip(): Unit = { + val c = new Capture("Capture") + val lambda = (p: Param) => ("a", p, c) + val reconstituted1 = serializeDeserialize(lambda).asInstanceOf[Object => Any] + val p = new Param + assert(reconstituted1.apply(p) == ("a", p, c)) + val reconstituted2 = serializeDeserialize(lambda).asInstanceOf[Object => Any] + assert(reconstituted1.getClass == reconstituted2.getClass) + + val reconstituted3 = serializeDeserialize(reconstituted1) + assert(reconstituted3.apply(p) == ("a", p, c)) + + val specializedLambda = (p: Int) => List(p, c).length + assert(serializeDeserialize(specializedLambda).apply(42) == 2) + assert(serializeDeserialize(serializeDeserialize(specializedLambda)).apply(42) == 2) + } + + // lambda targeting a SAM, not a FunctionN (should behave the same way) + def roundTripIndySam(): Unit = { + val lambda: IntToString = (x: Int) => "yo!" * x + val reconstituted1 = serializeDeserialize(lambda).asInstanceOf[IntToString] + val reconstituted2 = serializeDeserialize(reconstituted1).asInstanceOf[IntToString] + assert(reconstituted1.apply(2) == "yo!yo!") + assert(reconstituted1.getClass == reconstituted2.getClass) + } + + def serializeDeserialize[T <: AnyRef](obj: T) = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } +} + +case class Capture(s: String) extends Serializable +class Param diff --git a/tests/run/lambda-serialization.scala b/tests/run/lambda-serialization.scala new file mode 100644 index 000000000000..e1419c5ff394 --- /dev/null +++ b/tests/run/lambda-serialization.scala @@ -0,0 +1,66 @@ +import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream, PrintWriter, StringWriter} +import java.lang.invoke.{MethodHandleInfo, SerializedLambda} + +class C extends java.io.Serializable { + val fs = List( + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => (), + () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => (), () => () ,() => (), () => (), () => (), () => (), () => () + ) + private def foo(): Unit = { + assert(false, "should not be called!!!") + } +} + +trait FakeSam { def apply(): Unit } + +object Test { + def main(args: Array[String]): Unit = { + allRealLambdasRoundTrip() + fakeLambdaFailsToDeserialize() + } + + def allRealLambdasRoundTrip(): Unit = { + new C().fs.map(x => serializeDeserialize(x).apply()) + } + + def fakeLambdaFailsToDeserialize(): Unit = { + val fake = new SerializedLambda(classOf[C], classOf[FakeSam].getName, "apply", "()V", + MethodHandleInfo.REF_invokeVirtual, classOf[C].getName, "foo", "()V", "()V", Array(new C)) + try { + serializeDeserialize(fake).asInstanceOf[FakeSam].apply() + assert(false) + } catch { + case ex: Exception => + val stackTrace = stackTraceString(ex) + assert(stackTrace.contains("Illegal lambda deserialization"), stackTrace) + } + } + + def serializeDeserialize[T <: AnyRef](obj: T) = { + val buffer = new ByteArrayOutputStream + val out = new ObjectOutputStream(buffer) + out.writeObject(obj) + val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray)) + in.readObject.asInstanceOf[T] + } + + def stackTraceString(ex: Throwable): String = { + val writer = new StringWriter + ex.printStackTrace(new PrintWriter(writer)) + writer.toString + } +} + diff --git a/tests/run/serialization-new.check b/tests/run/serialization-new.check new file mode 100644 index 000000000000..40646e993a0b --- /dev/null +++ b/tests/run/serialization-new.check @@ -0,0 +1,283 @@ +a1 = Array[1,2,3] +_a1 = Array[1,2,3] +arrayEquals(a1, _a1): true + +e1 = Left(1) +_e1 = Left(1) +e1 eq _e1: false, _e1 eq e1: false +e1 equals _e1: true, _e1 equals e1: true + +x7 = RoundingMode +y7 = RoundingMode +x7 eq y7: true, y7 eq x7: true +x7 equals y7: true, y7 equals x7: true + +x8 = WeekDay +y8 = WeekDay +x8 eq y8: true, y8 eq x8: true +x8 equals y8: true, y8 equals x8: true + +x9 = UP +y9 = UP +x9 eq y9: true, y9 eq x9: true +x9 equals y9: true, y9 equals x9: true + +x10 = Monday +y10 = Monday +x10 eq y10: true, y10 eq x10: true +x10 equals y10: true, y10 equals x10: true + +x9 eq x10: false, x10 eq x9: false +x9 equals x10: false, x10 equals x9: false +x9 eq y10: false, y10 eq x9: false +x9 equals y10: false, y10 equals x9: false + +f1 = +_f1 = +f1(2): 4, _f1(2): 4 + +xs0 = List(1, 2, 3) +_xs0 = List(1, 2, 3) +xs0 eq _xs0: false, _xs0 eq xs0: false +xs0 equals _xs0: true, _xs0 equals xs0: true + +xs1 = List() +_xs1 = List() +xs1 eq _xs1: true, _xs1 eq xs1: true + +o1 = None +_o1 = None +o1 eq _o1: true, _o1 eq o1: true + +o2 = Some(1) +_o2 = Some(1) +o2 eq _o2: false, _o2 eq o2: false +o2 equals _o2: true, _o2 equals o2: true + +s1 = 'hello +_s1 = 'hello +s1 eq _s1: true, _s1 eq s1: true +s1 equals _s1: true, _s1 equals s1: true + +t1 = (BannerLimit,12345) +_t1 = (BannerLimit,12345) +t1 eq _t1: false, _t1 eq t1: false +t1 equals _t1: true, _t1 equals t1: true + +x = BitSet(1, 2) +y = BitSet(1, 2) +x equals y: true, y equals x: true + +x = BitSet(2, 3) +y = BitSet(2, 3) +x equals y: true, y equals x: true + +x = Map(1 -> A, 2 -> B, 3 -> C) +y = Map(1 -> A, 2 -> B, 3 -> C) +x equals y: true, y equals x: true + +x = Set(1, 2) +y = Set(1, 2) +x equals y: true, y equals x: true + +x = List((buffers,20), (layers,2), (title,3)) +y = List((buffers,20), (layers,2), (title,3)) +x equals y: true, y equals x: true + +x = ListMap(buffers -> 20, layers -> 2, title -> 3) +y = ListMap(buffers -> 20, layers -> 2, title -> 3) +x equals y: true, y equals x: true + +x = ListSet(3, 5) +y = ListSet(3, 5) +x equals y: true, y equals x: true + +x = Queue(a, b, c) +y = Queue(a, b, c) +x equals y: true, y equals x: true + +x = Range 0 until 10 +y = Range 0 until 10 +x equals y: true, y equals x: true + +x = NumericRange 0 until 10 +y = NumericRange 0 until 10 +x equals y: true, y equals x: true + +x = Map(1 -> A, 2 -> B, 3 -> C) +y = Map(1 -> A, 2 -> B, 3 -> C) +x equals y: true, y equals x: true + +x = TreeSet(1, 2, 3) +y = TreeSet(1, 2, 3) +x equals y: true, y equals x: true + +x = Stack(c, b, a) +y = Stack(c, b, a) +x equals y: true, y equals x: true + +x = Stream(0, ?) +y = Stream(0, ?) +x equals y: true, y equals x: true + +x = Map(42 -> FortyTwo) +y = Map(42 -> FortyTwo) +x equals y: true, y equals x: true + +x = TreeSet(0, 2) +y = TreeSet(0, 2) +x equals y: true, y equals x: true + +x = Vector('a, 'b, 'c) +y = Vector('a, 'b, 'c) +x equals y: true, y equals x: true + +x = ArrayBuffer(one, two) +y = ArrayBuffer(one, two) +x equals y: true, y equals x: true + +x = ArrayBuilder.ofLong +y = ArrayBuilder.ofLong +x equals y: true, y equals x: true + +x = ArrayBuilder.ofFloat +y = ArrayBuilder.ofFloat +x equals y: true, y equals x: true + +x = ArraySeq(1, 2, 3) +y = ArraySeq(1, 2, 3) +x equals y: true, y equals x: true + +x = ArrayStack(3, 2, 20) +y = ArrayStack(3, 2, 20) +x equals y: true, y equals x: true + +x = BitSet(0, 8, 9) +y = BitSet(0, 8, 9) +x equals y: true, y equals x: true + +x = Map(A -> 1, C -> 3, B -> 2) +y = Map(A -> 1, C -> 3, B -> 2) +x equals y: true, y equals x: true + +x = Set(buffers, title, layers) +y = Set(buffers, title, layers) +x equals y: true, y equals x: true + +x = History() +y = History() +x equals y: true, y equals x: true + +x = Map(Linked -> 1, Hash -> 2, Map -> 3) +y = Map(Linked -> 1, Hash -> 2, Map -> 3) +x equals y: true, y equals x: true + +x = ArrayBuffer((Linked,1), (Hash,2), (Map,3)) +y = ArrayBuffer((Linked,1), (Hash,2), (Map,3)) +x equals y: true, y equals x: true + +x = ArrayBuffer((Linked,1), (Hash,2), (Map,3)) +y = List((Linked,1), (Hash,2), (Map,3)) +x equals y: true, y equals x: true + +x = Set(layers, buffers, title) +y = Set(layers, buffers, title) +x equals y: true, y equals x: true + +x = ArrayBuffer(layers, buffers, title) +y = ArrayBuffer(layers, buffers, title) +x equals y: true, y equals x: true + +x = ArrayBuffer(layers, buffers, title) +y = List(layers, buffers, title) +x equals y: true, y equals x: true + +x = ListBuffer(white, black) +y = ListBuffer(white, black) +x equals y: true, y equals x: true + +x = Queue(20, 2, 3) +y = Queue(20, 2, 3) +x equals y: true, y equals x: true + +x = Stack(3, 2, 20) +y = Stack(3, 2, 20) +x equals y: true, y equals x: true + +x = abc +y = abc +x equals y: true, y equals x: true + +x = WrappedArray(1, 2, 3) +y = WrappedArray(1, 2, 3) +x equals y: true, y equals x: true + +x = TreeSet(1, 2, 3) +y = TreeSet(1, 2, 3) +x equals y: true, y equals x: true + +x = TrieMap(1 -> one, 2 -> two, 3 -> three) +y = TrieMap(1 -> one, 2 -> two, 3 -> three) +x equals y: true, y equals x: true + +x = Tim +y = Tim +x equals y: true, y equals x: true + +x = Bob +y = Bob +x equals y: true, y equals x: true + +x = John +y = John +x equals y: true, y equals x: true + +x = Bill +y = Bill +x equals y: true, y equals x: true + +x = Paul +y = Paul +x equals y: true, y equals x: true + +1 +2 +1 +2 + +x = UnrolledBuffer(one, two) +y = UnrolledBuffer(one, two) +x equals y: true, y equals x: true + +x = ParArray(abc, def, etc) +y = ParArray(abc, def, etc) +x equals y: true, y equals x: true + +x = ParHashMap(2 -> 4, 1 -> 2) +y = ParHashMap(2 -> 4, 1 -> 2) +x equals y: true, y equals x: true + +x = ParTrieMap(1 -> 2, 2 -> 4) +y = ParTrieMap(1 -> 2, 2 -> 4) +x equals y: true, y equals x: true + +x = ParHashSet(1, 2, 3) +y = ParHashSet(1, 2, 3) +x equals y: true, y equals x: true + +x = ParRange 0 to 4 +y = ParRange 0 to 4 +x equals y: true, y equals x: true + +x = ParRange 0 until 4 +y = ParRange 0 until 4 +x equals y: true, y equals x: true + +x = ParMap(5 -> 1, 10 -> 2) +y = ParMap(5 -> 1, 10 -> 2) +x equals y: true, y equals x: true + +x = ParSet(two, one) +y = ParSet(two, one) +x equals y: true, y equals x: true + diff --git a/tests/run/serialization-new.scala b/tests/run/serialization-new.scala new file mode 100644 index 000000000000..8da9d4b3db30 --- /dev/null +++ b/tests/run/serialization-new.scala @@ -0,0 +1,622 @@ +//############################################################################ +// Serialization +//############################################################################ + +object Serialize { + @throws(classOf[java.io.IOException]) + def write[A](o: A): Array[Byte] = { + val ba = new java.io.ByteArrayOutputStream(512) + val out = new java.io.ObjectOutputStream(ba) + out.writeObject(o) + out.close() + ba.toByteArray() + } + @throws(classOf[java.io.IOException]) + @throws(classOf[ClassNotFoundException]) + def read[A](buffer: Array[Byte]): A = { + val in = + new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(buffer)) + in.readObject().asInstanceOf[A] + } + def check[A, B](x: A, y: B): Unit = { + println("x = " + x) + println("y = " + y) + println("x equals y: " + (x equals y) + ", y equals x: " + (y equals x)) + assert((x equals y) && (y equals x)) + println() + } +} +import Serialize._ + +//############################################################################ +// Test classes in package "scala" + +object Test1_scala { + + private def arrayToString[A](arr: Array[A]): String = + arr.mkString("Array[",",","]") + + private def arrayEquals[A, B](a1: Array[A], a2: Array[B]): Boolean = + (a1.length == a2.length) && + (Iterator.range(0, a1.length) forall { i => a1(i) == a2(i) }) + + object WeekDay extends Enumeration { + type WeekDay = Value + val Monday, Tuesday, Wednesday, Thusday, Friday, Saturday, Sunday = Value + } + import WeekDay._, BigDecimal._, RoundingMode._ + + // in alphabetic order + try { + // Array + val a1 = Array(1, 2, 3) + val _a1: Array[Int] = read(write(a1)) + println("a1 = " + arrayToString(a1)) + println("_a1 = " + arrayToString(_a1)) + println("arrayEquals(a1, _a1): " + arrayEquals(a1, _a1)) + println() + + // Either + val e1 = Left(1) + val _e1: Either[Int, String] = read(write(e1)) + println("e1 = " + e1) + println("_e1 = " + _e1) + println("e1 eq _e1: " + (e1 eq _e1) + ", _e1 eq e1: " + (_e1 eq e1)) + println("e1 equals _e1: " + (e1 equals _e1) + ", _e1 equals e1: " + (_e1 equals e1)) + println() + + // Enumeration + val x7 = BigDecimal.RoundingMode + val y7: RoundingMode.type = read(write(x7)) + println("x7 = " + x7) + println("y7 = " + y7) + println("x7 eq y7: " + (x7 eq y7) + ", y7 eq x7: " + (y7 eq x7)) + println("x7 equals y7: " + (x7 equals y7) + ", y7 equals x7: " + (y7 equals x7)) + println() + + val x8 = WeekDay + val y8: WeekDay.type = read(write(x8)) + println("x8 = " + x8) + println("y8 = " + y8) + println("x8 eq y8: " + (x8 eq y8) + ", y8 eq x8: " + (y8 eq x8)) + println("x8 equals y8: " + (x8 equals y8) + ", y8 equals x8: " + (y8 equals x8)) + println() + + val x9 = UP + val y9: RoundingMode = read(write(x9)) + println("x9 = " + x9) + println("y9 = " + y9) + println("x9 eq y9: " + (x9 eq y9) + ", y9 eq x9: " + (y9 eq x9)) + println("x9 equals y9: " + (x9 equals y9) + ", y9 equals x9: " + (y9 equals x9)) + println() + + val x10 = Monday + val y10: WeekDay = read(write(x10)) + println("x10 = " + x10) + println("y10 = " + y10) + println("x10 eq y10: " + (x10 eq y10) + ", y10 eq x10: " + (y10 eq x10)) + println("x10 equals y10: " + (x10 equals y10) + ", y10 equals x10: " + (y10 equals x10)) + println() + + println("x9 eq x10: " + (x9 eq x10) + ", x10 eq x9: " + (x10 eq x9)) + println("x9 equals x10: " + (x9 equals x10) + ", x10 equals x9: " + (x10 equals x9)) + println("x9 eq y10: " + (x9 eq y10) + ", y10 eq x9: " + (y10 eq x9)) + println("x9 equals y10: " + (x9 equals y10) + ", y10 equals x9: " + (y10 equals x9)) + println() + + // Function + val f1 = { x: Int => 2 * x } + val _f1: Function[Int, Int] = read(write(f1)) + println("f1 = ") + println("_f1 = ") + println("f1(2): " + f1(2) + ", _f1(2): " + _f1(2)) + println() + + // List + val xs0 = List(1, 2, 3) + val _xs0: List[Int] = read(write(xs0)) + println("xs0 = " + xs0) + println("_xs0 = " + _xs0) + println("xs0 eq _xs0: " + (xs0 eq _xs0) + ", _xs0 eq xs0: " + (_xs0 eq xs0)) + println("xs0 equals _xs0: " + (xs0 equals _xs0) + ", _xs0 equals xs0: " + (_xs0 equals xs0)) + println() + + val xs1 = Nil + val _xs1: List[Nothing] = read(write(xs1)) + println("xs1 = " + xs1) + println("_xs1 = " + _xs1) + println("xs1 eq _xs1: " + (xs1 eq _xs1) + ", _xs1 eq xs1: " + (_xs1 eq xs1)) + println() + + // Option + val o1 = None + val _o1: Option[Nothing] = read(write(o1)) + println("o1 = " + o1) + println("_o1 = " + _o1) + println("o1 eq _o1: " + (o1 eq _o1) + ", _o1 eq o1: " + (_o1 eq o1)) + println() + + val o2 = Some(1) + val _o2: Option[Int] = read(write(o2)) + println("o2 = " + o2) + println("_o2 = " + _o2) + println("o2 eq _o2: " + (o2 eq _o2) + ", _o2 eq o2: " + (_o2 eq o2)) + println("o2 equals _o2: " + (o2 equals _o2) + ", _o2 equals o2: " + (_o2 equals o2)) + println() +/* + // Responder + val r1 = Responder.constant("xyz") + val _r1: Responder[String] = read(write(r1)) + check(r1, _r1) +*/ + // Symbol + val s1 = Symbol("hello") + val _s1: Symbol = read(write(s1)) + println("s1 = " + s1) + println("_s1 = " + _s1) + println("s1 eq _s1: " + (s1 eq _s1) + ", _s1 eq s1: " + (_s1 eq s1)) + println("s1 equals _s1: " + (s1 equals _s1) + ", _s1 equals s1: " + (_s1 equals s1)) + println() + + // Tuple + val t1 = ("BannerLimit", 12345) + val _t1: (String, Int) = read(write(t1)) + println("t1 = " + t1) + println("_t1 = " + _t1) + println("t1 eq _t1: " + (t1 eq _t1) + ", _t1 eq t1: " + (_t1 eq t1)) + println("t1 equals _t1: " + (t1 equals _t1) + ", _t1 equals t1: " + (_t1 equals t1)) + println() + } + catch { + case e: Exception => + println("Error in Test1_scala: " + e) + throw e + } +} + +//############################################################################ +// Test classes in package "scala.collection.immutable" + +object Test2_immutable { + import scala.collection.immutable.{ + BitSet, HashMap, HashSet, ListMap, ListSet, Queue, Range, SortedMap, + SortedSet, Stack, Stream, TreeMap, TreeSet, Vector} + + // in alphabetic order + try { + // BitSet + val bs1 = BitSet.empty + 1 + 2 + val _bs1: BitSet = read(write(bs1)) + check(bs1, _bs1) + + val bs2 = { + val bs = new collection.mutable.BitSet() + bs += 2; bs += 3 + bs.toImmutable + } + val _bs2: BitSet = read(write(bs2)) + check(bs2, _bs2) + + // HashMap + val hm1 = new HashMap[Int, String] + (1 -> "A", 2 -> "B", 3 -> "C") + val _hm1: HashMap[Int, String] = read(write(hm1)) + check(hm1, _hm1) + + // HashSet + val hs1 = new HashSet[Int] + 1 + 2 + val _hs1: HashSet[Int] = read(write(hs1)) + check(hs1, _hs1) + + // List + val xs1 = List(("buffers", 20), ("layers", 2), ("title", 3)) + val _xs1: List[(String, Int)] = read(write(xs1)) + check(xs1, _xs1) + + // ListMap + val lm1 = new ListMap[String, Int] + ("buffers" -> 20, "layers" -> 2, "title" -> 3) + val _lm1: ListMap[String, Int] = read(write(lm1)) + check(lm1, _lm1) + + // ListSet + val ls1 = new ListSet[Int] + 3 + 5 + val _ls1: ListSet[Int] = read(write(ls1)) + check(ls1, _ls1) + + // Queue + val q1 = Queue("a", "b", "c") + val _q1: Queue[String] = read(write(q1)) + check(q1, _q1) + + // Range + val r1 = 0 until 10 + val _r1: Range = read(write(r1)) + check(r1, _r1) + + val r2 = Range.Long(0L, 10L, 1) + val _r2: r2.type = read(write(r2)) + check(r2, _r2) + + // SortedMap + val sm1 = SortedMap.empty[Int, String] + (2 -> "B", 3 -> "C", 1 -> "A") + val _sm1: SortedMap[Int, String] = read(write(sm1)) + check(sm1, _sm1) + + // SortedSet + val ss1 = SortedSet.empty[Int] + 2 + 3 + 1 + val _ss1: SortedSet[Int] = read(write(ss1)) + check(ss1, _ss1) + + // Stack + val s1 = new Stack().push("a", "b", "c") + val _s1: Stack[String] = read(write(s1)) + check(s1, _s1) + + // Stream + val st1 = Stream.range(0, 10) + val _st1: Stream[Int] = read(write(st1)) + check(st1, _st1) + + // TreeMap + val tm1 = new TreeMap[Int, String] + (42 -> "FortyTwo") + val _tm1: TreeMap[Int, String] = read(write(tm1)) + check(tm1, _tm1) + + // TreeSet + val ts1 = new TreeSet[Int]() + 2 + 0 + val _ts1: TreeSet[Int] = read(write(ts1)) + check(ts1, _ts1) + + // Vector + val v1 = Vector(Symbol("a"), Symbol("b"), Symbol("c")) + val _v1: Vector[Symbol] = read(write(v1)) + check(v1, _v1) + } + catch { + case e: Exception => + println("Error in Test2_immutable: " + e) + throw e + } +} + +//############################################################################ +// Test classes in package "scala.collection.mutable" + +object Test3_mutable { + import scala.reflect.ClassTag + import scala.collection.mutable.{ + ArrayBuffer, ArrayBuilder, ArraySeq, ArrayStack, BitSet, DoubleLinkedList, + HashMap, HashSet, History, LinkedHashMap, LinkedHashSet, LinkedList, ListBuffer, + Publisher, Queue, Stack, StringBuilder, WrappedArray, TreeSet} + import scala.collection.concurrent.TrieMap + + // in alphabetic order + try { + // ArrayBuffer + val ab1 = new ArrayBuffer[String] + ab1 ++= List("one", "two") + val _ab1: ArrayBuffer[String] = read(write(ab1)) + check(ab1, _ab1) + + // ArrayBuilder + val abu1 = ArrayBuilder.make[Long] + val _abu1: ArrayBuilder[ClassTag[Long]] = read(write(abu1)) + check(abu1, _abu1) + + val abu2 = ArrayBuilder.make[Float] + val _abu2: ArrayBuilder[ClassTag[Float]] = read(write(abu2)) + check(abu2, _abu2) + + // ArraySeq + val aq1 = ArraySeq(1, 2, 3) + val _aq1: ArraySeq[Int] = read(write(aq1)) + check(aq1, _aq1) + + // ArrayStack + val as1 = new ArrayStack[Int] + as1 ++= List(20, 2, 3).iterator + val _as1: ArrayStack[Int] = read(write(as1)) + check(as1, _as1) + + // BitSet + val bs1 = new BitSet() + bs1 += 0 + bs1 += 8 + bs1 += 9 + val _bs1: BitSet = read(write(bs1)) + check(bs1, _bs1) +/* + // DoubleLinkedList + val dl1 = new DoubleLinkedList[Int](2, null) + dl1.append(new DoubleLinkedList(3, null)) + val _dl1: DoubleLinkedList[Int] = read(write(dl1)) + check(dl1, _dl1) +*/ + // HashMap + val hm1 = new HashMap[String, Int] + hm1 ++= List(("A", 1), ("B", 2), ("C", 3)).iterator + val _hm1: HashMap[String, Int] = read(write(hm1)) + check(hm1, _hm1) + + // HashSet + val hs1 = new HashSet[String] + hs1 ++= List("layers", "buffers", "title").iterator + val _hs1: HashSet[String] = read(write(hs1)) + check(hs1, _hs1) + + val h1 = new History[String, Int] + val _h1: History[String, Int] = read(write(h1)) + check(h1, _h1) + + // LinkedHashMap + { val lhm1 = new LinkedHashMap[String, Int] + val list = List(("Linked", 1), ("Hash", 2), ("Map", 3)) + lhm1 ++= list.iterator + val _lhm1: LinkedHashMap[String, Int] = read(write(lhm1)) + check(lhm1, _lhm1) + check(lhm1.toSeq, _lhm1.toSeq) // check elements order + check(lhm1.toSeq, list) // check elements order + } + + // LinkedHashSet + { val lhs1 = new LinkedHashSet[String] + val list = List("layers", "buffers", "title") + lhs1 ++= list.iterator + val _lhs1: LinkedHashSet[String] = read(write(lhs1)) + check(lhs1, _lhs1) + check(lhs1.toSeq, _lhs1.toSeq) // check elements order + check(lhs1.toSeq, list) // check elements order + } +/* + // LinkedList + val ll1 = new LinkedList[Int](2, null) + ll1.append(new LinkedList(3, null)) + val _ll1: LinkedList[Int] = read(write(ll1)) + check(ll1, _ll1) +*/ + // ListBuffer + val lb1 = new ListBuffer[String] + lb1 ++= List("white", "black") + val _lb1: ListBuffer[String] = read(write(lb1)) + check(lb1, _lb1) + + // Queue + val q1 = new Queue[Int] + q1 ++= List(20, 2, 3).iterator + val _q1: Queue[Int] = read(write(q1)) + check(q1, _q1) + + // Stack + val s1 = new Stack[Int] + s1 pushAll q1 + val _s1: Stack[Int] = read(write(s1)) + check(s1, _s1) + + // StringBuilder + val sb1 = new StringBuilder + sb1 append "abc" + val _sb1: StringBuilder = read(write(sb1)) + check(sb1, _sb1) + + // WrappedArray + val wa1 = WrappedArray.make(Array(1, 2, 3)) + val _wa1: WrappedArray[Int] = read(write(wa1)) + check(wa1, _wa1) + + // TreeSet + val ts1 = TreeSet[Int]() ++= Array(1, 2, 3) + val _ts1: TreeSet[Int] = read(write(ts1)) + check(ts1, _ts1) + + // concurrent.TrieMap + val ct1 = TrieMap[Int, String]() ++= Array(1 -> "one", 2 -> "two", 3 -> "three") + val _ct1: TrieMap[Int, String] = read(write(ct1)) + check(ct1, _ct1) + } + catch { + case e: Exception => + println("Error in Test3_mutable: " + e) + throw e + } +} + +//############################################################################ +// Test user-defined classes WITHOUT nesting + +class Person(_name: String) extends Serializable { + private var name = _name + override def toString() = name + override def equals(that: Any): Boolean = + that.isInstanceOf[Person] && + (name == that.asInstanceOf[Person].name) +} + +class Employee(_name: String) extends Serializable { + private var name = _name + override def toString() = name +} + +object bob extends Employee("Bob") + +object Test5 { + val x1 = new Person("Tim") + val x2 = bob + + try { + val y1: Person = read(write(x1)) + val y2: Employee = read(write(x2)) + + check(x1, y1) + check(x2, y2) + } + catch { + case e: Exception => + println("Error in Test5: " + e) + } +} + +//############################################################################ +// Test user-defined classes WITH nesting + +object Test6 { + object bill extends Employee("Bill") { + val x = paul + } + object paul extends Person("Paul") { + val x = 4 // bill; => StackOverflowException !!! + } + val x1 = new Person("John") + val x2 = bill + val x3 = paul + + try { + val y1: Person = read(write(x1)) + val y2: Employee = read(write(x2)) + val y3: Person = read(write(x3)) + + check(x1, y1) + check(x2, y2) + check(x3, y3) + } + catch { + case e: Exception => + println("Error in Test6: " + e) + } +} + +//############################################################################ +// Nested objects cannot get readresolve automatically because after deserialization +// they would be null (they are treated as lazy vals) +class Outer extends Serializable { + object Inner extends Serializable +} + +object Test7 { + val x = new Outer + val _ = x.Inner // initialize + val y:Outer = read(write(x)) + if (y.Inner == null) + println("Inner object is null") +} + +// Verify that transient lazy vals don't get serialized +class WithTransient extends Serializable { + @transient lazy val a1 = 1 + @transient private lazy val a2 = 2 + @transient object B extends Serializable + @transient private object C extends Serializable + + def test = { + println(a1) + println(a2) + if (B == null || C == null) + println("Transient nested object failed to serialize properly") + } +} + +object Test8 { + val x = new WithTransient + x.test + try { + val y:WithTransient = read(write(x)) + y.test + } + catch { + case e: Exception => + println("Error in Test8: " + e) + } +} + +//############################################################################ +// Test code + +object Test { + def main(args: Array[String]): Unit = { + Test1_scala + Test2_immutable + Test3_mutable + Test5 + Test6 + Test7 + Test8 + Test9_parallel + Test10_util + } +} + +//############################################################################ + + +//############################################################################ +// Test classes in package "scala.collection.parallel" and subpackages +object Test9_parallel { + import scala.collection.parallel._ + + try { + println() + + // UnrolledBuffer + val ub = new collection.mutable.UnrolledBuffer[String] + ub ++= List("one", "two") + val _ub: collection.mutable.UnrolledBuffer[String] = read(write(ub)) + check(ub, _ub) + + // mutable.ParArray + val pa = mutable.ParArray("abc", "def", "etc") + val _pa: mutable.ParArray[String] = read(write(pa)) + check(pa, _pa) + + // mutable.ParHashMap + val mpm = mutable.ParHashMap(1 -> 2, 2 -> 4) + val _mpm: mutable.ParHashMap[Int, Int] = read(write(mpm)) + check(mpm, _mpm) + + // mutable.ParTrieMap + val mpc = mutable.ParTrieMap(1 -> 2, 2 -> 4) + val _mpc: mutable.ParTrieMap[Int, Int] = read(write(mpc)) + check(mpc, _mpc) + + // mutable.ParHashSet + val mps = mutable.ParHashSet(1, 2, 3) + val _mps: mutable.ParHashSet[Int] = read(write(mps)) + check(mps, _mps) + + // immutable.ParRange + val pr1 = immutable.ParRange(0, 4, 1, true) + val _pr1: immutable.ParRange = read(write(pr1)) + check(pr1, _pr1) + + val pr2 = immutable.ParRange(0, 4, 1, false) + val _pr2: immutable.ParRange = read(write(pr2)) + check(pr2, _pr2) + + // immutable.ParHashMap + val ipm = immutable.ParHashMap(5 -> 1, 10 -> 2) + val _ipm: immutable.ParHashMap[Int, Int] = read(write(ipm)) + check(ipm, _ipm) + + // immutable.ParHashSet + val ips = immutable.ParHashSet("one", "two") + val _ips: immutable.ParHashSet[String] = read(write(ips)) + check(ips, _ips) + + } catch { + case e: Exception => + println("Error in Test5_parallel: " + e) + throw e + } +} + +//############################################################################ +// Test classes in package scala.util + +object Test10_util { + import scala.util.Random + def rep[A](n: Int)(f: => A): Unit = { if (n > 0) { f; rep(n-1)(f) } } + + { + val random = new Random(345) + val random2: Random = read(write(random)) + rep(5) { assert(random.nextInt == random2.nextInt) } + } +} + diff --git a/tests/run/t10232.scala b/tests/run/t10232.scala new file mode 100644 index 000000000000..3b3a8e7fad26 --- /dev/null +++ b/tests/run/t10232.scala @@ -0,0 +1,275 @@ +import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream} + +object Test { + val lambdas: List[Any => String] = List( + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" }, + { (t: Any) => "ab" } + ) + + def main(args: Array[String]): Unit = { + for (lambda <- lambdas) { + val outStream = new ByteArrayOutputStream + val oo = new ObjectOutputStream(outStream) + oo.writeObject(lambda) + + val inStream = new ByteArrayInputStream(outStream.toByteArray) + val oi = new ObjectInputStream(inStream) + val lambda2 = oi.readObject().asInstanceOf[Any => String] + assert(lambda2(1) == "ab") + } + } +} diff --git a/tests/run/t6260-delambdafy.check b/tests/run/t6260-delambdafy.check index b3ec1b3cc667..ed107b4c8132 100644 --- a/tests/run/t6260-delambdafy.check +++ b/tests/run/t6260-delambdafy.check @@ -2,3 +2,4 @@ f(C@2e) apply get$Lambda +writeReplace diff --git a/tests/run/tasty-extractors-2.check b/tests/run/tasty-extractors-2.check index d566b57c87dc..68b0372d7d9e 100644 --- a/tests/run/tasty-extractors-2.check +++ b/tests/run/tasty-extractors-2.check @@ -25,7 +25,7 @@ Type.OrType(Type.SymRef(IsClassSymbol(), Type.SymRef(IsPackageSymbol( Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, Nil)), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) -Term.Inlined(None, Nil, Term.Block(List(ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), ""), Nil))), ClassDef("Foo$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), Nil)), Term.Literal(Constant.Unit()))) +Term.Inlined(None, Nil, Term.Block(List(ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), ""), Nil))), ClassDef("Foo$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), Nil)), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) Term.Inlined(None, Nil, Term.Block(List(TypeDef("Foo", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred()))), Term.Literal(Constant.Unit()))) @@ -49,7 +49,7 @@ Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymb Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(DefDef("a", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0))))))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) -Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Product"), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, None, List(DefDef("hashCode", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Literal(Constant.Int(394005536)))), DefDef("equals", Nil, List(List(ValDef("x$0", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.Apply(Term.Select(Term.This(Some(Id("Foo"))), "eq"), List(Term.TypeApply(Term.Select(Term.Ident("x$0"), "asInstanceOf"), List(TypeTree.Inferred())))), "||"), List(Term.Match(Term.Ident("x$0"), List(CaseDef(Pattern.Bind("x$0", Pattern.TypeTest(TypeTree.Inferred())), None, Term.Literal(Constant.Boolean(true))), CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Literal(Constant.Boolean(false))))))))), DefDef("toString", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Ident("_toString"), List(Term.This(Some(Id("Foo"))))))), DefDef("canEqual", Nil, List(List(ValDef("that", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.TypeApply(Term.Select(Term.Ident("that"), "isInstanceOf"), List(TypeTree.Inferred())))), DefDef("productArity", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0)))), DefDef("productPrefix", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.String("Foo")))), DefDef("productElement", Nil, List(List(ValDef("n", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Match(Term.Ident("n"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), List(Term.Apply(Term.Select(Term.Ident("n"), "toString"), Nil)))))))))), DefDef("productElementName", Nil, List(List(ValDef("x$1", TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Int"), None))), TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "String"), Some(Term.Match(Term.Ident("x$1"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "IndexOutOfBoundsException")), ""), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("java"), "lang"), "String"), "valueOf"), List(Term.Ident("x$1")))))))))))), DefDef("copy", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil))))), ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), ""), Nil))), ClassDef("Foo$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Inferred()))), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), List(DefDef("apply", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil))), DefDef("unapply", Nil, List(List(ValDef("x$1", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Literal(Constant.Boolean(true))))))), Term.Literal(Constant.Unit()))) +Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Product"), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, None, List(DefDef("hashCode", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Literal(Constant.Int(394005536)))), DefDef("equals", Nil, List(List(ValDef("x$0", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.Apply(Term.Select(Term.This(Some(Id("Foo"))), "eq"), List(Term.TypeApply(Term.Select(Term.Ident("x$0"), "asInstanceOf"), List(TypeTree.Inferred())))), "||"), List(Term.Match(Term.Ident("x$0"), List(CaseDef(Pattern.Bind("x$0", Pattern.TypeTest(TypeTree.Inferred())), None, Term.Literal(Constant.Boolean(true))), CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Literal(Constant.Boolean(false))))))))), DefDef("toString", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Ident("_toString"), List(Term.This(Some(Id("Foo"))))))), DefDef("canEqual", Nil, List(List(ValDef("that", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.TypeApply(Term.Select(Term.Ident("that"), "isInstanceOf"), List(TypeTree.Inferred())))), DefDef("productArity", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(0)))), DefDef("productPrefix", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.String("Foo")))), DefDef("productElement", Nil, List(List(ValDef("n", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Match(Term.Ident("n"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), List(Term.Apply(Term.Select(Term.Ident("n"), "toString"), Nil)))))))))), DefDef("productElementName", Nil, List(List(ValDef("x$1", TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Int"), None))), TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "String"), Some(Term.Match(Term.Ident("x$1"), List(CaseDef(Pattern.Value(Term.Ident("_")), None, Term.Apply(Term.Ident("throw"), List(Term.Apply(Term.Select(Term.New(TypeTree.Select(Term.Select(Term.Ident("java"), "lang"), "IndexOutOfBoundsException")), ""), List(Term.Apply(Term.Select(Term.Select(Term.Select(Term.Ident("java"), "lang"), "String"), "valueOf"), List(Term.Ident("x$1")))))))))))), DefDef("copy", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil))))), ValDef("Foo", TypeTree.Ident("Foo$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo$")), ""), Nil))), ClassDef("Foo$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Applied(TypeTree.Inferred(), List(TypeTree.Inferred())), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo")), None)), List(DefDef("apply", Nil, List(Nil), TypeTree.Inferred(), Some(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil))), DefDef("unapply", Nil, List(List(ValDef("x$1", TypeTree.Inferred(), None))), TypeTree.Inferred(), Some(Term.Literal(Constant.Boolean(true))))))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo1", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None)))), Term.Literal(Constant.Unit()))) @@ -58,13 +58,13 @@ Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymb Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo2", DefDef("", Nil, List(List(ValDef("b", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("b", TypeTree.Inferred(), None)))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) -Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo3", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None))), ValDef("Foo3", TypeTree.Ident("Foo3$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo3$")), ""), Nil))), ClassDef("Foo3$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo3")), None)), List(DefDef("$lessinit$greater$default$1", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5))))))), Term.Literal(Constant.Unit()))) +Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo3", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None))), ValDef("Foo3", TypeTree.Ident("Foo3$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo3$")), ""), Nil))), ClassDef("Foo3$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo3")), None)), List(DefDef("$lessinit$greater$default$1", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5))))))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo4", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None)), List(ValDef("b", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None), ValDef("b", TypeTree.Inferred(), None)))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) -Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo5", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None)), List(ValDef("b", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None), ValDef("b", TypeTree.Inferred(), None))), ValDef("Foo5", TypeTree.Ident("Foo5$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo5$")), ""), Nil))), ClassDef("Foo5$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo5")), None)), List(DefDef("$lessinit$greater$default$2", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), Some(Term.Ident("a")))))), Term.Literal(Constant.Unit()))) +Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo5", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None)), List(ValDef("b", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None), ValDef("b", TypeTree.Inferred(), None))), ValDef("Foo5", TypeTree.Ident("Foo5$"), Some(Term.Apply(Term.Select(Term.New(TypeTree.Ident("Foo5$")), ""), Nil))), ClassDef("Foo5$", DefDef("", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil), TypeTree.Select(Term.Select(Term.Ident("_root_"), "scala"), "Serializable")), Nil, Some(ValDef("_", TypeTree.Singleton(Term.Ident("Foo5")), None)), List(DefDef("$lessinit$greater$default$2", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None))), TypeTree.Inferred(), Some(Term.Ident("a")))))), Term.Literal(Constant.Unit()))) Type.SymRef(IsClassSymbol(), Type.ThisType(Type.SymRef(IsPackageSymbol(), NoPrefix()))) Term.Inlined(None, Nil, Term.Block(List(ClassDef("Foo6", DefDef("", Nil, List(List(ValDef("a", TypeTree.Ident("Int"), None)), List(ValDef("b", TypeTree.Singleton(Term.Ident("a")), None))), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), ""), Nil)), Nil, None, List(ValDef("a", TypeTree.Inferred(), None), ValDef("b", TypeTree.Inferred(), None)))), Term.Literal(Constant.Unit())))