@Nullable
  @Override
  public Ref<PyType> getCallType(@NotNull PyFunction function, @NotNull PyCallSiteExpression callSite, @NotNull Context context) {
    final String functionQName = function.getQualifiedName();

    if ("typing.cast".equals(functionQName)) {
      return Optional
        .ofNullable(as(callSite, PyCallExpression.class))
        .map(PyCallExpression::getArguments)
        .filter(args -> args.length > 0)
        .map(args -> getType(args[0], context))
        .orElse(null);
    }

    if (callSite instanceof PyCallExpression callExpression && isTypeGuard(function, context.myContext)) {
      var arguments = callSite.getArguments(function);
      if (!arguments.isEmpty() && arguments.get(0) instanceof PyReferenceExpression refExpr) {
        var qname = PyPsiUtilsCore.asQualifiedName(refExpr);
        if (qname != null) {
          var narrowedType = getTypeFromTypeGuardLikeType(function, context.myContext);
          if (narrowedType != null) {
            return Ref.create(PyNarrowedType.Companion.create(callSite, qname.toString(), narrowedType, callExpression, false));
          }
        }
      }
      return Ref.create(PyBuiltinCache.getInstance(function).getBoolType());
    }

    if (callSite instanceof PyCallExpression) {
      final LanguageLevel level = "open".equals(functionQName)
                                  ? LanguageLevel.forElement(callSite)
                                  : "pathlib.Path.open".equals(functionQName) || "_io.open".equals(functionQName)
                                    ? LanguageLevel.PYTHON34
                                    : null;

      if (level != null) {
        return getOpenFunctionCallType(function, (PyCallExpression)callSite, level, context.myContext);
      }
    }

    final PyClass initializedClass = PyUtil.turnConstructorIntoClass(function);
    if (initializedClass != null && (TYPE_VAR.equals(initializedClass.getQualifiedName()) ||
                                     TYPE_VAR_TUPLE.equals(initializedClass.getQualifiedName()) ||
                                     TYPE_VAR_TUPLE_EXT.equals(initializedClass.getQualifiedName()))) {
      // `typing.TypeVar` call should be assigned to a target and hence should be processed by [getReferenceType]
      // but the corresponding type is also returned here to suppress type checker on `T = TypeVar("T")` assignment.
      return Ref.create(getTypeParameterTypeFromDeclaration(callSite, context));
    }

    if (initializedClass != null && callSite instanceof PyCallExpression && PyNames.DICT.equals(initializedClass.getQualifiedName())) {
      final PyType inferredTypedDict =
        PyTypedDictTypeProvider.Companion.inferTypedDictFromCallExpression((PyCallExpression)callSite, context.myContext);
      if (inferredTypedDict != null) {
        return Ref.create(inferredTypedDict);
      }
    }

    if (functionReturningCallSiteAsAType(function)) {
      return getAsClassObjectType(callSite, context);
    }

    return null;
  }
@Nullable
  @Override
  public Ref<PyType> getCallType(@NotNull PyFunction function, @NotNull PyCallSiteExpression callSite, @NotNull Context context)