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