Expected return type is in use now during function literal analysis #KT-9134 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-09-11 21:01:05 +03:00
parent 65b77558a1
commit 7dbd5b75cc
10 changed files with 76 additions and 5 deletions
@@ -310,7 +310,7 @@ class FunctionDescriptorResolver(
val type: JetType
if (typeReference != null) {
type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
if (expectedType != null) {
if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
}
@@ -23,7 +23,9 @@ import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.name.Name;
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.types.JetType;
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.ExpressionTypingServices;
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 javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -81,16 +85,19 @@ public class CallResolver {
private CallCompleter callCompleter;
private final TaskPrioritizer taskPrioritizer;
private final ResolutionResultsHandler resolutionResultsHandler;
@NotNull private KotlinBuiltIns builtIns;
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);
public CallResolver(
@NotNull TaskPrioritizer taskPrioritizer,
@NotNull ResolutionResultsHandler resolutionResultsHandler
@NotNull ResolutionResultsHandler resolutionResultsHandler,
@NotNull KotlinBuiltIns builtIns
) {
this.taskPrioritizer = taskPrioritizer;
this.resolutionResultsHandler = resolutionResultsHandler;
this.builtIns = builtIns;
}
// 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)
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(
context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
context.scope, calleeExpression, expectedType, context.dataFlowInfo, context.trace);
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.CommonSupertypes
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.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
@@ -185,7 +186,7 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
val returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
if (KotlinBuiltIns.isUnit(expectedReturnType!!)) {
if (!TypeUtils.noExpectedType(expectedReturnType!!) && KotlinBuiltIns.isUnit(expectedReturnType)) {
return components.builtIns.getUnitType()
}
}
@@ -201,7 +202,8 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
val functionLiteral = expression.getFunctionLiteral()
val declaredReturnType = functionLiteral.getTypeReference()?.let {
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))
}
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);
}
@TestMetadata("LiteralAsResult.kt")
public void testLiteralAsResult() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LiteralAsResult.kt");
doTest(fileName);
}
@TestMetadata("LocalClassAndShortSubpackageNames.kt")
public void testLocalClassAndShortSubpackageNames() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/LocalClassAndShortSubpackageNames.kt");
@@ -13305,6 +13311,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
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")
public void testNoErrorCheckForPackageLevelVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt");