001 /*
002 * Copyright 2010-2013 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.jet.lang.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.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.diagnostics.Errors;
027 import org.jetbrains.jet.lang.psi.*;
028 import org.jetbrains.jet.lang.resolve.*;
029 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
030 import org.jetbrains.jet.lang.resolve.calls.model.MutableDataFlowInfoForArguments;
031 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
032 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
034 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
035 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
036 import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
037 import org.jetbrains.jet.lang.types.*;
038 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
039 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
040
041 import java.util.ArrayList;
042 import java.util.Collections;
043 import java.util.List;
044
045 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
046 import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory;
047 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
048 import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
049 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
050 import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
051 import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
052 import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall;
053 import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
054
055 public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
056
057 public static final String RETURN_NOT_ALLOWED_MESSAGE = "Return not allowed";
058
059 protected ControlStructureTypingVisitor(@NotNull ExpressionTypingInternals facade) {
060 super(facade);
061 }
062
063 @NotNull
064 private DataFlowInfo checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
065 if (condition != null) {
066 JetTypeInfo typeInfo = facade.getTypeInfo(condition, context.replaceScope(scope)
067 .replaceExpectedType(KotlinBuiltIns.getInstance().getBooleanType()).replaceContextDependency(INDEPENDENT));
068 JetType conditionType = typeInfo.getType();
069
070 if (conditionType != null && !isBoolean(conditionType)) {
071 context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
072 }
073
074 return typeInfo.getDataFlowInfo();
075 }
076 return context.dataFlowInfo;
077 }
078
079 ////////////////////////////////////////////////////////////////////////////////////////////////////
080
081
082 @Override
083 public JetTypeInfo visitIfExpression(@NotNull JetIfExpression expression, ExpressionTypingContext context) {
084 return visitIfExpression(expression, context, false);
085 }
086
087 public JetTypeInfo visitIfExpression(JetIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
088 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
089 JetExpression condition = ifExpression.getCondition();
090 DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
091
092 JetExpression elseBranch = ifExpression.getElse();
093 JetExpression thenBranch = ifExpression.getThen();
094
095 WritableScopeImpl thenScope = newWritableScopeImpl(context, "Then scope");
096 WritableScopeImpl elseScope = newWritableScopeImpl(context, "Else scope");
097 DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
098 DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
099
100 if (elseBranch == null) {
101 if (thenBranch != null) {
102 return getTypeInfoWhenOnlyOneBranchIsPresent(
103 thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
104 }
105 return DataFlowUtils.checkImplicitCast(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, contextWithExpectedType,
106 isStatement, thenInfo.or(elseInfo));
107 }
108 if (thenBranch == null) {
109 return getTypeInfoWhenOnlyOneBranchIsPresent(
110 elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
111 }
112 JetPsiFactory psiFactory = JetPsiFactory(ifExpression);
113 JetBlockExpression thenBlock = psiFactory.wrapInABlock(thenBranch);
114 JetBlockExpression elseBlock = psiFactory.wrapInABlock(elseBranch);
115 Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
116 MutableDataFlowInfoForArguments dataFlowInfoForArguments =
117 createDataFlowInfoForArgumentsForIfCall(callForIf, thenInfo, elseInfo);
118 ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
119 callForIf, "If", Lists.newArrayList("thenBranch", "elseBranch"),
120 Lists.newArrayList(false, false),
121 contextWithExpectedType, dataFlowInfoForArguments);
122
123 JetTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, context.trace.getBindingContext());
124 JetTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, context.trace.getBindingContext());
125 assert thenTypeInfo != null : "'Then' branch of if expression was not processed: " + ifExpression;
126 assert elseTypeInfo != null : "'Else' branch of if expression was not processed: " + ifExpression;
127
128 JetType thenType = thenTypeInfo.getType();
129 JetType elseType = elseTypeInfo.getType();
130 DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
131 DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
132
133 boolean jumpInThen = thenType != null && KotlinBuiltIns.getInstance().isNothing(thenType);
134 boolean jumpInElse = elseType != null && KotlinBuiltIns.getInstance().isNothing(elseType);
135
136 JetTypeInfo result;
137 if (thenType == null && elseType == null) {
138 result = JetTypeInfo.create(null, thenDataFlowInfo.or(elseDataFlowInfo));
139 }
140 else if (thenType == null || (jumpInThen && !jumpInElse)) {
141 result = elseTypeInfo;
142 }
143 else if (elseType == null || (jumpInElse && !jumpInThen)) {
144 result = thenTypeInfo;
145 }
146 else {
147 result = JetTypeInfo.create(resolvedCall.getResultingDescriptor().getReturnType(), thenDataFlowInfo.or(elseDataFlowInfo));
148 }
149
150 return DataFlowUtils.checkImplicitCast(result.getType(), ifExpression, contextWithExpectedType, isStatement, result.getDataFlowInfo());
151 }
152
153 @NotNull
154 private JetTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
155 @NotNull JetExpression presentBranch,
156 @NotNull WritableScopeImpl presentScope,
157 @NotNull DataFlowInfo presentInfo,
158 @NotNull DataFlowInfo otherInfo,
159 @NotNull ExpressionTypingContext context,
160 @NotNull JetIfExpression ifExpression,
161 boolean isStatement
162 ) {
163 ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
164 .replaceContextDependency(INDEPENDENT);
165 JetTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
166 presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext, context.trace);
167 JetType type = typeInfo.getType();
168 DataFlowInfo dataFlowInfo;
169 if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
170 dataFlowInfo = otherInfo;
171 } else {
172 dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
173 }
174 JetType typeForIfExpression = DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), ifExpression, context);
175 return DataFlowUtils.checkImplicitCast(typeForIfExpression, ifExpression, context, isStatement, dataFlowInfo);
176 }
177
178 @Override
179 public JetTypeInfo visitWhileExpression(@NotNull JetWhileExpression expression, ExpressionTypingContext context) {
180 return visitWhileExpression(expression, context, false);
181 }
182
183 public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
184 if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
185
186 ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(
187 INDEPENDENT);
188 JetExpression condition = expression.getCondition();
189 DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
190
191 JetExpression body = expression.getBody();
192 if (body != null) {
193 WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in while's condition");
194 DataFlowInfo conditionInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
195 components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
196 scopeToExtend, Collections.singletonList(body),
197 CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace);
198 }
199
200 if (!containsJumpOutOfLoop(expression, context)) {
201 dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
202 }
203 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
204 }
205
206 private boolean containsJumpOutOfLoop(final JetLoopExpression loopExpression, final ExpressionTypingContext context) {
207 final boolean[] result = new boolean[1];
208 result[0] = false;
209 //todo breaks in inline function literals
210 loopExpression.accept(new JetTreeVisitor<List<JetLoopExpression>>() {
211 @Override
212 public Void visitBreakExpression(@NotNull JetBreakExpression breakExpression, List<JetLoopExpression> outerLoops) {
213 JetSimpleNameExpression targetLabel = breakExpression.getTargetLabel();
214 PsiElement element = targetLabel != null ? context.trace.get(LABEL_TARGET, targetLabel) : null;
215 if (element == loopExpression || (targetLabel == null && outerLoops.get(outerLoops.size() - 1) == loopExpression)) {
216 result[0] = true;
217 }
218 return null;
219 }
220
221 @Override
222 public Void visitContinueExpression(@NotNull JetContinueExpression expression, List<JetLoopExpression> outerLoops) {
223 // continue@someOuterLoop is also considered as break
224 JetSimpleNameExpression targetLabel = expression.getTargetLabel();
225 if (targetLabel != null) {
226 PsiElement element = context.trace.get(LABEL_TARGET, targetLabel);
227 if (element instanceof JetLoopExpression && !outerLoops.contains(element)) {
228 result[0] = true;
229 }
230 }
231 return null;
232 }
233
234 @Override
235 public Void visitLoopExpression(@NotNull JetLoopExpression loopExpression, List<JetLoopExpression> outerLoops) {
236 List<JetLoopExpression> newOuterLoops = Lists.newArrayList(outerLoops);
237 newOuterLoops.add(loopExpression);
238 return super.visitLoopExpression(loopExpression, newOuterLoops);
239 }
240 }, Lists.newArrayList(loopExpression));
241
242 return result[0];
243 }
244
245 @Override
246 public JetTypeInfo visitDoWhileExpression(@NotNull JetDoWhileExpression expression, ExpressionTypingContext context) {
247 return visitDoWhileExpression(expression, context, false);
248 }
249 public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
250 if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
251
252 ExpressionTypingContext context =
253 contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
254 JetExpression body = expression.getBody();
255 JetScope conditionScope = context.scope;
256 if (body instanceof JetFunctionLiteralExpression) {
257 JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body;
258 JetFunctionLiteral functionLiteral = function.getFunctionLiteral();
259 if (!functionLiteral.hasParameterSpecification()) {
260 WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
261 conditionScope = writableScope;
262 components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, functionLiteral.getBodyExpression().getStatements(), CoercionStrategy.NO_COERCION, context, context.trace);
263 context.trace.record(BindingContext.BLOCK, function);
264 }
265 else {
266 facade.getTypeInfo(body, context.replaceScope(context.scope));
267 }
268 }
269 else if (body != null) {
270 WritableScope writableScope = newWritableScopeImpl(context, "do..while body scope");
271 conditionScope = writableScope;
272 List<JetElement> block;
273 if (body instanceof JetBlockExpression) {
274 block = ((JetBlockExpression)body).getStatements();
275 }
276 else {
277 block = Collections.<JetElement>singletonList(body);
278 }
279 components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(writableScope, block, CoercionStrategy.NO_COERCION, context, context.trace);
280 }
281 JetExpression condition = expression.getCondition();
282 DataFlowInfo conditionDataFlowInfo = checkCondition(conditionScope, condition, context);
283 DataFlowInfo dataFlowInfo;
284 if (!containsJumpOutOfLoop(expression, context)) {
285 dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
286 }
287 else {
288 dataFlowInfo = context.dataFlowInfo;
289 }
290 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
291 }
292
293 @Override
294 public JetTypeInfo visitForExpression(@NotNull JetForExpression expression, ExpressionTypingContext context) {
295 return visitForExpression(expression, context, false);
296 }
297
298 public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
299 if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade);
300
301 ExpressionTypingContext context =
302 contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
303 JetExpression loopRange = expression.getLoopRange();
304 JetType expectedParameterType = null;
305 DataFlowInfo dataFlowInfo = context.dataFlowInfo;
306 if (loopRange != null) {
307 ExpressionReceiver loopRangeReceiver = getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
308 dataFlowInfo = facade.getTypeInfo(loopRange, context).getDataFlowInfo();
309 if (loopRangeReceiver != null) {
310 expectedParameterType = components.forLoopConventionsChecker.checkIterableConvention(loopRangeReceiver, context);
311 }
312 }
313
314 WritableScope loopScope = newWritableScopeImpl(context, "Scope with for-loop index");
315
316 JetParameter loopParameter = expression.getLoopParameter();
317 if (loopParameter != null) {
318 VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
319
320 loopScope.addVariableDescriptor(variableDescriptor);
321 }
322 else {
323 JetMultiDeclaration multiParameter = expression.getMultiParameter();
324 if (multiParameter != null && loopRange != null) {
325 JetType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
326 TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
327 components.expressionTypingUtils.defineLocalVariablesFromMultiDeclaration(loopScope, multiParameter, iteratorNextAsReceiver,
328 loopRange, context);
329 }
330 }
331
332 JetExpression body = expression.getBody();
333 if (body != null) {
334 components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body),
335 CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(dataFlowInfo), context.trace);
336 }
337
338 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getUnitType(), expression, contextWithExpectedType, dataFlowInfo);
339 }
340
341 private VariableDescriptor createLoopParameterDescriptor(
342 JetParameter loopParameter,
343 JetType expectedParameterType,
344 ExpressionTypingContext context
345 ) {
346 DescriptorResolver.checkParameterHasNoValOrVar(context.trace, loopParameter, VAL_OR_VAR_ON_LOOP_PARAMETER);
347
348 JetTypeReference typeReference = loopParameter.getTypeReference();
349 VariableDescriptor variableDescriptor;
350 if (typeReference != null) {
351 variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
352 JetType actualParameterType = variableDescriptor.getType();
353 if (expectedParameterType != null &&
354 !JetTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) {
355 context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
356 }
357 }
358 else {
359 if (expectedParameterType == null) {
360 expectedParameterType = ErrorUtils.createErrorType("Error");
361 }
362 variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(loopParameter, expectedParameterType, context.trace, context.scope);
363 }
364
365 {
366 // http://youtrack.jetbrains.net/issue/KT-527
367
368 VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName());
369 if (olderVariable != null && isLocal(context.scope.getContainingDeclaration(), olderVariable)) {
370 PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
371 context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
372 }
373 }
374 return variableDescriptor;
375 }
376
377 @Override
378 public JetTypeInfo visitTryExpression(@NotNull JetTryExpression expression, ExpressionTypingContext typingContext) {
379 ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
380 JetExpression tryBlock = expression.getTryBlock();
381 List<JetCatchClause> catchClauses = expression.getCatchClauses();
382 JetFinallySection finallyBlock = expression.getFinallyBlock();
383 List<JetType> types = new ArrayList<JetType>();
384 for (JetCatchClause catchClause : catchClauses) {
385 JetParameter catchParameter = catchClause.getCatchParameter();
386 JetExpression catchBody = catchClause.getCatchBody();
387 if (catchParameter != null) {
388 DescriptorResolver.checkParameterHasNoValOrVar(context.trace, catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
389 DescriptorResolver.checkParameterHasNoModifier(context.trace, catchParameter);
390
391 VariableDescriptor variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(
392 context.scope, catchParameter, context.trace);
393 JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
394 DataFlowUtils.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType));
395 if (catchBody != null) {
396 WritableScope catchScope = newWritableScopeImpl(context, "Catch scope");
397 catchScope.addVariableDescriptor(variableDescriptor);
398 JetType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
399 if (type != null) {
400 types.add(type);
401 }
402 }
403 }
404 }
405
406 DataFlowInfo dataFlowInfo = context.dataFlowInfo;
407 if (finallyBlock != null) {
408 dataFlowInfo = facade.getTypeInfo(finallyBlock.getFinalExpression(),
409 context.replaceExpectedType(NO_EXPECTED_TYPE)).getDataFlowInfo();
410 }
411
412 JetType type = facade.getTypeInfo(tryBlock, context).getType();
413 if (type != null) {
414 types.add(type);
415 }
416 if (types.isEmpty()) {
417 return JetTypeInfo.create(null, dataFlowInfo);
418 }
419 else {
420 return JetTypeInfo.create(CommonSupertypes.commonSupertype(types), dataFlowInfo);
421 }
422 }
423
424 @Override
425 public JetTypeInfo visitThrowExpression(@NotNull JetThrowExpression expression, ExpressionTypingContext context) {
426 JetExpression thrownExpression = expression.getThrownExpression();
427 if (thrownExpression != null) {
428 JetType throwableType = KotlinBuiltIns.getInstance().getThrowable().getDefaultType();
429 facade.getTypeInfo(thrownExpression, context
430 .replaceExpectedType(throwableType).replaceScope(context.scope).replaceContextDependency(INDEPENDENT));
431 }
432 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
433 }
434
435 @Override
436 public JetTypeInfo visitReturnExpression(@NotNull JetReturnExpression expression, ExpressionTypingContext context) {
437 JetElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);
438
439 JetExpression returnedExpression = expression.getReturnedExpression();
440
441 JetType expectedType = NO_EXPECTED_TYPE;
442 JetType resultType = KotlinBuiltIns.getInstance().getNothingType();
443 JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
444
445 if (parentDeclaration instanceof JetParameter) {
446 // In a default value for parameter
447 context.trace.report(RETURN_NOT_ALLOWED.on(expression));
448 }
449
450 if (expression.getTargetLabel() == null) {
451 assert parentDeclaration != null;
452 DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
453 Pair<FunctionDescriptor, PsiElement> containingFunInfo =
454 BindingContextUtils.getContainingFunctionSkipFunctionLiterals(declarationDescriptor, false);
455 FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();
456
457 if (containingFunctionDescriptor != null) {
458 if (!InlineDescriptorUtils.checkNonLocalReturnUsage(containingFunctionDescriptor, expression, context.trace) ||
459 containingFunctionDescriptor instanceof ConstructorDescriptor) {
460 // Unqualified, in a function literal
461 context.trace.report(RETURN_NOT_ALLOWED.on(expression));
462 resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
463 }
464
465 expectedType = getFunctionExpectedReturnType(containingFunctionDescriptor, (JetElement) containingFunInfo.getSecond());
466 }
467 else {
468 // Outside a function
469 context.trace.report(RETURN_NOT_ALLOWED.on(expression));
470 resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
471 }
472 }
473 else if (labelTargetElement != null) {
474 SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
475 if (functionDescriptor != null) {
476 expectedType = getFunctionExpectedReturnType(functionDescriptor, labelTargetElement);
477 if (!InlineDescriptorUtils.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) {
478 // Qualified, non-local
479 context.trace.report(RETURN_NOT_ALLOWED.on(expression));
480 resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
481 }
482 else if (expectedType == NO_EXPECTED_TYPE) {
483 // expectedType is NO_EXPECTED_TYPE iff the return type of the corresponding function descriptor is not computed yet
484 // our temporary policy is to prohibit returns in this case. It mostly applies to local returns in lambdas
485 context.trace.report(RETURN_NOT_ALLOWED_EXPLICIT_RETURN_TYPE_REQUIRED.on(expression));
486 }
487 }
488 else {
489 context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
490 }
491 }
492 if (returnedExpression != null) {
493 facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)
494 .replaceContextDependency(INDEPENDENT));
495 }
496 else {
497 if (expectedType != null && !noExpectedType(expectedType) && !KotlinBuiltIns.getInstance().isUnit(expectedType)) {
498 context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
499 }
500 }
501 return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
502 }
503
504 @Override
505 public JetTypeInfo visitBreakExpression(@NotNull JetBreakExpression expression, ExpressionTypingContext context) {
506 LabelResolver.INSTANCE.resolveControlLabel(expression, context);
507 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
508 }
509
510 @Override
511 public JetTypeInfo visitContinueExpression(@NotNull JetContinueExpression expression, ExpressionTypingContext context) {
512 LabelResolver.INSTANCE.resolveControlLabel(expression, context);
513 return DataFlowUtils.checkType(KotlinBuiltIns.getInstance().getNothingType(), expression, context, context.dataFlowInfo);
514 }
515
516 @NotNull
517 private static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) {
518 JetType expectedType;
519 if (function instanceof JetFunction) {
520 if (((JetFunction) function).getReturnTypeRef() != null || ((JetFunction) function).hasBlockBody()) {
521 expectedType = descriptor.getReturnType();
522 }
523 else {
524 expectedType = TypeUtils.NO_EXPECTED_TYPE;
525 }
526 }
527 else {
528 expectedType = descriptor.getReturnType();
529 }
530 return expectedType != null ? expectedType : TypeUtils.NO_EXPECTED_TYPE;
531 }
532 }