@@ -758,6 +758,8 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
758758{
759759 PyObject * k , * v ;
760760 Py_ssize_t pos = 0 ;
761+ int remove_dunder_class = 0 ;
762+
761763 while (PyDict_Next (comp -> ste_symbols , & pos , & k , & v )) {
762764 // skip comprehension parameter
763765 long comp_flags = PyLong_AS_LONG (v );
@@ -779,6 +781,19 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
779781 if (!existing ) {
780782 // name does not exist in scope, copy from comprehension
781783 assert (scope != FREE || PySet_Contains (comp_free , k ) == 1 );
784+ if (scope == FREE && ste -> ste_type == ClassBlock &&
785+ _PyUnicode_EqualToASCIIString (k , "__class__" )) {
786+ // if __class__ is unbound in the enclosing class scope and free
787+ // in the comprehension scope, it needs special handling; just
788+ // letting it be marked as free in class scope will break due to
789+ // drop_class_free
790+ scope = GLOBAL_IMPLICIT ;
791+ only_flags &= ~DEF_FREE ;
792+ if (PySet_Discard (comp_free , k ) < 0 ) {
793+ return 0 ;
794+ }
795+ remove_dunder_class = 1 ;
796+ }
782797 PyObject * v_flags = PyLong_FromLong (only_flags );
783798 if (v_flags == NULL ) {
784799 return 0 ;
@@ -803,6 +818,10 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,
803818 }
804819 }
805820 }
821+ comp -> ste_free = PySet_Size (comp_free ) > 0 ;
822+ if (remove_dunder_class && PyDict_DelItemString (comp -> ste_symbols , "__class__" ) < 0 ) {
823+ return 0 ;
824+ }
806825 return 1 ;
807826}
808827
0 commit comments