diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index cbe6ccf8ecd..848c241e38a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -49,7 +49,6 @@ import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument; @@ -411,72 +410,78 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private boolean isGenericToArrayPresent() { - Collection functions = - descriptor.getDefaultType().getMemberScope().getContributedFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND); - for (FunctionDescriptor function : functions) { - if (CallResolverUtilKt.isOrOverridesSynthesized(function)) { - continue; - } + private boolean isGenericToArray(@NotNull FunctionDescriptor function) { + if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { + return false; + } - if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { - continue; - } - - KotlinType returnType = function.getReturnType(); - assert returnType != null : function.toString(); - KotlinType paramType = function.getValueParameters().get(0).getType(); - if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) { - KotlinType elementType = function.getTypeParameters().get(0).getDefaultType(); - if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt.getBuiltIns(descriptor).getArrayElementType(returnType)) - && KotlinTypeChecker.DEFAULT.equalTypes(elementType, DescriptorUtilsKt - .getBuiltIns(descriptor).getArrayElementType(paramType))) { - return true; - } + KotlinType returnType = function.getReturnType(); + assert returnType != null : function.toString(); + KotlinType paramType = function.getValueParameters().get(0).getType(); + if (KotlinBuiltIns.isArray(returnType) && KotlinBuiltIns.isArray(paramType)) { + KotlinType elementType = function.getTypeParameters().get(0).getDefaultType(); + KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor); + if (KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(returnType)) + && KotlinTypeChecker.DEFAULT.equalTypes(elementType, builtIns.getArrayElementType(paramType))) { + return true; } } - return false; + return false; + } + + private static boolean isNonGenericToArray(@NotNull FunctionDescriptor function) { + if (!function.getValueParameters().isEmpty() || !function.getTypeParameters().isEmpty()) { + return false; + } + + KotlinType returnType = function.getReturnType(); + return returnType != null && KotlinBuiltIns.isArray(returnType); } private void generateToArray() { + if (descriptor.getKind() == ClassKind.INTERFACE) return; + KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor); if (!isSubclass(descriptor, builtIns.getCollection())) return; - int access = descriptor.getKind() == ClassKind.INTERFACE ? - ACC_PUBLIC | ACC_ABSTRACT : - ACC_PUBLIC; - if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) { - MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "()[Ljava/lang/Object;", null, null); - - if (descriptor.getKind() != ClassKind.INTERFACE) { - InstructionAdapter iv = new InstructionAdapter(mv); - mv.visitCode(); - - iv.load(0, classAsmType); - iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false); - iv.areturn(Type.getType("[Ljava/lang/Object;")); - - FunctionCodegen.endVisit(mv, "toArray", myClass); - } + Collection functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions( + Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND + ); + boolean hasGenericToArray = false; + boolean hasNonGenericToArray = false; + for (FunctionDescriptor function : functions) { + hasGenericToArray |= isGenericToArray(function); + hasNonGenericToArray |= isNonGenericToArray(function); } - if (!isGenericToArrayPresent()) { - MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); + if (!hasNonGenericToArray) { + MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null); - if (descriptor.getKind() != ClassKind.INTERFACE) { - InstructionAdapter iv = new InstructionAdapter(mv); - mv.visitCode(); + InstructionAdapter iv = new InstructionAdapter(mv); + mv.visitCode(); - iv.load(0, classAsmType); - iv.load(1, Type.getType("[Ljava/lang/Object;")); + iv.load(0, classAsmType); + iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false); + iv.areturn(Type.getType("[Ljava/lang/Object;")); - iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", - "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false); - iv.areturn(Type.getType("[Ljava/lang/Object;")); + FunctionCodegen.endVisit(mv, "toArray", myClass); + } - FunctionCodegen.endVisit(mv, "toArray", myClass); - } + if (!hasGenericToArray) { + MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); + + InstructionAdapter iv = new InstructionAdapter(mv); + mv.visitCode(); + + iv.load(0, classAsmType); + iv.load(1, Type.getType("[Ljava/lang/Object;")); + + iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", + "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false); + iv.areturn(Type.getType("[Ljava/lang/Object;")); + + FunctionCodegen.endVisit(mv, "toArray", myClass); } } diff --git a/compiler/testData/codegen/bytecodeListing/specialBridges/contains.txt b/compiler/testData/codegen/bytecodeListing/specialBridges/contains.txt index dda6a8dfc4d..187b18cbb76 100644 --- a/compiler/testData/codegen/bytecodeListing/specialBridges/contains.txt +++ b/compiler/testData/codegen/bytecodeListing/specialBridges/contains.txt @@ -122,8 +122,6 @@ public interface I1 { inner class I1$DefaultImpls public abstract method contains(p0: java.lang.Object): boolean public abstract method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean - public abstract method toArray(): java.lang.Object[] - public abstract method toArray(p0: java.lang.Object[]): java.lang.Object[] } @kotlin.Metadata @@ -138,6 +136,4 @@ public interface I2 { inner class I2$DefaultImpls public abstract method contains(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean public abstract method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean - public abstract method toArray(): java.lang.Object[] - public abstract method toArray(p0: java.lang.Object[]): java.lang.Object[] } \ No newline at end of file diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt index 47547114797..b0b6cc54f30 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib.txt @@ -2089,8 +2089,6 @@ public abstract interface class kotlin/text/MatchGroupCollection : java/util/Col public abstract fun remove (Lkotlin/text/MatchGroup;)Z public abstract fun removeAll (Ljava/util/Collection;)Z public abstract fun retainAll (Ljava/util/Collection;)Z - public abstract fun toArray ()[Ljava/lang/Object; - public abstract fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; } public abstract interface class kotlin/text/MatchResult {