diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt index 19e6fa14063..4a12951a295 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -157,45 +157,17 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : BaseImportingSc } } - override fun doSubstitute( - originalSubstitutor: TypeSubstitutor, - newOwner: DeclarationDescriptor, - newModality: Modality, - newVisibility: Visibility, - isOperator: Boolean, - isInfix: Boolean, - isExternal: Boolean, - isInline: Boolean, - isTailrec: Boolean, - hasStableParameterNames: Boolean, - hasSynthesizedParameterNames: Boolean, - original: FunctionDescriptor?, - copyOverrides: Boolean, - kind: CallableMemberDescriptor.Kind, - newValueParameterDescriptors: MutableList, - newExtensionReceiverParameterType: KotlinType?, - newReturnType: KotlinType, - name: Name?, - preserveSource: Boolean, - signatureChange: Boolean - ): FunctionDescriptor? { - val descriptor = super.doSubstitute( - originalSubstitutor, newOwner, newModality, newVisibility, - isOperator, isInfix, isExternal, isInline, isTailrec, hasStableParameterNames, hasSynthesizedParameterNames, original, - copyOverrides, kind, newValueParameterDescriptors, newExtensionReceiverParameterType, newReturnType, name, - preserveSource, signatureChange) - as MyFunctionDescriptor? ?: return null - - if (original == null) { - throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension") - } + override fun doSubstitute(configuration: CopyConfiguration): FunctionDescriptor? { + val descriptor = super.doSubstitute(configuration) as MyFunctionDescriptor? ?: return null + val original = configuration.original + ?: throw UnsupportedOperationException("doSubstitute with no original should not be called for synthetic extension") original as MyFunctionDescriptor assert(original.original == original) { "original in doSubstitute should have no other original" } val substitutionMap = HashMap() for (typeParameter in original.typeParameters) { - val typeProjection = originalSubstitutor.substitution[typeParameter.defaultType] ?: continue + val typeProjection = configuration.originalSubstitutor.substitution[typeParameter.defaultType] ?: continue val sourceTypeParameter = original.toSourceFunctionTypeParameters!![typeParameter]!! substitutionMap[sourceTypeParameter.typeConstructor] = typeProjection diff --git a/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.kt b/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.kt new file mode 100644 index 00000000000..ffc1f27d5dc --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.kt @@ -0,0 +1,15 @@ +// FILE: A.java + +import java.util.*; + +public interface A { + void foo(); +} + +// FILE: B.java + +public interface B extends A {} + +// FILE: k.kt + +class C(x: A) : A by x, B {} diff --git a/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.txt b/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.txt new file mode 100644 index 00000000000..3332cf4c4d9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.txt @@ -0,0 +1,23 @@ +package + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B : A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C : A, B { + public constructor C(/*0*/ x: A) + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*delegation*/ fun foo(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 3f1e36c6578..cab66426043 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -11370,6 +11370,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/platformTypes"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("delegateByComplexInheritance.kt") + public void testDelegateByComplexInheritance() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/delegateByComplexInheritance.kt"); + doTest(fileName); + } + @TestMetadata("dereference.kt") public void testDereference() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/dereference.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java index 82bdbc3b45c..5ec1fed9ff2 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeSubstitutor; import org.jetbrains.kotlin.util.OperatorChecks; import java.util.List; @@ -142,12 +141,13 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement // We use `doSubstitute` here because it does exactly what we need: // 1. creates full copy of descriptor // 2. copies method's type parameters (with new containing declaration) and properly substitute to them in value parameters, return type and etc. - JavaMethodDescriptor enhancedMethod = (JavaMethodDescriptor) doSubstitute( - TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), - isOperator(), isInfix(), isExternal(), isInline(), isTailrec(), hasStableParameterNames(), hasSynthesizedParameterNames(), - getOriginal(), /* copyOverrides = */ true, getKind(), - enhancedValueParameters, enhancedReceiverType, enhancedReturnType, - null, /* preserveSource */false, /* signatureChange = */ false); + JavaMethodDescriptor enhancedMethod = + (JavaMethodDescriptor) newCopyBuilder() + .setValueParameters(enhancedValueParameters) + .setReturnType(enhancedReturnType) + .setExtensionReceiverType(enhancedReceiverType) + .setOriginal(getOriginal()) + .build(); assert enhancedMethod != null : "null after substitution while enhancing " + toString(); return enhancedMethod; diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ConstructorDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ConstructorDescriptorImpl.java index 765e7b045ac..1267e541077 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ConstructorDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ConstructorDescriptorImpl.java @@ -147,10 +147,14 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @NotNull @Override public ConstructorDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) { + //noinspection ConstantConditions return (ConstructorDescriptor) doSubstitute( - TypeSubstitutor.EMPTY, newOwner, modality, visibility, - isOperator(), isInfix(), isExternal(), isInline(), isTailrec(), hasStableParameterNames(), hasSynthesizedParameterNames(), - null, copyOverrides, kind + newCopyBuilder() + .setOwner(newOwner) + .setModality(modality) + .setVisibility(visibility) + .setKind(kind) + .setCopyOverrides(copyOverrides) ); } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java index aec239db003..b35dbd9cbfb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java @@ -261,34 +261,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo if (originalSubstitutor.isEmpty()) { return this; } - return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, - isOperator, isInfix, isExternal, isInline, isTailrec, - hasStableParameterNames, hasSynthesizedParameterNames, - getOriginal(), true, getKind()); - } - - @Nullable - protected FunctionDescriptor doSubstitute(@NotNull TypeSubstitutor originalSubstitutor, - @NotNull DeclarationDescriptor newOwner, - @NotNull Modality newModality, - @NotNull Visibility newVisibility, - boolean isOperator, - boolean isInfix, - boolean isExternal, - boolean isInline, - boolean isTailrec, - boolean hasStableParameterNames, - boolean hasSynthesizedParameterNames, - @Nullable FunctionDescriptor original, - boolean copyOverrides, - @NotNull Kind kind - ) { - return doSubstitute(originalSubstitutor, - newOwner, newModality, newVisibility, isOperator, isInfix, isExternal, isInline, isTailrec, - hasStableParameterNames, hasSynthesizedParameterNames, - original, copyOverrides, kind, - getValueParameters(), getExtensionReceiverParameterType(), getReturnType(), - null, /* preserveSource = */ false, /* signatureChange */ false); + return doSubstitute(newCopyBuilder(originalSubstitutor).setOriginal(getOriginal())); } @Nullable @@ -297,41 +270,157 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo return extensionReceiverParameter.getType(); } + public class CopyConfiguration { + protected @NotNull TypeSubstitutor originalSubstitutor; + protected @NotNull DeclarationDescriptor newOwner; + protected @NotNull Modality newModality; + protected @NotNull Visibility newVisibility; + protected @Nullable FunctionDescriptor original = null; + protected @NotNull Kind kind; + protected @NotNull List newValueParameterDescriptors; + protected @Nullable KotlinType newExtensionReceiverParameterType; + protected @NotNull KotlinType newReturnType; + protected @Nullable Name name; + protected boolean copyOverrides; + protected boolean signatureChange; + + public CopyConfiguration( + @NotNull TypeSubstitutor originalSubstitutor, + @NotNull DeclarationDescriptor newOwner, + @NotNull Modality newModality, + @NotNull Visibility newVisibility, + @NotNull Kind kind, + @NotNull List newValueParameterDescriptors, + @Nullable KotlinType newExtensionReceiverParameterType, + @NotNull KotlinType newReturnType, + @Nullable Name name + ) { + this.originalSubstitutor = originalSubstitutor; + this.newOwner = newOwner; + this.newModality = newModality; + this.newVisibility = newVisibility; + this.kind = kind; + this.newValueParameterDescriptors = newValueParameterDescriptors; + this.newExtensionReceiverParameterType = newExtensionReceiverParameterType; + this.newReturnType = newReturnType; + this.name = name; + this.copyOverrides = true; + this.signatureChange = false; + } + + @NotNull + protected CopyConfiguration setOwner(@NotNull DeclarationDescriptor owner) { + this.newOwner = owner; + return this; + } + + @NotNull + public CopyConfiguration setModality(@NotNull Modality modality) { + this.newModality = modality; + return this; + } + + @NotNull + public CopyConfiguration setVisibility(@NotNull Visibility visibility) { + this.newVisibility = visibility; + return this; + } + + @NotNull + public CopyConfiguration setKind(@NotNull Kind kind) { + this.kind = kind; + return this; + } + + @NotNull + public CopyConfiguration setCopyOverrides(boolean copyOverrides) { + this.copyOverrides = copyOverrides; + return this; + } + + @NotNull + public CopyConfiguration setName(@NotNull Name name) { + this.name = name; + return this; + } + + @NotNull + public CopyConfiguration setValueParameters(@NotNull List parameters) { + this.newValueParameterDescriptors = parameters; + return this; + } + + @NotNull + public CopyConfiguration setTypeParameters(@NotNull List parameters) { + this.newTypeParameters = parameters; + return this; + } + + public CopyConfiguration setReturnType(@NotNull KotlinType type) { + this.newReturnType = type; + return this; + } + + public CopyConfiguration setExtensionReceiverType(@Nullable KotlinType type) { + this.newExtensionReceiverParameterType = type; + return this; + } + + @NotNull + public CopyConfiguration setOriginal(@NotNull FunctionDescriptor original) { + this.original = original; + return this; + } + + @NotNull + public CopyConfiguration setSignatureChange() { + this.signatureChange = true; + return this; + } + + public FunctionDescriptor build() { + return doSubstitute(this); + } + + @Nullable + public FunctionDescriptor getOriginal() { + return original; + } + + @NotNull + public TypeSubstitutor getOriginalSubstitutor() { + return originalSubstitutor; + } + } + + @NotNull + public CopyConfiguration newCopyBuilder() { + return newCopyBuilder(TypeSubstitutor.EMPTY); + } + + @NotNull + private CopyConfiguration newCopyBuilder(@NotNull TypeSubstitutor substitutor) { + return new CopyConfiguration( + substitutor, + getContainingDeclaration(), getModality(), getVisibility(), getKind(), getValueParameters(), + getExtensionReceiverParameterType(), getReturnType(), null); + } @Nullable - protected FunctionDescriptor doSubstitute( - @NotNull TypeSubstitutor originalSubstitutor, - @NotNull DeclarationDescriptor newOwner, - @NotNull Modality newModality, - @NotNull Visibility newVisibility, - boolean isOperator, - boolean isInfix, - boolean isExternal, - boolean isInline, - boolean isTailrec, - boolean hasStableParameterNames, - boolean hasSynthesizedParameterNames, - @Nullable FunctionDescriptor original, - boolean copyOverrides, - @NotNull Kind kind, - @NotNull List newValueParameterDescriptors, - @Nullable KotlinType newExtensionReceiverParameterType, - @NotNull KotlinType newReturnType, - @Nullable Name name, - boolean preserveSource, - boolean signatureChange - ) { - FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, original, kind, name, preserveSource); + protected FunctionDescriptor doSubstitute(@NotNull CopyConfiguration configuration) { + FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy( + configuration.newOwner, configuration.original, configuration.kind, configuration.name, + /* preserveSource = */ configuration.signatureChange); List originalTypeParameters = getTypeParameters(); List substitutedTypeParameters = new ArrayList(originalTypeParameters.size()); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters( - originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters + originalTypeParameters, configuration.originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters ); KotlinType substitutedReceiverParameterType = null; - if (newExtensionReceiverParameterType != null) { - substitutedReceiverParameterType = substitutor.substitute(newExtensionReceiverParameterType, Variance.IN_VARIANCE); + if (configuration.newExtensionReceiverParameterType != null) { + substitutedReceiverParameterType = substitutor.substitute(configuration.newExtensionReceiverParameterType, Variance.IN_VARIANCE); if (substitutedReceiverParameterType == null) { return null; } @@ -356,13 +445,13 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo } List substitutedValueParameters = getSubstitutedValueParameters( - substitutedDescriptor, newValueParameterDescriptors, substitutor + substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor ); if (substitutedValueParameters == null) { return null; } - KotlinType substitutedReturnType = substitutor.substitute(newReturnType, Variance.OUT_VARIANCE); + KotlinType substitutedReturnType = substitutor.substitute(configuration.newReturnType, Variance.OUT_VARIANCE); if (substitutedReturnType == null) { return null; } @@ -373,8 +462,8 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo substitutedTypeParameters, substitutedValueParameters, substitutedReturnType, - newModality, - newVisibility + configuration.newModality, + configuration.newVisibility ); substitutedDescriptor.setOperator(isOperator); substitutedDescriptor.setInfix(isInfix); @@ -384,13 +473,13 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames); substitutedDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames); - if (signatureChange || getInitialSignatureDescriptor() != null) { + if (configuration.signatureChange || getInitialSignatureDescriptor() != null) { FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this); FunctionDescriptor initialSignatureSubstituted = initialSignature.substitute(substitutor); substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted); } - if (copyOverrides) { + if (configuration.copyOverrides) { for (FunctionDescriptor overriddenFunction : overriddenFunctions) { substitutedDescriptor.addOverriddenDescriptor(overriddenFunction.substitute(substitutor)); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java index 89f6ee7cb6a..ed906c5bb63 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeSubstitutor; import java.util.List; @@ -100,33 +99,27 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme Kind kind, boolean copyOverrides ) { - return (SimpleFunctionDescriptorImpl) doSubstitute( - TypeSubstitutor.EMPTY, newOwner, modality, visibility, - isOperator(), isInfix(), isExternal(), isInline(), isTailrec(), - hasStableParameterNames(), hasSynthesizedParameterNames(), - null, copyOverrides, kind - ); + //noinspection ConstantConditions + return (SimpleFunctionDescriptor) newCopyBuilder() + .setOwner(newOwner) + .setModality(modality) + .setVisibility(visibility) + .setKind(kind) + .setCopyOverrides(copyOverrides) + .build(); } @NotNull @Override public SimpleFunctionDescriptor createRenamedCopy(@NotNull Name name) { //noinspection ConstantConditions - return (SimpleFunctionDescriptorImpl) doSubstitute( - TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), - isOperator(), isInfix(), isExternal(), isInline(), isTailrec(), hasStableParameterNames(), hasSynthesizedParameterNames(), - null, /* copyOverrides = */ true, getKind(), getValueParameters(), getExtensionReceiverParameterType(), getReturnType(), name, - /* preserveSource = */ true, /* signatureChange = */ true); + return (SimpleFunctionDescriptor) newCopyBuilder().setName(name).setSignatureChange().build(); } @NotNull @Override public SimpleFunctionDescriptor createCopyWithNewValueParameters(@NotNull List valueParameters) { //noinspection ConstantConditions - return (SimpleFunctionDescriptorImpl) doSubstitute( - TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), - isOperator(), isInfix(), isExternal(), isInline(), isTailrec(), hasStableParameterNames(), hasSynthesizedParameterNames(), - null, /* copyOverrides = */ true, getKind(), valueParameters, getExtensionReceiverParameterType(), getReturnType(), null, - /* preserveSource = */ true, /* signatureChange = */ true); + return (SimpleFunctionDescriptor) newCopyBuilder().setValueParameters(valueParameters).setSignatureChange().build(); } }