@@ -123,27 +123,37 @@ impl PySuper {
123123
124124impl SlotGetattro for PySuper {
125125 fn getattro ( zelf : PyRef < Self > , name : PyStrRef , vm : & VirtualMachine ) -> PyResult {
126- let ( inst, obj_type) = match zelf. obj . clone ( ) {
126+ let skip = |zelf : PyRef < Self > , name| vm. generic_getattribute ( zelf. into_object ( ) , name) ;
127+ let ( obj, start_type) : ( PyObjectRef , PyTypeRef ) = match zelf. obj . clone ( ) {
127128 Some ( o) => o,
128- None => return vm . generic_getattribute ( zelf. into_object ( ) , name) ,
129+ None => return skip ( zelf, name) ,
129130 } ;
130- // skip the classes in obj_type.mro up to and including zelf.typ
131- let it = obj_type
131+ // We want __class__ to return the class of the super object
132+ // (i.e. super, or a subclass), not the class of su->obj.
133+
134+ if name. as_str ( ) == "__class__" {
135+ return skip ( zelf, name) ;
136+ }
137+
138+ // skip the classes in start_type.mro up to and including zelf.typ
139+ let mro: Vec < _ > = start_type
132140 . iter_mro ( )
133141 . skip_while ( |cls| !cls. is ( & zelf. typ ) )
134- . skip ( 1 ) ;
135- for cls in it {
142+ . skip ( 1 ) // skip su->type (if any)
143+ . collect ( ) ;
144+ for cls in mro {
136145 if let Some ( descr) = cls. get_direct_attr ( name. as_str ( ) ) {
137146 return vm
138147 . call_get_descriptor_specific (
139148 descr. clone ( ) ,
140- if inst. is ( & obj_type) { None } else { Some ( inst) } ,
141- Some ( obj_type. clone ( ) . into_object ( ) ) ,
149+ // Only pass 'obj' param if this is instance-mode super (See https://bugs.python.org/issue743267)
150+ if obj. is ( & start_type) { None } else { Some ( obj) } ,
151+ Some ( start_type. as_object ( ) . clone ( ) ) ,
142152 )
143153 . unwrap_or ( Ok ( descr) ) ;
144154 }
145155 }
146- vm . generic_getattribute ( zelf. into_object ( ) , name)
156+ skip ( zelf, name)
147157 }
148158}
149159
0 commit comments