diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 916150aa61a..52965db96ff 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -226,9 +226,9 @@ public class AsmUtil { int flags = getVisibilityAccessFlag(functionDescriptor); flags |= getVarargsFlag(functionDescriptor); flags |= getDeprecatedAccessFlag(functionDescriptor); - if (DeprecationUtilKt.isAnnotatedAsHidden(functionDescriptor) + if (DeprecationUtilKt.isHiddenInResolution(functionDescriptor) || functionDescriptor instanceof PropertyAccessorDescriptor - && DeprecationUtilKt.isAnnotatedAsHidden(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) { + && DeprecationUtilKt.isHiddenInResolution(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) { flags |= ACC_SYNTHETIC; } return flags; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index 897fc311c87..de978cfdb84 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -708,7 +708,7 @@ public class CallResolver { ) { final List> candidateResolutionContexts = ContainerUtil.newArrayList(); for (final ResolutionCandidate resolutionCandidate : task.getCandidates()) { - if (DeprecationUtilKt.isAnnotatedAsHidden(resolutionCandidate.getDescriptor())) continue; + if (DeprecationUtilKt.isHiddenInResolution(resolutionCandidate.getDescriptor())) continue; candidatePerfCounter.time(new Function0() { @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt index 1cbebda0fae..552b95221e8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolveOldInference.kt @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke -import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden +import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.types.DeferredType import org.jetbrains.kotlin.types.ErrorUtils @@ -201,7 +201,7 @@ class NewResolveOldInference( return Candidate(ResolutionCandidateStatus(listOf(ExtensionWithStaticTypeWithDynamicReceiver)), candidateCall) } - if (towerCandidate.descriptor.isAnnotatedAsHidden()) { + if (towerCandidate.descriptor.isHiddenInResolution()) { return Candidate(ResolutionCandidateStatus(listOf(HiddenDescriptor)), candidateCall) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt index 0eb0fb3d95e..251696dbe50 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt @@ -97,7 +97,8 @@ fun DeclarationDescriptor.getDeprecatedAnnotationLevel(): DeprecationLevelValue? @Deprecated("Should be removed together with kotlin.HiddenDeclaration") private val HIDDEN_ANNOTATION_FQ_NAME = FqName("kotlin.HiddenDeclaration") -fun DeclarationDescriptor.isAnnotatedAsHidden(): Boolean { +fun DeclarationDescriptor.isHiddenInResolution(): Boolean { + if (this is FunctionDescriptor && this.isHiddenToOvercomeSignatureClash) return true return annotations.findAnnotation(HIDDEN_ANNOTATION_FQ_NAME) != null || getDeprecatedAnnotationLevel() == DeprecationLevelValue.HIDDEN } diff --git a/compiler/testData/codegen/box/specialBuiltins/emptyList.kt b/compiler/testData/codegen/box/specialBuiltins/emptyList.kt index 857d218abcd..7bf715cb145 100644 --- a/compiler/testData/codegen/box/specialBuiltins/emptyList.kt +++ b/compiler/testData/codegen/box/specialBuiltins/emptyList.kt @@ -15,11 +15,17 @@ private object EmptyList : List { } fun box(): String { - val n = EmptyList as List + val n = EmptyList as List - if (n.contains(null)) return "fail 1" - if (n.indexOf(null) != -1) return "fail 2" - if (n.lastIndexOf(null) != -1) return "fail 3" + if (n.contains("")) return "fail 1" + if (n.indexOf("") != -1) return "fail 2" + if (n.lastIndexOf("") != -1) return "fail 3" + + val nullAny = EmptyList as List + + if (nullAny.contains(null)) return "fail 4" + if (nullAny.indexOf(null) != -1) return "fail 5" + if (nullAny.lastIndexOf(null) != -1) return "fail 6" return "OK" } diff --git a/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.java b/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.java new file mode 100644 index 00000000000..604a41846c7 --- /dev/null +++ b/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.java @@ -0,0 +1,27 @@ +public abstract class CharBuffer implements CharSequence { + public final int length() { + return 0; + } + + public final char charAt(int index) { + return 'K'; + } + + // The key problem here is that `get` has the same signature as kotlin.CharSequence.get but completely different semantics + public abstract char get(int index); + public abstract CharBuffer subSequence(int start, int end); + + public static CharBuffer impl() { + return new CharBuffer() { + @Override + public char get(int index) { + return 'O'; + } + + @Override + public CharBuffer subSequence(int start, int end) { + return null; + } + }; + } +} diff --git a/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.kt b/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.kt new file mode 100644 index 00000000000..20fec2031b8 --- /dev/null +++ b/compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.kt @@ -0,0 +1,5 @@ +fun box(): String { + val cb: CharBuffer = CharBuffer.impl() + + return cb.get(0).toString() + (cb as CharSequence).get(1).toString() +} diff --git a/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java index 54a7984f212..6fd107fc11f 100644 --- a/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java +++ b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java @@ -1,5 +1,5 @@ import java.util.*; public class J implements Container { - final public String removeAt(int index) { return "abc"; } + final public String removeAt(int index) { return "abc"; } } diff --git a/compiler/testData/codegen/boxWithStdlib/fullJdk/charBuffer.kt b/compiler/testData/codegen/boxWithStdlib/fullJdk/charBuffer.kt new file mode 100644 index 00000000000..a2f45009a43 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/fullJdk/charBuffer.kt @@ -0,0 +1,9 @@ +import java.nio.CharBuffer + +fun box(): String { + val cb = CharBuffer.wrap("OK") + cb.position(1) + val o = cb[0] + val k = (cb as CharSequence).get(0) + return o.toString() + k +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.kt new file mode 100644 index 00000000000..1b32d392513 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.kt @@ -0,0 +1,22 @@ +// FILE: CharBuffer.java + +public class CharBuffer implements CharSequence { + public final int length() { + return 0; + } + + public final char charAt(int index) { + return get(position() + checkIndex(index, 1)); + } + + // The key problem here is that `get` has the same signature as kotlin.CharSequence.get but completely different semantics + public abstract char get(int index); + public abstract CharBuffer subSequence(int start, int end); +} + +// FILE: main.kt + +fun test(cb: CharBuffer) { + cb.get(0) + (cb as CharSequence).get(0) +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.txt new file mode 100644 index 00000000000..d72b9257f65 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.txt @@ -0,0 +1,14 @@ +package + +public fun test(/*0*/ cb: CharBuffer): kotlin.Unit + +public open class CharBuffer : kotlin.CharSequence { + public constructor CharBuffer() + public final override /*1*/ val length: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract operator fun get(/*0*/ index: kotlin.Int): kotlin.Char + public final override /*1*/ /*isHiddenToOvercomeSignatureClash*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): CharBuffer + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.kt new file mode 100644 index 00000000000..08b86b53d45 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.kt @@ -0,0 +1,85 @@ +// FILE: CollectionStringImpl.java + +import java.util.Collection; +import java.util.Iterator; + +public class CollectionStringImpl implements Collection { + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + + @Override + public Iterator iterator() { + return null; + } + + + @Override + public Object[] toArray() { + return new Object[0]; + } + + + @Override + public T[] toArray(T[] a) { + return null; + } + + @Override + public boolean add(String s) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public void clear() { + + } + + public boolean contains(String o) { + return true; + } +} + +// FILE: main.kt + +fun test(x: CollectionStringImpl) { + x.contains("") + (x as Collection).contains("") +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.txt new file mode 100644 index 00000000000..3bc4ee4da29 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.txt @@ -0,0 +1,24 @@ +package + +public fun test(/*0*/ x: CollectionStringImpl): kotlin.Unit + +public open class CollectionStringImpl : kotlin.MutableCollection { + public constructor CollectionStringImpl() + public open override /*1*/ val size: kotlin.Int + @java.lang.Override() public open override /*1*/ fun add(/*0*/ element: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun addAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun clear(): kotlin.Unit + @java.lang.Override() public open override /*1*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ o: kotlin.String!): kotlin.Boolean + public open operator fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun containsAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @java.lang.Override() public open override /*1*/ fun isEmpty(): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun iterator(): kotlin.MutableIterator + @java.lang.Override() public open override /*1*/ fun remove(/*0*/ o: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun removeAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ fun retainAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean + @java.lang.Override() public open fun toArray(): kotlin.Array<(out) kotlin.Any!>! + @java.lang.Override() public open fun toArray(/*0*/ a: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.kt index 564636d378b..7ed19ccd35c 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.kt @@ -7,8 +7,8 @@ abstract public class A implements java.util.Collection { } // FILE: main.kt -abstract class KA: A() { - override fun contains(x: String) = false +abstract class KA : A() { + override fun contains(x: String) = false } fun foo(a: A, ka: KA) { diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.txt index f3791ca8e31..b92c3701d10 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/containsAndOverload.txt @@ -8,7 +8,8 @@ public abstract class A : kotlin.MutableCollection { public abstract override /*1*/ /*fake_override*/ fun add(/*0*/ element: kotlin.String!): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun addAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit - public open override /*1*/ fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean + public open override /*1*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ x: kotlin.String!): kotlin.Boolean + public open operator fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun containsAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int @@ -27,6 +28,7 @@ public abstract class KA : A { public abstract override /*1*/ /*fake_override*/ fun addAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit public open override /*1*/ fun contains(/*0*/ x: kotlin.String): kotlin.Boolean + public open override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ x: kotlin.String!): kotlin.Boolean public abstract override /*1*/ /*fake_override*/ fun containsAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt index 6b212417edc..086d8d68163 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/getCharSequence.txt @@ -26,7 +26,8 @@ public abstract class C : kotlin.CharSequence { public constructor C() public open override /*1*/ val length: kotlin.Int public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char + public open operator fun get(/*0*/ index: kotlin.Int): kotlin.Char + public abstract override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun get(/*0*/ index: kotlin.Int): kotlin.Char public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public abstract override /*1*/ /*fake_override*/ fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt index 5f93550d448..e81f71dd00d 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt @@ -143,7 +143,7 @@ public class X implements java.util.List { // FILE: main.kt -class Y : X() +class Y : X() fun main() { X().remove("") @@ -154,4 +154,7 @@ fun main() { Y().remove("") Y().removeAt(1) + + X().remove("") + X().removeAt(1) } diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt index 1832e9d6dc2..a75f9789190 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt @@ -10,7 +10,8 @@ public open class X : kotlin.MutableList { @java.lang.Override() public open override /*1*/ fun addAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun clear(): kotlin.Unit - public open override /*1*/ fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ o: kotlin.String!): kotlin.Boolean + public open operator fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun containsAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun get(/*0*/ index: kotlin.Int): kotlin.String! @@ -23,7 +24,8 @@ public open class X : kotlin.MutableList { @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator @java.lang.Override() public open override /*1*/ fun remove(/*0*/ o: kotlin.String!): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun removeAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean - public open override /*1*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! + @java.lang.Override() public open override /*1*/ /*isHiddenToOvercomeSignatureClash*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! + public open fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! @java.lang.Override() public open override /*1*/ fun retainAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.String!): kotlin.String! @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.MutableList @@ -40,6 +42,7 @@ public final class Y : X { @java.lang.Override() public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit + @java.lang.Override() public open override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ o: kotlin.String!): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean @java.lang.Override() public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -53,6 +56,7 @@ public final class Y : X { @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator @java.lang.Override() public open override /*1*/ /*fake_override*/ fun remove(/*0*/ o: kotlin.String!): kotlin.Boolean @java.lang.Override() public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! public open override /*1*/ /*fake_override*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! @java.lang.Override() public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean @java.lang.Override() public open override /*1*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.String!): kotlin.String! diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt index 6a776a29a9a..76af6ae284f 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.kt @@ -1,7 +1,7 @@ // FILE: A.java abstract public class A extends B { - public Integer remove(int x) { } - public boolean remove(Object x) { } + public Integer removeAt(int x) { } + public boolean remove(Integer x) { } } // FILE: main.kt diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt index ae448a51a73..aaaf61eb9d7 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/removeAtInt.txt @@ -24,9 +24,9 @@ public abstract class A : B { public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.MutableListIterator invisible_fake open override /*1*/ /*fake_override*/ fun outOfBoundsMsg(/*0*/ p0: kotlin.Int): kotlin.String! invisible_fake open override /*1*/ /*fake_override*/ fun rangeCheckForAdd(/*0*/ p0: kotlin.Int): kotlin.Unit - public open override /*1*/ /*fake_override*/ fun remove(/*0*/ element: kotlin.Int): kotlin.Boolean + public open override /*1*/ fun remove(/*0*/ element: kotlin.Int): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean - public open override /*1*/ fun removeAt(/*0*/ x: kotlin.Int): kotlin.Int + public open override /*1*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.Int protected/*protected and package*/ open override /*1*/ /*fake_override*/ fun removeRange(/*0*/ p0: kotlin.Int, /*1*/ p1: kotlin.Int): kotlin.Unit public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ elements: kotlin.Collection): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.Int): kotlin.Int diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index e2cf551a4b9..7a8baf339af 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9641,6 +9641,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/j+k/collectionOverrides"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("charBuffer.kt") + public void testCharBuffer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/charBuffer.kt"); + doTest(fileName); + } + + @TestMetadata("collectionStringImpl.kt") + public void testCollectionStringImpl() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/collectionStringImpl.kt"); + doTest(fileName); + } + @TestMetadata("commonCollections.kt") public void testCommonCollections() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/collectionOverrides/commonCollections.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java index 4de87959acf..45ee503185e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxAgainstJavaCodegenTestGenerated.java @@ -830,6 +830,21 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod } } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/specialBuiltins") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SpecialBuiltins extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInSpecialBuiltins() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/specialBuiltins"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("CharBuffer.kt") + public void testCharBuffer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/specialBuiltins/CharBuffer.kt"); + doTestAgainstJava(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxAgainstJava/staticFun") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 697dfc2bd6b..31d90007d9c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -1621,6 +1621,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/fullJdk"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("charBuffer.kt") + public void testCharBuffer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/fullJdk/charBuffer.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("classpath.kt") public void testClasspath() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/fullJdk/classpath.kt"); diff --git a/core/descriptor.loader.java/src/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition b/core/descriptor.loader.java/src/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition index f205b1d9ec1..af683875f4a 100644 --- a/core/descriptor.loader.java/src/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition +++ b/core/descriptor.loader.java/src/META-INF/services/org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition @@ -1,2 +1,3 @@ org.jetbrains.kotlin.load.java.FieldOverridabilityCondition -org.jetbrains.kotlin.load.java.ErasedOverridabilityCondition \ No newline at end of file +org.jetbrains.kotlin.load.java.ErasedOverridabilityCondition +org.jetbrains.kotlin.load.java.BuiltinOverridabilityCondition \ No newline at end of file diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/BuiltinOverridabilityCondition.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/BuiltinOverridabilityCondition.kt new file mode 100644 index 00000000000..cfd2e7c87e2 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/BuiltinOverridabilityCondition.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.java + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithDifferentJvmName.sameAsRenamedInJvmBuiltin +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.sameAsBuiltinMethodWithErasedValueParameters +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor +import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition +import org.jetbrains.kotlin.resolve.ExternalOverridabilityCondition.Result +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.descriptorUtil.isDocumentedAnnotation + +class BuiltinOverridabilityCondition : ExternalOverridabilityCondition { + override fun isOverridable(superDescriptor: CallableDescriptor, subDescriptor: CallableDescriptor, subClassDescriptor: ClassDescriptor?): Result { + if (superDescriptor !is CallableMemberDescriptor || subDescriptor !is FunctionDescriptor || subDescriptor.isFromBuiltins()) { + return Result.UNKNOWN + } + + if (!subDescriptor.name.sameAsBuiltinMethodWithErasedValueParameters && !subDescriptor.name.sameAsRenamedInJvmBuiltin) { + return Result.UNKNOWN + } + + // This overridability condition checks two things: + // 1. Method accidentally having the same signature as special builtin has does not supposed to be override for it in Java class + // 2. In such Java class (with special signature clash) special builtin is loaded as hidden function with special signature, and + // it should not override non-special method in further inheritance + // See java.nio.Buffer + + val overriddenBuiltin = superDescriptor.getOverriddenSpecialBuiltin() + + // Checking second condition: special hidden override is not supposed to be an override to non-special irrelevant Java declaration + val isOneOfDescriptorsHidden = + subDescriptor.isHiddenToOvercomeSignatureClash != (superDescriptor as? FunctionDescriptor)?.isHiddenToOvercomeSignatureClash + if ((overriddenBuiltin == null || !subDescriptor.isHiddenToOvercomeSignatureClash) && isOneOfDescriptorsHidden) { + return Result.INCOMPATIBLE + } + + // If new containing class is not Java class or subDescriptor signature was artificially changed, use basic overridability rules + if (subClassDescriptor !is JavaClassDescriptor || subDescriptor.initialSignatureDescriptor != null) { + return Result.UNKNOWN + } + + // If current Java class has Kotlin super class with override of overriddenBuiltin, then common overridability rules can be applied + // because of final special bridge generated in Kotlin super class + if (subClassDescriptor.hasRealKotlinSuperClassWithOverrideOf(overriddenBuiltin ?: return Result.UNKNOWN)) return Result.UNKNOWN + + // Here we know that something in Java with common signature is going to override some special builtin that is supposed to be + // incompatible override + return Result.INCOMPATIBLE + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/DescriptorResolverUtils.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/DescriptorResolverUtils.java index 5115ffeb6c0..1966d02d6fc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/DescriptorResolverUtils.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/DescriptorResolverUtils.java @@ -30,10 +30,7 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.OverridingUtil; import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; public final class DescriptorResolverUtils { private DescriptorResolverUtils() { @@ -47,7 +44,7 @@ public final class DescriptorResolverUtils { @NotNull ClassDescriptor classDescriptor, @NotNull final ErrorReporter errorReporter ) { - final Set result = new HashSet(); + final Set result = new LinkedHashSet(); OverridingUtil.generateOverridesInFunctionGroup( name, membersFromSupertypes, membersFromCurrent, classDescriptor, diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index 447ed9196fc..ff089ff12bd 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -152,8 +152,8 @@ public class LazyJavaClassMemberScope( } private fun CallableDescriptor.doesOverride(superDescriptor: CallableDescriptor): Boolean { - return OverridingUtil.DEFAULT.isOverridableByIncludingReturnType( - superDescriptor, this + return OverridingUtil.DEFAULT.isOverridableByWithoutExternalConditions( + superDescriptor, this, /* checkReturnType = */ true ).result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE } @@ -214,7 +214,11 @@ public class LazyJavaClassMemberScope( val functionsFromSupertypes = getFunctionsFromSupertypes(name) if (!name.sameAsRenamedInJvmBuiltin && !name.sameAsBuiltinMethodWithErasedValueParameters) { - addFunctionFromSupertypes(result, name, functionsFromSupertypes.filter { isVisibleAsFunctionInCurrentClass(it) }) + // Simple fast path in case of name is not suspicious (i.e. name is not one of builtins that have different signature in Java) + addFunctionFromSupertypes( + result, name, + functionsFromSupertypes.filter { isVisibleAsFunctionInCurrentClass(it) }, + isSpecialBuiltinName = false) return } @@ -237,16 +241,33 @@ public class LazyJavaClassMemberScope( val visibleFunctionsFromSupertypes = functionsFromSupertypes.filter { isVisibleAsFunctionInCurrentClass(it) } + specialBuiltinsFromSuperTypes - addFunctionFromSupertypes(result, name, visibleFunctionsFromSupertypes) + addFunctionFromSupertypes(result, name, visibleFunctionsFromSupertypes, isSpecialBuiltinName = true) } private fun addFunctionFromSupertypes( result: MutableCollection, name: Name, - functionsFromSupertypes: Collection + functionsFromSupertypes: Collection, + isSpecialBuiltinName: Boolean ) { - result.addAll(DescriptorResolverUtils.resolveOverrides( - name, functionsFromSupertypes, result, ownerDescriptor, c.components.errorReporter)) + + val additionalOverrides = + DescriptorResolverUtils.resolveOverrides(name, functionsFromSupertypes, result, ownerDescriptor, c.components.errorReporter) + + if (!isSpecialBuiltinName) { + result.addAll(additionalOverrides) + } + else { + val allDescriptors = result + additionalOverrides + result.addAll( + additionalOverrides.map { + resolvedOverride -> + val overriddenBuiltin = resolvedOverride.getOverriddenSpecialBuiltin() + ?: return@map resolvedOverride + + resolvedOverride.createHiddenCopyIfBuiltinAlreadyAccidentallyOverridden(overriddenBuiltin, allDescriptors) + }) + } } private fun addOverriddenBuiltinMethods( @@ -259,14 +280,14 @@ public class LazyJavaClassMemberScope( for (descriptor in candidatesForOverride) { val overriddenBuiltin = descriptor.getOverriddenBuiltinWithDifferentJvmName() ?: continue - if (alreadyDeclaredFunctions.any { it.doesOverride(overriddenBuiltin) }) continue - val nameInJava = getJvmMethodNameIfSpecial(overriddenBuiltin)!! for (method in functions(Name.identifier(nameInJava))) { val renamedCopy = method.createRenamedCopy(name) if (isOverridableRenamedDescriptor(overriddenBuiltin, renamedCopy)) { - result.add(renamedCopy) + result.add( + renamedCopy.createHiddenCopyIfBuiltinAlreadyAccidentallyOverridden(overriddenBuiltin, alreadyDeclaredFunctions)) + break } } } @@ -276,17 +297,29 @@ public class LazyJavaClassMemberScope( BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) ?: continue - if (alreadyDeclaredFunctions.any { it.doesOverride(overriddenBuiltin) }) continue - createOverrideForBuiltinFunctionWithErasedParameterIfNeeded(overriddenBuiltin, functions)?.let { override -> if (isVisibleAsFunctionInCurrentClass(override)) { - result.add(override) + result.add(override.createHiddenCopyIfBuiltinAlreadyAccidentallyOverridden(overriddenBuiltin, alreadyDeclaredFunctions)) } } } } + // In case when Java has declaration with signature reflecting one of special builtin we load override of builtin as hidden function + // Unless we do it then signature clash happens. + // For example see java.nio.CharBuffer implementing CharSequence and defining irrelevant 'get' method having the same signature as in kotlin.CharSequence + // We load java.nio.CharBuffer as having both 'get' functions, but one that is override of kotlin.CharSequence is hidden, + // so when someone calls CharBuffer.get it results in invoking java method CharBuffer.get + // But we still have the way to call 'charAt' java method by upcasting CharBuffer to kotlin.CharSequence + private fun SimpleFunctionDescriptor.createHiddenCopyIfBuiltinAlreadyAccidentallyOverridden( + specialBuiltin: CallableDescriptor, + alreadyDeclaredFunctions: Collection + ) = if (alreadyDeclaredFunctions.none { this != it && it.doesOverride(specialBuiltin) }) + this + else + createHiddenCopyToOvercomeSignatureClash() + private fun createOverrideForBuiltinFunctionWithErasedParameterIfNeeded( overridden: FunctionDescriptor, functions: (Name) -> Collection diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt index 3700c1abd48..dde2e7ed712 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/specialBuiltinMembers.kt @@ -286,10 +286,10 @@ public fun ClassDescriptor.hasRealKotlinSuperClassWithOverrideOf( } // Util methods -private val CallableMemberDescriptor.isFromJava: Boolean +public val CallableMemberDescriptor.isFromJava: Boolean get() = propertyIfAccessor is JavaCallableMemberDescriptor && propertyIfAccessor.containingDeclaration is JavaClassDescriptor -private fun CallableMemberDescriptor.isFromBuiltins(): Boolean { +public fun CallableMemberDescriptor.isFromBuiltins(): Boolean { val fqName = propertyIfAccessor.fqNameOrNull() ?: return false return fqName.toUnsafe().startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME) && this.module == this.builtIns.builtInsModule diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java index 257a5778c14..00bbdd9d9eb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/FunctionDescriptor.java @@ -39,9 +39,19 @@ public interface FunctionDescriptor extends CallableMemberDescriptor { @NotNull Collection getOverriddenDescriptors(); + /** + * @return descriptor that represents initial signature, e.g in case of result SimpleFunctionDescriptor.createRenamedCopy it returns + * descriptor before rename + */ @Nullable FunctionDescriptor getInitialSignatureDescriptor(); + /** + * @return true if descriptor signature clashed with some other signature and it's supposed to be legal + * See java.nio.CharBuffer + */ + boolean isHiddenToOvercomeSignatureClash(); + @NotNull @Override FunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java index aa1ec26c4d9..c2beeb1e15f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SimpleFunctionDescriptor.java @@ -38,6 +38,9 @@ public interface SimpleFunctionDescriptor extends FunctionDescriptor { @NotNull SimpleFunctionDescriptor createCopyWithNewTypeParameters(@NotNull List typeParameters); + @NotNull + SimpleFunctionDescriptor createHiddenCopyToOvercomeSignatureClash(); + @NotNull @Override SimpleFunctionDescriptor getOriginal(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/EnumEntrySyntheticClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/EnumEntrySyntheticClassDescriptor.java index 3bb475cde27..9ec108dd98d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/EnumEntrySyntheticClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/EnumEntrySyntheticClassDescriptor.java @@ -241,7 +241,7 @@ public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase { @NotNull Name name, @NotNull Collection fromSupertypes ) { - final Set result = new HashSet(); + final Set result = new LinkedHashSet(); OverridingUtil.generateOverridesInFunctionGroup( name, fromSupertypes, Collections.emptySet(), EnumEntrySyntheticClassDescriptor.this, 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 e555e8322c7..0d5c7384397 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java @@ -47,6 +47,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo private boolean isExternal = false; private boolean isInline = false; private boolean isTailrec = false; + private boolean isHidden = false; private boolean hasStableParameterNames = true; private boolean hasSynthesizedParameterNames = false; private final Set overriddenFunctions = SmartSet.create(); @@ -129,6 +130,10 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo this.isTailrec = isTailrec; } + public void setHidden(boolean hidden) { + isHidden = hidden; + } + public void setReturnType(@NotNull KotlinType unsubstitutedReturnType) { if (this.unsubstitutedReturnType != null) { // TODO: uncomment and fix tests @@ -212,6 +217,11 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo return isTailrec; } + @Override + public boolean isHiddenToOvercomeSignatureClash() { + return isHidden; + } + @Override public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overriddenFunction) { overriddenFunctions.add((FunctionDescriptor) overriddenFunction); @@ -283,6 +293,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo protected @Nullable Name name; protected boolean copyOverrides; protected boolean signatureChange; + private boolean isHiddenToOvercomeSignatureClash; private List newTypeParameters = null; public CopyConfiguration( @@ -307,6 +318,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo this.name = name; this.copyOverrides = true; this.signatureChange = false; + this.isHiddenToOvercomeSignatureClash = isHiddenToOvercomeSignatureClash(); } @NotNull @@ -379,6 +391,12 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo return this; } + @NotNull + public CopyConfiguration setHidden() { + isHiddenToOvercomeSignatureClash = true; + return this; + } + public FunctionDescriptor build() { return doSubstitute(this); } @@ -483,6 +501,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo substitutedDescriptor.setTailrec(isTailrec); substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames); substitutedDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames); + substitutedDescriptor.setHidden(configuration.isHiddenToOvercomeSignatureClash); if (configuration.signatureChange || getInitialSignatureDescriptor() != null) { FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java index 71cb0e98686..8ecc910cb79 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyAccessorDescriptorImpl.java @@ -201,4 +201,9 @@ public abstract class PropertyAccessorDescriptorImpl extends DeclarationDescript public void setInitialSignatureDescriptor(@Nullable FunctionDescriptor initialSignatureDescriptor) { this.initialSignatureDescriptor = initialSignatureDescriptor; } + + @Override + public boolean isHiddenToOvercomeSignatureClash() { + return false; + } } 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 497bd6e87f8..ea84c96cfc2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/SimpleFunctionDescriptorImpl.java @@ -129,4 +129,11 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme //noinspection ConstantConditions return (SimpleFunctionDescriptor) newCopyBuilder().setTypeParameters(typeParameters).build(); } + + @NotNull + @Override + public SimpleFunctionDescriptor createHiddenCopyToOvercomeSignatureClash() { + //noinspection ConstantConditions + return (SimpleFunctionDescriptor) newCopyBuilder().setHidden().build(); + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt index a6ff29c0f0e..4e0e19730b6 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt @@ -603,6 +603,10 @@ internal class DescriptorRendererImpl( renderOverride(function, builder) renderMemberKind(function, builder) + if (verbose && function.isHiddenToOvercomeSignatureClash) { + builder.append("/*isHiddenToOvercomeSignatureClash*/ ") + } + builder.append(renderKeyword("fun")).append(" ") renderTypeParameters(function.getTypeParameters(), builder, true) renderReceiver(function, builder) diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java index 1d87c9ab1f4..1cd19ee5523 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/OverridingUtil.java @@ -82,12 +82,14 @@ public class OverridingUtil { @Nullable ClassDescriptor subClassDescriptor, boolean checkReturnType ) { + boolean wasSuccessfulExternalCondition = false; for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) { ExternalOverridabilityCondition.Result result = externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor); switch (result) { case OVERRIDABLE: - return OverrideCompatibilityInfo.success(); + wasSuccessfulExternalCondition = true; + break; case CONFLICT: return OverrideCompatibilityInfo.conflict("External condition failed"); case INCOMPATIBLE: @@ -98,6 +100,10 @@ public class OverridingUtil { } } + if (wasSuccessfulExternalCondition) { + return OverrideCompatibilityInfo.success(); + } + return isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/error/ErrorSimpleFunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/types/error/ErrorSimpleFunctionDescriptorImpl.java index b2c8ca25e32..617826b623e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/error/ErrorSimpleFunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/error/ErrorSimpleFunctionDescriptorImpl.java @@ -73,6 +73,12 @@ public class ErrorSimpleFunctionDescriptorImpl extends SimpleFunctionDescriptorI return this; } + @NotNull + @Override + public SimpleFunctionDescriptor createHiddenCopyToOvercomeSignatureClash() { + return this; + } + @Override public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overriddenFunction) { // nop diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt index 0c5abad125f..cefaf65860a 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager -import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden +import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered @@ -71,7 +71,7 @@ class ReferenceVariantsHelper( ): Collection { var variants: Collection = getReferenceVariantsNoVisibilityFilter(contextElement, kindFilter, nameFilter, callTypeAndReceiver, useReceiverType) - .filter { !it.isAnnotatedAsHidden() && visibilityFilter(it) } + .filter { !it.isHiddenInResolution() && visibilityFilter(it) } if (filterOutShadowed) { ShadowedDeclarationsFilter.create(bindingContext, resolutionFacade, contextElement, callTypeAndReceiver)?.let { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 1ec7b6dc80d..93814ed1c26 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -50,7 +50,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden +import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.KotlinType @@ -70,7 +70,7 @@ public class KotlinIndicesHelper( private val project = resolutionFacade.project private val descriptorFilter: (DeclarationDescriptor) -> Boolean = filter@ { - if (it.isAnnotatedAsHidden()) return@filter false + if (it.isHiddenInResolution()) return@filter false if (!visibilityFilter(it)) return@filter false if (applyExcludeSettings && isExcludedFromAutoImport(it)) return@filter false true diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt index ba83bba5911..d2eee9157f9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt @@ -48,7 +48,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess -import org.jetbrains.kotlin.resolve.isAnnotatedAsHidden +import org.jetbrains.kotlin.resolve.isHiddenInResolution import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.utils.collectSyntheticExtensionProperties import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor @@ -70,7 +70,7 @@ public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection() val conflictingExtension = conflictingSyntheticExtension(propertyDescriptor, fileScope) ?: return // don't report on hidden declarations - if (propertyDescriptor.isAnnotatedAsHidden()) return + if (propertyDescriptor.isHiddenInResolution()) return val fixes = createFixes(property, conflictingExtension, isOnTheFly)