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