diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java index 20d21081143..5e3f04b7a9d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java @@ -155,13 +155,13 @@ public class CallMaker { return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.emptyList()); } - public static Call makeArraySetCall(@NotNull ReceiverDescriptor arrayAsReceiver, JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide) { + public static Call makeArraySetCall(@NotNull ReceiverDescriptor arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide) { List arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions()); arguments.add(rightHandSide); return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments); } - public static Call makeArrayGetCall(@NotNull ReceiverDescriptor arrayAsReceiver, JetArrayAccessExpression arrayAccessExpression) { + public static Call makeArrayGetCall(@NotNull ReceiverDescriptor arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression) { return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java index 91d2e14013b..89200d8182e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java @@ -28,10 +28,6 @@ public class ResolutionDebugInfo { public static final WritableSlice, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice(); public static final WritableSlice, Collection> UNKNOWNS = Slices.createSimpleSlice(); - static { - BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class); - } - public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false; public static boolean isResolutionDebugEnabled() { @@ -113,4 +109,8 @@ public class ResolutionDebugInfo { System.out.println(message); } } + + static { + BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 7c9d7bf03ba..acf7b2db7fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -30,8 +30,7 @@ import org.jetbrains.jet.lexer.JetTokens; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*; @@ -662,8 +661,26 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression")); return null; } - ExpressionReceiver receiver = getExpressionReceiver(facade, baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope)); - if (receiver == null) return null; + JetType type = null; + + if ((operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) && baseExpression instanceof JetArrayAccessExpression) { + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); + JetType expressionType = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceBindingTrace(temporaryTrace)); + if (expressionType != null) { + JetExpression stubExpression = ExpressionTypingUtils.createStubExpressionOfNecessaryType(baseExpression.getProject(), expressionType, context.trace); + type = resolveArrayAccessToLValue((JetArrayAccessExpression) baseExpression, stubExpression, context, true); + } + else { + temporaryTrace.commit(); + context.trace.report(UNRESOLVED_REFERENCE.on(operationSign)); + } + } + else { + type = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); + } + if (type == null) return null; + + ExpressionReceiver receiver = new ExpressionReceiver(baseExpression, type); OverloadResolutionResults functionDescriptor = context.resolveCallWithGivenNameToDescriptor( CallMaker.makeCall(receiver, expression), @@ -891,6 +908,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return DataFlowUtils.checkType(results.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType); } } + context.trace.report(NO_GET_METHOD.on(expression.getIndicesNode())); return null; } @@ -981,4 +999,45 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName())); return null; } + + /*package*/ JetType resolveArrayAccessToLValue(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression right, @NotNull ExpressionTypingContext context, final boolean getterNeeded) { + ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE)); + if (receiver == null) return null; + + OverloadResolutionResults getFunctionResults = null; + if (getterNeeded) { + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); + getFunctionResults = context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceBindingTrace(temporaryTrace).resolveCallWithGivenName( + CallMaker.makeArrayGetCall(receiver, arrayAccessExpression), + arrayAccessExpression, + "get"); + if (!getFunctionResults.isSuccess()) { + temporaryTrace.commit(); + context.trace.report(NO_GET_METHOD.on(arrayAccessExpression.getIndicesNode())); + return null; + } + context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionResults.getResultingCall()); + } + + Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, right); + OverloadResolutionResults setFunctionResults = context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( + call, + arrayAccessExpression, + "set"); + if (!setFunctionResults.isSuccess()) { + context.trace.report(NO_SET_METHOD.on(arrayAccessExpression.getIndicesNode())); + if (getterNeeded) { + return getFunctionResults.getResultingDescriptor().getReturnType(); + } + return null; + } + FunctionDescriptor setFunctionDescriptor = setFunctionResults.getResultingDescriptor(); + context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionResults.getResultingCall()); + + if (getterNeeded) { + return getFunctionResults.getResultingDescriptor().getReturnType(); + } + + return setFunctionDescriptor.getReturnType(); + } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 368b8e912b3..ced28ae91e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.types.expressions; +import com.intellij.openapi.project.Project; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; @@ -10,8 +11,10 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; @@ -20,20 +23,22 @@ import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import static org.jetbrains.jet.lang.diagnostics.Errors.RESULT_TYPE_MISMATCH; -import static org.jetbrains.jet.lang.resolve.BindingContext.MUST_BE_WRAPPED_IN_A_REF; +import static org.jetbrains.jet.lang.resolve.BindingContext.*; /** * @author abreslav */ public class ExpressionTypingUtils { + + @Nullable + protected static ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, @Nullable JetType type) { + if (type == null) return null; + return new ExpressionReceiver(expression, type); + } @Nullable protected static ExpressionReceiver getExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) { - JetType type = facade.getType(expression, context); - if (type == null) { - return null; - } - return new ExpressionReceiver(expression, type); + return getExpressionReceiver(expression, facade.getType(expression, context)); } @NotNull @@ -113,4 +118,12 @@ public class ExpressionTypingUtils { } } } + + @NotNull + public static JetExpression createStubExpressionOfNecessaryType(@NotNull Project project, @NotNull JetType type, @NotNull BindingTrace trace) { + JetExpression expression = JetPsiFactory.createExpression(project, "$e"); + trace.record(PROCESSED, expression); + trace.record(EXPRESSION_TYPE, expression, type); + return expression; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index d9684f96950..d3551d4041a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -10,20 +10,15 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; -import org.jetbrains.jet.lang.resolve.calls.CallMaker; -import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lexer.JetTokens; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET; import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT; -import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver; /** * @author abreslav @@ -161,7 +156,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito if (left instanceof JetArrayAccessExpression) { JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left; - resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), operationSign, context); + basic.resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), context.replaceScope(scope), false); } assignmentOperationType = basic.getTypeForBinaryCall(scope, counterpartName, context, expression); if (assignmentOperationType != null) { @@ -201,7 +196,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito JetExpression right = expression.getRight(); if (left instanceof JetArrayAccessExpression) { JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left; - JetType assignmentType = resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context); + JetType assignmentType = basic.resolveArrayAccessToLValue(arrayAccessExpression, right, context.replaceScope(scope), false); //todo basic.checkLValue(context.trace, arrayAccessExpression); return checkAssignmentType(assignmentType, expression, contextWithExpectedType); } @@ -218,33 +213,6 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito return DataFlowUtils.checkStatementType(expression, contextWithExpectedType); } - private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) { - ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceScope(scope)); - if (receiver == null) return null; - - Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide); - OverloadResolutionResults setFunctionResults = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( - call, - arrayAccessExpression, - "set"); - if (!setFunctionResults.isSuccess()) return null; - FunctionDescriptor setFunctionDescriptor = setFunctionResults.getResultingDescriptor(); - - context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionResults.getResultingCall()); - -// if (getterNeeded) { -// ResolvedCall getFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( -// CallMaker.makeArrayGetCall(receiver, arrayAccessExpression), -// arrayAccessExpression, -// "get"); -// if (getFunctionCall == null) return null; -// context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionCall); -// } -// else { -// context.trace.record(REFERENCE_TARGET, operationSign, setFunctionDescriptor); -// } - return setFunctionDescriptor.getReturnType(); - } @Override public JetType visitExpression(JetExpression expression, ExpressionTypingContext context) { diff --git a/compiler/testData/codegen/regressions/kt471.kt b/compiler/testData/codegen/regressions/kt471.kt index 271cebf2d7c..0c33b4fe0e5 100644 --- a/compiler/testData/codegen/regressions/kt471.kt +++ b/compiler/testData/codegen/regressions/kt471.kt @@ -37,7 +37,7 @@ fun test4() : Boolean { return true } -fun test5() : Boolean { +/*fun test5() : Boolean { var mnr = Array(2,{MyNumber(42)}) mnr[0]++ if (mnr[0].i != 43) return false @@ -52,7 +52,6 @@ fun test6() : Boolean { return true } -/* fun test7() : Boolean { var mnr = ArrayList() mnr.add(MyNumber(42)) @@ -79,9 +78,9 @@ fun box() : String { if (!test2()) return "fail test 2" if (!test3()) return "fail test 3" if (!test4()) return "fail test 4" +/* if (!test5()) return "fail test 5" if (!test6()) return "fail test 6" -/* if (!test7()) return "fail test 7" if (!test8()) return "fail test 8"