[FIR] Fix incorrect resolve of callable reference in function signature (^KT-48304 Fixed)
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ FILE: referenceToField.kt
|
|||||||
|
|
||||||
public final val x: R|kotlin/Int| = Int(1)
|
public final val x: R|kotlin/Int| = Int(1)
|
||||||
public get(): R|kotlin/Int| {
|
public get(): R|kotlin/Int| {
|
||||||
::F|/A.x|
|
::<References to variables aren't supported yet>#
|
||||||
^ this@R|/A|.F|/A.x|
|
^ this@R|/A|.F|/A.x|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-10
@@ -50,15 +50,5 @@ object FirCallableReferenceChecker : FirQualifiedAccessExpressionChecker() {
|
|||||||
) {
|
) {
|
||||||
reporter.reportOn(source, FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED, referredSymbol, context)
|
reporter.reportOn(source, FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED, referredSymbol, context)
|
||||||
}
|
}
|
||||||
// The counterpart in FE 1.0 checks if the given descriptor is VariableDescriptor yet not PropertyDescriptor.
|
|
||||||
// Here, we explicitly check if the referred declaration/symbol is value parameter, local variable, or backing field.
|
|
||||||
if (
|
|
||||||
referredSymbol is FirValueParameterSymbol ||
|
|
||||||
(referredSymbol is FirPropertySymbol && referredSymbol.isLocal) ||
|
|
||||||
reference.resolvedSymbol is FirBackingFieldSymbol
|
|
||||||
) {
|
|
||||||
// TODO: we can't set positioning strategy to meta error. Should report on reference expression, not entire reference access.
|
|
||||||
reporter.reportOn(source, FirErrors.UNSUPPORTED, "References to variables aren't supported yet", context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -89,7 +89,7 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
|||||||
is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead
|
is ConeTypeParameterInQualifiedAccess -> null // reported in various checkers instead
|
||||||
is ConeNotAnnotationContainer -> null
|
is ConeNotAnnotationContainer -> null
|
||||||
is ConeImportFromSingleton -> FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.createOn(source, this.name)
|
is ConeImportFromSingleton -> FirErrors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.createOn(source, this.name)
|
||||||
is ConeUnsupportedDynamicType -> FirErrors.UNSUPPORTED.createOn(source, this.reason)
|
is ConeUnsupported -> FirErrors.UNSUPPORTED.createOn(this.source ?: source, this.reason)
|
||||||
is ConeLocalVariableNoTypeOrInitializer ->
|
is ConeLocalVariableNoTypeOrInitializer ->
|
||||||
runIf(variable.isLocalMember) { FirErrors.VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.createOn(source) }
|
runIf(variable.isLocalMember) { FirErrors.VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.createOn(source) }
|
||||||
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
|
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
|
||||||
|
|||||||
@@ -378,7 +378,12 @@ class FirCallResolver(
|
|||||||
noSuccessfulCandidates -> {
|
noSuccessfulCandidates -> {
|
||||||
val errorReference = buildErrorReference(
|
val errorReference = buildErrorReference(
|
||||||
info,
|
info,
|
||||||
ConeUnresolvedReferenceError(info.name),
|
if (applicability == CandidateApplicability.UNSUPPORTED) {
|
||||||
|
val unsupportedResolutionDiagnostic = reducedCandidates.firstOrNull()?.diagnostics?.firstOrNull() as? Unsupported
|
||||||
|
ConeUnsupported(unsupportedResolutionDiagnostic?.message ?: "", unsupportedResolutionDiagnostic?.source)
|
||||||
|
} else {
|
||||||
|
ConeUnresolvedReferenceError(info.name)
|
||||||
|
},
|
||||||
callableReferenceAccess.source
|
callableReferenceAccess.source
|
||||||
)
|
)
|
||||||
resolvedCallableReferenceAtom.resultingReference = errorReference
|
resolvedCallableReferenceAtom.resultingReference = errorReference
|
||||||
|
|||||||
+12
-3
@@ -17,8 +17,7 @@ import org.jetbrains.kotlin.fir.moduleData
|
|||||||
import org.jetbrains.kotlin.fir.returnExpressions
|
import org.jetbrains.kotlin.fir.returnExpressions
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.classId
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
@@ -51,7 +50,7 @@ class CandidateFactory private constructor(
|
|||||||
extensionReceiverValue: ReceiverValue? = null,
|
extensionReceiverValue: ReceiverValue? = null,
|
||||||
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
|
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
|
||||||
): Candidate {
|
): Candidate {
|
||||||
return Candidate(
|
val result = Candidate(
|
||||||
symbol, dispatchReceiverValue, extensionReceiverValue,
|
symbol, dispatchReceiverValue, extensionReceiverValue,
|
||||||
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
|
explicitReceiverKind, context.inferenceComponents.constraintSystemFactory, baseSystem,
|
||||||
builtInExtensionFunctionReceiverValue?.receiverExpression?.let {
|
builtInExtensionFunctionReceiverValue?.receiverExpression?.let {
|
||||||
@@ -65,6 +64,16 @@ class CandidateFactory private constructor(
|
|||||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> false
|
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, ExplicitReceiverKind.BOTH_RECEIVERS -> false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The counterpart in FE 1.0 checks if the given descriptor is VariableDescriptor yet not PropertyDescriptor.
|
||||||
|
// Here, we explicitly check if the referred declaration/symbol is value parameter, local variable, or backing field.
|
||||||
|
val callSite = callInfo.callSite
|
||||||
|
if (callSite is FirCallableReferenceAccess) {
|
||||||
|
if (symbol is FirValueParameterSymbol || symbol is FirPropertySymbol && symbol.isLocal || symbol is FirBackingFieldSymbol) {
|
||||||
|
result.addDiagnostic(Unsupported("References to variables aren't supported yet", callSite.calleeReference.source))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ReceiverValue?.isCandidateFromCompanionObjectTypeScope(): Boolean {
|
private fun ReceiverValue?.isCandidateFromCompanionObjectTypeScope(): Boolean {
|
||||||
|
|||||||
+3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
@@ -94,3 +95,5 @@ class ManyLambdaExpressionArguments(
|
|||||||
|
|
||||||
class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER)
|
class InfixCallOfNonInfixFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER)
|
||||||
class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER)
|
class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) : ResolutionDiagnostic(INAPPLICABLE_MODIFIER)
|
||||||
|
|
||||||
|
class Unsupported(val message: String, val source: FirSourceElement? = null) : ResolutionDiagnostic(UNSUPPORTED)
|
||||||
+4
-2
@@ -156,10 +156,12 @@ class ConeImportFromSingleton(val name: Name) : ConeDiagnostic() {
|
|||||||
override val reason: String get() = "Import from singleton $name is not allowed"
|
override val reason: String get() = "Import from singleton $name is not allowed"
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConeUnsupportedDynamicType() : ConeDiagnostic() {
|
open class ConeUnsupported(val message: String, val source: FirSourceElement? = null) : ConeDiagnostic() {
|
||||||
override val reason: String get() = "Dynamic types are not supported in this context"
|
override val reason: String get() = message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ConeUnsupportedDynamicType : ConeUnsupported("Dynamic types are not supported in this context")
|
||||||
|
|
||||||
class ConeDeprecated(val source: FirSourceElement?, val symbol: FirBasedSymbol<*>, val deprecation: Deprecation) : ConeDiagnostic() {
|
class ConeDeprecated(val source: FirSourceElement?, val symbol: FirBasedSymbol<*>, val deprecation: Deprecation) : ConeDiagnostic() {
|
||||||
override val reason: String get() = "Deprecated: ${deprecation.message}"
|
override val reason: String get() = "Deprecated: ${deprecation.message}"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
|||||||
enum class CandidateApplicability {
|
enum class CandidateApplicability {
|
||||||
RESOLVED_TO_SAM_WITH_VARARG, // migration warning up to 1.5 (when resolve to function with SAM conversion and array without spread as vararg)
|
RESOLVED_TO_SAM_WITH_VARARG, // migration warning up to 1.5 (when resolve to function with SAM conversion and array without spread as vararg)
|
||||||
HIDDEN, // removed from resolve
|
HIDDEN, // removed from resolve
|
||||||
|
UNSUPPORTED, // unsupported feature
|
||||||
INAPPLICABLE_WRONG_RECEIVER, // receiver not matched
|
INAPPLICABLE_WRONG_RECEIVER, // receiver not matched
|
||||||
INAPPLICABLE_ARGUMENTS_MAPPING_ERROR, // arguments not mapped to parameters (i.e. different size of arguments and parameters)
|
INAPPLICABLE_ARGUMENTS_MAPPING_ERROR, // arguments not mapped to parameters (i.e. different size of arguments and parameters)
|
||||||
INAPPLICABLE, // arguments have wrong types
|
INAPPLICABLE, // arguments have wrong types
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
|
||||||
|
fun a() {
|
||||||
|
val x = 10
|
||||||
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(::<!UNSUPPORTED!>x<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(a: Any) {}
|
||||||
|
|
||||||
|
fun test1(test2: () -> Unit = ::test2) {} // Resolve to function
|
||||||
|
private fun test2() {}
|
||||||
|
fun test3(test4: () -> Unit = ::<!UNSUPPORTED!>test4<!>) {}
|
||||||
|
|
||||||
|
fun test5(test6: (test: Test) -> Unit = Test::helper) {
|
||||||
|
test6(Test())
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun helper() {}
|
||||||
|
}
|
||||||
|
|
||||||
+14
-1
@@ -1,9 +1,22 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
|
||||||
fun a() {
|
fun a() {
|
||||||
val x = 10
|
val x = 10
|
||||||
foo(::<!UNSUPPORTED!>x<!>)
|
foo(::<!UNSUPPORTED!>x<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(a: Any) {}
|
fun foo(a: Any) {}
|
||||||
|
|
||||||
|
fun test1(test2: () -> Unit = ::test2) {} // Resolve to function
|
||||||
|
private fun test2() {}
|
||||||
|
fun test3(test4: () -> Unit = ::<!UNSUPPORTED!>test4<!>) {}
|
||||||
|
|
||||||
|
fun test5(test6: (test: Test) -> Unit = Test::helper) {
|
||||||
|
test6(Test())
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun helper() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+13
@@ -2,3 +2,16 @@ package
|
|||||||
|
|
||||||
public fun a(): kotlin.Unit
|
public fun a(): kotlin.Unit
|
||||||
public fun foo(/*0*/ a: kotlin.Any): kotlin.Unit
|
public fun foo(/*0*/ a: kotlin.Any): kotlin.Unit
|
||||||
|
public fun test1(/*0*/ test2: () -> kotlin.Unit = ...): kotlin.Unit
|
||||||
|
private fun test2(): kotlin.Unit
|
||||||
|
public fun test3(/*0*/ test4: () -> kotlin.Unit = ...): kotlin.Unit
|
||||||
|
public fun test5(/*0*/ test6: (test: Test) -> kotlin.Unit = ...): kotlin.Unit
|
||||||
|
|
||||||
|
public final class Test {
|
||||||
|
public constructor Test()
|
||||||
|
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 helper(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
fun eat(value: Any) {}
|
||||||
|
|
||||||
|
fun test(param: String) {
|
||||||
|
val a = ::<!UNSUPPORTED!>param<!>
|
||||||
|
|
||||||
|
val local = "local"
|
||||||
|
val b = ::<!UNSUPPORTED!>local<!>
|
||||||
|
|
||||||
|
val lambda = { -> }
|
||||||
|
val g = ::<!UNSUPPORTED!>lambda<!>
|
||||||
|
|
||||||
|
<!INAPPLICABLE_CANDIDATE!>eat<!>(::<!UNSUPPORTED!>param<!>)
|
||||||
|
}
|
||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
fun eat(value: Any) {}
|
fun eat(value: Any) {}
|
||||||
|
|||||||
+1
-1
@@ -9,6 +9,6 @@ class Foo {
|
|||||||
fun main() {
|
fun main() {
|
||||||
val f = Foo()
|
val f = Foo()
|
||||||
val a: Int
|
val a: Int
|
||||||
<!VARIABLE_EXPECTED!>get()<!> = f.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getValue<!>(null, ::<!UNSUPPORTED!>a<!>) // no exception after fix
|
<!VARIABLE_EXPECTED!>get()<!> = f.<!INAPPLICABLE_CANDIDATE!>getValue<!>(null, ::<!UNSUPPORTED!>a<!>) // no exception after fix
|
||||||
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
|
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -9,6 +9,6 @@ class Foo {
|
|||||||
fun main(x: Int) {
|
fun main(x: Int) {
|
||||||
val f = Foo()
|
val f = Foo()
|
||||||
val a: Int
|
val a: Int
|
||||||
<!VARIABLE_EXPECTED!>get()<!> = f.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getValue<!>(null, ::<!UNSUPPORTED!>x<!>) // no exception after fix
|
<!VARIABLE_EXPECTED!>get()<!> = f.<!INAPPLICABLE_CANDIDATE!>getValue<!>(null, ::<!UNSUPPORTED!>x<!>) // no exception after fix
|
||||||
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
|
<!UNRESOLVED_REFERENCE!>print<!>(<!UNINITIALIZED_VARIABLE!>a<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -3,6 +3,6 @@
|
|||||||
internal class Z<K> {
|
internal class Z<K> {
|
||||||
val map = HashMap<String, String>()
|
val map = HashMap<String, String>()
|
||||||
inline fun compute(key: String, producer: () -> String): String {
|
inline fun compute(key: String, producer: () -> String): String {
|
||||||
return map.<!INAPPLICABLE_CANDIDATE!>getOrPut<!>(key, ::<!UNRESOLVED_REFERENCE!>producer<!>)
|
return map.<!INAPPLICABLE_CANDIDATE!>getOrPut<!>(key, ::<!UNSUPPORTED!>producer<!>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user