diff --git a/crates/vm/src/stdlib/_abc.rs b/crates/vm/src/stdlib/_abc.rs index 19cf47415a9..4d2971949e5 100644 --- a/crates/vm/src/stdlib/_abc.rs +++ b/crates/vm/src/stdlib/_abc.rs @@ -272,7 +272,9 @@ mod _abc { let impl_data = get_impl(&cls, vm)?; // Get instance.__class__ - let subclass = instance.get_attr("__class__", vm)?; + let subclass = vm + .get_attribute_opt(&instance, "__class__")? + .unwrap_or_else(|| instance.class().to_owned().into()); // Check cache if in_weak_set(&impl_data.cache, &subclass, vm)? { diff --git a/extra_tests/snippets/stdlib_abc.py b/extra_tests/snippets/stdlib_abc.py index 30b4ef37068..df1833a419f 100644 --- a/extra_tests/snippets/stdlib_abc.py +++ b/extra_tests/snippets/stdlib_abc.py @@ -36,3 +36,28 @@ class SubConcrete(Concrete): assert isinstance(Concrete(), CustomInterface) assert isinstance(SubConcrete(), CustomInterface) assert not isinstance((), CustomInterface) + + +class NoClassAttribute: + @property + def __class__(self): + raise AttributeError("no class attribute") + + +instance = NoClassAttribute() +assert not isinstance(instance, CustomInterface) +CustomInterface.register(NoClassAttribute) +assert isinstance(instance, CustomInterface) + +class_error = RuntimeError("class lookup failed") + + +class BrokenClassAttribute: + @property + def __class__(self): + raise class_error + + +with assert_raises(RuntimeError) as caught: + isinstance(BrokenClassAttribute(), CustomInterface) +assert caught.exception is class_error