[NI] Support callable references on qualified types with generics
#KT-32154 Fixed
This commit is contained in:
+5
@@ -1719,6 +1719,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/parsingPriorityOfGenericArgumentsVsLess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyOfNestedGenericClass.kt")
|
||||
public void testPropertyOfNestedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rewriteAtSliceOnGetOperator.kt")
|
||||
public void testRewriteAtSliceOnGetOperator() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/rewriteAtSliceOnGetOperator.kt");
|
||||
|
||||
@@ -683,10 +683,7 @@ class PSICallResolver(
|
||||
is DoubleColonLHS.Type -> {
|
||||
val qualifiedExpression = ktExpression.receiverExpression!!.let { it.referenceExpression() ?: it }
|
||||
val qualifier = expressionTypingContext.trace.get(BindingContext.QUALIFIER, qualifiedExpression)
|
||||
when (qualifier) {
|
||||
is ClassQualifier, is TypeAliasQualifier -> LHSResult.Type(qualifier, lhsResult.type.unwrap())
|
||||
else -> LHSResult.Error
|
||||
}
|
||||
LHSResult.Type(qualifier, lhsResult.type.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-14
@@ -19,10 +19,11 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.EXTENSION_R
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.expressions.CoercionStrategy
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
@@ -32,11 +33,10 @@ import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
sealed class CallableReceiver(val receiver: ReceiverValueWithSmartCastInfo) {
|
||||
class UnboundReference(val qualifier: QualifierReceiver, receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
class BoundValueReference(val qualifier: QualifierReceiver, receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
class UnboundReference(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
class BoundValueReference(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
class ScopeReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
class ExplicitValueReceiver(val lhsArgument: SimpleKotlinCallArgument, receiver: ReceiverValueWithSmartCastInfo) :
|
||||
CallableReceiver(receiver)
|
||||
class ExplicitValueReceiver(receiver: ReceiverValueWithSmartCastInfo) : CallableReceiver(receiver)
|
||||
}
|
||||
|
||||
// todo investigate similar code in CheckVisibility
|
||||
@@ -89,7 +89,7 @@ fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory
|
||||
// note that if we use PrioritizedCompositeScopeTowerProcessor then static will win over unbound members
|
||||
val staticOrUnbound = SamePriorityCompositeScopeTowerProcessor(static, unbound)
|
||||
|
||||
val asValue = lhsResult.qualifier.classValueReceiverWithSmartCastInfo ?: return staticOrUnbound
|
||||
val asValue = lhsResult.qualifier?.classValueReceiverWithSmartCastInfo ?: return staticOrUnbound
|
||||
return PrioritizedCompositeScopeTowerProcessor(staticOrUnbound, factory.createCallableProcessor(asValue))
|
||||
}
|
||||
is LHSResult.Object -> {
|
||||
@@ -329,17 +329,16 @@ class CallableReferencesCandidateFactory(
|
||||
private fun toCallableReceiver(receiver: ReceiverValueWithSmartCastInfo, isExplicit: Boolean): CallableReceiver {
|
||||
if (!isExplicit) return CallableReceiver.ScopeReceiver(receiver)
|
||||
|
||||
val lhsResult = argument.lhsResult
|
||||
return when (lhsResult) {
|
||||
is LHSResult.Expression -> CallableReceiver.ExplicitValueReceiver(lhsResult.lshCallArgument, receiver)
|
||||
return when (val lhsResult = argument.lhsResult) {
|
||||
is LHSResult.Expression -> CallableReceiver.ExplicitValueReceiver(receiver)
|
||||
is LHSResult.Type -> {
|
||||
if (lhsResult.qualifier.classValueReceiver?.type == receiver.receiverValue.type) {
|
||||
CallableReceiver.BoundValueReference(lhsResult.qualifier, receiver)
|
||||
if (lhsResult.qualifier?.classValueReceiver?.type == receiver.receiverValue.type) {
|
||||
CallableReceiver.BoundValueReference(receiver)
|
||||
} else {
|
||||
CallableReceiver.UnboundReference(lhsResult.qualifier, receiver)
|
||||
CallableReceiver.UnboundReference(receiver)
|
||||
}
|
||||
}
|
||||
is LHSResult.Object -> CallableReceiver.BoundValueReference(lhsResult.qualifier, receiver)
|
||||
is LHSResult.Object -> CallableReceiver.BoundValueReference(receiver)
|
||||
else -> throw IllegalStateException("Unsupported kind of lhsResult: $lhsResult")
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -167,7 +167,11 @@ private fun preprocessCallableReference(
|
||||
val lhsType = it.unboundDetailedReceiver.stableType
|
||||
if (ReflectionTypes.isNumberedTypeWithOneOrMoreNumber(expectedType)) {
|
||||
val lhsTypeVariable = expectedType.arguments.first().type.unwrap()
|
||||
csBuilder.addSubtypeConstraint(lhsType, lhsTypeVariable, LHSArgumentConstraintPosition(it.qualifier))
|
||||
csBuilder.addSubtypeConstraint(
|
||||
lhsType,
|
||||
lhsTypeVariable,
|
||||
LHSArgumentConstraintPosition(it.qualifier ?: it.unboundDetailedReceiver)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (notCallableTypeConstructor != null) {
|
||||
|
||||
+2
-3
@@ -21,9 +21,8 @@ import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
@@ -58,7 +57,7 @@ class KnownTypeParameterConstraintPosition(val typeArgument: KotlinType) : Const
|
||||
override fun toString() = "TypeArgument $typeArgument"
|
||||
}
|
||||
|
||||
class LHSArgumentConstraintPosition(val receiver: QualifierReceiver) : ConstraintPosition() {
|
||||
class LHSArgumentConstraintPosition(val receiver: DetailedReceiver) : ConstraintPosition() {
|
||||
override fun toString(): String {
|
||||
return "LHS receiver $receiver"
|
||||
}
|
||||
|
||||
+5
-3
@@ -78,12 +78,14 @@ interface FunctionExpression : LambdaKotlinCallArgument {
|
||||
* D.E::foo <-> Expression
|
||||
*/
|
||||
sealed class LHSResult {
|
||||
class Type(val qualifier: QualifierReceiver, resolvedType: UnwrappedType) : LHSResult() {
|
||||
class Type(val qualifier: QualifierReceiver?, resolvedType: UnwrappedType) : LHSResult() {
|
||||
val unboundDetailedReceiver: ReceiverValueWithSmartCastInfo
|
||||
|
||||
init {
|
||||
assert(qualifier.descriptor is ClassDescriptor || qualifier.descriptor is TypeAliasDescriptor) {
|
||||
"Should be ClassDescriptor: ${qualifier.descriptor}"
|
||||
if (qualifier != null) {
|
||||
assert(qualifier.descriptor is ClassDescriptor || qualifier.descriptor is TypeAliasDescriptor) {
|
||||
"Should be ClassDescriptor: ${qualifier.descriptor}"
|
||||
}
|
||||
}
|
||||
|
||||
val unboundReceiver = TransientReceiver(resolvedType)
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION -UNUSED_VARIABLE
|
||||
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
class Scope {
|
||||
abstract class Nested<T> {
|
||||
abstract val key: Int
|
||||
abstract val keyT: T
|
||||
}
|
||||
}
|
||||
|
||||
fun simple(a: Any?) {}
|
||||
fun <K> id(x: K): K = x
|
||||
|
||||
fun test() {
|
||||
simple(Scope.Nested<String>::key)
|
||||
val a = id(Scope.Nested<String>::keyT)
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty1<Scope.Nested<kotlin.String>, kotlin.String>")!>a<!>
|
||||
|
||||
val b = id(Scope.Nested<*>::keyT)
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty1<Scope.Nested<*>, kotlin.Any?>")!>b<!>
|
||||
|
||||
val c = id(Scope.Nested<out Number?>::keyT)
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty1<Scope.Nested<out kotlin.Number?>, kotlin.Number?>")!>c<!>
|
||||
|
||||
val d = id(Scope.Nested<*>::keyT <!UNCHECKED_CAST!>as Scope.Nested<Number><!>)
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("Scope.Nested<kotlin.Number>")!>d<!>
|
||||
|
||||
val g = id<KProperty1<Scope.Nested<*>, Any?>>(Scope.Nested<*>::keyT)
|
||||
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty1<Scope.Nested<*>, kotlin.Any?>")!>g<!>
|
||||
}
|
||||
|
||||
fun justResolve() {
|
||||
val a = Scope.Nested<String>::key
|
||||
val b = Scope.Nested<String>::keyT
|
||||
val c = Scope.Nested<*>::keyT
|
||||
val d = Scope.Nested<out Number?>::keyT
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ K> id(/*0*/ x: K): K
|
||||
public fun justResolve(): kotlin.Unit
|
||||
public fun simple(/*0*/ a: kotlin.Any?): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public final class Scope {
|
||||
public constructor Scope()
|
||||
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 abstract class Nested</*0*/ T> {
|
||||
public constructor Nested</*0*/ T>()
|
||||
public abstract val key: kotlin.Int
|
||||
public abstract val keyT: T
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1726,6 +1726,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/parsingPriorityOfGenericArgumentsVsLess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyOfNestedGenericClass.kt")
|
||||
public void testPropertyOfNestedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rewriteAtSliceOnGetOperator.kt")
|
||||
public void testRewriteAtSliceOnGetOperator() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/rewriteAtSliceOnGetOperator.kt");
|
||||
|
||||
Generated
+5
@@ -1721,6 +1721,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/parsingPriorityOfGenericArgumentsVsLess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyOfNestedGenericClass.kt")
|
||||
public void testPropertyOfNestedGenericClass() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rewriteAtSliceOnGetOperator.kt")
|
||||
public void testRewriteAtSliceOnGetOperator() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/callableReference/rewriteAtSliceOnGetOperator.kt");
|
||||
|
||||
Reference in New Issue
Block a user