in runtime/type-builtins.cpp [117:230]
static word computeAttributeTypeFlags(Thread* thread, const Type& type,
SymbolId name, word flags) {
Runtime* runtime = thread->runtime();
// Custom MROs can contain types that are not part of the subclass hierarchy
// which does not fit our cache invalidation strategy for the flags. Be safe
// and do not set any!
if (flags & Type::Flag::kHasCustomMro) {
return flags & ~Type::kAttributeFlags;
}
if (name == ID(__getattribute__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (value == runtime->objectDunderGetattribute()) {
flags |= Type::Flag::kHasObjectDunderGetattribute;
} else {
flags &= ~Type::Flag::kHasObjectDunderGetattribute;
}
if (value == runtime->typeDunderGetattribute()) {
flags |= Type::Flag::kHasTypeDunderGetattribute;
} else {
flags &= ~Type::Flag::kHasTypeDunderGetattribute;
}
if (value == runtime->moduleDunderGetattribute()) {
flags |= Type::Flag::kHasModuleDunderGetattribute;
} else {
flags &= ~Type::Flag::kHasModuleDunderGetattribute;
}
return flags;
}
if (name == ID(__new__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (value == runtime->objectDunderNew()) {
flags |= Type::Flag::kHasObjectDunderNew;
} else {
flags &= ~Type::Flag::kHasObjectDunderNew;
}
return flags;
}
if (name == ID(__hash__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (value == runtime->objectDunderHash()) {
flags |= Type::Flag::kHasObjectDunderHash;
} else if (value == runtime->strDunderHash()) {
flags |= Type::Flag::kHasStrDunderHash;
} else {
flags &=
~(Type::Flag::kHasObjectDunderHash | Type::Flag::kHasStrDunderHash);
}
return flags;
}
if (name == ID(__bool__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (!value.isErrorNotFound()) {
flags |= Type::Flag::kHasDunderBool;
} else {
flags &= ~Type::Flag::kHasDunderBool;
}
return flags;
}
if (name == ID(__len__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (!value.isErrorNotFound()) {
flags |= Type::Flag::kHasDunderLen;
} else {
flags &= ~Type::Flag::kHasDunderLen;
}
return flags;
}
if (name == ID(__class__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (value == runtime->objectDunderClass()) {
flags |= Type::Flag::kHasObjectDunderClass;
} else {
flags &= ~Type::Flag::kHasObjectDunderClass;
}
return flags;
}
if (name == ID(__eq__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (value == runtime->objectDunderEq()) {
flags |= Type::Flag::kHasObjectDunderEq;
} else {
flags &= ~Type::Flag::kHasObjectDunderEq;
}
return flags;
}
if (name == ID(__get__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (!value.isErrorNotFound()) {
flags |= Type::Flag::kHasDunderGet;
} else {
flags &= ~Type::Flag::kHasDunderGet;
}
return flags;
}
if (name == ID(__set__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (!value.isErrorNotFound()) {
flags |= Type::Flag::kHasDunderSet;
} else {
flags &= ~Type::Flag::kHasDunderSet;
}
return flags;
}
if (name == ID(__delete__)) {
RawObject value = typeLookupInMroById(thread, *type, name);
if (!value.isErrorNotFound()) {
flags |= Type::Flag::kHasDunderDelete;
} else {
flags &= ~Type::Flag::kHasDunderDelete;
}
return flags;
}
return flags;
}