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