Deduce receiver type of callable reference from LHS, not from descriptor

This commit is contained in:
Alexander Udalov
2015-10-15 13:05:55 +03:00
parent 2cf437c0e2
commit bf4a681589
6 changed files with 59 additions and 8 deletions
@@ -201,6 +201,7 @@ private fun bindPropertyReference(expression: JetCallableReferenceExpression, re
private fun createReflectionTypeForCallableDescriptor( private fun createReflectionTypeForCallableDescriptor(
descriptor: CallableDescriptor, descriptor: CallableDescriptor,
lhsType: JetType?,
reflectionTypes: ReflectionTypes, reflectionTypes: ReflectionTypes,
trace: BindingTrace?, trace: BindingTrace?,
reportOn: JetExpression? reportOn: JetExpression?
@@ -220,7 +221,10 @@ private fun createReflectionTypeForCallableDescriptor(
return null return null
} }
val receiverType = extensionReceiver?.getType() ?: dispatchReceiver?.getType() val receiverType =
if (extensionReceiver != null || dispatchReceiver != null)
lhsType ?: extensionReceiver?.type ?: dispatchReceiver?.type
else null
return when (descriptor) { return when (descriptor) {
is FunctionDescriptor -> is FunctionDescriptor ->
@@ -242,16 +246,18 @@ public fun getReflectionTypeForCandidateDescriptor(
descriptor: CallableDescriptor, descriptor: CallableDescriptor,
reflectionTypes: ReflectionTypes reflectionTypes: ReflectionTypes
): JetType? = ): JetType? =
createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, null, null) createReflectionTypeForCallableDescriptor(descriptor, null, reflectionTypes, null, null)
public fun createReflectionTypeForResolvedCallableReference( public fun createReflectionTypeForResolvedCallableReference(
reference: JetCallableReferenceExpression, reference: JetCallableReferenceExpression,
lhsType: JetType?,
descriptor: CallableDescriptor, descriptor: CallableDescriptor,
context: ResolutionContext<*>, context: ResolutionContext<*>,
reflectionTypes: ReflectionTypes reflectionTypes: ReflectionTypes
): JetType? { ): JetType? {
val type = createReflectionTypeForCallableDescriptor(descriptor, reflectionTypes, context.trace, reference.getCallableReference()) val type = createReflectionTypeForCallableDescriptor(
?: return null descriptor, lhsType, reflectionTypes, context.trace, reference.getCallableReference()
) ?: return null
when (descriptor) { when (descriptor) {
is FunctionDescriptor -> { is FunctionDescriptor -> {
bindFunctionReference(reference, type, context) bindFunctionReference(reference, type, context)
@@ -265,6 +271,7 @@ public fun createReflectionTypeForResolvedCallableReference(
public fun getResolvedCallableReferenceShapeType( public fun getResolvedCallableReferenceShapeType(
reference: JetCallableReferenceExpression, reference: JetCallableReferenceExpression,
lhsType: JetType?,
overloadResolutionResults: OverloadResolutionResults<CallableDescriptor>?, overloadResolutionResults: OverloadResolutionResults<CallableDescriptor>?,
context: ResolutionContext<*>, context: ResolutionContext<*>,
expectedTypeUnknown: Boolean, expectedTypeUnknown: Boolean,
@@ -275,9 +282,9 @@ public fun getResolvedCallableReferenceShapeType(
when { when {
overloadResolutionResults == null -> overloadResolutionResults == null ->
null null
overloadResolutionResults.isSingleResult() -> overloadResolutionResults.isSingleResult ->
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call -> OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call ->
createReflectionTypeForCallableDescriptor(call.getResultingDescriptor(), reflectionTypes, context.trace, reference) createReflectionTypeForCallableDescriptor(call.resultingDescriptor, lhsType, reflectionTypes, context.trace, reference)
} }
expectedTypeUnknown /* && overload resolution was ambiguous */ -> expectedTypeUnknown /* && overload resolution was ambiguous */ ->
functionPlaceholders.createFunctionPlaceholderType(emptyList(), false) functionPlaceholders.createFunctionPlaceholderType(emptyList(), false)
@@ -250,7 +250,7 @@ public class ArgumentTypeResolver {
callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS, callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
callResolver); callResolver);
return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType( return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType(
callableReferenceExpression, overloadResolutionResults, context, expectedTypeIsUnknown, callableReferenceExpression, receiverType, overloadResolutionResults, context, expectedTypeIsUnknown,
reflectionTypes, builtIns, functionPlaceholders); reflectionTypes, builtIns, functionPlaceholders);
} }
@@ -700,7 +700,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(CALLABLE_REFERENCE_TO_OBJECT_MEMBER.on(reference)); context.trace.report(CALLABLE_REFERENCE_TO_OBJECT_MEMBER.on(reference));
} }
return CallableReferencesResolutionUtilsKt.createReflectionTypeForResolvedCallableReference(expression, descriptor, context, components.reflectionTypes); return CallableReferencesResolutionUtilsKt.createReflectionTypeForResolvedCallableReference(
expression, lhsType, descriptor, context, components.reflectionTypes
);
} }
@Override @Override
@@ -0,0 +1,18 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.*
interface A
interface B : A
fun A.foo() {}
fun take(f: (A) -> Unit) {}
fun take(f: () -> Unit) {}
fun test() {
B::foo checkType { _<KFunction1<B, Unit>>() }
<!NONE_APPLICABLE!>take<!>(B::foo)
}
@@ -0,0 +1,18 @@
package
public fun take(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
public fun take(/*0*/ f: (A) -> kotlin.Unit): kotlin.Unit
public fun test(): kotlin.Unit
public fun A.foo(): 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 interface B : 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
}
@@ -1721,6 +1721,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("extensionToSupertype.kt")
public void testExtensionToSupertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/function/extensionToSupertype.kt");
doTest(fileName);
}
@TestMetadata("fakeOverrideType.kt") @TestMetadata("fakeOverrideType.kt")
public void testFakeOverrideType() throws Exception { public void testFakeOverrideType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/function/fakeOverrideType.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/function/fakeOverrideType.kt");