Issue #24731: Fixed crash on converting objects with special methods
__bytes__, __trunc__, and __float__ returning instances of subclasses of
bytes, int, and float to subclasses of bytes, int, and float correspondingly.
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index b00573f..0a73fcb 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -744,6 +744,14 @@
             def __index__(self):
                 return 42
         self.assertEqual(bytes(A()), b'a')
+        # Issue #24731
+        class A:
+            def __bytes__(self):
+                return OtherBytesSubclass(b'abc')
+        self.assertEqual(bytes(A()), b'abc')
+        self.assertIs(type(bytes(A())), OtherBytesSubclass)
+        self.assertEqual(BytesSubclass(A()), b'abc')
+        self.assertIs(type(BytesSubclass(A())), BytesSubclass)
 
     # Test PyBytes_FromFormat()
     def test_from_format(self):
@@ -1465,6 +1473,9 @@
 class BytesSubclass(bytes):
     pass
 
+class OtherBytesSubclass(bytes):
+    pass
+
 class ByteArraySubclassTest(SubclassTest, unittest.TestCase):
     type2test = bytearray
     subclass2test = ByteArraySubclass
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py
index 504f39c..24fe128 100644
--- a/Lib/test/test_float.py
+++ b/Lib/test/test_float.py
@@ -25,6 +25,12 @@
 test_dir = os.path.dirname(__file__) or os.curdir
 format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
 
+class FloatSubclass(float):
+    pass
+
+class OtherFloatSubclass(float):
+    pass
+
 class GeneralFloatCases(unittest.TestCase):
 
     def test_float(self):
@@ -167,6 +173,15 @@
                 return ""
         self.assertRaises(TypeError, time.sleep, Foo5())
 
+        # Issue #24731
+        class F:
+            def __float__(self):
+                return OtherFloatSubclass(42.)
+        self.assertAlmostEqual(float(F()), 42.)
+        self.assertIs(type(float(F())), OtherFloatSubclass)
+        self.assertAlmostEqual(FloatSubclass(F()), 42.)
+        self.assertIs(type(FloatSubclass(F())), FloatSubclass)
+
     def test_is_integer(self):
         self.assertFalse((1.1).is_integer())
         self.assertTrue((1.).is_integer())
diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py
index ab3917f..4906e46 100644
--- a/Lib/test/test_int.py
+++ b/Lib/test/test_int.py
@@ -24,6 +24,9 @@
         ("\u0200", ValueError)
 ]
 
+class IntSubclass(int):
+    pass
+
 class IntTestCases(unittest.TestCase):
 
     def test_basic(self):
@@ -441,6 +444,10 @@
         good_int = TruncReturnsIntSubclass()
         n = int(good_int)
         self.assertEqual(n, 1)
+        self.assertIs(type(n), bool)
+        n = IntSubclass(good_int)
+        self.assertEqual(n, 1)
+        self.assertIs(type(n), IntSubclass)
 
     def test_error_message(self):
         def check(s, base=None):
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index d664465..d54642f 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -42,6 +42,9 @@
     """
     return text.encode().decode()
 
+class StrSubclass(str):
+    pass
+
 class UnicodeTest(string_tests.CommonTest,
         string_tests.MixinStrUnicodeUserStringTest,
         string_tests.MixinStrUnicodeTest,
@@ -1412,11 +1415,8 @@
             'unicode remains unicode'
         )
 
-        class UnicodeSubclass(str):
-            pass
-
         for text in ('ascii', '\xe9', '\u20ac', '\U0010FFFF'):
-            subclass = UnicodeSubclass(text)
+            subclass = StrSubclass(text)
             self.assertEqual(str(subclass), text)
             self.assertEqual(len(subclass), len(text))
             if text == 'ascii':
@@ -2169,6 +2169,9 @@
         s = str(StrSubclassToStrSubclass("foo"))
         self.assertEqual(s, "foofoo")
         self.assertIs(type(s), StrSubclassToStrSubclass)
+        s = StrSubclass(StrSubclassToStrSubclass("foo"))
+        self.assertEqual(s, "foofoo")
+        self.assertIs(type(s), StrSubclass)
 
     def test_unicode_repr(self):
         class s1: