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 }