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 }