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