001    /*
002     * Copyright 2010-2015 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.kotlin.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.kotlin.builtins.KotlinBuiltIns;
026    import org.jetbrains.kotlin.descriptors.*;
027    import org.jetbrains.kotlin.psi.*;
028    import org.jetbrains.kotlin.resolve.BindingContext;
029    import org.jetbrains.kotlin.resolve.BindingContextUtils;
030    import org.jetbrains.kotlin.resolve.ModifierCheckerCore;
031    import org.jetbrains.kotlin.resolve.ModifiersChecker;
032    import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
033    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
034    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
035    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
036    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
037    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
038    import org.jetbrains.kotlin.resolve.inline.InlineUtil;
039    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
040    import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
041    import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
042    import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
043    import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
044    import org.jetbrains.kotlin.types.*;
045    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
046    import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct;
047    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
048    
049    import java.util.ArrayList;
050    import java.util.Collections;
051    import java.util.List;
052    
053    import static org.jetbrains.kotlin.diagnostics.Errors.*;
054    import static org.jetbrains.kotlin.resolve.BindingContext.*;
055    import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
056    import static org.jetbrains.kotlin.types.TypeUtils.*;
057    import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
058    import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall;
059    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
060    
061    public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
062    
063        public static final String RETURN_NOT_ALLOWED_MESSAGE = "Return not allowed";
064    
065        protected ControlStructureTypingVisitor(@NotNull ExpressionTypingInternals facade) {
066            super(facade);
067        }
068    
069        @NotNull
070        private DataFlowInfo checkCondition(@NotNull LexicalScope scope, @Nullable KtExpression condition, ExpressionTypingContext context) {
071            if (condition != null) {
072                KotlinTypeInfo typeInfo = facade.getTypeInfo(condition, context.replaceScope(scope)
073                        .replaceExpectedType(components.builtIns.getBooleanType()).replaceContextDependency(INDEPENDENT));
074                KotlinType conditionType = typeInfo.getType();
075    
076                if (conditionType != null && !components.builtIns.isBooleanOrSubtype(conditionType)) {
077                    context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
078                }
079    
080                return typeInfo.getDataFlowInfo();
081            }
082            return context.dataFlowInfo;
083        }
084    
085        ////////////////////////////////////////////////////////////////////////////////////////////////////
086    
087    
088        @Override
089        public KotlinTypeInfo visitIfExpression(@NotNull KtIfExpression expression, ExpressionTypingContext context) {
090            return visitIfExpression(expression, context, false);
091        }
092    
093        public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
094            components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, ifExpression, contextWithExpectedType.expectedType);
095    
096            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
097            KtExpression condition = ifExpression.getCondition();
098            DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
099            boolean loopBreakContinuePossibleInCondition = condition != null && containsJumpOutOfLoop(condition, context);
100    
101            KtExpression elseBranch = ifExpression.getElse();
102            KtExpression thenBranch = ifExpression.getThen();
103    
104            LexicalWritableScope thenScope = newWritableScopeImpl(context, LexicalScopeKind.THEN);
105            LexicalWritableScope elseScope = newWritableScopeImpl(context, LexicalScopeKind.ELSE);
106            DataFlowInfo thenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
107            DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
108    
109            if (elseBranch == null) {
110                if (thenBranch != null) {
111                    KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(
112                            thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
113                    // If jump was possible, take condition check info as the jump info
114                    return result.getJumpOutPossible()
115                           ? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
116                           : result;
117                }
118                return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getUnitType(), thenInfo.or(elseInfo));
119            }
120            if (thenBranch == null) {
121                return getTypeInfoWhenOnlyOneBranchIsPresent(
122                        elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
123            }
124            KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
125            KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
126            KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch);
127            Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
128            MutableDataFlowInfoForArguments dataFlowInfoForArguments =
129                        createDataFlowInfoForArgumentsForIfCall(callForIf, conditionDataFlowInfo, thenInfo, elseInfo);
130            ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
131                    callForIf, ResolveConstruct.IF, Lists.newArrayList("thenBranch", "elseBranch"),
132                    Lists.newArrayList(false, false),
133                    contextWithExpectedType, dataFlowInfoForArguments);
134    
135            BindingContext bindingContext = context.trace.getBindingContext();
136            KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
137            KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
138            assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
139    
140            KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
141            boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
142            DataFlowInfo resultDataFlowInfo;
143    
144            if (elseTypeInfo == null) {
145                loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
146                resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
147            }
148            else if (thenTypeInfo == null) {
149                loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
150                resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
151            }
152            else {
153                KotlinType thenType = thenTypeInfo.getType();
154                KotlinType elseType = elseTypeInfo.getType();
155                DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
156                DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
157                if (resultType != null && thenType != null && elseType != null) {
158                    DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
159                    DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
160                    thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
161                    DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
162                    elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
163                }
164    
165                loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
166    
167                boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
168                boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
169    
170                if (thenType == null && elseType == null) {
171                    resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
172                }
173                else if (thenType == null || (jumpInThen && !jumpInElse)) {
174                    resultDataFlowInfo = elseDataFlowInfo;
175                }
176                else if (elseType == null || (jumpInElse && !jumpInThen)) {
177                    resultDataFlowInfo = thenDataFlowInfo;
178                }
179                else {
180                    resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
181                }
182            }
183            // If break or continue was possible, take condition check info as the jump info
184            return TypeInfoFactoryKt.createTypeInfo(resultType, resultDataFlowInfo, loopBreakContinuePossible,
185                                                    loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
186        }
187    
188        @NotNull
189        private KotlinTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
190                @NotNull KtExpression presentBranch,
191                @NotNull LexicalWritableScope presentScope,
192                @NotNull DataFlowInfo presentInfo,
193                @NotNull DataFlowInfo otherInfo,
194                @NotNull ExpressionTypingContext context,
195                @NotNull KtIfExpression ifExpression
196        ) {
197            ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
198                    .replaceContextDependency(INDEPENDENT);
199            KotlinTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
200                    presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext);
201            KotlinType type = typeInfo.getType();
202            DataFlowInfo dataFlowInfo;
203            if (type != null && KotlinBuiltIns.isNothing(type)) {
204                dataFlowInfo = otherInfo;
205            } else {
206                dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
207            }
208            return components.dataFlowAnalyzer.checkType(
209                    typeInfo.replaceType(components.builtIns.getUnitType()),
210                    ifExpression,
211                    context
212            ).replaceDataFlowInfo(dataFlowInfo);
213        }
214    
215        @Override
216        public KotlinTypeInfo visitWhileExpression(@NotNull KtWhileExpression expression, ExpressionTypingContext context) {
217            return visitWhileExpression(expression, context, false);
218        }
219    
220        public KotlinTypeInfo visitWhileExpression(KtWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
221            if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
222    
223            ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
224                    INDEPENDENT);
225            // Preliminary analysis
226            PreliminaryLoopVisitor loopVisitor = PreliminaryLoopVisitor.visitLoop(expression);
227            context = context.replaceDataFlowInfo(
228                    loopVisitor.clearDataFlowInfoForAssignedLocalVariables(context.dataFlowInfo)
229            );
230    
231            KtExpression condition = expression.getCondition();
232            // Extract data flow info from condition itself without taking value into account
233            DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
234    
235            KtExpression body = expression.getBody();
236            KotlinTypeInfo bodyTypeInfo;
237            DataFlowInfo conditionInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
238            if (body != null) {
239                LexicalWritableScope scopeToExtend = newWritableScopeImpl(context, LexicalScopeKind.WHILE_BODY);
240                bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
241                        scopeToExtend, Collections.singletonList(body),
242                        CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo));
243            }
244            else {
245                bodyTypeInfo = TypeInfoFactoryKt.noTypeInfo(conditionInfo);
246            }
247    
248            // Condition is false at this point only if there is no jumps outside
249            if (!containsJumpOutOfLoop(expression, context)) {
250                dataFlowInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
251            }
252    
253            // Special case: while (true)
254            // In this case we must record data flow information at the nearest break / continue and
255            // .and it with entrance data flow information, because while body until break is executed at least once in this case
256            // See KT-6284
257            if (body != null && KtPsiUtil.isTrueConstant(condition)) {
258                // We should take data flow info from the first jump point,
259                // but without affecting changing variables
260                dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
261            }
262            return components.dataFlowAnalyzer
263                    .checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
264                    .replaceDataFlowInfo(dataFlowInfo);
265        }
266    
267        private boolean containsJumpOutOfLoop(@NotNull final KtExpression expression, final ExpressionTypingContext context) {
268            final boolean[] result = new boolean[1];
269            result[0] = false;
270            //todo breaks in inline function literals
271            expression.accept(new KtTreeVisitor<List<KtLoopExpression>>() {
272                @Override
273                public Void visitBreakExpression(@NotNull KtBreakExpression breakExpression, List<KtLoopExpression> outerLoops) {
274                    KtSimpleNameExpression targetLabel = breakExpression.getTargetLabel();
275                    PsiElement element = targetLabel != null ? context.trace.get(LABEL_TARGET, targetLabel) : null;
276                    if (outerLoops.isEmpty() || element == expression ||
277                        (targetLabel == null && outerLoops.get(outerLoops.size() - 1) == expression)) {
278                        result[0] = true;
279                    }
280                    return null;
281                }
282    
283                @Override
284                public Void visitContinueExpression(@NotNull KtContinueExpression expression, List<KtLoopExpression> outerLoops) {
285                    // continue@someOuterLoop is also considered as break
286                    KtSimpleNameExpression targetLabel = expression.getTargetLabel();
287                    if (targetLabel != null) {
288                        PsiElement element = context.trace.get(LABEL_TARGET, targetLabel);
289                        if (element instanceof KtLoopExpression && !outerLoops.contains(element)) {
290                            result[0] = true;
291                        }
292                    }
293                    return null;
294                }
295    
296                @Override
297                public Void visitLoopExpression(@NotNull KtLoopExpression loopExpression, List<KtLoopExpression> outerLoops) {
298                    List<KtLoopExpression> newOuterLoops = Lists.newArrayList(outerLoops);
299                    newOuterLoops.add(loopExpression);
300                    return super.visitLoopExpression(loopExpression, newOuterLoops);
301                }
302            }, expression instanceof KtLoopExpression
303               ? Lists.newArrayList((KtLoopExpression) expression)
304               : Lists.<KtLoopExpression>newArrayList());
305    
306            return result[0];
307        }
308    
309        @Override
310        public KotlinTypeInfo visitDoWhileExpression(@NotNull KtDoWhileExpression expression, ExpressionTypingContext context) {
311            return visitDoWhileExpression(expression, context, false);
312        }
313    
314        public KotlinTypeInfo visitDoWhileExpression(KtDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
315            if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
316    
317            ExpressionTypingContext context =
318                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
319            KtExpression body = expression.getBody();
320            LexicalScope conditionScope = context.scope;
321            // Preliminary analysis
322            PreliminaryLoopVisitor loopVisitor = PreliminaryLoopVisitor.visitLoop(expression);
323            context = context.replaceDataFlowInfo(
324                    loopVisitor.clearDataFlowInfoForAssignedLocalVariables(context.dataFlowInfo)
325            );
326            // Here we must record data flow information at the end of the body (or at the first jump, to be precise) and
327            // .and it with entrance data flow information, because do-while body is executed at least once
328            // See KT-6283
329            KotlinTypeInfo bodyTypeInfo;
330            if (body instanceof KtLambdaExpression) {
331                // As a matter of fact, function literal is always unused at this point
332                bodyTypeInfo = facade.getTypeInfo(body, context.replaceScope(context.scope));
333            }
334            else if (body != null) {
335                LexicalWritableScope writableScope = newWritableScopeImpl(context, LexicalScopeKind.DO_WHILE_BODY);
336                conditionScope = writableScope;
337                List<KtExpression> block;
338                if (body instanceof KtBlockExpression) {
339                    block = ((KtBlockExpression)body).getStatements();
340                }
341                else {
342                    block = Collections.singletonList(body);
343                }
344                bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
345                        writableScope, block, CoercionStrategy.NO_COERCION, context);
346            }
347            else {
348                bodyTypeInfo = TypeInfoFactoryKt.noTypeInfo(context);
349            }
350            KtExpression condition = expression.getCondition();
351            DataFlowInfo conditionDataFlowInfo = checkCondition(conditionScope, condition, context);
352            DataFlowInfo dataFlowInfo;
353            // Without jumps out, condition is entered and false, with jumps out, we know nothing about it
354            if (!containsJumpOutOfLoop(expression, context)) {
355                dataFlowInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
356            }
357            else {
358                dataFlowInfo = context.dataFlowInfo;
359            }
360            // Here we must record data flow information at the end of the body (or at the first jump, to be precise) and
361            // .and it with entrance data flow information, because do-while body is executed at least once
362            // See KT-6283
363            // NB: it's really important to do it for non-empty body which is not a function literal
364            // If it's a function literal, it appears always unused so it's no matter what we do at this point
365            if (body != null) {
366                // We should take data flow info from the first jump point,
367                // but without affecting changing variables
368                dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo()));
369            }
370            return components.dataFlowAnalyzer
371                    .checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
372                    .replaceDataFlowInfo(dataFlowInfo);
373        }
374    
375        @Override
376        public KotlinTypeInfo visitForExpression(@NotNull KtForExpression expression, ExpressionTypingContext context) {
377            return visitForExpression(expression, context, false);
378        }
379    
380        public KotlinTypeInfo visitForExpression(KtForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
381            if (!isStatement) return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
382    
383            ExpressionTypingContext context =
384                    contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
385            // Preliminary analysis
386            PreliminaryLoopVisitor loopVisitor = PreliminaryLoopVisitor.visitLoop(expression);
387            context = context.replaceDataFlowInfo(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(context.dataFlowInfo));
388    
389            KtExpression loopRange = expression.getLoopRange();
390            KotlinType expectedParameterType = null;
391            KotlinTypeInfo loopRangeInfo;
392            if (loopRange != null) {
393                ExpressionReceiver loopRangeReceiver = getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
394                loopRangeInfo = facade.getTypeInfo(loopRange, context);
395                if (loopRangeReceiver != null) {
396                    expectedParameterType = components.forLoopConventionsChecker.checkIterableConvention(loopRangeReceiver, context);
397                }
398            }
399            else {
400                loopRangeInfo = TypeInfoFactoryKt.noTypeInfo(context);
401            }
402    
403            LexicalWritableScope loopScope = newWritableScopeImpl(context, LexicalScopeKind.FOR);
404    
405            KtParameter loopParameter = expression.getLoopParameter();
406            if (loopParameter != null) {
407                VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
408                components.modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(loopParameter, variableDescriptor);
409                components.identifierChecker.checkDeclaration(loopParameter, context.trace);
410    
411                loopScope.addVariableDescriptor(variableDescriptor);
412            }
413            else {
414                KtDestructuringDeclaration multiParameter = expression.getDestructuringParameter();
415                if (multiParameter != null && loopRange != null) {
416                    KotlinType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
417                    TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
418                    components.annotationResolver.resolveAnnotationsWithArguments(loopScope, multiParameter.getModifierList(), context.trace);
419                    components.destructuringDeclarationResolver.defineLocalVariablesFromMultiDeclaration(
420                            loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
421                    );
422                    components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiParameter);
423                    components.modifiersChecker.withTrace(context.trace).checkParameterHasNoValOrVar(multiParameter, VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER);
424                    components.identifierChecker.checkDeclaration(multiParameter, context.trace);
425                }
426            }
427    
428            KtExpression body = expression.getBody();
429            KotlinTypeInfo bodyTypeInfo;
430            if (body != null) {
431                bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body),
432                        CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo()));
433            }
434            else {
435                bodyTypeInfo = loopRangeInfo;
436            }
437    
438            return components.dataFlowAnalyzer
439                    .checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
440                    .replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
441        }
442    
443        private VariableDescriptor createLoopParameterDescriptor(
444                KtParameter loopParameter,
445                KotlinType expectedParameterType,
446                ExpressionTypingContext context
447        ) {
448            components.modifiersChecker.withTrace(context.trace).checkParameterHasNoValOrVar(loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);
449    
450            KtTypeReference typeReference = loopParameter.getTypeReference();
451            VariableDescriptor variableDescriptor;
452            if (typeReference != null) {
453                variableDescriptor = components.descriptorResolver.
454                        resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
455                KotlinType actualParameterType = variableDescriptor.getType();
456                if (expectedParameterType != null &&
457                        !KotlinTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) {
458                    context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
459                }
460            }
461            else {
462                if (expectedParameterType == null) {
463                    expectedParameterType = ErrorUtils.createErrorType("Error");
464                }
465                variableDescriptor = components.descriptorResolver.
466                        resolveLocalVariableDescriptor(loopParameter, expectedParameterType, context.trace, context.scope);
467            }
468    
469            checkVariableShadowing(context.scope, context.trace, variableDescriptor);
470    
471            return variableDescriptor;
472        }
473    
474        @Override
475        public KotlinTypeInfo visitTryExpression(@NotNull KtTryExpression expression, ExpressionTypingContext typingContext) {
476            ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
477            KtExpression tryBlock = expression.getTryBlock();
478            List<KtCatchClause> catchClauses = expression.getCatchClauses();
479            KtFinallySection finallyBlock = expression.getFinallyBlock();
480            List<KotlinType> types = new ArrayList<KotlinType>();
481            boolean nothingInAllCatchBranches = true;
482            for (KtCatchClause catchClause : catchClauses) {
483                KtParameter catchParameter = catchClause.getCatchParameter();
484                KtExpression catchBody = catchClause.getCatchBody();
485                boolean nothingInCatchBranch = false;
486                if (catchParameter != null) {
487                    components.identifierChecker.checkDeclaration(catchParameter, context.trace);
488                    ModifiersChecker.ModifiersCheckingProcedure modifiersChecking = components.modifiersChecker.withTrace(context.trace);
489                    modifiersChecking.checkParameterHasNoValOrVar(catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
490                    ModifierCheckerCore.INSTANCE.check(catchParameter, context.trace, null);
491    
492                    VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(
493                            context.scope, catchParameter, context.trace);
494                    KotlinType catchParameterType = variableDescriptor.getType();
495                    if (TypeUtils.isReifiedTypeParameter(catchParameterType)) {
496                        context.trace.report(REIFIED_TYPE_IN_CATCH_CLAUSE.on(catchParameter));
497                    }
498    
499                    KotlinType throwableType = components.builtIns.getThrowable().getDefaultType();
500                    components.dataFlowAnalyzer.checkType(catchParameterType, catchParameter, context.replaceExpectedType(throwableType));
501                    if (catchBody != null) {
502                        LexicalWritableScope catchScope = newWritableScopeImpl(context, LexicalScopeKind.CATCH);
503                        catchScope.addVariableDescriptor(variableDescriptor);
504                        KotlinType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
505                        if (type != null) {
506                            types.add(type);
507                            if (KotlinBuiltIns.isNothing(type)) {
508                                nothingInCatchBranch = true;
509                            }
510                        }
511                    }
512                }
513                if (!nothingInCatchBranch) {
514                    nothingInAllCatchBranches =  false;
515                }
516            }
517    
518            KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
519            KotlinTypeInfo tryResult = facade.getTypeInfo(tryBlock, context);
520            if (finallyBlock != null) {
521                result = facade.getTypeInfo(finallyBlock.getFinalExpression(),
522                                            context.replaceExpectedType(NO_EXPECTED_TYPE));
523            }
524            else if (nothingInAllCatchBranches) {
525                result = tryResult;
526            }
527    
528            KotlinType type = tryResult.getType();
529            if (type != null) {
530                types.add(type);
531            }
532            if (types.isEmpty()) {
533                return result.clearType();
534            }
535            else {
536                return result.replaceType(CommonSupertypes.commonSupertype(types));
537            }
538        }
539    
540        @Override
541        public KotlinTypeInfo visitThrowExpression(@NotNull KtThrowExpression expression, ExpressionTypingContext context) {
542            KtExpression thrownExpression = expression.getThrownExpression();
543            if (thrownExpression != null) {
544                KotlinType throwableType = components.builtIns.getThrowable().getDefaultType();
545                facade.getTypeInfo(thrownExpression, context
546                        .replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
547            }
548            return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression);
549        }
550    
551        @Override
552        public KotlinTypeInfo visitReturnExpression(@NotNull KtReturnExpression expression, ExpressionTypingContext context) {
553            KtElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);
554    
555            KtExpression returnedExpression = expression.getReturnedExpression();
556    
557            KotlinType expectedType = NO_EXPECTED_TYPE;
558            KotlinType resultType = components.builtIns.getNothingType();
559            KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtDeclaration.class);
560    
561            if (parentDeclaration instanceof KtParameter) {
562                // In a default value for parameter
563                context.trace.report(RETURN_NOT_ALLOWED.on(expression));
564            }
565    
566            if (expression.getTargetLabel() == null) {
567                while (parentDeclaration instanceof KtDestructuringDeclaration) {
568                    //TODO: It's hacking fix for KT-5100: Strange "Return is not allowed here" for multi-declaration initializer with elvis expression
569                    parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
570                }
571    
572                assert parentDeclaration != null : "Can't find parent declaration for " + expression.getText();
573                DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
574                Pair<FunctionDescriptor, PsiElement> containingFunInfo =
575                        BindingContextUtils.getContainingFunctionSkipFunctionLiterals(declarationDescriptor, false);
576                FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();
577    
578                if (containingFunctionDescriptor != null) {
579                    if (!InlineUtil.checkNonLocalReturnUsage(containingFunctionDescriptor, expression, context.trace) ||
580                        isClassInitializer(containingFunInfo)) {
581                        // Unqualified, in a function literal
582                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
583                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
584                    }
585    
586                    expectedType = getFunctionExpectedReturnType(containingFunctionDescriptor, (KtElement) containingFunInfo.getSecond(), context);
587                }
588                else {
589                    // Outside a function
590                    context.trace.report(RETURN_NOT_ALLOWED.on(expression));
591                    resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
592                }
593            }
594            else if (labelTargetElement != null) {
595                SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
596                if (functionDescriptor != null) {
597                    expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context);
598                    if (!InlineUtil.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) {
599                        // Qualified, non-local
600                        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
601                        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
602                    }
603                }
604                else {
605                    context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
606                }
607            }
608            if (returnedExpression != null) {
609                facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)
610                        .replaceContextDependency(INDEPENDENT));
611            }
612            else {
613                if (expectedType != null &&
614                    !noExpectedType(expectedType) &&
615                    !KotlinBuiltIns.isUnit(expectedType) &&
616                    !isDontCarePlaceholder(expectedType)) // for lambda with implicit return type Unit
617                {
618                    context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
619                }
620            }
621            return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression);
622        }
623    
624        private static boolean isClassInitializer(@NotNull Pair<FunctionDescriptor, PsiElement> containingFunInfo) {
625            return containingFunInfo.getFirst() instanceof ConstructorDescriptor &&
626                   !(containingFunInfo.getSecond() instanceof KtSecondaryConstructor);
627        }
628    
629        @Override
630        public KotlinTypeInfo visitBreakExpression(@NotNull KtBreakExpression expression, ExpressionTypingContext context) {
631            LabelResolver.INSTANCE.resolveControlLabel(expression, context);
632            return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
633                    replaceJumpOutPossible(true);
634        }
635    
636        @Override
637        public KotlinTypeInfo visitContinueExpression(@NotNull KtContinueExpression expression, ExpressionTypingContext context) {
638            LabelResolver.INSTANCE.resolveControlLabel(expression, context);
639            return components.dataFlowAnalyzer.createCheckedTypeInfo(components.builtIns.getNothingType(), context, expression).
640                    replaceJumpOutPossible(true);
641        }
642    
643        @NotNull
644        private static KotlinType getFunctionExpectedReturnType(
645                @NotNull FunctionDescriptor descriptor,
646                @NotNull KtElement function,
647                @NotNull ExpressionTypingContext context
648        ) {
649            KotlinType expectedType;
650            if (function instanceof KtSecondaryConstructor) {
651                expectedType = DescriptorUtilsKt.getBuiltIns(descriptor).getUnitType();
652            }
653            else if (function instanceof KtFunction) {
654                KtFunction ktFunction = (KtFunction) function;
655                expectedType = context.trace.get(EXPECTED_RETURN_TYPE, ktFunction);
656    
657                if ((expectedType == null) && (ktFunction.getTypeReference() != null || ktFunction.hasBlockBody())) {
658                    expectedType = descriptor.getReturnType();
659                }
660            }
661            else {
662                expectedType = descriptor.getReturnType();
663            }
664            return expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE;
665        }
666    }