diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 13b47845a66..ef356283043 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -12,7 +12,6 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; @@ -1976,14 +1975,16 @@ public class ExpressionCodegen extends JetVisitor { boolean isGetter = accessor.getSignature().getName().equals("get"); if(isGetter) { - FunctionDescriptor setterDescriptor = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); + ResolvedCall resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); + FunctionDescriptor setterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); return StackValue.collectionElement( accessor.getSignature().getReturnType(), accessor, setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION) : null); } else { - FunctionDescriptor getterDescriptor = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); + ResolvedCall resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); + FunctionDescriptor getterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); return StackValue.collectionElement( accessor.getSignature().getArgumentTypes()[1], getterDescriptor != null ? typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION) : null, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index bf967fee95b..fe0b5f8ace8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -36,8 +36,8 @@ public interface BindingContext { WritableSlice LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT"); WritableSlice LOOP_RANGE_NEXT = Slices.createSimpleSlice("LOOP_RANGE_NEXT"); - WritableSlice INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET"); - WritableSlice INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET"); + WritableSlice> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET"); + WritableSlice> INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET"); WritableSlice AUTOCAST = Slices.createSimpleSlice("AUTOCAST"); WritableSlice RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 5b93320fe05..f722e29c6b2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -78,7 +78,7 @@ public class CallResolver { } @Nullable - public FunctionDescriptor resolveCallWithGivenName( + public ResolvedCall resolveCallWithGivenName( @NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull final Call call, @@ -86,7 +86,7 @@ public class CallResolver { @NotNull String name, @NotNull JetType expectedType) { List> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo); - return resolveCallToDescriptor(trace, scope, call, expectedType, tasks, functionReference); + return doResolveCall(trace, scope, call, expectedType, tasks, functionReference); } @Nullable @@ -174,7 +174,8 @@ public class CallResolver { prioritizedTasks = Collections.singletonList(new ResolutionTask(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY)); } else { - throw new UnsupportedOperationException("Type argument inference not implemented for " + call); + trace.report(UNSUPPORTED.on(call.getCallNode(), "Type argument inference is not supported for this callee: " + calleeExpression)); + return null; } } 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 8a5c6b3f531..2255ebe885d 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 @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.CallMaker; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.constants.*; @@ -559,11 +560,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { ExpressionReceiver receiver = getExpressionReceiver(facade, baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope)); if (receiver == null) return null; - FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName( + FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor( CallMaker.makeCall(receiver, expression), expression.getOperationSign(), - name, - receiver); + name); if (functionDescriptor == null) return null; JetType returnType = functionDescriptor.getReturnType(); @@ -705,10 +705,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) { String name = "contains"; ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE)); - FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName( + FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor( CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)), operationSign, - name, receiver); + name); JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; ensureBooleanResult(operationSign, name, containsType, context); } @@ -752,14 +752,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope)); if (receiver != null) { - FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName( + ResolvedCall resolvedCall = context.resolveCallWithGivenName( CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()), expression, - "get", - receiver); - if (functionDescriptor != null) { - context.trace.record(INDEXED_LVALUE_GET, expression, functionDescriptor); - return DataFlowUtils.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); + "get" + ); + if (resolvedCall != null) { + context.trace.record(INDEXED_LVALUE_GET, expression, resolvedCall); + return DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType); } } return null; @@ -768,11 +768,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @Nullable protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) { ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope)); - FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenName( + FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor( CallMaker.makeCall(receiver, binaryExpression), binaryExpression.getOperationReference(), - name, - receiver); + name + ); if (functionDescriptor != null) { return functionDescriptor.getReturnType(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index c84fbf93516..f81094254b2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallResolver; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; @@ -172,10 +173,16 @@ import java.util.Map; ////////// Call resolution utilities @Nullable - public FunctionDescriptor resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name, @NotNull ReceiverDescriptor receiver) { + public ResolvedCall resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) { return getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType); } + @Nullable + public FunctionDescriptor resolveCallWithGivenNameToDescriptor(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) { + ResolvedCall resolvedCall = resolveCallWithGivenName(call, functionReference, name); + return resolvedCall == null ? null : resolvedCall.getResultingDescriptor(); + } + @Nullable public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { return getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType); 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 1eea9c06ae8..ab79f9cb225 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 @@ -9,15 +9,16 @@ import org.jetbrains.jet.lang.resolve.BindingContext; 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.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.types.ErrorUtils; 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_GET; import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver; @@ -123,7 +124,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV if (typeForBinaryCall != null) { JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); if (left instanceof JetArrayAccessExpression) { - resolveArrayAccessToLValue((JetArrayAccessExpression) left, expression.getRight(), expression.getOperationReference(), context, true); + resolveArrayAccessToLValue((JetArrayAccessExpression) left, expression.getRight(), expression.getOperationReference(), context); } context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression); @@ -138,14 +139,14 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV @Override protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) { - boolean getterNeeded = false; JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); JetExpression right = expression.getRight(); if (left instanceof JetArrayAccessExpression) { JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left; - return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context, getterNeeded); + return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context); } - JetType leftType = facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope)); + JetType leftType = left == null ? ErrorUtils.createErrorType("No expression") + : facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope)); if (right != null) { JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope)); } @@ -164,30 +165,32 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV return checkExpectedType(expression, context); } - private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context, boolean getterNeeded) { + 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); - FunctionDescriptor setFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( + ResolvedCall setFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( call, arrayAccessExpression, - "set", receiver); - if (setFunction == null) return null; - context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunction); + "set"); + if (setFunctionCall == null) return null; + FunctionDescriptor setFunctionDescriptor = setFunctionCall.getResultingDescriptor(); - if (getterNeeded) { - FunctionDescriptor getFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName( - CallMaker.makeArrayGetCall(receiver, arrayAccessExpression), - arrayAccessExpression, - "get", receiver); - if (getFunction == null) return null; - context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunction); - } - else { - context.trace.record(REFERENCE_TARGET, operationSign, setFunction); - } - return DataFlowUtils.checkType(setFunction.getReturnType(), arrayAccessExpression, context); + context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionCall); + +// 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 DataFlowUtils.checkType(setFunctionDescriptor.getReturnType(), arrayAccessExpression, context); } @Override diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetArrayAccessReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetArrayAccessReference.java index cdc32fa6d6b..66c3f2eee31 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetArrayAccessReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetArrayAccessReference.java @@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.JetArrayAccessExpression; import org.jetbrains.jet.lang.psi.JetContainerNode; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; @@ -40,8 +41,8 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer @Override protected PsiElement doResolve() { BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile()); - FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); - FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); + ResolvedCall getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); + ResolvedCall setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); if (getFunction != null && setFunction != null) { return null; // Call doMultiResolve } @@ -51,10 +52,10 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer @Override protected ResolveResult[] doMultiResolve() { BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile()); - FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); - PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction); - FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); - PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction); + ResolvedCall getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); + PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction.getResultingDescriptor()); + ResolvedCall setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); + PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction.getResultingDescriptor()); return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)}; // return super.doMultiResolve(); }