@@ -1999,6 +1999,49 @@ def two(_) -> C1 | C2:
19991999 self .assertEqual (A .two_f_ga1 , A .two_f_ga2 )
20002000 self .assertEqual (hash (A .two_f_ga1 ), hash (A .two_f_ga2 ))
20012001
2002+ def test_forward_equality_and_hash_with_extra_names (self ):
2003+ """Regression test for the __extra_names__ sibling of GH-143831."""
2004+ class Unhashable :
2005+ __hash__ = None
2006+
2007+ # An unhashable value referenced in an annotation is kept in the
2008+ # forward ref's __extra_names__.
2009+ ns = support .run_code (
2010+ "def f(a: undefined | obj): pass" ,
2011+ extra_names = {"obj" : Unhashable ()},
2012+ )
2013+ fr1 = get_annotations (ns ["f" ], format = Format .FORWARDREF )["a" ]
2014+ fr2 = get_annotations (ns ["f" ], format = Format .FORWARDREF )["a" ]
2015+ self .assertIsInstance (fr1 .__extra_names__ , dict )
2016+
2017+ self .assertEqual (fr1 , fr2 )
2018+ self .assertEqual (hash (fr1 ), hash (fr2 ))
2019+ self .assertEqual (len ({fr1 , fr2 }), 1 )
2020+
2021+ # Forward refs with different extra-name values are unequal.
2022+ ns2 = support .run_code (
2023+ "def g(a: undefined | obj): pass" ,
2024+ extra_names = {"obj" : Unhashable ()},
2025+ )
2026+ fr3 = get_annotations (ns2 ["g" ], format = Format .FORWARDREF )["a" ]
2027+ self .assertNotEqual (fr1 , fr3 )
2028+ self .assertEqual (len ({fr1 , fr2 , fr3 }), 2 )
2029+
2030+ def test_forward_equality_and_hash_with_unhashable_owner (self ):
2031+ """Regression test for an unhashable __owner__ (GH-143831 sibling)."""
2032+ class MetaNoHash (type ):
2033+ __hash__ = None
2034+
2035+ class D (metaclass = MetaNoHash ):
2036+ x : undefined
2037+
2038+ fr1 = get_annotations (D , format = Format .FORWARDREF )["x" ]
2039+ fr2 = get_annotations (D , format = Format .FORWARDREF )["x" ]
2040+ self .assertIs (fr1 .__owner__ , D )
2041+ self .assertEqual (fr1 , fr2 )
2042+ self .assertEqual (hash (fr1 ), hash (fr2 ))
2043+ self .assertEqual (len ({fr1 , fr2 }), 1 )
2044+
20022045 def test_forward_equality_namespace (self ):
20032046 def namespace1 ():
20042047 a = ForwardRef ("A" )
0 commit comments