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.psi.PsiElement;
021    import com.intellij.psi.util.PsiTreeUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
025    import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
026    import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
027    import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
028    import org.jetbrains.jet.lang.diagnostics.Errors;
029    import org.jetbrains.jet.lang.psi.*;
030    import org.jetbrains.jet.lang.resolve.BindingContext;
031    import org.jetbrains.jet.lang.resolve.BindingContextUtils;
032    import org.jetbrains.jet.lang.resolve.DescriptorResolver;
033    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
034    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
035    import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
036    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
037    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
038    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
039    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
040    import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
041    import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
042    import org.jetbrains.jet.lang.types.*;
043    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
044    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
045    
046    import java.util.ArrayList;
047    import java.util.Collections;
048    import java.util.List;
049    
050    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
051    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
052    import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
053    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
054    import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
055    import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
056    import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall;
057    import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
058    
059    public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
060    
061        public static final String RETURN_NOT_ALLOWED_MESSAGE = "Return not allowed";
062    
063        protected ControlStructureTypingVisitor(@NotNull ExpressionTypingInternals facade) {
064            super(facade);
065        }
066    
067        @NotNull
068        private DataFlowInfo checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
069            if (condition != null) {
070                JetTypeInfo typeInfo = facade.getTypeInfo(condition, context.replaceScope(scope)
071                        .replaceExpectedType(KotlinBuiltIns.getInstance().getBooleanType()).replaceContextDependency(INDEPENDENT));
072                JetType conditionType = typeInfo.getType();
073    
074                if (conditionType != null && !isBoolean(conditionType)) {
075                    context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
076                }
077    
078                return typeInfo.getDataFlowInfo();
079            }
080            return context.dataFlowInfo;
081        }
082    
083        ////////////////////////////////////////////////////////////////////////////////////////////////////
084    
085    
086        @Override
087        public JetTypeInfo visitIfExpression(@NotNull JetIfExpression expression, ExpressionTypingContext context) {
088            return visitIfExpression(expression, context, false);
089        }
090    
091        public JetTypeInfo visitIfExpression(JetIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
092            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
093            JetExpression condition = ifExpression.getCondition();
094            DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
095    
096            JetExpression elseBranch = ifExpression.getElse();
097            JetExpression thenBranch = ifExpression.getThen();
098    
099            WritableScopeImpl thenScope = newWritableScopeImpl(context, "Then scope");
100            WritableScopeImpl elseScope = newWritableScopeImpl(context, "Else scope");
101            DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
102            DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
103    
104            if (elseBranch == null) {
105                if (thenBranch != null) {
106                    return getTypeInfoWhenOnlyOneBranchIsPresent(
107                            thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
108                }
109                return DataFlowUtils.checkImplicitCast(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, contextWithExpectedType,
110                                                       isStatement, thenInfo.or(elseInfo));
111            }
112            if (thenBranch == null) {
113                return getTypeInfoWhenOnlyOneBranchIsPresent(
114                        elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
115            }
116            JetBlockExpression thenBlock = JetPsiFactory.wrapInABlock(thenBranch);
117            JetBlockExpression elseBlock = JetPsiFactory.wrapInABlock(elseBranch);
118            Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
119            MutableDataFlowInfoForArguments dataFlowInfoForArguments =
120                        createDataFlowInfoForArgumentsForIfCall(callForIf, thenInfo, elseInfo);
121            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
122                    callForIf, "If", Lists.newArrayList("thenBranch", "elseBranch"),
123                    Lists.newArrayList(false, false),
124                    contextWithExpectedType, dataFlowInfoForArguments);
125    
126            JetTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, context.trace.getBindingContext());
127            JetTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, context.trace.getBindingContext());
128            assert thenTypeInfo != null : "'Then' branch of if expression  was not processed: " + ifExpression;
129            assert elseTypeInfo != null : "'Else' branch of if expression  was not processed: " + ifExpression;
130    
131            JetType thenType = thenTypeInfo.getType();
132            JetType elseType = elseTypeInfo.getType();
133            DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
134            DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
135    
136            boolean jumpInThen = thenType != null && KotlinBuiltIns.getInstance().isNothing(thenType);
137            boolean jumpInElse = elseType != null && KotlinBuiltIns.getInstance().isNothing(elseType);
138    
139            JetTypeInfo result;
140            if (thenType == null && elseType == null) {
141                result = JetTypeInfo.create(null, thenDataFlowInfo.or(elseDataFlowInfo));
142            }
143            else if (thenType == null || (jumpInThen && !jumpInElse)) {
144                result = elseTypeInfo;
145            }
146            else if (elseType == null || (jumpInElse && !jumpInThen)) {
147                result = thenTypeInfo;
148            }
149            else {
150                result = JetTypeInfo.create(resolvedCall.getResultingDescriptor().getReturnType(), thenDataFlowInfo.or(elseDataFlowInfo));
151            }
152    
153            return DataFlowUtils.checkImplicitCast(result.getType(), ifExpression, contextWithExpectedType, isStatement, result.getDataFlowInfo());
154        }
155    
156        @NotNull
157        private JetTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
158                @NotNull JetExpression presentBranch,
159                @NotNull WritableScopeImpl presentScope,
160                @NotNull DataFlowInfo presentInfo,
161                @NotNull DataFlowInfo otherInfo,
162                @NotNull ExpressionTypingContext context,
163                @NotNull JetIfExpression ifExpression,
164                boolean isStatement
165        ) {
166            ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
167                    .replaceContextDependency(INDEPENDENT);
168            JetTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
169                    presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext, context.trace);
170            JetType type = typeInfo.getType();
171            DataFlowInfo dataFlowInfo;
172            if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
173                dataFlowInfo = otherInfo;
174            } else {
175                dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
176            }
177            JetType typeForIfExpression = DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, context);
178            return DataFlowUtils.checkImplicitCast(typeForIfExpression, ifExpression, context, isStatement, dataFlowInfo);
179        }
180    
181        @Override
182        public JetTypeInfo visitWhileExpression(@NotNull JetWhileExpression expression, ExpressionTypingContext context) {
183            return visitWhileExpression(expression, context, false);
184        }
185    
186        public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
187            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
188    
189            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
190                    INDEPENDENT);
191            JetExpression condition = expression.getCondition();
192            DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
193    
194            JetExpression body = expression.getBody();
195            if (body != null) {
196                WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
197                DataFlowInfo conditionInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
198                components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
199                        scopeToExtend, Collections.singletonList(body),
200                        CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
201            }
202    
203            if (!containsJumpOutOfLoop(expression, context)) {
204                dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
205            }
206            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
207        }
208    
209        private boolean containsJumpOutOfLoop(final JetLoopExpression loopExpression, final ExpressionTypingContext context) {
210            final boolean[] result = new boolean[1];
211            result[0] = false;
212            //todo breaks in inline function literals
213            loopExpression.accept(new JetTreeVisitor<List<JetLoopExpression>>() {
214                @Override
215                public Void visitBreakExpression(@NotNull JetBreakExpression breakExpression, List<JetLoopExpression> outerLoops) {
216                    JetSimpleNameExpression targetLabel = breakExpression.getTargetLabel();
217                    PsiElement element = targetLabel != null ? context.trace.get(LABEL_TARGET, targetLabel) : null;
218                    if (element == loopExpression || (targetLabel == null && outerLoops.get(outerLoops.size() - 1) == loopExpression)) {
219                        result[0] = true;
220                    }
221                    return null;
222                }
223    
224                @Override
225                public Void visitContinueExpression(@NotNull JetContinueExpression expression, List<JetLoopExpression> outerLoops) {
226                    // continue@someOuterLoop is also considered as break
227                    JetSimpleNameExpression targetLabel = expression.getTargetLabel();
228                    if (targetLabel != null) {
229                        PsiElement element = context.trace.get(LABEL_TARGET, targetLabel);
230                        if (element instanceof JetLoopExpression && !outerLoops.contains(element)) {
231                            result[0] = true;
232                        }
233                    }
234                    return null;
235                }
236    
237                @Override
238                public Void visitLoopExpression(@NotNull JetLoopExpression loopExpression, List<JetLoopExpression> outerLoops) {
239                    List<JetLoopExpression> newOuterLoops = Lists.newArrayList(outerLoops);
240                    newOuterLoops.add(loopExpression);
241                    return super.visitLoopExpression(loopExpression, newOuterLoops);
242                }
243            }, Lists.newArrayList(loopExpression));
244    
245            return result[0];
246        }
247    
248        @Override
249        public JetTypeInfo visitDoWhileExpression(@NotNull JetDoWhileExpression expression, ExpressionTypingContext context) {
250            return visitDoWhileExpression(expression, context, false);
251        }
252        public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
253            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
254    
255            ExpressionTypingContext context =
256                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
257            JetExpression body = expression.getBody();
258            JetScope conditionScope = context.scope;
259            if (body instanceof JetFunctionLiteralExpression) {
260                JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
261                JetFunctionLiteral functionLiteral = function.getFunctionLiteral();
262                if (!functionLiteral.hasParameterSpecification()) {
263                    WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
264                    conditionScope = writableScope;
265                    components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, functionLiteral.getBodyExpression().getStatements(), CoercionStrategy.NO_COERCION, context, context.trace);
266                    context.trace.record(BindingContext.BLOCK, function);
267                }
268                else {
269                    facade.getTypeInfo(body, context.replaceScope(context.scope));
270                }
271                context.trace.report(UNUSED_FUNCTION_LITERAL.on(function));
272            }
273            else if (body != null) {
274                WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
275                conditionScope = writableScope;
276                List<JetElement> block;
277                if (body instanceof JetBlockExpression) {
278                    block = ((JetBlockExpression)body).getStatements();
279                }
280                else {
281                    block = Collections.<JetElement>singletonList(body);
282                }
283                components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, block, CoercionStrategy.NO_COERCION, context, context.trace);
284            }
285            JetExpression condition = expression.getCondition();
286            DataFlowInfo conditionDataFlowInfo = checkCondition(conditionScope, condition, context);
287            DataFlowInfo dataFlowInfo;
288            if (!containsJumpOutOfLoop(expression, context)) {
289                dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
290            }
291            else {
292                dataFlowInfo = context.dataFlowInfo;
293            }
294            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
295        }
296    
297        @Override
298        public JetTypeInfo visitForExpression(@NotNull JetForExpression expression, ExpressionTypingContext context) {
299            return visitForExpression(expression, context, false);
300        }
301    
302        public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
303            if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
304    
305            ExpressionTypingContext context =
306                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
307            JetExpression loopRange = expression.getLoopRange();
308            JetType expectedParameterType = null;
309            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
310            if (loopRange != null) {
311                ExpressionReceiver loopRangeReceiver = getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
312                dataFlowInfo = facade.getTypeInfo(loopRange, context).getDataFlowInfo();
313                if (loopRangeReceiver != null) {
314                    expectedParameterType = components.forLoopConventionsChecker.checkIterableConvention(loopRangeReceiver, context);
315                }
316            }
317    
318            WritableScope loopScope = newWritableScopeImpl(context, "Scope with for-loop index");
319    
320            JetParameter loopParameter = expression.getLoopParameter();
321            if (loopParameter != null) {
322                VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
323    
324                loopScope.addVariableDescriptor(variableDescriptor);
325            }
326            else {
327                JetMultiDeclaration multiParameter = expression.getMultiParameter();
328                if (multiParameter != null && loopRange != null) {
329                    JetType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
330                    TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
331                    components.expressionTypingUtils.defineLocalVariablesFromMultiDeclaration(loopScope, multiParameter, iteratorNextAsReceiver,
332                                                                                              loopRange, context);
333                }
334            }
335    
336            JetExpression body = expression.getBody();
337            if (body != null) {
338                components.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 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 = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
356                JetType actualParameterType = variableDescriptor.getType();
357                if (expectedParameterType != null &&
358                        !JetTypeChecker.DEFAULT.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 = components.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 && 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        @Override
382        public JetTypeInfo visitTryExpression(@NotNull JetTryExpression expression, ExpressionTypingContext typingContext) {
383            ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
384            JetExpression tryBlock = expression.getTryBlock();
385            List<JetCatchClause> catchClauses = expression.getCatchClauses();
386            JetFinallySection finallyBlock = expression.getFinallyBlock();
387            List<JetType> types = new ArrayList<JetType>();
388            for (JetCatchClause catchClause : catchClauses) {
389                JetParameter catchParameter = catchClause.getCatchParameter();
390                JetExpression catchBody = catchClause.getCatchBody();
391                if (catchParameter != null) {
392                    DescriptorResolver.checkParameterHasNoValOrVar(context.trace, catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
393                    DescriptorResolver.checkParameterHasNoModifier(context.trace, catchParameter);
394    
395                    VariableDescriptor variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(
396                            context.scope, catchParameter, context.trace);
397                    JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
398                    DataFlowUtils.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType));
399                    if (catchBody != null) {
400                        WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
401                        catchScope.addVariableDescriptor(variableDescriptor);
402                        JetType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
403                        if (type != null) {
404                            types.add(type);
405                        }
406                    }
407                }
408            }
409    
410            DataFlowInfo dataFlowInfo = context.dataFlowInfo;
411            if (finallyBlock != null) {
412                dataFlowInfo = facade.getTypeInfo(finallyBlock.getFinalExpression(),
413                                                  context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
414            }
415    
416            JetType type = facade.getTypeInfo(tryBlock, context).getType();
417            if (type != null) {
418                types.add(type);
419            }
420            if (types.isEmpty()) {
421                return JetTypeInfo.create(null, dataFlowInfo);
422            }
423            else {
424                return JetTypeInfo.create(CommonSupertypes.commonSupertype(types), dataFlowInfo);
425            }
426        }
427    
428        @Override
429        public JetTypeInfo visitThrowExpression(@NotNull JetThrowExpression expression, ExpressionTypingContext context) {
430            JetExpression thrownExpression = expression.getThrownExpression();
431            if (thrownExpression != null) {
432                JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
433                facade.getTypeInfo(thrownExpression, context
434                        .replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
435            }
436            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
437        }
438    
439        @Override
440        public JetTypeInfo visitReturnExpression(@NotNull JetReturnExpression expression, ExpressionTypingContext context) {
441            JetElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);
442    
443            JetExpression returnedExpression = expression.getReturnedExpression();
444    
445            JetType expectedType = NO_EXPECTED_TYPE;
446            JetType resultType = KotlinBuiltIns.getInstance().getNothingType();
447            JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
448    
449            if (parentDeclaration instanceof JetParameter) {
450                // In a default value for parameter
451                context.trace.report(RETURN_NOT_ALLOWED.on(expression));
452            }
453            assert parentDeclaration != null;
454            DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
455            FunctionDescriptor containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, FunctionDescriptor.class, false);
456    
457            if (expression.getTargetLabel() == null) {
458                if (containingFunctionDescriptor != null) {
459                    PsiElement containingFunction = BindingContextUtils.callableDescriptorToDeclaration(context.trace.getBindingContext(), containingFunctionDescriptor);
460                    assert containingFunction != null;
461                    if (containingFunction instanceof JetFunctionLiteral) {
462                        do {
463                            containingFunctionDescriptor = DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class);
464                            containingFunction = containingFunctionDescriptor != null ? BindingContextUtils.callableDescriptorToDeclaration(context.trace.getBindingContext(), containingFunctionDescriptor) : null;
465                        } while (containingFunction instanceof JetFunctionLiteral);
466                        // Unqualified, in a function literal
467                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
468                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
469                    }
470                    if (containingFunctionDescriptor != null) {
471                        expectedType = getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunction);
472                    }
473                }
474                else {
475                    // Outside a function
476                    context.trace.report(RETURN_NOT_ALLOWED.on(expression));
477                    resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
478                }
479            }
480            else if (labelTargetElement != null) {
481                SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
482                if (functionDescriptor != null) {
483                    expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement);
484                    if (functionDescriptor != containingFunctionDescriptor) {
485                        // Qualified, non-local
486                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
487                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
488                    }
489                    else if (expectedType == NO_EXPECTED_TYPE) {
490                        // expectedType is NO_EXPECTED_TYPE iff the return type of the corresponding function descriptor is not computed yet
491                        // our temporary policy is to prohibit returns in this case. It mostly applies to local returns in lambdas
492                        context.trace.report(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED.on(expression));
493                    }
494                }
495                else {
496                    context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
497                }
498            }
499            if (returnedExpression != null) {
500                facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)
501                        .replaceContextDependency(INDEPENDENT));
502            }
503            else {
504                if (expectedType != null && !noExpectedType(expectedType) && !KotlinBuiltIns.getInstance().isUnit(expectedType)) {
505                    context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
506                }
507            }
508            return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
509        }
510    
511        @Override
512        public JetTypeInfo visitBreakExpression(@NotNull JetBreakExpression expression, ExpressionTypingContext context) {
513            LabelResolver.INSTANCE.resolveControlLabel(expression, context);
514            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
515        }
516    
517        @Override
518        public JetTypeInfo visitContinueExpression(@NotNull JetContinueExpression expression, ExpressionTypingContext context) {
519            LabelResolver.INSTANCE.resolveControlLabel(expression, context);
520            return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
521        }
522    
523        @NotNull
524        private static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) {
525            JetType expectedType;
526            if (function instanceof JetFunction) {
527                if (((JetFunction) function).getReturnTypeRef() != null || ((JetFunction) function).hasBlockBody()) {
528                    expectedType = descriptor.getReturnType();
529                }
530                else {
531                    expectedType = TypeUtils.NO_EXPECTED_TYPE;
532                }
533            }
534            else {
535                expectedType = descriptor.getReturnType();
536            }
537            return expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE;
538        }
539    }