Lazy Initialization of Foreign Import VWT


(Saleem Abdulrasool) #1


So, now that Foundation builds on Windows, I am running into a fun little aspect of the lazy initialization that was unexpected. It seems that there are some cases where the VWT for the foreign type is not initialized (as it is done lazily), but, is expected to be for the bridged cast. This shows up for CFString types which are bridged to _NSCFConstantString. A quick workaround for this is for those paths to do something silly like if arg is _NSCFString { } to invoke the registration for that. However, this seems less than ideal. I'm not sure what the right place is to ensure that the VWT for the bridged type is initialized. Should we perhaps consider doing that as a startup thing?

I'm running into this in the XCTest test suite and the Foundation test suite itself.

CC: @John_McCall @Joe_Groff @millenomi

(John McCall) #2

Are you saying that the bridging machinery is somehow manipulating type metadata that hasn't been fully initialized? How is it getting a handle on that metadata?

(Saleem Abdulrasool) #3

It isn't manipulating it, it is querying it. This occurs with passing it as Any all the way through, and then casting it to NSObject which then fails as the VWT has not yet been installed. There is no call made to the accessor which will install the VWT. The terrible hack of if object is _NSCFConstantString { } causes the metadata accessor to be invoked, installing the VWT, and then everything works as desired. This is almost entirely contained in the Foundation Bridging.swift.

(John McCall) #4

Okay, so the improperly-initialized metadata is being held as the Self type in any Any value. Can you figure out what code is storing it there and how it's getting the metadata without calling a metadata accessor? There really isn't supposed to be any code that fetches incompletely-initialized metadata and stores it around like that.

(Saleem Abdulrasool) #5

I'm trying to see if I can reduce it, but, its been instances of bridged constant CFStrings (which is bridged to _NSCFConstantString and that is bridged to String). I'll try to see if I can figure out how to reduce this into something that we can work with.

(Lily Vulcano) #6

We form static references to the metadata of bridged as part of building CF, to mirror what we do on Darwin with ObjC classes. Is there anything we can do on Windows to trigger correct setup, e.g. from __CFInitialize?