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

diff --git a/Objects/abstract.c b/Objects/abstract.c
index 68d06ed..77d0914 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1373,6 +1373,13 @@
         }
         return result;
     }
+    if (m && m->nb_index) {
+        result = _PyLong_FromNbIndexOrNbInt(o);
+        if (result != NULL && !PyLong_CheckExact(result)) {
+            Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
+        }
+        return result;
+    }
     trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__);
     if (trunc_func) {
         result = _PyObject_CallNoArg(trunc_func);
@@ -1480,6 +1487,18 @@
         Py_DECREF(res);
         return PyFloat_FromDouble(val);
     }
+    if (m && m->nb_index) {
+        PyObject *res = PyNumber_Index(o);
+        if (!res) {
+            return NULL;
+        }
+        double val = PyLong_AsDouble(res);
+        Py_DECREF(res);
+        if (val == -1.0 && PyErr_Occurred()) {
+            return NULL;
+        }
+        return PyFloat_FromDouble(val);
+    }
     if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */
         return PyFloat_FromDouble(PyFloat_AS_DOUBLE(o));
     }
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index a5f9518..f78c0fd 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -984,7 +984,7 @@
     }
 
     nbr = r->ob_type->tp_as_number;
-    if (nbr == NULL || nbr->nb_float == NULL) {
+    if (nbr == NULL || (nbr->nb_float == NULL && nbr->nb_index == NULL)) {
         PyErr_Format(PyExc_TypeError,
                      "complex() first argument must be a string or a number, "
                      "not '%.200s'",
@@ -996,7 +996,7 @@
     }
     if (i != NULL) {
         nbi = i->ob_type->tp_as_number;
-        if (nbi == NULL || nbi->nb_float == NULL) {
+        if (nbi == NULL || (nbi->nb_float == NULL && nbi->nb_index == NULL)) {
             PyErr_Format(PyExc_TypeError,
                          "complex() second argument must be a number, "
                          "not '%.200s'",
@@ -1052,7 +1052,7 @@
         /* The "imag" part really is entirely imaginary, and
            contributes nothing in the real direction.
            Just treat it as a double. */
-        tmp = (*nbi->nb_float)(i);
+        tmp = PyNumber_Float(i);
         if (tmp == NULL)
             return NULL;
         ci.real = PyFloat_AsDouble(tmp);
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 2bf7061..15cbe5c 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -246,6 +246,15 @@
 
     nb = Py_TYPE(op)->tp_as_number;
     if (nb == NULL || nb->nb_float == NULL) {
+        if (nb && nb->nb_index) {
+            PyObject *res = PyNumber_Index(op);
+            if (!res) {
+                return -1;
+            }
+            double val = PyLong_AsDouble(res);
+            Py_DECREF(res);
+            return val;
+        }
         PyErr_Format(PyExc_TypeError, "must be real number, not %.50s",
                      op->ob_type->tp_name);
         return -1;