@@ -3402,6 +3402,42 @@ class EnumDecl final : public NominalTypeDecl {
3402
3402
class StructDecl final : public NominalTypeDecl {
3403
3403
SourceLoc StructLoc;
3404
3404
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
+
3405
3441
public:
3406
3442
StructDecl (SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc,
3407
3443
ArrayRef<TypeLoc> Inherited,
@@ -3445,6 +3481,9 @@ class StructDecl final : public NominalTypeDecl {
3445
3481
bool isCxxNonTrivial () const { return Bits.StructDecl .IsCxxNonTrivial ; }
3446
3482
3447
3483
void setIsCxxNonTrivial (bool v) { Bits.StructDecl .IsCxxNonTrivial = v; }
3484
+
3485
+ Type getTemplateInstantiationType () const { return TemplateInstantiationType; }
3486
+ void setTemplateInstantiationType (Type t) { TemplateInstantiationType = t; }
3448
3487
};
3449
3488
3450
3489
// / This is the base type for AncestryOptions. Each flag describes possible
0 commit comments