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 017package org.jetbrains.jet.lang.types.expressions; 018 019import com.google.common.collect.Lists; 020import com.intellij.openapi.util.Pair; 021import com.intellij.psi.PsiElement; 022import com.intellij.psi.util.PsiTreeUtil; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 026import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 027import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; 028import org.jetbrains.jet.lang.descriptors.VariableDescriptor; 029import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory1; 030import org.jetbrains.jet.lang.diagnostics.Errors; 031import org.jetbrains.jet.lang.psi.*; 032import org.jetbrains.jet.lang.resolve.BindingContext; 033import org.jetbrains.jet.lang.resolve.BindingContextUtils; 034import org.jetbrains.jet.lang.resolve.DescriptorResolver; 035import org.jetbrains.jet.lang.resolve.DescriptorUtils; 036import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; 037import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 038import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; 039import org.jetbrains.jet.lang.resolve.name.Name; 040import org.jetbrains.jet.lang.resolve.scopes.JetScope; 041import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 042import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; 043import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; 044import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; 045import org.jetbrains.jet.lang.types.*; 046import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 047import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 048import org.jetbrains.jet.util.slicedmap.WritableSlice; 049 050import java.util.ArrayList; 051import java.util.Arrays; 052import java.util.Collections; 053import java.util.List; 054 055import static org.jetbrains.jet.lang.diagnostics.Errors.*; 056import static org.jetbrains.jet.lang.resolve.BindingContext.*; 057import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*; 058 059public 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}