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