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