001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.types.expressions;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.openapi.util.Pair;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.psi.util.PsiTreeUtil;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
026    import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
027    import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
028    import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
029    import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1;
030    import org.jetbrains.jet.lang.diagnostics.Errors;
031    import org.jetbrains.jet.lang.psi.*;
032    import org.jetbrains.jet.lang.resolve.BindingContext;
033    import org.jetbrains.jet.lang.resolve.BindingContextUtils;
034    import org.jetbrains.jet.lang.resolve.DescriptorResolver;
035    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
036    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
037    import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
038    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
039    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
040    import org.jetbrains.jet.lang.resolve.name.Name;
041    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
042    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
043    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
044    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
045    import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
046    import org.jetbrains.jet.lang.types.*;
047    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
048    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
049    import org.jetbrains.jet.util.slicedmap.WritableSlice;
050    
051    import java.util.*;
052    
053    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
054    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
055    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
056    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
057    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
058    import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.*;
059    import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
060    
061    public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
062    
063        public static final String RETURN_NOT_ALLOWED_MESSAGE = "Return not allowed";
064    
065        protected ControlStructureTypingVisitor(@NotNull ExpressionTypingInternals facade) {
066            super(facade);
067        }
068    
069        @NotNull
070        private DataFlowInfo checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
071            if (condition != null) {
072                JetTypeInfo typeInfo = facade.getTypeInfo(condition, context.replaceScope(scope)
073                        .replaceExpectedType(KotlinBuiltIns.getInstance().getBooleanType()).replaceContextDependency(INDEPENDENT));
074                JetType conditionType = typeInfo.getType();
075    
076                if (conditionType != null && !isBoolean(conditionType)) {
077                    context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
078                }
079    
080                return typeInfo.getDataFlowInfo();
081            }
082            return context.dataFlowInfo;
083        }
084    
085        ////////////////////////////////////////////////////////////////////////////////////////////////////
086    
087    
088        @Override
089        public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
090            return visitIfExpression(expression, context, false);
091        }
092    
093        public JetTypeInfo visitIfExpression(JetIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
094            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
095            JetExpression condition = ifExpression.getCondition();
096            DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
097    
098            JetExpression elseBranch = ifExpression.getElse();
099            JetExpression thenBranch = ifExpression.getThen();
100    
101            WritableScopeImpl thenScope = newWritableScopeImpl(context, "Then scope");
102            WritableScopeImpl elseScope = newWritableScopeImpl(context, "Else scope");
103            DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
104            DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
105    
106            if (elseBranch == null) {
107                if (thenBranch != null) {
108                    return getTypeInfoWhenOnlyOneBranchIsPresent(
109                            thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
110                }
111                return JetTypeInfo.create(null, context.dataFlowInfo);
112            }
113            if (thenBranch == null) {
114                return getTypeInfoWhenOnlyOneBranchIsPresent(
115                        elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
116            }
117            JetBlockExpression thenBlock = JetPsiFactory.wrapInABlock(thenBranch);
118            JetBlockExpression elseBlock = JetPsiFactory.wrapInABlock(elseBranch);
119            Call callForIf = createCallForSpecialConstruction(ifExpression, Lists.newArrayList(thenBlock, elseBlock));
120            MutableDataFlowInfoForArguments dataFlowInfoForArguments =
121                        createDataFlowInfoForArgumentsForIfCall(callForIf, thenInfo, elseInfo);
122            ResolvedCall<FunctionDescriptor> resolvedCall = resolveSpecialConstructionAsCall(
123                    callForIf, "If", Lists.newArrayList("thenBranch", "elseBranch"),
124                    Lists.newArrayList(false, false),
125                    contextWithExpectedType, dataFlowInfoForArguments);
126    
127            JetTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, context.trace.getBindingContext());
128            JetTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, context.trace.getBindingContext());
129            assert thenTypeInfo != null : "'Then' branch of if expression  was not processed: " + ifExpression;
130            assert elseTypeInfo != null : "'Else' branch of if expression  was not processed: " + ifExpression;
131    
132            JetType thenType = thenTypeInfo.getType();
133            JetType elseType = elseTypeInfo.getType();
134            DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
135            DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
136    
137            boolean jumpInThen = thenType != null && KotlinBuiltIns.getInstance().isNothing(thenType);
138            boolean jumpInElse = elseType != null && KotlinBuiltIns.getInstance().isNothing(elseType);
139    
140            JetTypeInfo result;
141            if (thenType == null && elseType == null) {
142                result = JetTypeInfo.create(null, thenDataFlowInfo.or(elseDataFlowInfo));
143            }
144            else if (thenType == null || (jumpInThen && !jumpInElse)) {
145                result = elseTypeInfo;
146            }
147            else if (elseType == null || (jumpInElse && !jumpInThen)) {
148                result = thenTypeInfo;
149            }
150            else {
151                result = JetTypeInfo.create(resolvedCall.getResultingDescriptor().getReturnType(), thenDataFlowInfo.or(elseDataFlowInfo));
152            }
153    
154            return DataFlowUtils.checkImplicitCast(result.getType(), ifExpression, contextWithExpectedType, isStatement, result.getDataFlowInfo());
155        }
156    
157        @NotNull
158        private static JetTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
159                @NotNull JetExpression presentBranch,
160                @NotNull WritableScopeImpl presentScope,
161                @NotNull DataFlowInfo presentInfo,
162                @NotNull DataFlowInfo otherInfo,
163                @NotNull ExpressionTypingContext context,
164                @NotNull JetIfExpression ifExpression,
165                boolean isStatement
166        ) {
167            ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
168                    .replaceContextDependency(INDEPENDENT);
169            JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
170                    presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext, context.trace);
171            JetType type = typeInfo.getType();
172            DataFlowInfo dataFlowInfo;
173            if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
174                dataFlowInfo = otherInfo;
175            } else {
176                dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
177            }
178            JetType typeForIfExpression = DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, context);
179            return DataFlowUtils.checkImplicitCast(typeForIfExpression, ifExpression, context, isStatement, dataFlowInfo);
180        }
181    
182        @Override
183        public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
184            return visitWhileExpression(expression, context, false);
185        }
186    
187        public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
188            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
189    
190            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
191                    INDEPENDENT);
192            JetExpression condition = expression.getCondition();
193            DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
194    
195            JetExpression body = expression.getBody();
196            if (body != null) {
197                WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
198                DataFlowInfo conditionInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
199                context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
200                        scopeToExtend, Collections.singletonList(body),
201                        CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
202            }
203    
204            if (!containsJumpOutOfLoop(expression, context)) {
205                dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
206            }
207            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
208        }
209    
210        private boolean containsJumpOutOfLoop(final JetLoopExpression loopExpression, final ExpressionTypingContext context) {
211            final boolean[] result = new boolean[1];
212            result[0] = false;
213            //todo breaks in inline function literals
214            loopExpression.accept(new JetTreeVisitor<List<JetLoopExpression>>() {
215                @Override
216                public Void visitBreakExpression(JetBreakExpression breakExpression, List<JetLoopExpression> outerLoops) {
217                    JetSimpleNameExpression targetLabel = breakExpression.getTargetLabel();
218                    PsiElement element = targetLabel != null ? context.trace.get(LABEL_TARGET, targetLabel) : null;
219                    if (element == loopExpression || (targetLabel == null && outerLoops.get(outerLoops.size() - 1) == loopExpression)) {
220                        result[0] = true;
221                    }
222                    return null;
223                }
224    
225                @Override
226                public Void visitContinueExpression(JetContinueExpression expression, List<JetLoopExpression> outerLoops) {
227                    // continue@someOuterLoop is also considered as break
228                    JetSimpleNameExpression targetLabel = expression.getTargetLabel();
229                    if (targetLabel != null) {
230                        PsiElement element = context.trace.get(LABEL_TARGET, targetLabel);
231                        if (element instanceof JetLoopExpression && !outerLoops.contains(element)) {
232                            result[0] = true;
233                        }
234                    }
235                    return null;
236                }
237    
238                @Override
239                public Void visitLoopExpression(JetLoopExpression loopExpression, List<JetLoopExpression> outerLoops) {
240                    List<JetLoopExpression> newOuterLoops = Lists.newArrayList(outerLoops);
241                    newOuterLoops.add(loopExpression);
242                    return super.visitLoopExpression(loopExpression, newOuterLoops);
243                }
244            }, Lists.newArrayList(loopExpression));
245    
246            return result[0];
247        }
248    
249        @Override
250        public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
251            return visitDoWhileExpression(expression, context, false);
252        }
253        public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
254            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
255    
256            ExpressionTypingContext context =
257                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
258            JetExpression body = expression.getBody();
259            JetScope conditionScope = context.scope;
260            if (body instanceof JetFunctionLiteralExpression) {
261                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
262                JetFunctionLiteral functionLiteral = function.getFunctionLiteral();
263                if (!functionLiteral.hasParameterSpecification()) {
264                    WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
265                    conditionScope = writableScope;
266                    context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, functionLiteral.getBodyExpression().getStatements(), CoercionStrategy.NO_COERCION, context, context.trace);
267                    context.trace.record(BindingContext.BLOCK, function);
268                }
269                else {
270                    facade.getTypeInfo(body, context.replaceScope(context.scope));
271                }
272                context.trace.report(UNUSED_FUNCTION_LITERAL.on(function));
273            }
274            else if (body != null) {
275                WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
276                conditionScope = writableScope;
277                List<JetElement> block;
278                if (body instanceof JetBlockExpression) {
279                    block = ((JetBlockExpression)body).getStatements();
280                }
281                else {
282                    block = Collections.<JetElement>singletonList(body);
283                }
284                context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, block, CoercionStrategy.NO_COERCION, context, context.trace);
285            }
286            JetExpression condition = expression.getCondition();
287            DataFlowInfo conditionDataFlowInfo = checkCondition(conditionScope, condition, context);
288            DataFlowInfo dataFlowInfo;
289            if (!containsJumpOutOfLoop(expression, context)) {
290                dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
291            }
292            else {
293                dataFlowInfo = context.dataFlowInfo;
294            }
295            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
296        }
297    
298        @Override
299        public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
300            return visitForExpression(expression, context, false);
301        }
302    
303        public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
304            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
305    
306            ExpressionTypingContext context =
307                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
308            JetExpression loopRange = expression.getLoopRange();
309            JetType expectedParameterType = null;
310            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
311            if (loopRange != null) {
312                ExpressionReceiver loopRangeReceiver = getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
313                dataFlowInfo = facade.getTypeInfo(loopRange, context).getDataFlowInfo();
314                if (loopRangeReceiver != null) {
315                    expectedParameterType = checkIterableConvention(loopRangeReceiver, context);
316                }
317            }
318    
319            WritableScope loopScope = newWritableScopeImpl(context, "Scope with for-loop index");
320    
321            JetParameter loopParameter = expression.getLoopParameter();
322            if (loopParameter != null) {
323                VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
324    
325                loopScope.addVariableDescriptor(variableDescriptor);
326            }
327            else {
328                JetMultiDeclaration multiParameter = expression.getMultiParameter();
329                if (multiParameter != null && loopRange != null) {
330                    JetType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
331                    TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
332                    ExpressionTypingUtils.defineLocalVariablesFromMultiDeclaration(loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context);
333                }
334            }
335    
336            JetExpression body = expression.getBody();
337            if (body != null) {
338                context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body),
339                        CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(dataFlowInfo), context.trace);
340            }
341    
342            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
343        }
344    
345        private static VariableDescriptor createLoopParameterDescriptor(
346                JetParameter loopParameter,
347                JetType expectedParameterType,
348                ExpressionTypingContext context
349        ) {
350            DescriptorResolver.checkParameterHasNoValOrVar(context.trace, loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);
351    
352            JetTypeReference typeReference = loopParameter.getTypeReference();
353            VariableDescriptor variableDescriptor;
354            if (typeReference != null) {
355                variableDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
356                JetType actualParameterType = variableDescriptor.getType();
357                if (expectedParameterType != null &&
358                        !JetTypeChecker.INSTANCE.isSubtypeOf(expectedParameterType, actualParameterType)) {
359                    context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
360                }
361            }
362            else {
363                if (expectedParameterType == null) {
364                    expectedParameterType = ErrorUtils.createErrorType("Error");
365                }
366                variableDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(loopParameter, expectedParameterType, context.trace, context.scope);
367            }
368    
369            {
370                // http://youtrack.jetbrains.net/issue/KT-527
371    
372                VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName());
373                if (olderVariable != null && DescriptorUtils.isLocal(context.scope.getContainingDeclaration(), olderVariable)) {
374                    PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context.trace.getBindingContext(), variableDescriptor);
375                    context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
376                }
377            }
378            return variableDescriptor;
379        }
380    
381        @Nullable
382        /*package*/ static JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) {
383            JetExpression loopRangeExpression = loopRange.getExpression();
384    
385            // Make a fake call loopRange.iterator(), and try to resolve it
386            Name iterator = Name.identifier("iterator");
387            Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = makeAndResolveFakeCall(loopRange, context, Collections.<JetExpression>emptyList(), iterator);
388            Call iteratorCall = calls.getFirst();
389            OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
390    
391            if (iteratorResolutionResults.isSuccess()) {
392                ResolvedCall<FunctionDescriptor> iteratorResolvedCall = iteratorResolutionResults.getResultingCall();
393                context.trace.record(LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall);
394                context.trace.record(LOOP_RANGE_ITERATOR_CALL, loopRangeExpression, iteratorCall);
395    
396                FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
397                JetType iteratorType = iteratorFunction.getReturnType();
398                JetType hasNextType = checkConventionForIterator(context, loopRangeExpression, iteratorType, "hasNext",
399                                                                 HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE,
400                                                                 LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
401                if (hasNextType != null && !isBoolean(hasNextType)) {
402                    context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
403                }
404                return checkConventionForIterator(context, loopRangeExpression, iteratorType, "next",
405                                                  NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE,
406                                                  LOOP_RANGE_NEXT_RESOLVED_CALL);
407            }
408            else {
409                if (iteratorResolutionResults.isAmbiguity()) {
410    //                    StringBuffer stringBuffer = new StringBuffer("Method 'iterator()' is ambiguous for this expression: ");
411    //                    for (FunctionDescriptor functionDescriptor : iteratorResolutionResults.getResultingCalls()) {
412    //                        stringBuffer.append(DescriptorRendererImpl.TEXT.render(functionDescriptor)).append(" ");
413    //                    }
414    //                    errorMessage = stringBuffer.toString();
415                    context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResults.getResultingCalls()));
416                }
417                else {
418                    context.trace.report(ITERATOR_MISSING.on(loopRangeExpression));
419                }
420            }
421            return null;
422        }
423    
424        @Nullable
425        private static JetType checkConventionForIterator(
426                @NotNull ExpressionTypingContext context,
427                @NotNull JetExpression loopRangeExpression,
428                @NotNull JetType iteratorType,
429                @NotNull String name,
430                @NotNull DiagnosticFactory1<JetExpression, JetType> ambiguity,
431                @NotNull DiagnosticFactory1<JetExpression, JetType> missing,
432                @NotNull DiagnosticFactory1<JetExpression, JetType> noneApplicable,
433                @NotNull WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
434        ) {
435            OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = resolveFakeCall(
436                    context, new TransientReceiver(iteratorType), Name.identifier(name));
437            if (nextResolutionResults.isAmbiguity()) {
438                context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
439            }
440            else if (nextResolutionResults.isNothing()) {
441                context.trace.report(missing.on(loopRangeExpression, iteratorType));
442            }
443            else if (!nextResolutionResults.isSuccess()) {
444                context.trace.report(noneApplicable.on(loopRangeExpression, iteratorType));
445            }
446            else {
447                assert nextResolutionResults.isSuccess();
448                ResolvedCall<FunctionDescriptor> resolvedCall = nextResolutionResults.getResultingCall();
449                context.trace.record(resolvedCallKey, loopRangeExpression, resolvedCall);
450                return resolvedCall.getResultingDescriptor().getReturnType();
451            }
452            return null;
453        }
454    
455        @Override
456        public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext typingContext) {
457            ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
458            JetExpression tryBlock = expression.getTryBlock();
459            List<JetCatchClause> catchClauses = expression.getCatchClauses();
460            JetFinallySection finallyBlock = expression.getFinallyBlock();
461            List<JetType> types = new ArrayList<JetType>();
462            for (JetCatchClause catchClause : catchClauses) {
463                JetParameter catchParameter = catchClause.getCatchParameter();
464                JetExpression catchBody = catchClause.getCatchBody();
465                if (catchParameter != null) {
466                    DescriptorResolver.checkParameterHasNoValOrVar(context.trace, catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
467                    DescriptorResolver.checkParameterHasNoModifier(context.trace, catchParameter);
468    
469                    VariableDescriptor variableDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(
470                            context.scope, catchParameter, context.trace);
471                    JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
472                    DataFlowUtils.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType));
473                    if (catchBody != null) {
474                        WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
475                        catchScope.addVariableDescriptor(variableDescriptor);
476                        JetType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
477                        if (type != null) {
478                            types.add(type);
479                        }
480                    }
481                }
482            }
483    
484            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
485            if (finallyBlock != null) {
486                dataFlowInfo = facade.getTypeInfo(finallyBlock.getFinalExpression(),
487                                                  context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
488            }
489    
490            JetType type = facade.getTypeInfo(tryBlock, context).getType();
491            if (type != null) {
492                types.add(type);
493            }
494            if (types.isEmpty()) {
495                return JetTypeInfo.create(null, dataFlowInfo);
496            }
497            else {
498                return JetTypeInfo.create(CommonSupertypes.commonSupertype(types), dataFlowInfo);
499            }
500        }
501    
502        @Override
503        public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) {
504            JetExpression thrownExpression = expression.getThrownExpression();
505            if (thrownExpression != null) {
506                JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
507                facade.getTypeInfo(thrownExpression, context
508                        .replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
509            }
510            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
511        }
512    
513        @Override
514        public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) {
515            JetElement labelTargetElement = context.labelResolver.resolveLabel(expression, context);
516    
517            JetExpression returnedExpression = expression.getReturnedExpression();
518    
519            JetType expectedType = NO_EXPECTED_TYPE;
520            JetType resultType = KotlinBuiltIns.getInstance().getNothingType();
521            JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
522    
523            if (parentDeclaration instanceof JetParameter) {
524                // In a default value for parameter
525                context.trace.report(RETURN_NOT_ALLOWED.on(expression));
526            }
527            assert parentDeclaration != null;
528            DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
529            FunctionDescriptor containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, FunctionDescriptor.class, false);
530    
531            if (expression.getTargetLabel() == null) {
532                if (containingFunctionDescriptor != null) {
533                    PsiElement containingFunction = BindingContextUtils.callableDescriptorToDeclaration(context.trace.getBindingContext(), containingFunctionDescriptor);
534                    assert containingFunction != null;
535                    if (containingFunction instanceof JetFunctionLiteral) {
536                        do {
537                            containingFunctionDescriptor = DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class);
538                            containingFunction = containingFunctionDescriptor != null ? BindingContextUtils.callableDescriptorToDeclaration(context.trace.getBindingContext(), containingFunctionDescriptor) : null;
539                        } while (containingFunction instanceof JetFunctionLiteral);
540                        // Unqualified, in a function literal
541                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
542                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
543                    }
544                    if (containingFunctionDescriptor != null) {
545                        expectedType = DescriptorUtils.getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunction);
546                    }
547                }
548                else {
549                    // Outside a function
550                    context.trace.report(RETURN_NOT_ALLOWED.on(expression));
551                    resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
552                }
553            }
554            else if (labelTargetElement != null) {
555                SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
556                if (functionDescriptor != null) {
557                    expectedType = DescriptorUtils.getFunctionExpectedReturnType(functionDescriptor, labelTargetElement);
558                    if (functionDescriptor != containingFunctionDescriptor) {
559                        // Qualified, non-local
560                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
561                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
562                    }
563                    else if (expectedType == NO_EXPECTED_TYPE) {
564                        // expectedType is NO_EXPECTED_TYPE iff the return type of the corresponding function descriptor is not computed yet
565                        // our temporary policy is to prohibit returns in this case. It mostly applies to local returns in lambdas
566                        context.trace.report(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED.on(expression));
567                    }
568                }
569                else {
570                    context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
571                }
572            }
573            if (returnedExpression != null) {
574                facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)
575                        .replaceContextDependency(INDEPENDENT));
576            }
577            else {
578                if (expectedType != null && !noExpectedType(expectedType) && !KotlinBuiltIns.getInstance().isUnit(expectedType)) {
579                    context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
580                }
581            }
582            return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
583        }
584    
585        @Override
586        public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext context) {
587            context.labelResolver.resolveLabel(expression, context);
588            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
589        }
590    
591        @Override
592        public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext context) {
593            context.labelResolver.resolveLabel(expression, context);
594            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
595        }
596    }