Resolve operation (unary, array access) on error element instead of ignoring it

(to record corresponding call for later simplification in control flow)
Generate code for unmapped arguments in control flow
This commit is contained in:
Svetlana Isakova
2014-07-12 14:18:44 +04:00
parent 3cc02c57fc
commit 4477a96ca7
14 changed files with 146 additions and 58 deletions
@@ -1490,11 +1490,17 @@ public class JetControlFlowProcessor {
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
Map<PseudoValue, ReceiverValue> receivers = getReceiverValues(resolvedCall);
SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues = SmartFMap.emptyMap();
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
if (argument == null) continue;
parameterValues = generateValueArgument(argument, parameterDescriptor, parameterValues);
List<ValueArgument> valueArguments = CallUtilPackage.getAllValueArguments(resolvedCall.getCall());
for (ValueArgument argument : valueArguments) {
ArgumentMapping argumentMapping = resolvedCall.getArgumentMapping(argument);
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentMapping instanceof ArgumentMatch) {
parameterValues = generateValueArgument(argument, ((ArgumentMatch) argumentMapping).getValueParameter(), parameterValues);
}
else if (argumentExpression != null) {
generateInstructions(argumentExpression);
createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression);
}
}
if (resultingDescriptor instanceof VariableDescriptor) {
@@ -1552,19 +1558,6 @@ public class JetControlFlowProcessor {
return receiverValues;
}
@NotNull
private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument(
ResolvedValueArgument argument,
ValueParameterDescriptor parameterDescriptor,
SmartFMap<PseudoValue, ValueParameterDescriptor> parameterValues
) {
for (ValueArgument valueArgument : argument.getArguments()) {
parameterValues = generateValueArgument(valueArgument, parameterDescriptor, parameterValues);
}
return parameterValues;
}
@NotNull
private SmartFMap<PseudoValue, ValueParameterDescriptor> generateValueArgument(
ValueArgument valueArgument,
@@ -40,7 +40,10 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.jet.lang.resolve.calls.context.TemporaryTraceAndCache;
import org.jetbrains.jet.lang.resolve.calls.model.*;
import org.jetbrains.jet.lang.resolve.calls.model.DataFlowInfoForArgumentsImpl;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
@@ -688,11 +691,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
// Type check the base expression
JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context);
JetType type = typeInfo.getType();
if (type == null) {
return typeInfo;
}
JetTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
JetType type = ExpressionTypingUtils.safeGetType(typeInfo);
ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
Call call = CallMaker.makeCall(receiver, expression);
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
// Conventions for unary operations
@@ -705,21 +708,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
// a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) {
JetExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "$e", type);
resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression,
stubExpression,
context.replaceBindingTrace(
TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression)),
context.trace);
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace
.create(context.trace, "trace to resolve array access set method for unary expression", expression);
ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
resolveArrayAccessSetMethod((JetArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
}
ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type);
// Resolve the operation reference
OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(
context,
CallMaker.makeCall(receiver, expression),
expression.getOperationReference(),
name);
context, call, expression.getOperationReference(), name);
if (!resolutionResults.isSuccess()) {
return JetTypeInfo.create(null, dataFlowInfo);
@@ -1302,29 +1299,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
if (arrayExpression == null) return JetTypeInfo.create(null, oldContext.dataFlowInfo);
JetTypeInfo arrayTypeInfo = facade.getTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
JetTypeInfo arrayTypeInfo = facade.safeGetTypeInfo(arrayExpression, oldContext.replaceExpectedType(NO_EXPECTED_TYPE)
.replaceContextDependency(INDEPENDENT));
JetType arrayType = arrayTypeInfo.getType();
if (arrayType == null) {
for (JetExpression indexExpression : arrayAccessExpression.getIndexExpressions()) {
facade.getTypeInfo(indexExpression, oldContext);
}
return arrayTypeInfo;
}
JetType arrayType = ExpressionTypingUtils.safeGetType(arrayTypeInfo);
DataFlowInfo dataFlowInfo = arrayTypeInfo.getDataFlowInfo();
ExpressionTypingContext context = oldContext.replaceDataFlowInfo(dataFlowInfo);
ExpressionReceiver receiver = new ExpressionReceiver(arrayExpression, arrayType);
if (!isGet) assert rightHandSide != null;
Call call = isGet
? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
: CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD);
OverloadResolutionResults<FunctionDescriptor> functionResults = components.callResolver.resolveCallWithGivenName(
context,
isGet
? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression, Call.CallType.ARRAY_GET_METHOD)
: CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide, Call.CallType.ARRAY_SET_METHOD),
arrayAccessExpression,
Name.identifier(isGet ? "get" : "set")
);
context, call, arrayAccessExpression, Name.identifier(isGet ? "get" : "set"));
List<JetExpression> indices = arrayAccessExpression.getIndexExpressions();
// The accumulated data flow info of all index expressions is saved on the last index
@@ -84,11 +84,17 @@ public class ExpressionTypingUtils {
@NotNull
protected static ExpressionReceiver safeGetExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) {
JetType type = facade.safeGetTypeInfo(expression, context).getType();
assert type != null : "safeGetTypeInfo should return @NotNull type";
JetType type = safeGetType(facade.safeGetTypeInfo(expression, context));
return new ExpressionReceiver(expression, type);
}
@NotNull
public static JetType safeGetType(@NotNull JetTypeInfo typeInfo) {
JetType type = typeInfo.getType();
assert type != null : "safeGetType should be invoked on safe JetTypeInfo; safeGetTypeInfo should return @NotNull type";
return type;
}
@NotNull
public static WritableScopeImpl newWritableScopeImpl(ExpressionTypingContext context, @NotNull String scopeDebugName) {
WritableScopeImpl scope = new WritableScopeImpl(
@@ -0,0 +1,47 @@
== foo ==
fun foo(a: Int, b: Int) = a + b
---------------------
L0:
1 <START>
v(a: Int)
magic[FAKE_INITIALIZER](a: Int) -> <v0>
w(a|<v0>)
v(b: Int)
magic[FAKE_INITIALIZER](b: Int) -> <v1>
w(b|<v1>)
r(a) -> <v2>
r(b) -> <v3>
mark(a + b)
call(a + b, plus|<v2>, <v3>) -> <v4>
ret(*|<v4>) L1
L1:
<END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
== bar ==
fun bar(i: Int) {
foo(1, 1, i)
}
---------------------
L0:
1 <START>
v(i: Int)
magic[FAKE_INITIALIZER](i: Int) -> <v0>
w(i|<v0>)
2 mark({ foo(1, 1, i) })
r(1) -> <v1>
r(1) -> <v2>
r(i) -> <v3>
magic[VALUE_CONSUMER](i|<v3>) -> <v4>
mark(foo(1, 1, i))
call(foo(1, 1, i), foo|<v1>, <v2>) -> <v5>
L1:
1 <END> NEXT:[<SINK>]
error:
<ERROR> PREV:[]
sink:
<SINK> PREV:[<ERROR>, <END>]
=====================
@@ -0,0 +1,5 @@
fun foo(a: Int, b: Int) = a + b
fun bar(i: Int) {
foo(1, 1, i)
}
@@ -0,0 +1,22 @@
== foo ==
fun foo(a: Int, b: Int) = a + b
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](a: Int) -> <v0>
<v1>: Int NEW: magic[FAKE_INITIALIZER](b: Int) -> <v1>
a <v2>: Int NEW: r(a) -> <v2>
b <v3>: Int NEW: r(b) -> <v3>
a + b <v4>: Int NEW: call(a + b, plus|<v2>, <v3>) -> <v4>
=====================
== bar ==
fun bar(i: Int) {
foo(1, 1, i)
}
---------------------
<v0>: Int NEW: magic[FAKE_INITIALIZER](i: Int) -> <v0>
<v4>: * NEW: magic[VALUE_CONSUMER](i|<v3>) -> <v4>
1 <v1>: Int NEW: r(1) -> <v1>
1 <v2>: Int NEW: r(1) -> <v2>
i <v3>: * NEW: r(i) -> <v3>
foo(1, 1, i) <v5>: * NEW: call(foo(1, 1, i), foo|<v1>, <v2>) -> <v5>
{ foo(1, 1, i) } <v5>: * COPY
=====================
@@ -0,0 +1,5 @@
fun foo(a: Int, b: Int) = a + b
fun bar(i: Int) {
foo(1, 1, <!TOO_MANY_ARGUMENTS!>i<!>)
}
@@ -9,7 +9,7 @@ class A(outer: Outer) {
var b: String by foo(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getMyProperty<!>())
var r: String by foo(outer.getContainer().<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getMyProperty<!>())
var e: String by <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getMyProperty<!>())
var e: String by <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>+<!> <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getMyProperty<!>())
var f: String by <!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>getMyProperty<!>()) <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>-<!> 1
}
@@ -1,7 +1,5 @@
package bar
fun main(args : Array<String>) {
<!DEBUG_INFO_MISSING_UNRESOLVED!><!NO_CLASS_OBJECT!>String<!>[<!SYNTAX!><!>]<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>names<!> <!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!>=<!> ["ads"]<!>
}
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!><!NO_CLASS_OBJECT!>String<!>[<!SYNTAX!><!>]<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>names<!> <!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!>=<!> ["ads"]<!>
}
@@ -1,5 +1,5 @@
//KT-4866 Resolve does not work inside brackets with unresolved reference before
fun test(i: Int, j: Int) {
<!UNRESOLVED_REFERENCE!>foo<!>[i, j]
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!><!UNRESOLVED_REFERENCE!>foo<!>[i, j]<!>
}
@@ -0,0 +1,4 @@
fun foo(a: Int) {
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>!<!><!UNRESOLVED_REFERENCE!>bbb<!>
<!UNRESOLVED_REFERENCE!>bbb<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>+<!> a
}
@@ -472,6 +472,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
doTest("compiler/testData/cfg/functions/DefaultValuesForArguments.kt");
}
@TestMetadata("unmappedArgs.kt")
public void testUnmappedArgs() throws Exception {
doTest("compiler/testData/cfg/functions/unmappedArgs.kt");
}
}
@TestMetadata("compiler/testData/cfg/tailCalls")
@@ -474,6 +474,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
doTest("compiler/testData/cfg/functions/DefaultValuesForArguments.kt");
}
@TestMetadata("unmappedArgs.kt")
public void testUnmappedArgs() throws Exception {
doTest("compiler/testData/cfg/functions/unmappedArgs.kt");
}
}
@TestMetadata("compiler/testData/cfg/tailCalls")
@@ -1435,6 +1435,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/UninitializedOrReassignedVariables.kt");
}
@TestMetadata("unmappedArgs.kt")
public void testUnmappedArgs() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/unmappedArgs.kt");
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/varInitializationInIfInCycle.kt");
@@ -3806,6 +3811,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/incompleteCode/unresolvedArguments.kt");
}
@TestMetadata("unresolvedOperation.kt")
public void testUnresolvedOperation() throws Exception {
doTest("compiler/testData/diagnostics/tests/incompleteCode/unresolvedOperation.kt");
}
@TestMetadata("variableDeclarationInSelector.kt")
public void testVariableDeclarationInSelector() throws Exception {
doTest("compiler/testData/diagnostics/tests/incompleteCode/variableDeclarationInSelector.kt");