analyze labeled function literals as usual ones

(specially as function literals, not as other expressions)
This commit is contained in:
Svetlana Isakova
2013-08-27 16:12:49 +04:00
parent 8f29968183
commit fd5a2056c1
4 changed files with 35 additions and 10 deletions
@@ -166,8 +166,9 @@ public class ArgumentTypeResolver {
if (expression == null) { if (expression == null) {
return JetTypeInfo.create(null, context.dataFlowInfo); return JetTypeInfo.create(null, context.dataFlowInfo);
} }
if (expression instanceof JetFunctionLiteralExpression) { JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression, false);
return getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) expression, context, resolveArgumentsMode); if (deparenthesizedExpression instanceof JetFunctionLiteralExpression) {
return getFunctionLiteralTypeInfo(expression, (JetFunctionLiteralExpression) deparenthesizedExpression, context, resolveArgumentsMode);
} }
JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext()); JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
if (recordedTypeInfo != null) { if (recordedTypeInfo != null) {
@@ -181,6 +182,7 @@ public class ArgumentTypeResolver {
@NotNull @NotNull
public JetTypeInfo getFunctionLiteralTypeInfo( public JetTypeInfo getFunctionLiteralTypeInfo(
@NotNull JetExpression expression,
@NotNull JetFunctionLiteralExpression functionLiteralExpression, @NotNull JetFunctionLiteralExpression functionLiteralExpression,
@NotNull CallResolutionContext<?> context, @NotNull CallResolutionContext<?> context,
@NotNull ResolveArgumentsMode resolveArgumentsMode @NotNull ResolveArgumentsMode resolveArgumentsMode
@@ -189,7 +191,7 @@ public class ArgumentTypeResolver {
JetType type = getFunctionLiteralType(functionLiteralExpression, context.scope, context.trace); JetType type = getFunctionLiteralType(functionLiteralExpression, context.scope, context.trace);
return JetTypeInfo.create(type, context.dataFlowInfo); return JetTypeInfo.create(type, context.dataFlowInfo);
} }
return expressionTypingServices.getTypeInfo(context.scope, functionLiteralExpression, context.expectedType, context.dataFlowInfo, context.trace); return expressionTypingServices.getTypeInfo(expression, context);
} }
@Nullable @Nullable
@@ -212,7 +214,8 @@ public class ArgumentTypeResolver {
JetType returnType = resolveTypeRefWithDefault(functionLiteral.getReturnTypeRef(), scope, temporaryTrace, DONT_CARE); JetType returnType = resolveTypeRefWithDefault(functionLiteral.getReturnTypeRef(), scope, temporaryTrace, DONT_CARE);
assert returnType != null; assert returnType != null;
JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeRef(), scope, temporaryTrace, null); JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeRef(), scope, temporaryTrace, null);
return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiverType, parameterTypes, returnType); return KotlinBuiltIns.getInstance().getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiverType, parameterTypes,
returnType);
} }
@Nullable @Nullable
@@ -217,8 +217,6 @@ public class CandidateResolver {
ValueParameterDescriptor valueParameterDescriptor = entry.getKey(); ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) { for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
if (!(valueArgument.getArgumentExpression() instanceof JetFunctionLiteralExpression)) continue;
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context); addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context);
} }
} }
@@ -538,7 +536,11 @@ public class CandidateResolver {
@NotNull CallCandidateResolutionContext<D> context @NotNull CallCandidateResolutionContext<D> context
) { ) {
JetExpression argumentExpression = valueArgument.getArgumentExpression(); JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression instanceof JetFunctionLiteralExpression; if (argumentExpression == null) return;
JetExpression deparenthesizedExpression = JetPsiUtil.deparenthesizeWithNoTypeResolution(argumentExpression, false);
if (!(deparenthesizedExpression instanceof JetFunctionLiteralExpression)) return;
JetFunctionLiteralExpression functionLiteralExpression = (JetFunctionLiteralExpression) deparenthesizedExpression;
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument); JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT); JetType expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT);
if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType) if (expectedType == null || !KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)
@@ -553,7 +555,7 @@ public class CandidateResolver {
TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create( TemporaryTraceAndCache temporaryToResolveFunctionLiteral = TemporaryTraceAndCache.create(
context, "trace to resolve function literal with expected return type", argumentExpression); context, "trace to resolve function literal with expected return type", argumentExpression);
JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(((JetFunctionLiteralExpression) argumentExpression).getBodyExpression()); JetElement statementExpression = JetPsiUtil.getLastStatementInABlock(functionLiteralExpression.getBodyExpression());
if (statementExpression == null) return; if (statementExpression == null) return;
boolean[] mismatch = new boolean[1]; boolean[] mismatch = new boolean[1];
ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch( ObservableBindingTrace errorInterceptingTrace = ExpressionTypingUtils.makeTraceInterceptingTypeMismatch(
@@ -562,7 +564,7 @@ public class CandidateResolver {
.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType) .replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType)
.replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache); .replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache);
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo( JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
(JetFunctionLiteralExpression) argumentExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType(); argumentExpression, functionLiteralExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
if (!mismatch[0]) { if (!mismatch[0]) {
constraintSystem.addSubtypeConstraint( constraintSystem.addSubtypeConstraint(
type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex())); type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
@@ -573,7 +575,7 @@ public class CandidateResolver {
JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType; JetType expectedTypeWithoutReturnType = hasExpectedReturnType ? CallResolverUtil.replaceReturnTypeByUnknown(expectedType) : expectedType;
CallCandidateResolutionContext<D> newContext = CallCandidateResolutionContext<D> newContext =
context.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument); context.replaceExpectedType(expectedTypeWithoutReturnType).replaceDataFlowInfo(dataFlowInfoForArgument);
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext, JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteralExpression, newContext,
RESOLVE_FUNCTION_ARGUMENTS).getType(); RESOLVE_FUNCTION_ARGUMENTS).getType();
constraintSystem.addSubtypeConstraint( constraintSystem.addSubtypeConstraint(
type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex())); type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
@@ -0,0 +1,15 @@
package h
//traits to make ambiguity with function literal as an argument
trait A
trait B
trait C: A, B
fun foo<T>(<!UNUSED_PARAMETER!>a<!>: A, f: () -> T): T = f()
fun foo<T>(<!UNUSED_PARAMETER!>b<!>: B, f: () -> T): T = f()
fun test(c: C) {
<!CANNOT_COMPLETE_RESOLVE!>foo<!>(c) @f {
c<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
}
}
@@ -2416,6 +2416,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/functionLiterals/kt2906.kt"); doTest("compiler/testData/diagnostics/tests/functionLiterals/kt2906.kt");
} }
@TestMetadata("LabeledFunctionLiterals.kt")
public void testLabeledFunctionLiterals() throws Exception {
doTest("compiler/testData/diagnostics/tests/functionLiterals/LabeledFunctionLiterals.kt");
}
@TestMetadata("NoDanglingFunctionLiteralForNestedCalls.kt") @TestMetadata("NoDanglingFunctionLiteralForNestedCalls.kt")
public void testNoDanglingFunctionLiteralForNestedCalls() throws Exception { public void testNoDanglingFunctionLiteralForNestedCalls() throws Exception {
doTest("compiler/testData/diagnostics/tests/functionLiterals/NoDanglingFunctionLiteralForNestedCalls.kt"); doTest("compiler/testData/diagnostics/tests/functionLiterals/NoDanglingFunctionLiteralForNestedCalls.kt");