@@ -3402,6 +3402,42 @@ class EnumDecl final : public NominalTypeDecl {
34023402class StructDecl final : public NominalTypeDecl {
34033403 SourceLoc StructLoc;
34043404
3405+ // We import C++ class templates as generic structs. Then when in Swift code
3406+ // we want to substitude generic parameters with actual arguments, we
3407+ // convert the arguments to C++ equivalents and ask Clang to instantiate the
3408+ // C++ template. Then we import the C++ class template instantiation
3409+ // as a non-generic structs with a name prefixed with `__CxxTemplateInst`.
3410+ //
3411+ // To reiterate:
3412+ // 1) We need to have a C++ class template declaration in the Clang AST. This
3413+ // declaration is simply imported from a Clang module.
3414+ // 2) We need a Swift generic struct in the Swift AST. This will provide
3415+ // template arguments to Clang.
3416+ // 3) We produce a C++ class template instantiation in the Clang AST
3417+ // using 1) and 2). This declaration does not exist in the Clang module
3418+ // AST initially in the general case, it's added there on instantiation.
3419+ // 4) We import the instantiation as a Swift struct, with the name prefixed
3420+ // with `__CxxTemplateInst`.
3421+ //
3422+ // This causes a problem for serialization/deserialization of the Swift
3423+ // module. Imagine the Swift struct from 4) is used in the function return
3424+ // type. We cannot just serialize the non generic Swift struct, because on
3425+ // deserialization we would need to find its backing Clang declaration
3426+ // (the C++ class template instantiation), and it won't be found in the
3427+ // general case. Only the C++ class template from step 1) is in the Clang
3428+ // AST.
3429+ //
3430+ // What we need is to serialize enough information to be
3431+ // able to instantiate C++ class template on deserialization. It turns out
3432+ // that all that information is conveniently covered by the BoundGenericType,
3433+ // which we store in this field. The field is set during the typechecking at
3434+ // the time when we instantiate the C++ class template.
3435+ //
3436+ // Alternative, and likely better solution long term, is to serialize the
3437+ // C++ class template instantiation into a synthetic Clang module, and load
3438+ // this Clang module on deserialization.
3439+ Type TemplateInstantiationType = Type();
3440+
34053441public:
34063442 StructDecl (SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
34073443 ArrayRef<TypeLoc> Inherited,
@@ -3445,6 +3481,9 @@ class StructDecl final : public NominalTypeDecl {
34453481 bool isCxxNonTrivial () const { return Bits.StructDecl .IsCxxNonTrivial ; }
34463482
34473483 void setIsCxxNonTrivial (bool v) { Bits.StructDecl .IsCxxNonTrivial = v; }
3484+
3485+ Type getTemplateInstantiationType () const { return TemplateInstantiationType; }
3486+ void setTemplateInstantiationType (Type t) { TemplateInstantiationType = t; }
34483487};
34493488
34503489// / This is the base type for AncestryOptions. Each flag describes possible
0 commit comments