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