@Nullable private static JetType computeUnsafeReturnType( @NotNull JetFunctionLiteralExpression expression, @NotNull ExpressionTypingContext context, @NotNull SimpleFunctionDescriptorImpl functionDescriptor, @Nullable JetType expectedReturnType) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); assert bodyExpression != null; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( context.scope, functionDescriptor, context.trace); JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); JetType declaredReturnType = null; if (returnTypeRef != null) { declaredReturnType = context .expressionTypingServices .getTypeResolver() .resolveType(context.scope, returnTypeRef, context.trace, true); // This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly // type-check returned expressions functionDescriptor.setReturnType(declaredReturnType); if (expectedReturnType != null) { if (!JetTypeChecker.INSTANCE.isSubtypeOf(declaredReturnType, expectedReturnType)) { context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); } } } // Type-check the body ExpressionTypingContext newContext = context .replaceScope(functionInnerScope) .replaceExpectedType( declaredReturnType != null ? declaredReturnType : (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE)); JetType typeOfBodyExpression = context .expressionTypingServices .getBlockReturnedType(bodyExpression, COERCION_TO_UNIT, newContext) .getType(); List<JetType> returnedExpressionTypes = Lists.newArrayList( getTypesOfLocallyReturnedExpressions( functionLiteral, context.trace, collectReturns(bodyExpression))); ContainerUtil.addIfNotNull(returnedExpressionTypes, typeOfBodyExpression); if (declaredReturnType != null) return declaredReturnType; if (returnedExpressionTypes.isEmpty()) return null; return CommonSupertypes.commonSupertype(returnedExpressionTypes); }
@Override public JetType visitFunctionLiteralExpression( JetFunctionLiteralExpression expression, ExpressionTypingContext context) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); if (bodyExpression == null) return null; JetType expectedType = context.expectedType; boolean functionTypeExpected = expectedType != TypeUtils.NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(expectedType); NamedFunctionDescriptorImpl functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected); List<JetType> parameterTypes = Lists.newArrayList(); List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters(); for (ValueParameterDescriptor valueParameter : valueParameters) { parameterTypes.add(valueParameter.getOutType()); } ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); JetType receiver = receiverParameter != NO_RECEIVER ? receiverParameter.getType() : null; JetType returnType = TypeUtils.NO_EXPECTED_TYPE; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( context.scope, functionDescriptor, context.trace); JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); if (returnTypeRef != null) { returnType = context.getTypeResolver().resolveType(context.scope, returnTypeRef); context .getServices() .checkFunctionReturnType( expression, context .replaceScope(functionInnerScope) .replaceExpectedType(returnType) .replaceExpectedReturnType(returnType) .replaceDataFlowInfo(context.dataFlowInfo)); } else { if (functionTypeExpected) { returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); } returnType = context .getServices() .getBlockReturnedType( functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType)); } JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType; functionDescriptor.setReturnType(safeReturnType); boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null; if (!hasDeclaredValueParameters && functionTypeExpected) { JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); if (JetStandardClasses.isUnit(expectedReturnType)) { functionDescriptor.setReturnType(JetStandardClasses.getUnitType()); return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context); } } return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context); }