As I've been fixing bugs to, mostly, prevent C++ interop from crashing when importing various APIs, I've noticed a common theme: these bugs often occur when we do something differently than Clang does it. This makes sense because we're using Clang and importing C++. Here are a few examples of such bugs:
https://github.com/apple/swift/pull/36553
https://github.com/apple/swift/pull/35963
https://github.com/apple/swift/pull/35962
https://github.com/apple/swift/pull/35819
In fact, all these bugs occur because Clang is lazy and we are not. What I mean by that is, Clang often won't evaluate types or members until it really needs to (i.e., until they are actually used). For example, Clang will lazily evaluate inline static data members. So, if there's an error, it will only be emitted when the member is used. Because we try to evaluate every member, (before that patch) we would sometimes find invalid members that Clang hadn't yet instantiated and therefore didn't mark as invalid.
Another example of this can be demonstrated with the following snippet:
template<class T> struct X { X<X<T>> test(); } ;
void test(X<int>);
Clang has no problem compiling this program, but we fail to import it (luckily, we no longer hang/crash). Why is this? Because Clang won't evaluate the function type until it's actually called, whereas we will evaluate and instantiate the function type as we're importing it.
So, what's the solution? We could redesign some parts of the Clang importer to be lazier (especially when dealing with C++ templates). We have already started to do this with function templates (see #35819), but I think we could integrate laziness into the Clang importer in a much more fundamental way.
This would not only fix some of the issues above but also allow us to import more C++ APIs, more closely match what Clang does, and be vastly more performant, especially when importing templates.
In this post, I'm not proposing we do anything. I'm just bringing up a "problem" (or, more accurately, an observation about related problems) and brainstorming some possible solutions. I'm creating this post in response to the discussion @typesanitizer and I had here: cxx-interop Improve performance of deep template instantiations. by zoecarver · Pull Request #36553 · apple/swift · GitHub.
I'd love to hear what people think about making the Clang importer lazy and if there are any suggestions as to the best way to design this (I know there are some other parts of the compiler that rely on lazy evaluation, it would be helpful to know how those are implemented and if the model works well). As Varun said, taking a step back and thinking about the best implementation for the Clang importer might be extremely beneficial in the long run.