bpo-20092. Use __index__ in constructors of int, float and complex. (GH-13108)

diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst
index 675bd01..06dbb25 100644
--- a/Doc/c-api/complex.rst
+++ b/Doc/c-api/complex.rst
@@ -129,4 +129,10 @@
 
    If *op* is not a Python complex number object but has a :meth:`__complex__`
    method, this method will first be called to convert *op* to a Python complex
-   number object. Upon failure, this method returns ``-1.0`` as a real value.
+   number object.  If ``__complex__()`` is not defined then it falls back to
+   :meth:`__float__`.  If ``__float__()`` is not defined then it falls back
+   to :meth:`__index__`.  Upon failure, this method returns ``-1.0`` as a real
+   value.
+
+   .. versionchanged:: 3.8
+      Use :meth:`__index__` if available.
diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst
index 8a99642..057ff52 100644
--- a/Doc/c-api/float.rst
+++ b/Doc/c-api/float.rst
@@ -47,9 +47,13 @@
    Return a C :c:type:`double` representation of the contents of *pyfloat*.  If
    *pyfloat* is not a Python floating point object but has a :meth:`__float__`
    method, this method will first be called to convert *pyfloat* into a float.
+   If ``__float__()`` is not defined then it falls back to :meth:`__index__`.
    This method returns ``-1.0`` upon failure, so one should call
    :c:func:`PyErr_Occurred` to check for errors.
 
+   .. versionchanged:: 3.8
+      Use :meth:`__index__` if available.
+
 
 .. c:function:: double PyFloat_AS_DOUBLE(PyObject *pyfloat)
 
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 425a985..d5c9f18 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -318,6 +318,11 @@
    :class:`int` and :class:`float`.  If both arguments are omitted, returns
    ``0j``.
 
+   For a general Python object ``x``, ``complex(x)`` delegates to
+   ``x.__complex__()``.  If ``__complex__()`` is not defined then it falls back
+   to :meth:`__float__`.  If ``__float__()`` is not defined then it falls back
+   to :meth:`__index__`.
+
    .. note::
 
       When converting from a string, the string must not contain whitespace
@@ -330,6 +335,10 @@
    .. versionchanged:: 3.6
       Grouping digits with underscores as in code literals is allowed.
 
+   .. versionchanged:: 3.8
+      Falls back to :meth:`__index__` if :meth:`__complex__` and
+      :meth:`__float__` are not defined.
+
 
 .. function:: delattr(object, name)
 
@@ -584,7 +593,8 @@
    float, an :exc:`OverflowError` will be raised.
 
    For a general Python object ``x``, ``float(x)`` delegates to
-   ``x.__float__()``.
+   ``x.__float__()``.  If ``__float__()`` is not defined then it falls back
+   to :meth:`__index__`.
 
    If no argument is given, ``0.0`` is returned.
 
@@ -609,6 +619,9 @@
    .. versionchanged:: 3.7
       *x* is now a positional-only parameter.
 
+   .. versionchanged:: 3.8
+      Falls back to :meth:`__index__` if :meth:`__float__` is not defined.
+
 
 .. index::
    single: __format__
@@ -780,7 +793,8 @@
 
    Return an integer object constructed from a number or string *x*, or return
    ``0`` if no arguments are given.  If *x* defines :meth:`__int__`,
-   ``int(x)`` returns ``x.__int__()``.  If *x* defines :meth:`__trunc__`,
+   ``int(x)`` returns ``x.__int__()``.  If *x* defines :meth:`__index__`,
+   it returns ``x.__index__()``.  If *x* defines :meth:`__trunc__`,
    it returns ``x.__trunc__()``.
    For floating point numbers, this truncates towards zero.
 
@@ -812,6 +826,9 @@
    .. versionchanged:: 3.7
       *x* is now a positional-only parameter.
 
+   .. versionchanged:: 3.8
+      Falls back to :meth:`__index__` if :meth:`__int__` is not defined.
+
 
 .. function:: isinstance(object, classinfo)
 
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 44017d8..fa47bf1 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -2394,11 +2394,9 @@
    functions). Presence of this method indicates that the numeric object is
    an integer type.  Must return an integer.
 
-   .. note::
-
-      In order to have a coherent integer type class, when :meth:`__index__` is
-      defined :meth:`__int__` should also be defined, and both should return
-      the same value.
+   If :meth:`__int__`, :meth:`__float__` and :meth:`__complex__` are not
+   defined then corresponding built-in functions :func:`int`, :func:`float`
+   and :func:`complex` fall back to :meth:`__index__`.
 
 
 .. method:: object.__round__(self, [,ndigits])
diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
index 4c5a9bb..591b454 100644
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -250,6 +250,12 @@
   compatible with the existing :meth:`float.as_integer_ratio` method.
   (Contributed by Lisa Roach in :issue:`33073`.)
 
+* Constructors of :class:`int`, :class:`float` and :class:`complex` will now
+  use the :meth:`~object.__index__` special method, if available and the
+  corresponding method :meth:`~object.__int__`, :meth:`~object.__float__`
+  or :meth:`~object.__complex__` is not available.
+  (Contributed by Serhiy Storchaka in :issue:`20092`.)
+
 * Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
   (Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
 
@@ -868,7 +874,10 @@
   ``__index__()`` method (like :class:`~decimal.Decimal` and
   :class:`~fractions.Fraction`).  :c:func:`PyNumber_Check` will now return
   ``1`` for objects implementing ``__index__()``.
-  (Contributed by Serhiy Storchaka in :issue:`36048`.)
+  :c:func:`PyNumber_Long`, :c:func:`PyNumber_Float` and
+  :c:func:`PyFloat_AsDouble` also now use the ``__index__()`` method if
+  available.
+  (Contributed by Serhiy Storchaka in :issue:`36048` and :issue:`20092`.)
 
 * Heap-allocated type objects will now increase their reference count
   in :c:func:`PyObject_Init` (and its parallel macro ``PyObject_INIT``)