bpo-33141: Have dataclasses.Field pass through __set_name__ to any default argument. (GH-6260)

This is part of PEP 487 and the descriptor protocol.
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py
index 8ccc4c8..8c197fe 100644
--- a/Lib/dataclasses.py
+++ b/Lib/dataclasses.py
@@ -240,6 +240,20 @@
                 f'metadata={self.metadata}'
                 ')')
 
+    # This is used to support the PEP 487 __set_name__ protocol in the
+    #  case where we're using a field that contains a descriptor as a
+    #  defaul value.  For details on __set_name__, see
+    #  https://www.python.org/dev/peps/pep-0487/#implementation-details.
+    # Note that in _process_class, this Field object is overwritten with
+    #  the default value, so the end result is a descriptor that had
+    #  __set_name__ called on it at the right time.
+    def __set_name__(self, owner, name):
+        func = getattr(self.default, '__set_name__', None)
+        if func:
+            # There is a __set_name__ method on the descriptor,
+            #  call it.
+            func(owner, name)
+
 
 class _DataclassParams:
     __slots__ = ('init',
diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py
index f7f132c..2745eaf 100755
--- a/Lib/test/test_dataclasses.py
+++ b/Lib/test/test_dataclasses.py
@@ -2698,6 +2698,48 @@
         # We can add a new field to the derived instance.
         d.z = 10
 
+class TestDescriptors(unittest.TestCase):
+    def test_set_name(self):
+        # See bpo-33141.
+
+        # Create a descriptor.
+        class D:
+            def __set_name__(self, owner, name):
+                self.name = name
+            def __get__(self, instance, owner):
+                if instance is not None:
+                    return 1
+                return self
+
+        # This is the case of just normal descriptor behavior, no
+        #  dataclass code is involved in initializing the descriptor.
+        @dataclass
+        class C:
+            c: int=D()
+        self.assertEqual(C.c.name, 'c')
+
+        # Now test with a default value and init=False, which is the
+        #  only time this is really meaningful.  If not using
+        #  init=False, then the descriptor will be overwritten, anyway.
+        @dataclass
+        class C:
+            c: int=field(default=D(), init=False)
+        self.assertEqual(C.c.name, 'c')
+        self.assertEqual(C().c, 1)
+
+    def test_non_descriptor(self):
+        # PEP 487 says __set_name__ should work on non-descriptors.
+        # Create a descriptor.
+
+        class D:
+            def __set_name__(self, owner, name):
+                self.name = name
+
+        @dataclass
+        class C:
+            c: int=field(default=D(), init=False)
+        self.assertEqual(C.c.name, 'c')
+
 
 if __name__ == '__main__':
     unittest.main()