diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index ecdd2817e33..fde898a4eeb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -204,16 +204,16 @@ public class CallExpressionResolver { private JetType getVariableType(@NotNull JetSimpleNameExpression nameExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull boolean[] result ) { - TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create( - context.trace, "trace to resolve as local variable or property", nameExpression); + TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create( + context, "trace to resolve as local variable or property", nameExpression); CallResolver callResolver = expressionTypingServices.getCallResolver(); Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression); BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create( - context.replaceBindingTrace(traceForVariable).replaceResolveMode(ResolveMode.TOP_LEVEL_CALL). - replaceResolutionResultsCache(), call, CheckValueArgumentsMode.ENABLED); + context.replaceTraceAndCache(temporaryForVariable), + call, CheckValueArgumentsMode.ENABLED); OverloadResolutionResults resolutionResult = callResolver.resolveSimpleProperty(contextForVariable); if (!resolutionResult.isNothing()) { - traceForVariable.commit(); + temporaryForVariable.commit(); checkSuper(receiver, resolutionResult, context.trace, nameExpression); result[0] = true; return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null; @@ -222,11 +222,11 @@ public class CallExpressionResolver { ResolutionContext newContext = receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context; - TemporaryBindingTrace traceForNamespaceOrClassObject = TemporaryBindingTrace.create( - context.trace, "trace to resolve as namespace or class object", nameExpression); - JetType jetType = lookupNamespaceOrClassObject(nameExpression, newContext.replaceBindingTrace(traceForNamespaceOrClassObject)); + TemporaryTraceAndCache temporaryForNamespaceOrClassObject = TemporaryTraceAndCache.create( + context, "trace to resolve as namespace or class object", nameExpression); + JetType jetType = lookupNamespaceOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForNamespaceOrClassObject)); if (jetType != null) { - traceForNamespaceOrClassObject.commit(); + temporaryForNamespaceOrClassObject.commit(); // Uncommitted changes in temp context context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope); @@ -236,6 +236,7 @@ public class CallExpressionResolver { result[0] = true; return jetType; } + temporaryForVariable.commit(); result[0] = false; return null; } @@ -246,10 +247,11 @@ public class CallExpressionResolver { ) { boolean[] result = new boolean[1]; - TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(context.trace, "trace to resolve as variable", nameExpression); - JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result); + TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create( + context, "trace to resolve as variable", nameExpression); + JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result); if (result[0]) { - traceForVariable.commit(); + temporaryForVariable.commit(); if (type instanceof NamespaceType && context.expressionPosition == ExpressionPosition.FREE) { type = null; } @@ -257,20 +259,21 @@ public class CallExpressionResolver { } Call call = CallMaker.makeCall(nameExpression, receiver, callOperationNode, nameExpression, Collections.emptyList()); - TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function", nameExpression); - ResolutionContext newContext = context.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL).replaceResolutionResultsCache(); + TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create( + context, "trace to resolve as function", nameExpression); + ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction); ResolvedCall resolvedCall = getResolvedCallForFunction( call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result); if (result[0]) { FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; - traceForFunction.commit(); + temporaryForFunction.commit(); boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters)); type = functionDescriptor != null ? functionDescriptor.getReturnType() : null; return JetTypeInfo.create(type, context.dataFlowInfo); } - traceForVariable.commit(); + temporaryForVariable.commit(); return JetTypeInfo.create(null, context.dataFlowInfo); } @@ -295,12 +298,14 @@ public class CallExpressionResolver { boolean[] result = new boolean[1]; Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression); - TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create(context.trace, "trace to resolve as function call", callExpression); + TemporaryTraceAndCache temporaryForFunction = TemporaryTraceAndCache.create( + context, "trace to resolve as function call", callExpression); ResolvedCallWithTrace resolvedCall = getResolvedCallForFunction( - call, callExpression, context.replaceBindingTrace(traceForFunction), CheckValueArgumentsMode.ENABLED, result); + call, callExpression, context.replaceTraceAndCache(temporaryForFunction), + CheckValueArgumentsMode.ENABLED, result); if (result[0]) { FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; - traceForFunction.commit(); + temporaryForFunction.commit(); if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) { // there are only type arguments boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; @@ -316,18 +321,18 @@ public class CallExpressionResolver { JetExpression calleeExpression = callExpression.getCalleeExpression(); if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) { - TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create( - context.trace, "trace to resolve as variable with 'invoke' call", callExpression); + TemporaryTraceAndCache temporaryForVariable = TemporaryTraceAndCache.create( + context, "trace to resolve as variable with 'invoke' call", callExpression); JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode, - context.replaceBindingTrace(traceForVariable), result); + context.replaceTraceAndCache(temporaryForVariable), result); if (result[0]) { - traceForVariable.commit(); + temporaryForVariable.commit(); context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression, type != null ? type : ErrorUtils.createErrorType(""))); return JetTypeInfo.create(null, context.dataFlowInfo); } } - traceForFunction.commit(); + temporaryForFunction.commit(); return JetTypeInfo.create(null, context.dataFlowInfo); } 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 17338e4308a..7669d6ade2b 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 @@ -143,7 +143,7 @@ public class CallResolver { ) { return resolveFunctionCall(BasicCallResolutionContext.create( trace, scope, call, expectedType, dataFlowInfo, ResolveMode.TOP_LEVEL_CALL, CheckValueArgumentsMode.ENABLED, - ExpressionPosition.FREE, ResolutionResultsCache.create())); + ExpressionPosition.FREE, ResolutionResultsCacheImpl.create())); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionContext.java index 1dbc8a045b0..1d4ba0f3641 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionContext.java @@ -67,7 +67,7 @@ public abstract class ResolutionContext {} + MemberType FUNCTION_MEMBER_TYPE = new MemberType(); + MemberType PROPERTY_MEMBER_TYPE = new MemberType(); -public class ResolutionResultsCache { - public static class MemberType {} - public static final MemberType FUNCTION_MEMBER_TYPE = new MemberType(); - public static final MemberType PROPERTY_MEMBER_TYPE = new MemberType(); - - public static final WritableSlice> RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice(); - public static final WritableSlice> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice(); - public static final WritableSlice TRACE_DELTAS_CACHE = Slices.createSimpleSlice(); - public static final WritableSlice> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice(); - - static { - BasicWritableSlice.initSliceDebugNames(ResolutionResultsCache.class); - } - - private final BindingTrace trace = new BindingTraceContext(); - - @NotNull - private static WritableSlice> getSliceByMemberType(@NotNull MemberType memberType) { - return (WritableSlice>) - (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY); - } - - public void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType, @NotNull OverloadResolutionResultsImpl results) { - trace.record(getSliceByMemberType(memberType), callKey, results); - } + void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType, @NotNull OverloadResolutionResultsImpl results); @Nullable - public OverloadResolutionResultsImpl getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType) { - return trace.get(getSliceByMemberType(memberType), callKey); - } + OverloadResolutionResultsImpl getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType); - public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) { - trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace); - } + void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace); @Nullable - public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) { - return trace.get(TRACE_DELTAS_CACHE, callKey); - } + DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey); - public void recordDeferredComputationForCall( + void recordDeferredComputationForCall( @NotNull CallKey callKey, @NotNull CallCandidateResolutionContext deferredComputation, @NotNull MemberType memberType - ) { - if (memberType == PROPERTY_MEMBER_TYPE) return; - trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext) deferredComputation); - } + ); @Nullable - public CallCandidateResolutionContext getDeferredComputation(@NotNull JetExpression expression) { - for (CallType callType : Lists.newArrayList(CallType.DEFAULT, CallType.ARRAY_GET_METHOD, CallType.ARRAY_SET_METHOD)) { - CallKey callKey = CallKey.create(callType, expression); - CallCandidateResolutionContext context = trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey); - if (context != null) { - return context; - } - } - return null; - } - - @NotNull - public static ResolutionResultsCache create() { - return new ResolutionResultsCache(); - } + CallCandidateResolutionContext getDeferredComputation(@Nullable JetExpression expression); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionResultsCacheImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionResultsCacheImpl.java new file mode 100644 index 00000000000..77304bbd65a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/ResolutionResultsCacheImpl.java @@ -0,0 +1,112 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.calls.context; + +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.psi.Call; +import org.jetbrains.jet.lang.psi.CallKey; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; +import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; +import org.jetbrains.jet.util.slicedmap.BasicWritableSlice; +import org.jetbrains.jet.util.slicedmap.Slices; +import org.jetbrains.jet.util.slicedmap.WritableSlice; + +public class ResolutionResultsCacheImpl implements ResolutionResultsCache { + public static final WritableSlice> + RESOLUTION_RESULTS_FOR_FUNCTION = Slices.createSimpleSlice(); + public static final WritableSlice> RESOLUTION_RESULTS_FOR_PROPERTY = Slices.createSimpleSlice(); + public static final WritableSlice TRACE_DELTAS_CACHE = Slices.createSimpleSlice(); + public static final WritableSlice> DEFERRED_COMPUTATION_FOR_CALL = Slices.createSimpleSlice(); + + static { + BasicWritableSlice.initSliceDebugNames(ResolutionResultsCacheImpl.class); + } + + private final DelegatingBindingTrace trace = new DelegatingBindingTrace( + new BindingTraceContext().getBindingContext(), "Internal binding context in resolution results cache"); + + @NotNull + private static WritableSlice> getSliceByMemberType(@NotNull MemberType memberType) { + //noinspection unchecked + return (WritableSlice>) + (memberType == FUNCTION_MEMBER_TYPE ? RESOLUTION_RESULTS_FOR_FUNCTION : RESOLUTION_RESULTS_FOR_PROPERTY); + } + + @Override + public void recordResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType, @NotNull OverloadResolutionResultsImpl results) { + trace.record(getSliceByMemberType(memberType), callKey, results); + } + + @Override + @Nullable + public OverloadResolutionResultsImpl getResolutionResults(@NotNull CallKey callKey, @NotNull MemberType memberType) { + return trace.get(getSliceByMemberType(memberType), callKey); + } + + @Override + public void recordResolutionTrace(@NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace) { + trace.record(TRACE_DELTAS_CACHE, callKey, delegatingTrace); + } + + @Override + @Nullable + public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) { + return trace.get(TRACE_DELTAS_CACHE, callKey); + } + + @Override + public void recordDeferredComputationForCall( + @NotNull CallKey callKey, + @NotNull CallCandidateResolutionContext deferredComputation, + @NotNull MemberType memberType + ) { + if (memberType == PROPERTY_MEMBER_TYPE) return; + //noinspection unchecked + trace.record(DEFERRED_COMPUTATION_FOR_CALL, callKey, (CallCandidateResolutionContext) deferredComputation); + } + + @Override + @Nullable + public CallCandidateResolutionContext getDeferredComputation(@Nullable JetExpression expression) { + if (expression == null) return null; + for (Call.CallType callType : Lists + .newArrayList(Call.CallType.DEFAULT, Call.CallType.ARRAY_GET_METHOD, Call.CallType.ARRAY_SET_METHOD)) { + CallKey callKey = CallKey.create(callType, expression); + CallCandidateResolutionContext context = trace.get(DEFERRED_COMPUTATION_FOR_CALL, callKey); + if (context != null) { + return context; + } + } + return null; + } + + @NotNull + public static ResolutionResultsCache create() { + return new ResolutionResultsCacheImpl(); + } + + /*package*/ void addData(@NotNull ResolutionResultsCacheImpl cache) { + cache.trace.addAllMyDataTo(this.trace); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryResolutionResultsCache.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryResolutionResultsCache.java new file mode 100644 index 00000000000..31f0824bd43 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryResolutionResultsCache.java @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.calls.context; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.CallKey; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; +import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl; + +public class TemporaryResolutionResultsCache implements ResolutionResultsCache { + private final ResolutionResultsCache parentCache; + private final ResolutionResultsCacheImpl innerCache; + + public TemporaryResolutionResultsCache(@NotNull ResolutionResultsCache parentCache) { + assert parentCache instanceof ResolutionResultsCacheImpl || parentCache instanceof TemporaryResolutionResultsCache : + "Unsupported parent cache: " + parentCache; + this.parentCache = parentCache; + this.innerCache = new ResolutionResultsCacheImpl(); + } + + @Override + public void recordResolutionResults( + @NotNull CallKey callKey, + @NotNull MemberType memberType, + @NotNull OverloadResolutionResultsImpl results + ) { + innerCache.recordResolutionResults(callKey, memberType, results); + } + + @Nullable + @Override + public OverloadResolutionResultsImpl getResolutionResults( + @NotNull CallKey callKey, @NotNull MemberType memberType + ) { + OverloadResolutionResultsImpl results = innerCache.getResolutionResults(callKey, memberType); + if (results != null) { + return results; + } + return parentCache.getResolutionResults(callKey, memberType); + } + + @Override + public void recordResolutionTrace( + @NotNull CallKey callKey, @NotNull DelegatingBindingTrace delegatingTrace + ) { + innerCache.recordResolutionTrace(callKey, delegatingTrace); + } + + @Nullable + @Override + public DelegatingBindingTrace getResolutionTrace(@NotNull CallKey callKey) { + DelegatingBindingTrace trace = innerCache.getResolutionTrace(callKey); + if (trace != null) { + return trace; + } + return parentCache.getResolutionTrace(callKey); + } + + @Override + public void recordDeferredComputationForCall( + @NotNull CallKey callKey, + @NotNull CallCandidateResolutionContext deferredComputation, + @NotNull MemberType memberType + ) { + innerCache.recordDeferredComputationForCall(callKey, deferredComputation, memberType); + } + + @Nullable + @Override + public CallCandidateResolutionContext getDeferredComputation(@Nullable JetExpression expression) { + CallCandidateResolutionContext computation = innerCache.getDeferredComputation(expression); + if (computation != null) { + return computation; + } + return parentCache.getDeferredComputation(expression); + } + + public void commit() { + if (parentCache instanceof ResolutionResultsCacheImpl) { + ((ResolutionResultsCacheImpl) parentCache).addData(innerCache); + return; + } + assert parentCache instanceof TemporaryResolutionResultsCache; + ((TemporaryResolutionResultsCache) parentCache).innerCache.addData(innerCache); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryTraceAndCache.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryTraceAndCache.java new file mode 100644 index 00000000000..705cf848198 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/context/TemporaryTraceAndCache.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.calls.context; + +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; + +public class TemporaryTraceAndCache { + public final TemporaryBindingTrace trace; + public final TemporaryResolutionResultsCache cache; + + public TemporaryTraceAndCache(ResolutionContext context, String debugName, JetExpression expression) { + trace = TemporaryBindingTrace.create(context.trace, debugName, expression); + cache = new TemporaryResolutionResultsCache(context.resolutionResultsCache); + } + + public static TemporaryTraceAndCache create(ResolutionContext context, String debugName, JetExpression expression) { + return new TemporaryTraceAndCache(context, debugName, expression); + } + + public void commit() { + trace.commit(); + cache.commit(); + } +} 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 0d42706a377..f559b438ea2 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 @@ -34,8 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory; import org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability; -import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; -import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition; +import org.jetbrains.jet.lang.resolve.calls.context.*; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; @@ -672,23 +671,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } ReceiverValue receiver = new TransientReceiver(lhsType); - TemporaryBindingTrace traceWithReceiver = TemporaryBindingTrace.create(context.trace, + TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(context, "trace to resolve callable reference with receiver", reference); FunctionDescriptor descriptor = resolveCallableNotCheckingArguments( - reference, receiver, context.replaceBindingTrace(traceWithReceiver).replaceResolutionResultsCache(), result); + reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result); if (result[0]) { - traceWithReceiver.commit(); + temporaryWithReceiver.commit(); return descriptor; } JetScope staticScope = getStaticNestedClassesScope((ClassDescriptor) classifier); - TemporaryBindingTrace traceForStatic = TemporaryBindingTrace.create(context.trace, - "trace to resolve callable reference in static scope", reference); + TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create( + context, "trace to resolve callable reference in static scope", reference); FunctionDescriptor possibleStaticNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER, - context.replaceBindingTrace(traceForStatic).replaceScope(staticScope).replaceResolutionResultsCache(), result); + context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result); if (result[0]) { - traceForStatic.commit(); + temporaryForStatic.commit(); return possibleStaticNestedClassConstructor; } 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 5ce18628641..00b328a5f6e 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 @@ -41,7 +41,7 @@ public class ExpressionTypingContext extends ResolutionContext binaryOperationDescriptors = BasicExpressionTypingVisitor.getResolutionResultsForBinaryCall( - scope, counterpartName, context.replaceBindingTrace(binaryOperationTrace).replaceResolutionResultsCache(), expression, receiver); + scope, counterpartName, context.replaceTraceAndCache(temporaryForBinaryOperation), expression, receiver); JetType binaryOperationType = OverloadResolutionResultsUtil.getResultingType(binaryOperationDescriptors, context.resolveMode); JetType type = assignmentOperationType != null ? assignmentOperationType : binaryOperationType; - if (assignmentOperationType != null && binaryOperationType != null) { + if (assignmentOperationDescriptors.isSuccess() && binaryOperationDescriptors.isSuccess()) { // Both 'plus()' and 'plusAssign()' available => ambiguity OverloadResolutionResults ambiguityResolutionResults = OverloadResolutionResultsUtil.ambiguity(assignmentOperationDescriptors, binaryOperationDescriptors); context.trace.report(ASSIGN_OPERATOR_AMBIGUITY.on(operationSign, ambiguityResolutionResults.getResultingCalls())); @@ -263,26 +266,26 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo(); context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors); } - else if (assignmentOperationType != null) { + else if (assignmentOperationType != null && (assignmentOperationDescriptors.isSuccess() || !binaryOperationDescriptors.isSuccess())) { // There's 'plusAssign()', so we do a.plusAssign(b) - assignmentOperationTrace.commit(); + temporaryForAssignmentOperation.commit(); if (!KotlinBuiltIns.getInstance().isUnit(assignmentOperationType)) { context.trace.report(ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT.on(operationSign, assignmentOperationDescriptors.getResultingDescriptor(), operationSign)); } } else { // There's only 'plus()', so we try 'a = a + b' - binaryOperationTrace.commit(); + temporaryForBinaryOperation.commit(); context.trace.record(VARIABLE_REASSIGNMENT, expression); if (left instanceof JetArrayAccessExpression) { ExpressionTypingContext contextForResolve = context.replaceScope(scope).replaceBindingTrace(TemporaryBindingTrace.create( - contextWithExpectedType.trace, "trace to resolve array set method for assignment", expression)); + context.trace, "trace to resolve array set method for assignment", expression)); basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace); } dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo(); BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand); } - temporaryBindingTrace.commit(); + temporary.commit(); return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo); }