@@ -813,6 +813,10 @@ class PrintAST : public ASTVisitor<PrintAST> {
813
813
TypeArrayView<GenericTypeParamType> genericParams,
814
814
ArrayRef<Requirement> requirements, unsigned flags,
815
815
llvm::function_ref<bool (const Requirement &)> filter);
816
+ void printSingleDepthOfGenericSignature (
817
+ TypeArrayView<GenericTypeParamType> genericParams,
818
+ ArrayRef<Requirement> requirements, bool &isFirstReq, unsigned flags,
819
+ llvm::function_ref<bool (const Requirement &)> filter);
816
820
void printRequirement (const Requirement &req);
817
821
818
822
private:
@@ -872,7 +876,12 @@ class PrintAST : public ASTVisitor<PrintAST> {
872
876
return false ; // not needed for the parser library.
873
877
#endif
874
878
875
- if (!shouldPrint (D, true ))
879
+ bool Synthesize =
880
+ Options.TransformContext &&
881
+ Options.TransformContext ->isPrintingSynthesizedExtension () &&
882
+ isa<ExtensionDecl>(D);
883
+
884
+ if (!shouldPrint (D, true ) && !Synthesize)
876
885
return false ;
877
886
878
887
Decl *Old = Current;
@@ -890,10 +899,6 @@ class PrintAST : public ASTVisitor<PrintAST> {
890
899
891
900
SWIFT_DEFER { CurrentType = OldType; };
892
901
893
- bool Synthesize =
894
- Options.TransformContext &&
895
- Options.TransformContext ->isPrintingSynthesizedExtension () &&
896
- isa<ExtensionDecl>(D);
897
902
if (Synthesize) {
898
903
Printer.setSynthesizedTarget (Options.TransformContext ->getDecl ());
899
904
}
@@ -1456,6 +1461,15 @@ void PrintAST::printSingleDepthOfGenericSignature(
1456
1461
TypeArrayView<GenericTypeParamType> genericParams,
1457
1462
ArrayRef<Requirement> requirements, unsigned flags,
1458
1463
llvm::function_ref<bool (const Requirement &)> filter) {
1464
+ bool isFirstReq = true ;
1465
+ printSingleDepthOfGenericSignature (genericParams, requirements, isFirstReq,
1466
+ flags, filter);
1467
+ }
1468
+
1469
+ void PrintAST::printSingleDepthOfGenericSignature (
1470
+ TypeArrayView<GenericTypeParamType> genericParams,
1471
+ ArrayRef<Requirement> requirements, bool &isFirstReq, unsigned flags,
1472
+ llvm::function_ref<bool (const Requirement &)> filter) {
1459
1473
bool printParams = (flags & PrintParams);
1460
1474
bool printRequirements = (flags & PrintRequirements);
1461
1475
printRequirements &= Options.PrintGenericRequirements ;
@@ -1502,7 +1516,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
1502
1516
}
1503
1517
1504
1518
if (printRequirements || printInherited) {
1505
- bool isFirstReq = true ;
1506
1519
for (const auto &req : requirements) {
1507
1520
if (!filter (req))
1508
1521
continue ;
@@ -1564,9 +1577,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
1564
1577
}
1565
1578
} else {
1566
1579
Printer.callPrintStructurePre (PrintStructureKind::GenericRequirement);
1567
-
1568
- // We don't substitute type for the printed requirement so that the
1569
- // printed requirement agrees with separately reported generic parameters.
1570
1580
printRequirement (req);
1571
1581
Printer.printStructurePost (PrintStructureKind::GenericRequirement);
1572
1582
}
@@ -1578,7 +1588,7 @@ void PrintAST::printSingleDepthOfGenericSignature(
1578
1588
}
1579
1589
1580
1590
void PrintAST::printRequirement (const Requirement &req) {
1581
- printType (req.getFirstType ());
1591
+ printTransformedType (req.getFirstType ());
1582
1592
switch (req.getKind ()) {
1583
1593
case RequirementKind::Layout:
1584
1594
Printer << " : " ;
@@ -1592,7 +1602,7 @@ void PrintAST::printRequirement(const Requirement &req) {
1592
1602
Printer << " == " ;
1593
1603
break ;
1594
1604
}
1595
- printType (req.getSecondType ());
1605
+ printTransformedType (req.getSecondType ());
1596
1606
}
1597
1607
1598
1608
bool PrintAST::shouldPrintPattern (const Pattern *P) {
@@ -2183,16 +2193,78 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
2183
2193
Ty->print (Printer, Options);
2184
2194
}
2185
2195
2196
+
2186
2197
void PrintAST::printSynthesizedExtension (Type ExtendedType,
2187
2198
ExtensionDecl *ExtDecl) {
2199
+
2200
+ auto printRequirementsFrom = [&](ExtensionDecl *ED, bool &IsFirst) {
2201
+ auto Sig = ED->getGenericSignature ();
2202
+ printSingleDepthOfGenericSignature (Sig->getGenericParams (),
2203
+ Sig->getRequirements (),
2204
+ IsFirst, PrintRequirements,
2205
+ [](const Requirement &Req){
2206
+ return true ;
2207
+ });
2208
+ };
2209
+
2210
+ auto printCombinedRequirementsIfNeeded = [&]() -> bool {
2211
+ if (!Options.TransformContext ||
2212
+ !Options.TransformContext ->isPrintingSynthesizedExtension ())
2213
+ return false ;
2214
+
2215
+ // Combined requirements only needed if the transform context is an enabling
2216
+ // extension of the protocol rather than a nominal (which can't have
2217
+ // constraints of its own).
2218
+ ExtensionDecl *Target = dyn_cast<ExtensionDecl>(
2219
+ Options.TransformContext ->getDecl ().getAsDecl ());
2220
+ if (!Target || Target == ExtDecl)
2221
+ return false ;
2222
+
2223
+ bool IsFirst = true ;
2224
+ if (ExtDecl->isConstrainedExtension ()) {
2225
+ printRequirementsFrom (ExtDecl, IsFirst);
2226
+ }
2227
+ if (Target->isConstrainedExtension ()) {
2228
+ if (auto *NTD = Target->getExtendedNominal ()) {
2229
+ // Update the current decl and type transform for Target rather than
2230
+ // ExtDecl.
2231
+ PrintOptions Adjusted = Options;
2232
+ Adjusted.initForSynthesizedExtension (NTD);
2233
+ llvm::SaveAndRestore<Decl*> TempCurrent (Current, NTD);
2234
+ llvm::SaveAndRestore<PrintOptions> TempOptions (Options, Adjusted);
2235
+ printRequirementsFrom (Target, IsFirst);
2236
+ }
2237
+ }
2238
+ return true ;
2239
+ };
2240
+
2241
+
2188
2242
if (Options.BracketOptions .shouldOpenExtension (ExtDecl)) {
2189
2243
printDocumentationComment (ExtDecl);
2190
2244
printAttributes (ExtDecl);
2191
2245
Printer << tok::kw_extension << " " ;
2192
2246
2193
2247
printExtendedTypeName (ExtendedType, Printer, Options);
2194
2248
printInherited (ExtDecl);
2195
- printDeclGenericRequirements (ExtDecl);
2249
+
2250
+ // We may need to combine requirements from ExtDecl (which has the members
2251
+ // to print) and the TransformContexts' decl if it is an enabling extension
2252
+ // of the base NominalDecl (which can have its own requirements) rather than
2253
+ // base NominalDecl itself (which can't). E.g:
2254
+ //
2255
+ // protocol Foo {}
2256
+ // extension Foo where <requirments from ExtDecl> { ... }
2257
+ // struct Bar {}
2258
+ // extension Bar: Foo where <requirments from TransformContext> { ... }
2259
+ //
2260
+ // should produce a synthesized extension of Bar with both sets of
2261
+ // requirments:
2262
+ //
2263
+ // extension Bar where <requirments from ExtDecl+TransformContext { ... }
2264
+ //
2265
+ if (!printCombinedRequirementsIfNeeded ())
2266
+ printDeclGenericRequirements (ExtDecl);
2267
+
2196
2268
}
2197
2269
if (Options.TypeDefinitions ) {
2198
2270
printMembersOfDecl (ExtDecl, false ,
0 commit comments