Expected return type is in use now during function literal analysis #KT-9134 Fixed
This commit is contained in:
@@ -310,7 +310,7 @@ class FunctionDescriptorResolver(
|
|||||||
val type: JetType
|
val type: JetType
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
|
type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
|
||||||
if (expectedType != null) {
|
if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
|
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
|
||||||
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
|
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import kotlin.Unit;
|
|||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||||
@@ -50,6 +52,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage;
|
import org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingVisitorDispatcher;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingVisitorDispatcher;
|
||||||
@@ -57,6 +60,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
|||||||
import org.jetbrains.kotlin.util.PerformanceCounter;
|
import org.jetbrains.kotlin.util.PerformanceCounter;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -81,16 +85,19 @@ public class CallResolver {
|
|||||||
private CallCompleter callCompleter;
|
private CallCompleter callCompleter;
|
||||||
private final TaskPrioritizer taskPrioritizer;
|
private final TaskPrioritizer taskPrioritizer;
|
||||||
private final ResolutionResultsHandler resolutionResultsHandler;
|
private final ResolutionResultsHandler resolutionResultsHandler;
|
||||||
|
@NotNull private KotlinBuiltIns builtIns;
|
||||||
|
|
||||||
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
|
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
|
||||||
private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
|
private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
|
||||||
|
|
||||||
public CallResolver(
|
public CallResolver(
|
||||||
@NotNull TaskPrioritizer taskPrioritizer,
|
@NotNull TaskPrioritizer taskPrioritizer,
|
||||||
@NotNull ResolutionResultsHandler resolutionResultsHandler
|
@NotNull ResolutionResultsHandler resolutionResultsHandler,
|
||||||
|
@NotNull KotlinBuiltIns builtIns
|
||||||
) {
|
) {
|
||||||
this.taskPrioritizer = taskPrioritizer;
|
this.taskPrioritizer = taskPrioritizer;
|
||||||
this.resolutionResultsHandler = resolutionResultsHandler;
|
this.resolutionResultsHandler = resolutionResultsHandler;
|
||||||
|
this.builtIns = builtIns;
|
||||||
}
|
}
|
||||||
|
|
||||||
// component dependency cycle
|
// component dependency cycle
|
||||||
@@ -289,8 +296,17 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
||||||
|
JetType expectedType = NO_EXPECTED_TYPE;
|
||||||
|
if (calleeExpression instanceof JetFunctionLiteralExpression) {
|
||||||
|
int parameterNumber = ((JetFunctionLiteralExpression) calleeExpression).getValueParameters().size();
|
||||||
|
List<JetType> parameterTypes = new ArrayList<JetType>(parameterNumber);
|
||||||
|
for (int i = 0; i < parameterNumber; i++) {
|
||||||
|
parameterTypes.add(NO_EXPECTED_TYPE);
|
||||||
|
}
|
||||||
|
expectedType = builtIns.getFunctionType(Annotations.EMPTY, null, parameterTypes, context.expectedType);
|
||||||
|
}
|
||||||
JetType calleeType = expressionTypingServices.safeGetType(
|
JetType calleeType = expressionTypingServices.safeGetType(
|
||||||
context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
context.scope, calleeExpression, expectedType, context.dataFlowInfo, context.trace);
|
||||||
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
|
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
|
||||||
|
|
||||||
Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
|
Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
|
||||||
|
|||||||
+4
-2
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
|
|||||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
import org.jetbrains.kotlin.types.CommonSupertypes
|
import org.jetbrains.kotlin.types.CommonSupertypes
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
|
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
@@ -185,7 +186,7 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
|||||||
val returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
|
val returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
|
||||||
|
|
||||||
if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
|
if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
|
||||||
if (KotlinBuiltIns.isUnit(expectedReturnType!!)) {
|
if (!TypeUtils.noExpectedType(expectedReturnType!!) && KotlinBuiltIns.isUnit(expectedReturnType)) {
|
||||||
return components.builtIns.getUnitType()
|
return components.builtIns.getUnitType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +202,8 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
|||||||
val functionLiteral = expression.getFunctionLiteral()
|
val functionLiteral = expression.getFunctionLiteral()
|
||||||
val declaredReturnType = functionLiteral.getTypeReference()?.let {
|
val declaredReturnType = functionLiteral.getTypeReference()?.let {
|
||||||
val type = components.typeResolver.resolveType(context.scope, it, context.trace, true)
|
val type = components.typeResolver.resolveType(context.scope, it, context.trace, true)
|
||||||
if (expectedReturnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(type, expectedReturnType)) {
|
if (expectedReturnType != null && !TypeUtils.noExpectedType(expectedReturnType)
|
||||||
|
&& !JetTypeChecker.DEFAULT.isSubtypeOf(type, expectedReturnType)) {
|
||||||
context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(it, expectedReturnType))
|
context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(it, expectedReturnType))
|
||||||
}
|
}
|
||||||
type
|
type
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// Here we want just to check return type
|
||||||
|
// Should be () -> Int
|
||||||
|
fun foo() = { 42 }
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(): () -> kotlin.Int
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// See KT-9134: smart cast is not provided inside lambda call
|
||||||
|
fun bar(): Int = {
|
||||||
|
var i: Int?
|
||||||
|
i = 42
|
||||||
|
<!DEBUG_INFO_SMARTCAST!>i<!>
|
||||||
|
}()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun bar(): kotlin.Int
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// See KT-9134: smart cast is not provided inside lambda call
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class My
|
||||||
|
|
||||||
|
fun bar(): Int = @My {
|
||||||
|
var i: Int?
|
||||||
|
i = 42
|
||||||
|
<!DEBUG_INFO_SMARTCAST!>i<!>
|
||||||
|
}()
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun bar(): kotlin.Int
|
||||||
|
|
||||||
|
kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) kotlin.annotation.annotation() public final class My : kotlin.Annotation {
|
||||||
|
public constructor My()
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -307,6 +307,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LiteralAsResult.kt")
|
||||||
|
public void testLiteralAsResult() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LiteralAsResult.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("LocalClassAndShortSubpackageNames.kt")
|
@TestMetadata("LocalClassAndShortSubpackageNames.kt")
|
||||||
public void testLocalClassAndShortSubpackageNames() throws Exception {
|
public void testLocalClassAndShortSubpackageNames() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LocalClassAndShortSubpackageNames.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LocalClassAndShortSubpackageNames.kt");
|
||||||
@@ -13305,6 +13311,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaCall.kt")
|
||||||
|
public void testLambdaCall() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/lambdaCall.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lambdaCallAnnotated.kt")
|
||||||
|
public void testLambdaCallAnnotated() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/lambdaCallAnnotated.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noErrorCheckForPackageLevelVal.kt")
|
@TestMetadata("noErrorCheckForPackageLevelVal.kt")
|
||||||
public void testNoErrorCheckForPackageLevelVal() throws Exception {
|
public void testNoErrorCheckForPackageLevelVal() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user