What constitutes a "foreign class" to the Swift runtime?

Specifically, this line in MetadataLayout.h. Is a foreign class anything that doesn't inherit from SwiftObject?

You can find a definition in TypeMetadata.rst:

"foreign" class types, which support Swift reference counting but are otherwise opaque to the Swift runtime.

Example: CoreFoundation classes.

See here:

1 Like


1 Like

This confuses me a bit... does Normal here mean "not foreign at all," in the context I'm referring to? At first glance, this enum seems to imply that there are 3 kinds of foreign classes, and that all Swift classes fall into the first category.

Yes. Just below that there is a β€œisForeign” getter that returns false if the kind is Normal.

1 Like

Gotcha, thank you!

1 Like

I think this is not correct. My understanding is that the runtime's notion of a foreign class is "a class not defined in Swift", but the compiler's is "a class that cannot be directly referenced". We should probably rename the one in the compiler, since "foreign" is used elsewhere in the compiler itself to refer to "non-Swift" (including ObjC and C things).

Gotcha, gotcha. Thanks for that clarification.

I'm looking for runtime data. Should I totally ignore that 4-case MetadataLayout.Kind enum? Is that not part of any runtime type information?

I'm not sure what you mean. There are different kinds of MetadataLayout with different fields and they are identified by that enum.

Hmm, now I’m confused, too :sweat_smile:

IRGen seems to think the concepts are equivalent:

@John_McCall or @Joe_Groff is going to have to correct me, then.

Swift's native class model requires support for a variety of different language features: subclassing, overriding, @objc dynamic extension, dynamic casting, etc. The concept is that "foreign" classes can't fully participate in this model. As you can imagine, different kinds of "foreign-ness" are differently limited, so the closer you look at this concept the weaker it seems as a unifying idea. For example, I'm not sure there's a fundamental reason we can't allow "runtime-only" ObjC classes to be subclassed; the only restriction I can think of is that we might not have a very good idea about what subobject initializers they provide, but they can certainly be dynamically casted. CF "classes", on the other hand, often don't have a real runtime existence in the same way as ObjC classes do; a CF object has to have an isa to interoperate with ObjC, but this can be a shared class that just forwards to CF's own mechanisms. A COM object model β€” well, who knows what it would support.

The assertion in IGM::getClassMetadataLayout is, strictly speaking, wrong β€” runtime-only ObjC classes still have an ObjC class object layout β€” but it hasn't mattered in practice because we have no reason to ever ask about their metadata layout because they don't support subclassing and have nothing interesting in their metadata.