Do not discriminate synthesized candidates.

#KT-9965 Fixed
This commit is contained in:
Stanislav Erokhin
2015-12-18 01:35:43 +03:00
parent 1b6f96ac2b
commit 8b5a194dd6
14 changed files with 166 additions and 17 deletions
@@ -74,7 +74,8 @@ data class ResolutionCandidateStatus(val diagnostics: List<ResolutionDiagnostic>
enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
RESOLVED_SYNTHESIZED,
RESOLVED_SYNTHESIZED, // todo remove it (need for SAM adapters which created inside some MemberScope)
RESOLVED_LOW_PRIORITY,
CONVENTION_ERROR, // missing infix, operator etc
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
RUNTIME_ERROR, // problems with visibility
@@ -94,8 +95,9 @@ class UnsupportedInnerClassCall(val message: String): ResolutionDiagnostic(Resol
class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType): ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED)
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED) // todo discuss and change to INAPPLICABLE
object SynthesizedDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object SynthesizedDescriptorDiagnostic : ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED)
object DynamicDescriptorDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY)
object UnstableSmartCastDiagnostic: ResolutionDiagnostic(ResolutionCandidateApplicability.MAY_THROW_RUNTIME_ERROR)
object ExtensionWithStaticTypeWithDynamicReceiver: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
object HiddenDescriptor: ResolutionDiagnostic(ResolutionCandidateApplicability.HIDDEN)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
@@ -55,6 +56,7 @@ internal abstract class AbstractScopeTowerLevel(
diagnostics.add(ErrorDescriptorDiagnostic)
}
else {
if (descriptor.hasLowPriorityInOverloadResolution()) diagnostics.add(LowPriorityDescriptorDiagnostic)
if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic)
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
@@ -85,7 +85,7 @@ class TowerResolver {
for (candidatesGroup in candidatesGroups) {
resultCollector.pushCandidates(candidatesGroup)
resultCollector.getResolved()?.let { return it }
resultCollector.getSuccessfulCandidates()?.let { return it }
}
return null
}
@@ -108,7 +108,7 @@ class TowerResolver {
internal abstract class ResultCollector<C>(val context: TowerContext<C>) {
abstract fun getResolved(): Collection<C>?
abstract fun getSuccessfulCandidates(): Collection<C>?
abstract fun getFinalCandidates(): Collection<C>
@@ -125,7 +125,7 @@ class TowerResolver {
internal class AllCandidatesCollector<C>(context: TowerContext<C>): ResultCollector<C>(context) {
private val allCandidates = ArrayList<C>()
override fun getResolved(): Collection<C>? = null
override fun getSuccessfulCandidates(): Collection<C>? = null
override fun getFinalCandidates(): Collection<C> = allCandidates
@@ -139,15 +139,19 @@ class TowerResolver {
private var currentCandidates: Collection<C> = emptyList()
private var currentLevel: ResolutionCandidateApplicability? = null
override fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
override fun getSuccessfulCandidates(): Collection<C>? = getResolved() ?: getResolvedSynthetic()
fun getSyntheticResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
fun getResolvedSynthetic() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
fun getResolvedLowPriority() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY }
fun getErrors() = currentCandidates.check {
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
}
override fun getFinalCandidates() = getResolved() ?: getSyntheticResolved() ?: getErrors() ?: emptyList()
override fun getFinalCandidates() = getResolved() ?: getResolvedSynthetic() ?: getResolvedLowPriority() ?: getErrors() ?: emptyList()
override fun addCandidates(candidates: Collection<C>) {
val minimalLevel = candidates.map { context.getStatus(it).resultingApplicability }.min()!!
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
@Deprecated("Temporary error")
@@ -37,11 +36,10 @@ internal fun createPreviousResolveError(status: ResolutionStatus): PreviousResol
}
internal val ResolutionCandidateApplicability.isSuccess: Boolean
get() = this == ResolutionCandidateApplicability.RESOLVED || this == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
internal val CallableDescriptor.isSynthesized: Boolean // todo dynamics calls
get() = (this is CallableMemberDescriptor && isOrOverridesSynthesized(this))
|| hasLowPriorityInOverloadResolution()
internal val CallableDescriptor.isSynthesized: Boolean
get() = (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED)
internal val CandidateWithBoundDispatchReceiver<*>.requiresExtensionReceiver: Boolean
get() = descriptor.extensionReceiverParameter != null
@@ -0,0 +1,20 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE
enum class Foo {
FOO;
companion object {
fun valueOf(something: String) = 2
fun values() = 1
}
}
fun test() {
Foo.values() checkType { _<Array<Foo>>() }
Foo.Companion.values() checkType { _<Int>() }
Foo.valueOf("") checkType { _<Foo>() }
Foo.Companion.valueOf("") checkType { _<Int>() }
}
@@ -0,0 +1,30 @@
package
public fun test(): kotlin.Unit
public final enum class Foo : kotlin.Enum<Foo> {
enum entry FOO
private constructor Foo()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Foo): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final fun valueOf(/*0*/ something: kotlin.String): kotlin.Int
public final fun values(): kotlin.Int
}
// Static members
@kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Use 'values()' function instead", replaceWith = kotlin.ReplaceWith(expression = "this.values()", imports = {})) public final /*synthesized*/ val values: kotlin.Array<Foo>
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Foo
public final /*synthesized*/ fun values(): kotlin.Array<Foo>
}
@@ -0,0 +1,10 @@
// !CHECK_TYPE
data class A(val foo: Int)
operator fun A.component1(): String = ""
fun test(a: A) {
val (b) = a
b checkType { _<Int>() }
}
@@ -0,0 +1,14 @@
package
public fun test(/*0*/ a: A): kotlin.Unit
public operator fun A.component1(): kotlin.String
public final data class A {
public constructor A(/*0*/ foo: kotlin.Int)
public final val foo: kotlin.Int
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final /*synthesized*/ fun copy(/*0*/ foo: kotlin.Int = ...): A
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,30 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
// FILE: s/SamConstructor.java
package s;
public class SamConstructor {
public SamConstructor(Runnable r) {
}
public static void foo(Runnable r) {}
}
// FILE: 1.kt
package a
fun SamConstructor(a: () -> Unit) {}
// FILE: 2.kt
package b
import s.SamConstructor
import a.*
fun test() {
val a: s.SamConstructor = SamConstructor { }
val b: s.SamConstructor = SamConstructor(null)
SamConstructor.foo(null)
}
@@ -0,0 +1,9 @@
package
package a {
public fun SamConstructor(/*0*/ a: () -> kotlin.Unit): kotlin.Unit
}
package b {
public fun test(): kotlin.Unit
}
@@ -13710,6 +13710,27 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
}
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/priority")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Priority extends AbstractDiagnosticsTest {
public void testAllFilesPresentInPriority() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/resolve/priority"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("kt9965.kt")
public void testKt9965() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/priority/kt9965.kt");
doTest(fileName);
}
@TestMetadata("synthesizedMembersVsExtension.kt")
public void testSynthesizedMembersVsExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/resolve/priority/synthesizedMembersVsExtension.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/resolve/specialConstructions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1014,6 +1014,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/resolve/kt4711.kt");
doTest(fileName);
}
@TestMetadata("samConstructorVsFun.kt")
public void testSamConstructorVsFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/resolve/samConstructorVsFun.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/smartcasts")
@@ -1,4 +1,7 @@
data class A(val a: Int, val b: String)
class A(val a: Int, val b: String)
operator fun A.component1() = a
operator fun A.component2() = b
fun foo1() {
<selection>val (a, b) = A(1, "2")</selection>
@@ -34,7 +34,7 @@ import bar.*
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/X
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/X./*c:foo.E*/a
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/Y./*c:foo.E*/foo()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E p:foo(invoke) p:bar(invoke) p:java.lang(invoke) p:kotlin(invoke) p:kotlin.annotation(invoke) p:kotlin.jvm(invoke) p:kotlin.collections(invoke) p:kotlin.ranges(invoke) p:kotlin.sequences(invoke) p:kotlin.text(invoke) p:kotlin.io(invoke)*/values()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/values()
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/valueOf("")
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/foo
/*p:foo p:bar p:java.lang p:kotlin p:kotlin.annotation p:kotlin.jvm p:kotlin.collections p:kotlin.ranges p:kotlin.sequences p:kotlin.text p:kotlin.io*/E./*c:foo.E*/bar()