Backport recent improvements to the error message when trying to call `issubclass()` against a protocol with non-method members (#304)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ff6a1e..43569fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,9 @@
   is called on all objects that define `__set_name__` and exist in the values
   of the `NamedTuple` class's class dictionary. Patch by Alex Waygood,
   backporting https://github.com/python/cpython/pull/111876.
+- Improve the error message when trying to call `issubclass()` against a
+  `Protocol` that has non-method members. Patch by Alex Waygood (backporting
+  https://github.com/python/cpython/pull/112344, by Randolph Scholz).
 
 # Release 4.8.0 (September 17, 2023)
 
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index b54c592..f4c211f 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -3446,6 +3446,23 @@
         self.assertIsInstance(Foo(), ProtocolWithMixedMembers)
         self.assertNotIsInstance(42, ProtocolWithMixedMembers)
 
+    @skip_if_early_py313_alpha
+    def test_protocol_issubclass_error_message(self):
+        class Vec2D(Protocol):
+            x: float
+            y: float
+
+            def square_norm(self) -> float:
+                return self.x ** 2 + self.y ** 2
+
+        self.assertEqual(Vec2D.__protocol_attrs__, {'x', 'y', 'square_norm'})
+        expected_error_message = (
+            "Protocols with non-method members don't support issubclass()."
+            " Non-method members: 'x', 'y'."
+        )
+        with self.assertRaisesRegex(TypeError, re.escape(expected_error_message)):
+            issubclass(int, Vec2D)
+
 
 class Point2DGeneric(Generic[T], TypedDict):
     a: T
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index f85b0aa..5e4932b 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -570,8 +570,13 @@
                     not cls.__callable_proto_members_only__
                     and cls.__dict__.get("__subclasshook__") is _proto_hook
                 ):
+                    non_method_attrs = sorted(
+                        attr for attr in cls.__protocol_attrs__
+                        if not callable(getattr(cls, attr, None))
+                    )
                     raise TypeError(
-                        "Protocols with non-method members don't support issubclass()"
+                        "Protocols with non-method members don't support issubclass()."
+                        f" Non-method members: {str(non_method_attrs)[1:-1]}."
                     )
                 if not getattr(cls, '_is_runtime_protocol', False):
                     raise TypeError(