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