Skip to content

Commit 76d3246

Browse files
committed
Fix type of member references without explicit class on LHS
Type of '::foo' for a function foo in a class A should be KFunction0<Unit>, not KFunction1<A, Unit>. Continue to report an error in this case, to be maybe supported in the future
1 parent d8263eb commit 76d3246

File tree

5 files changed

+38
-33
lines changed

5 files changed

+38
-33
lines changed

compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -181,24 +181,6 @@ fun resolveCallableReferenceTarget(
181181
}
182182
}
183183

184-
private fun createReflectionTypeForFunction(
185-
descriptor: FunctionDescriptor,
186-
receiverType: KotlinType?,
187-
reflectionTypes: ReflectionTypes
188-
): KotlinType? {
189-
val returnType = descriptor.returnType ?: return null
190-
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters)
191-
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
192-
}
193-
194-
private fun createReflectionTypeForProperty(
195-
descriptor: PropertyDescriptor,
196-
receiverType: KotlinType?,
197-
reflectionTypes: ReflectionTypes
198-
): KotlinType {
199-
return reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, descriptor.isVar)
200-
}
201-
202184
private fun bindFunctionReference(expression: KtCallableReferenceExpression, type: KotlinType, context: ResolutionContext<*>) {
203185
val functionDescriptor = AnonymousFunctionDescriptor(
204186
context.scope.ownerDescriptor,
@@ -230,7 +212,8 @@ private fun createReflectionTypeForCallableDescriptor(
230212
lhsType: KotlinType?,
231213
reflectionTypes: ReflectionTypes,
232214
trace: BindingTrace?,
233-
reportOn: KtExpression?
215+
reportOn: KtExpression?,
216+
ignoreReceiver: Boolean
234217
): KotlinType? {
235218
val extensionReceiver = descriptor.extensionReceiverParameter
236219
val dispatchReceiver = descriptor.dispatchReceiverParameter?.let { dispatchReceiver ->
@@ -248,15 +231,19 @@ private fun createReflectionTypeForCallableDescriptor(
248231
}
249232

250233
val receiverType =
251-
if (extensionReceiver != null || dispatchReceiver != null)
234+
if ((extensionReceiver != null || dispatchReceiver != null) && !ignoreReceiver)
252235
lhsType ?: extensionReceiver?.type ?: dispatchReceiver?.type
253236
else null
254237

255238
return when (descriptor) {
256-
is FunctionDescriptor ->
257-
createReflectionTypeForFunction(descriptor, receiverType, reflectionTypes)
258-
is PropertyDescriptor ->
259-
createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes)
239+
is FunctionDescriptor -> {
240+
val returnType = descriptor.returnType ?: return null
241+
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters)
242+
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
243+
}
244+
is PropertyDescriptor -> {
245+
reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, descriptor.isVar)
246+
}
260247
is VariableDescriptor -> {
261248
if (reportOn != null) {
262249
trace?.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet"))
@@ -270,9 +257,10 @@ private fun createReflectionTypeForCallableDescriptor(
270257

271258
fun getReflectionTypeForCandidateDescriptor(
272259
descriptor: CallableDescriptor,
273-
reflectionTypes: ReflectionTypes
260+
reflectionTypes: ReflectionTypes,
261+
ignoreReceiver: Boolean
274262
): KotlinType? =
275-
createReflectionTypeForCallableDescriptor(descriptor, null, reflectionTypes, null, null)
263+
createReflectionTypeForCallableDescriptor(descriptor, null, reflectionTypes, null, null, ignoreReceiver)
276264

277265
fun createReflectionTypeForResolvedCallableReference(
278266
reference: KtCallableReferenceExpression,
@@ -282,7 +270,7 @@ fun createReflectionTypeForResolvedCallableReference(
282270
reflectionTypes: ReflectionTypes
283271
): KotlinType? {
284272
val type = createReflectionTypeForCallableDescriptor(
285-
descriptor, lhsType, reflectionTypes, context.trace, reference.getCallableReference()
273+
descriptor, lhsType, reflectionTypes, context.trace, reference.callableReference, reference.typeReference == null
286274
) ?: return null
287275
when (descriptor) {
288276
is FunctionDescriptor -> {
@@ -310,7 +298,8 @@ fun getResolvedCallableReferenceShapeType(
310298
null
311299
overloadResolutionResults.isSingleResult ->
312300
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call ->
313-
createReflectionTypeForCallableDescriptor(call.resultingDescriptor, lhsType, reflectionTypes, context.trace, reference)
301+
createReflectionTypeForCallableDescriptor(call.resultingDescriptor, lhsType, reflectionTypes, context.trace, reference,
302+
reference.typeReference == null)
314303
}
315304
expectedTypeUnknown /* && overload resolution was ambiguous */ ->
316305
functionPlaceholders.createFunctionPlaceholderType(emptyList(), false)

compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,11 @@ class CandidateResolver(
157157
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.checkExpectedCallableType()
158158
= check {
159159
if (!noExpectedType(expectedType)) {
160-
val candidate = candidateCall.getCandidateDescriptor()
161-
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, reflectionTypes);
160+
val candidate = candidateCall.candidateDescriptor
161+
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(
162+
candidate, reflectionTypes,
163+
call.callElement.parent.let { it is KtCallableReferenceExpression && it.typeReference == null }
164+
);
162165
if (candidateReflectionType != null) {
163166
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) {
164167
candidateCall.addStatus(OTHER_ERROR)
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// !CHECK_TYPE
22

3-
import kotlin.reflect.KFunction1
3+
import kotlin.reflect.KFunction0
4+
5+
fun explicitlyExpectFunction0(f: () -> Unit) = f
6+
fun explicitlyExpectFunction1(f: (A) -> Unit) = f
47

58
fun foo() {}
69

@@ -10,6 +13,12 @@ class A {
1013
fun main() {
1114
val x = ::<!CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS!>foo<!>
1215

13-
checkSubtype<KFunction1<A, Unit>>(x)
16+
checkSubtype<KFunction0<Unit>>(x)
17+
18+
explicitlyExpectFunction0(x)
19+
explicitlyExpectFunction1(<!TYPE_MISMATCH!>x<!>)
20+
21+
explicitlyExpectFunction0(::<!CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS!>foo<!>)
22+
explicitlyExpectFunction1(<!TYPE_MISMATCH!>::<!CALLABLE_REFERENCE_TO_MEMBER_OR_EXTENSION_WITH_EMPTY_LHS!>foo<!><!>)
1423
}
1524
}

compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package
22

3+
public fun explicitlyExpectFunction0(/*0*/ f: () -> kotlin.Unit): () -> kotlin.Unit
4+
public fun explicitlyExpectFunction1(/*0*/ f: (A) -> kotlin.Unit): (A) -> kotlin.Unit
35
public fun foo(): kotlin.Unit
46

57
public final class A {

idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ private fun MutableCollection<LookupElement>.addLookupElementsForNullable(factor
248248

249249
fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade): FuzzyType? {
250250
if (!CallType.CALLABLE_REFERENCE.descriptorKindFilter.accepts(this)) return null // not supported by callable references
251-
return getReflectionTypeForCandidateDescriptor(this, resolutionFacade.getFrontendService(ReflectionTypes::class.java))?.toFuzzyType(emptyList())
251+
return getReflectionTypeForCandidateDescriptor(
252+
this, resolutionFacade.getFrontendService(ReflectionTypes::class.java), false
253+
)?.toFuzzyType(emptyList())
252254
}
253255

254256
enum class SmartCompletionItemPriority {

0 commit comments

Comments
 (0)