in runtime/runtime.cpp [1937:2056]
void Runtime::builtinTypeCreated(Thread* thread, const Type& type) {
LayoutId layout_id = type.instanceLayoutId();
switch (layout_id) {
case LayoutId::kObject:
object_dunder_class_ = typeAtById(thread, type, ID(__class__));
object_dunder_eq_ = typeAtById(thread, type, ID(__eq__));
object_dunder_getattribute_ =
typeAtById(thread, type, ID(__getattribute__));
object_dunder_hash_ = typeAtById(thread, type, ID(__hash__));
object_dunder_init_ = typeAtById(thread, type, ID(__init__));
object_dunder_new_ = typeAtById(thread, type, ID(__new__));
object_dunder_setattr_ = typeAtById(thread, type, ID(__setattr__));
type.setFlags(static_cast<Type::Flag>(
type.flags() | Type::Flag::kHasObjectDunderGetattribute |
Type::Flag::kHasObjectDunderNew | Type::Flag::kHasObjectDunderHash));
break;
case LayoutId::kModule:
module_dunder_getattribute_ =
typeAtById(thread, type, ID(__getattribute__));
type.setFlags(static_cast<Type::Flag>(
type.flags() | Type::Flag::kHasModuleDunderGetattribute));
break;
case LayoutId::kNoneType:
// NoneType.__class__ does *not* point to the same object as
// object.__class_ to avoid descriptor resolution for NoneType, but their
// observable behaviors are same. See the definition of NoneType in
// builtins.py.
type.setFlags(static_cast<Type::Flag>(type.flags() |
Type::Flag::kHasObjectDunderClass));
break;
case LayoutId::kStr:
str_dunder_eq_ = typeAtById(thread, type, ID(__eq__));
str_dunder_hash_ = typeAtById(thread, type, ID(__hash__));
type.setFlags(static_cast<Type::Flag>(type.flags() |
Type::Flag::kHasStrDunderHash));
break;
case LayoutId::kType:
type_dunder_getattribute_ =
typeAtById(thread, type, ID(__getattribute__));
type.setFlags(static_cast<Type::Flag>(
type.flags() | Type::Flag::kHasTypeDunderGetattribute));
break;
default:
break;
}
HandleScope scope(thread);
Function dunder_getattribute(
&scope, typeLookupInMroById(thread, *type, ID(__getattribute__)));
// This detects two instances of `object.__getattribute__`:
// 1) Manually created `object.__getattribute__` before initializing `object`.
// 2) Real `object.__getattribute__` after.
if (Str::cast(dunder_getattribute.qualname())
.equalsCStr("object.__getattribute__")) {
type.setFlags(static_cast<Type::Flag>(
type.flags() | Type::Flag::kHasObjectDunderGetattribute));
}
Object dunder_new(&scope, typeLookupInMroById(thread, *type, ID(__new__)));
if (*dunder_new == object_dunder_new_ ||
// __new__ cannot be found in this type and this type is initialized
// before `object`.
(dunder_new.isErrorNotFound() && object_dunder_new_.isNoneType())) {
type.setFlags(static_cast<Type::Flag>(type.flags() |
Type::Flag::kHasObjectDunderNew));
}
Object dunder_hash(&scope, typeLookupInMroById(thread, *type, ID(__hash__)));
if (*dunder_hash == object_dunder_hash_ ||
// __hash__ cannot be found in this type and this type is initialized
// before `object`.
(dunder_hash.isErrorNotFound() && object_dunder_hash_.isNoneType())) {
type.setFlags(static_cast<Type::Flag>(type.flags() |
Type::Flag::kHasObjectDunderHash));
}
if (!typeLookupInMroById(thread, *type, ID(__bool__)).isErrorNotFound()) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderBool));
}
if (!typeLookupInMroById(thread, *type, ID(__len__)).isErrorNotFound()) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderLen));
}
Object dunder_class(&scope,
typeLookupInMroById(thread, *type, ID(__class__)));
if (*dunder_class == object_dunder_class_ ||
// __class__ cannot be found in this type and this type is initialized
// before `object`.
(dunder_class.isErrorNotFound() && object_dunder_class_.isNoneType())) {
type.setFlags(static_cast<Type::Flag>(type.flags() |
Type::Flag::kHasObjectDunderClass));
}
Object dunder_eq(&scope, typeLookupInMroById(thread, *type, ID(__eq__)));
if (*dunder_eq == object_dunder_eq_ ||
// __eq__ cannot be found in this type and this type is initialized
// before `object`.
(dunder_eq.isErrorNotFound() && object_dunder_eq_.isNoneType())) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasObjectDunderEq));
}
if (!typeLookupInMroById(thread, *type, ID(__get__)).isErrorNotFound()) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderGet));
}
if (!typeLookupInMroById(thread, *type, ID(__set__)).isErrorNotFound()) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderSet));
}
if (!typeLookupInMroById(thread, *type, ID(__delete__)).isErrorNotFound()) {
type.setFlags(
static_cast<Type::Flag>(type.flags() | Type::Flag::kHasDunderDelete));
}
}