diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 3faeec79c8f..17a61b320dd 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -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"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index d8ef1849cf6..1414156b4c0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.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()) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt index 26098f933aa..4d5c2feaf04 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt @@ -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") } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt index d23ffd97890..958660cffd3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponeArgumentsChecks.kt @@ -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) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index cbbc742ccbf..f93d5e43cf2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -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" } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt index efdd5636b82..d8317281573 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt @@ -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) diff --git a/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt b/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt new file mode 100644 index 00000000000..89e2e3aa823 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.kt @@ -0,0 +1,43 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION -UNUSED_VARIABLE + +import kotlin.reflect.KProperty1 + +class Scope { + abstract class Nested { + abstract val key: Int + abstract val keyT: T + } +} + +fun simple(a: Any?) {} +fun id(x: K): K = x + +fun test() { + simple(Scope.Nested::key) + val a = id(Scope.Nested::keyT) + + , kotlin.String>")!>a + + val b = id(Scope.Nested<*>::keyT) + + , kotlin.Any?>")!>b + + val c = id(Scope.Nested::keyT) + + , kotlin.Number?>")!>c + + val d = id(Scope.Nested<*>::keyT as Scope.Nested) + + ")!>d + + val g = id, Any?>>(Scope.Nested<*>::keyT) + + , kotlin.Any?>")!>g +} + +fun justResolve() { + val a = Scope.Nested::key + val b = Scope.Nested::keyT + val c = Scope.Nested<*>::keyT + val d = Scope.Nested::keyT +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.txt b/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.txt new file mode 100644 index 00000000000..750b503ead9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/propertyOfNestedGenericClass.txt @@ -0,0 +1,22 @@ +package + +public fun 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 { + public constructor Nested() + 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 8c69459b93c..767be9a14ad 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 5bd7765022f..56d42ee5fbb 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -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");