KT-7068 None of the following functions can be called with two functions with extention function parameter
#KT-7068 Fixed
This commit is contained in:
@@ -56,6 +56,7 @@ import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumen
|
|||||||
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke;
|
import static org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
|
import static org.jetbrains.kotlin.resolve.calls.inference.InferencePackage.createCorrespondingExtensionFunctionTypeIfNecessary;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION;
|
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION;
|
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
|
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
|
||||||
@@ -536,13 +537,13 @@ public class CandidateResolver {
|
|||||||
}
|
}
|
||||||
else if (!noExpectedType(expectedType)) {
|
else if (!noExpectedType(expectedType)) {
|
||||||
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
||||||
JetType smartCastType = smartCastValueArgumentTypeIfPossible(expression, expectedType, type, newContext);
|
JetType morePreciseType = makeMorePreciseType(type, expression, newContext);
|
||||||
if (smartCastType == null) {
|
if (morePreciseType == null) {
|
||||||
resultStatus = OTHER_ERROR;
|
resultStatus = OTHER_ERROR;
|
||||||
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
|
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resultingType = smartCastType;
|
resultingType = morePreciseType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
||||||
@@ -556,6 +557,27 @@ public class CandidateResolver {
|
|||||||
return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
|
return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static <C extends CallResolutionContext<C>> JetType makeMorePreciseType(
|
||||||
|
@NotNull JetType type,
|
||||||
|
@NotNull JetExpression expression,
|
||||||
|
@NotNull CallResolutionContext<C> context
|
||||||
|
) {
|
||||||
|
JetType smartCastType = smartCastValueArgumentTypeIfPossible(expression, context.expectedType, type, context);
|
||||||
|
if (smartCastType != null) {
|
||||||
|
return smartCastType;
|
||||||
|
}
|
||||||
|
// function literal without declaring receiver type { x -> ... }
|
||||||
|
// can be considered as extension function if one is expected
|
||||||
|
if (ArgumentTypeResolver.isFunctionLiteralArgument(expression, context)) {
|
||||||
|
JetType extensionFunctionType = createCorrespondingExtensionFunctionTypeIfNecessary(type, context.expectedType);
|
||||||
|
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(extensionFunctionType, context.expectedType)) {
|
||||||
|
return extensionFunctionType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JetType smartCastValueArgumentTypeIfPossible(
|
private static JetType smartCastValueArgumentTypeIfPossible(
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun withLambda(block : Int.(String) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withLambda(o : Int, block : Int.(String) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
withLambda {
|
||||||
|
it.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
withLambda { r -> // no error should be here
|
||||||
|
r.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun test(): kotlin.Unit
|
||||||
|
internal fun withLambda(/*0*/ o: kotlin.Int, /*1*/ block: kotlin.Int.(kotlin.String) -> kotlin.Unit): kotlin.Unit
|
||||||
|
internal fun withLambda(/*0*/ block: kotlin.Int.(kotlin.String) -> kotlin.Unit): kotlin.Unit
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun withLambda(block : Int.(String) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withLambda(block : Int.(String, String) -> Unit) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
withLambda { r ->
|
||||||
|
r.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
withLambda { x, y ->
|
||||||
|
x.length() + y.length()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun test(): kotlin.Unit
|
||||||
|
internal fun withLambda(/*0*/ block: kotlin.Int.(kotlin.String) -> kotlin.Unit): kotlin.Unit
|
||||||
|
internal fun withLambda(/*0*/ block: kotlin.Int.(kotlin.String, kotlin.String) -> kotlin.Unit): kotlin.Unit
|
||||||
@@ -8443,6 +8443,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt7068.kt")
|
||||||
|
public void testKt7068() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/kt7068.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt7068_2.kt")
|
||||||
|
public void testKt7068_2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/kt7068_2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OverloadFunRegularAndExt.kt")
|
@TestMetadata("OverloadFunRegularAndExt.kt")
|
||||||
public void testOverloadFunRegularAndExt() throws Exception {
|
public void testOverloadFunRegularAndExt() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/OverloadFunRegularAndExt.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/OverloadFunRegularAndExt.kt");
|
||||||
|
|||||||
+27
-22
@@ -270,10 +270,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
// function literal without declaring receiver type { x -> ... }
|
// function literal without declaring receiver type { x -> ... }
|
||||||
// can be considered as extension function if one is expected
|
// can be considered as extension function if one is expected
|
||||||
// (special type constructor for function/ extension function should be introduced like PLACEHOLDER_FUNCTION_TYPE)
|
// (special type constructor for function/ extension function should be introduced like PLACEHOLDER_FUNCTION_TYPE)
|
||||||
val newSubType = if (constraintKind == SUB_TYPE
|
val newSubType = if (constraintKind == SUB_TYPE) {
|
||||||
&& KotlinBuiltIns.isFunctionType(subType)
|
createCorrespondingExtensionFunctionTypeIfNecessary(subType, superType)
|
||||||
&& KotlinBuiltIns.isExtensionFunctionType(superType)) {
|
|
||||||
createCorrespondingExtensionFunctionType(subType, DONT_CARE)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subType : JetType
|
subType : JetType
|
||||||
@@ -422,26 +420,33 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType().setApproximateCapturedTypes()
|
override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType().setApproximateCapturedTypes()
|
||||||
|
|
||||||
override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE).setApproximateCapturedTypes()
|
override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE).setApproximateCapturedTypes()
|
||||||
|
}
|
||||||
|
|
||||||
private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType {
|
fun createCorrespondingExtensionFunctionTypeIfNecessary(functionType: JetType, expectedType: JetType): JetType {
|
||||||
assert(KotlinBuiltIns.isFunctionType(functionType))
|
if (KotlinBuiltIns.isFunctionType(functionType) && KotlinBuiltIns.isExtensionFunctionType(expectedType)) {
|
||||||
|
return createCorrespondingExtensionFunctionType(functionType, DONT_CARE)
|
||||||
val typeArguments = functionType.getArguments()
|
|
||||||
assert(!typeArguments.isEmpty())
|
|
||||||
|
|
||||||
val arguments = ArrayList<JetType>()
|
|
||||||
// excluding the last type argument of the function type, which is the return type
|
|
||||||
var index = 0
|
|
||||||
val lastIndex = typeArguments.size() - 1
|
|
||||||
for (typeArgument in typeArguments) {
|
|
||||||
if (index < lastIndex) {
|
|
||||||
arguments.add(typeArgument.getType())
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
val returnType = typeArguments.get(lastIndex).getType()
|
|
||||||
return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType)
|
|
||||||
}
|
}
|
||||||
|
return functionType
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType {
|
||||||
|
assert(KotlinBuiltIns.isFunctionType(functionType))
|
||||||
|
|
||||||
|
val typeArguments = functionType.getArguments()
|
||||||
|
assert(!typeArguments.isEmpty())
|
||||||
|
|
||||||
|
val arguments = ArrayList<JetType>()
|
||||||
|
// excluding the last type argument of the function type, which is the return type
|
||||||
|
var index = 0
|
||||||
|
val lastIndex = typeArguments.size() - 1
|
||||||
|
for (typeArgument in typeArguments) {
|
||||||
|
if (index < lastIndex) {
|
||||||
|
arguments.add(typeArgument.getType())
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
val returnType = typeArguments.get(lastIndex).getType()
|
||||||
|
return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
||||||
|
|||||||
Reference in New Issue
Block a user