@Override
  public JetTypeInfo visitFunctionLiteralExpression(
      @NotNull JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
    JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
    if (bodyExpression == null) return null;

    Name callerName = getCallerName(expression);
    if (callerName != null) {
      context.labelResolver.enterLabeledElement(new LabelName(callerName.asString()), expression);
    }

    JetType expectedType = context.expectedType;
    boolean functionTypeExpected =
        !noExpectedType(expectedType)
            && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType);

    AnonymousFunctionDescriptor functionDescriptor =
        createFunctionDescriptor(expression, context, functionTypeExpected);
    JetType safeReturnType =
        computeReturnType(expression, context, functionDescriptor, functionTypeExpected);
    functionDescriptor.setReturnType(safeReturnType);

    JetType receiver =
        DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter());
    List<JetType> valueParametersTypes =
        DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters());
    JetType resultType =
        KotlinBuiltIns.getInstance()
            .getFunctionType(
                Collections.<AnnotationDescriptor>emptyList(),
                receiver,
                valueParametersTypes,
                safeReturnType);
    if (!noExpectedType(expectedType)
        && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) {
      // all checks were done before
      return JetTypeInfo.create(resultType, context.dataFlowInfo);
    }

    if (callerName != null) {
      context.labelResolver.exitLabeledElement(expression);
    }

    return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
  }
  @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;
  }