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
017package org.jetbrains.jet.lang.types.expressions;
018
019import com.google.common.collect.Lists;
020import com.intellij.openapi.util.Pair;
021import com.intellij.psi.PsiElement;
022import com.intellij.psi.util.PsiTreeUtil;
023import org.jetbrains.annotations.NotNull;
024import org.jetbrains.annotations.Nullable;
025import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
026import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
027import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
028import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
029import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1;
030import org.jetbrains.jet.lang.diagnostics.Errors;
031import org.jetbrains.jet.lang.psi.*;
032import org.jetbrains.jet.lang.resolve.BindingContext;
033import org.jetbrains.jet.lang.resolve.BindingContextUtils;
034import org.jetbrains.jet.lang.resolve.DescriptorResolver;
035import org.jetbrains.jet.lang.resolve.DescriptorUtils;
036import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
037import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
038import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
039import org.jetbrains.jet.lang.resolve.name.Name;
040import org.jetbrains.jet.lang.resolve.scopes.JetScope;
041import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
042import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
043import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
044import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
045import org.jetbrains.jet.lang.types.*;
046import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
047import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
048import org.jetbrains.jet.util.slicedmap.WritableSlice;
049
050import java.util.ArrayList;
051import java.util.Arrays;
052import java.util.Collections;
053import java.util.List;
054
055import static org.jetbrains.jet.lang.diagnostics.Errors.*;
056import static org.jetbrains.jet.lang.resolve.BindingContext.*;
057import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
058
059public 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}