@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); }
@NotNull private static List<ValueParameterDescriptor> createValueParameterDescriptors( @NotNull ExpressionTypingContext context, @NotNull JetFunctionLiteral functionLiteral, @NotNull FunctionDescriptorImpl functionDescriptor, boolean functionTypeExpected) { List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList(); List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters(); List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected) ? KotlinBuiltIns.getInstance() .getValueParameters(functionDescriptor, context.expectedType) : null; JetParameterList valueParameterList = functionLiteral.getValueParameterList(); boolean hasDeclaredValueParameters = valueParameterList != null; if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) { ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); ValueParameterDescriptor it = new ValueParameterDescriptorImpl( functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"), valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()); valueParameterDescriptors.add(it); context.trace.record(AUTO_CREATED_IT, it); } else { if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); context.trace.report( EXPECTED_PARAMETERS_NUMBER_MISMATCH.on( functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); } for (int i = 0; i < declaredValueParameters.size(); i++) { ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor( context, functionDescriptor, declaredValueParameters, expectedValueParameters, i); valueParameterDescriptors.add(valueParameterDescriptor); } } return valueParameterDescriptors; }
@NotNull private static AnonymousFunctionDescriptor createFunctionDescriptor( @NotNull JetFunctionLiteralExpression expression, @NotNull ExpressionTypingContext context, boolean functionTypeExpected) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef(); AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor( context.scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), CallableMemberDescriptor.Kind.DECLARATION); List<ValueParameterDescriptor> valueParameterDescriptors = createValueParameterDescriptors( context, functionLiteral, functionDescriptor, functionTypeExpected); JetType effectiveReceiverType; if (receiverTypeRef == null) { if (functionTypeExpected) { effectiveReceiverType = KotlinBuiltIns.getInstance().getReceiverType(context.expectedType); } else { effectiveReceiverType = null; } } else { effectiveReceiverType = context .expressionTypingServices .getTypeResolver() .resolveType(context.scope, receiverTypeRef, context.trace, true); } functionDescriptor.initialize( effectiveReceiverType, ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER, Collections.<TypeParameterDescriptorImpl>emptyList(), valueParameterDescriptors, /*unsubstitutedReturnType = */ null, Modality.FINAL, Visibilities.LOCAL); BindingContextUtils.recordFunctionDeclarationToDescriptor( context.trace, functionLiteral, functionDescriptor); return functionDescriptor; }