11use super :: { PyDictRef , PyList , PyStr , PyStrRef , PyType , PyTypeRef } ;
22use crate :: common:: hash:: PyHash ;
3+ use crate :: types:: PyTypeFlags ;
34use crate :: {
45 class:: PyClassImpl ,
56 function:: { Either , FuncArgs , PyArithmeticValue , PyComparisonValue , PySetterValue } ,
@@ -281,7 +282,19 @@ impl PyBaseObject {
281282
282283 #[ pygetset( name = "__class__" , setter) ]
283284 fn set_class ( instance : PyObjectRef , value : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
284- if instance. payload_is :: < PyBaseObject > ( ) {
285+ let both_module = instance. class ( ) . fast_issubclass ( vm. ctx . types . module_type )
286+ && value. class ( ) . fast_issubclass ( vm. ctx . types . module_type ) ;
287+ let both_mutable = !instance
288+ . class ( )
289+ . slots
290+ . flags
291+ . has_feature ( PyTypeFlags :: IMMUTABLETYPE )
292+ && !value
293+ . class ( )
294+ . slots
295+ . flags
296+ . has_feature ( PyTypeFlags :: IMMUTABLETYPE ) ;
297+ if both_mutable || both_module {
285298 match value. downcast :: < PyType > ( ) {
286299 Ok ( cls) => {
287300 // FIXME(#1979) cls instances might have a payload
@@ -298,7 +311,8 @@ impl PyBaseObject {
298311 }
299312 } else {
300313 Err ( vm. new_type_error (
301- "__class__ assignment only supported for types without a payload" . to_owned ( ) ,
314+ "__class__ assignment only supported for mutable types or ModuleType subclasses"
315+ . to_owned ( ) ,
302316 ) )
303317 }
304318 }
0 commit comments