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