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