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