[NI] Add resolution applicability for resolved candidates with error
New resolution applicability is needed in cases when error is found, but candidate still should be selected. Currently there are two cases, when this behaviour is required: - unstable smartcast (choose candidate with non-nullable parameter) - unknown lambda parameter type (against non-functional expected type) KT-36264
This commit is contained in:
Generated
+5
@@ -18362,6 +18362,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/inferenceInLinkedLambdasDependentOnExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt36264.kt")
|
||||
public void testKt36264() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/kt36264.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localObject.kt")
|
||||
public void testLocalObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/localObject.kt");
|
||||
|
||||
+3
-1
@@ -875,7 +875,9 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
}
|
||||
|
||||
fun ResolutionCandidateApplicability.toResolutionStatus(): ResolutionStatus = when (this) {
|
||||
ResolutionCandidateApplicability.RESOLVED, ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY -> ResolutionStatus.SUCCESS
|
||||
ResolutionCandidateApplicability.RESOLVED,
|
||||
ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY,
|
||||
ResolutionCandidateApplicability.RESOLVED_WITH_ERROR -> ResolutionStatus.SUCCESS
|
||||
ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ResolutionStatus.RECEIVER_TYPE_ERROR
|
||||
else -> ResolutionStatus.OTHER_ERROR
|
||||
}
|
||||
|
||||
+2
-2
@@ -141,7 +141,7 @@ class SmartCastDiagnostic(
|
||||
class UnstableSmartCast(
|
||||
val argument: ExpressionKotlinCallArgument,
|
||||
val targetType: UnwrappedType
|
||||
) : KotlinCallDiagnostic(MAY_THROW_RUNTIME_ERROR) {
|
||||
) : KotlinCallDiagnostic(RESOLVED_WITH_ERROR) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : Kotl
|
||||
class NotEnoughInformationForLambdaParameter(
|
||||
val lambdaArgument: LambdaKotlinCallArgument,
|
||||
val parameterIndex: Int
|
||||
) : KotlinCallDiagnostic(RESOLVED) {
|
||||
) : KotlinCallDiagnostic(RESOLVED_WITH_ERROR) {
|
||||
override fun report(reporter: DiagnosticReporter) {
|
||||
reporter.onCallArgument(lambdaArgument, this)
|
||||
}
|
||||
|
||||
+2
-1
@@ -74,6 +74,7 @@ fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) =
|
||||
|
||||
enum class ResolutionCandidateApplicability {
|
||||
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate
|
||||
RESOLVED_WITH_ERROR, // call has error, but it is still successful from resolution perspective
|
||||
RESOLVED_LOW_PRIORITY,
|
||||
CONVENTION_ERROR, // missing infix, operator etc
|
||||
MAY_THROW_RUNTIME_ERROR, // unsafe call or unstable smart cast
|
||||
@@ -108,7 +109,7 @@ class UsedSmartCastForDispatchReceiver(val smartCastType: KotlinType) : Resoluti
|
||||
object ErrorDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED) // todo discuss and change to INAPPLICABLE
|
||||
object LowPriorityDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
|
||||
object DynamicDescriptorDiagnostic : ResolutionDiagnostic(RESOLVED_LOW_PRIORITY)
|
||||
object UnstableSmartCastDiagnostic : ResolutionDiagnostic(MAY_THROW_RUNTIME_ERROR)
|
||||
object UnstableSmartCastDiagnostic : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
|
||||
object HiddenExtensionRelatedToDynamicTypes : ResolutionDiagnostic(HIDDEN)
|
||||
object HiddenDescriptor : ResolutionDiagnostic(HIDDEN)
|
||||
|
||||
|
||||
@@ -311,10 +311,15 @@ class TowerResolver {
|
||||
override fun getSuccessfulCandidates(): Collection<C>? {
|
||||
if (!isSuccessful) return null
|
||||
val firstGroupWithResolved = candidateGroups.firstOrNull {
|
||||
it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||
it.any(::isSuccessfulCandidate)
|
||||
} ?: return null
|
||||
|
||||
return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||
return firstGroupWithResolved.filter(::isSuccessfulCandidate)
|
||||
}
|
||||
|
||||
private fun isSuccessfulCandidate(candidate: C): Boolean {
|
||||
return candidate.resultingApplicability == ResolutionCandidateApplicability.RESOLVED
|
||||
|| candidate.resultingApplicability == ResolutionCandidateApplicability.RESOLVED_WITH_ERROR
|
||||
}
|
||||
|
||||
override fun pushCandidates(candidates: Collection<C>) {
|
||||
|
||||
@@ -27,7 +27,7 @@ private val INAPPLICABLE_STATUSES = setOf(
|
||||
)
|
||||
|
||||
val ResolutionCandidateApplicability.isSuccess: Boolean
|
||||
get() = this <= ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
|
||||
get() = this <= ResolutionCandidateApplicability.RESOLVED_WITH_ERROR
|
||||
|
||||
val CallableDescriptor.isSynthesized: Boolean
|
||||
get() = (this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
interface A
|
||||
class B : A
|
||||
|
||||
val String.ext: A
|
||||
get() = TODO()
|
||||
|
||||
class Cls {
|
||||
fun take(arg: B) {}
|
||||
|
||||
fun test(s: String) {
|
||||
if (s.ext is B)
|
||||
take(s.ext)
|
||||
}
|
||||
}
|
||||
|
||||
fun take(arg: Any) {}
|
||||
@@ -0,0 +1,19 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
interface A
|
||||
class B : A
|
||||
|
||||
val String.ext: A
|
||||
get() = TODO()
|
||||
|
||||
class Cls {
|
||||
fun take(arg: B) {}
|
||||
|
||||
fun test(s: String) {
|
||||
if (s.ext is B)
|
||||
take(<!NI;SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>s.ext<!>)
|
||||
}
|
||||
}
|
||||
|
||||
fun take(arg: Any) {}
|
||||
@@ -0,0 +1,26 @@
|
||||
package
|
||||
|
||||
public val kotlin.String.ext: A
|
||||
public fun take(/*0*/ arg: kotlin.Any): kotlin.Unit
|
||||
|
||||
public interface 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
|
||||
}
|
||||
|
||||
public final class B : A {
|
||||
public constructor B()
|
||||
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 class Cls {
|
||||
public constructor Cls()
|
||||
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 final fun take(/*0*/ arg: B): kotlin.Unit
|
||||
public final fun test(/*0*/ s: kotlin.String): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun create(): Map<String, String> = null!!
|
||||
|
||||
operator fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> = null!!
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun create(): Map<String, String> = null!!
|
||||
|
||||
operator fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> = null!!
|
||||
@@ -14,7 +13,7 @@ class MyClass {
|
||||
m = create()
|
||||
// See KT-7428
|
||||
for ((k, v) in <!SMARTCAST_IMPOSSIBLE!>m<!>)
|
||||
res <!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>+=<!> (<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>k<!>.<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>length<!> <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>+<!> <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>v<!>.<!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>length<!>)
|
||||
res += (k.length + v.length)
|
||||
return res
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER
|
||||
// SKIP_TXT
|
||||
|
||||
/*
|
||||
* KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE)
|
||||
*
|
||||
* SECTIONS: dfa
|
||||
* NUMBER: 46
|
||||
* DESCRIPTION: Raw data flow analysis test
|
||||
* HELPERS: classes, objects, typealiases, functions, enumClasses, interfaces, sealedClasses
|
||||
*/
|
||||
|
||||
// TESTCASE NUMBER: 1
|
||||
fun case_1(x: Int) = ""
|
||||
fun case_1(x: Int?) = 10
|
||||
fun case_1() {
|
||||
var x: Int? = 10
|
||||
var y = { x = null }
|
||||
if (x != null) {
|
||||
val z = case_1(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
val case_2_prop: Int?
|
||||
get() = 10
|
||||
fun case_2(x: Int) = ""
|
||||
fun case_2(x: Int?) = 10
|
||||
fun case_2() {
|
||||
if (case_2_prop != null) {
|
||||
val z = case_2(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>case_2_prop<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
class Case4 {
|
||||
var x: Int? = 10
|
||||
}
|
||||
fun case_3(x: Int) = ""
|
||||
fun case_3(x: Int?) = 10
|
||||
fun case_3(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_3(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
open class Case5 {
|
||||
open val x: Int? = 10
|
||||
}
|
||||
fun case_4(x: Int) = ""
|
||||
fun case_4(x: Int?) = 10
|
||||
fun case_4(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_4(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 5
|
||||
class Case6 {
|
||||
val x: Int? by lazy { 10 }
|
||||
}
|
||||
fun case_5(x: Int) = ""
|
||||
fun case_5(x: Int?) = 10
|
||||
fun case_5(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_5(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 6
|
||||
var case_6_prop: Int?
|
||||
get() = 10
|
||||
set(value) {}
|
||||
fun case_6(x: Int) = ""
|
||||
fun case_6(x: Int?) = 10
|
||||
fun case_6() {
|
||||
if (case_6_prop != null) {
|
||||
val z = case_6(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?"), SMARTCAST_IMPOSSIBLE, SMARTCAST_IMPOSSIBLE!>case_6_prop<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
@@ -21,79 +21,3 @@ fun case_1() {
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(x: Int) = ""
|
||||
fun case_2(x: Int?) = 10
|
||||
fun case_2() {
|
||||
var x: Int? = 10
|
||||
var y = { x = null }
|
||||
if (x != null) {
|
||||
val z = case_2(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
val case_3_prop: Int?
|
||||
get() = 10
|
||||
fun case_3(x: Int) = ""
|
||||
fun case_3(x: Int?) = 10
|
||||
fun case_3() {
|
||||
if (case_3_prop != null) {
|
||||
val z = case_3(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>case_3_prop<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
class Case4 {
|
||||
var x: Int? = 10
|
||||
}
|
||||
fun case_4(x: Int) = ""
|
||||
fun case_4(x: Int?) = 10
|
||||
fun case_4(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_4(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 5
|
||||
open class Case5 {
|
||||
open val x: Int? = 10
|
||||
}
|
||||
fun case_5(x: Int) = ""
|
||||
fun case_5(x: Int?) = 10
|
||||
fun case_5(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_5(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 6
|
||||
class Case6 {
|
||||
val x: Int? by lazy { 10 }
|
||||
}
|
||||
fun case_6(x: Int) = ""
|
||||
fun case_6(x: Int?) = 10
|
||||
fun case_6(y: Case4) {
|
||||
if (y.x != null) {
|
||||
val z = case_6(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>y.x<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
// TESTCASE NUMBER: 7
|
||||
var case_7_prop: Int?
|
||||
get() = 10
|
||||
set(value) {}
|
||||
fun case_7(x: Int) = ""
|
||||
fun case_7(x: Int?) = 10
|
||||
fun case_7() {
|
||||
if (case_7_prop != null) {
|
||||
val z = case_7(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>case_7_prop<!>)
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>z<!>
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+5
@@ -4842,6 +4842,11 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
|
||||
runTest("compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/45.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("46.kt")
|
||||
public void test46() throws Exception {
|
||||
runTest("compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/46.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("5.kt")
|
||||
public void test5() throws Exception {
|
||||
runTest("compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/5.kt");
|
||||
|
||||
@@ -18374,6 +18374,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/inferenceInLinkedLambdasDependentOnExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt36264.kt")
|
||||
public void testKt36264() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/kt36264.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localObject.kt")
|
||||
public void testLocalObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/localObject.kt");
|
||||
|
||||
Generated
+5
@@ -18364,6 +18364,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/inferenceInLinkedLambdasDependentOnExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt36264.kt")
|
||||
public void testKt36264() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/kt36264.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localObject.kt")
|
||||
public void testLocalObject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/resolve/localObject.kt");
|
||||
|
||||
Reference in New Issue
Block a user