@@ -813,6 +813,10 @@ class PrintAST : public ASTVisitor<PrintAST> {
813813 TypeArrayView<GenericTypeParamType> genericParams,
814814 ArrayRef<Requirement> requirements, unsigned flags,
815815 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);
816820 void printRequirement (const Requirement &req);
817821
818822private:
@@ -872,7 +876,12 @@ class PrintAST : public ASTVisitor<PrintAST> {
872876 return false ; // not needed for the parser library.
873877 #endif
874878
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)
876885 return false ;
877886
878887 Decl *Old = Current;
@@ -890,10 +899,6 @@ class PrintAST : public ASTVisitor<PrintAST> {
890899
891900 SWIFT_DEFER { CurrentType = OldType; };
892901
893- bool Synthesize =
894- Options.TransformContext &&
895- Options.TransformContext ->isPrintingSynthesizedExtension () &&
896- isa<ExtensionDecl>(D);
897902 if (Synthesize) {
898903 Printer.setSynthesizedTarget (Options.TransformContext ->getDecl ());
899904 }
@@ -1456,6 +1461,15 @@ void PrintAST::printSingleDepthOfGenericSignature(
14561461 TypeArrayView<GenericTypeParamType> genericParams,
14571462 ArrayRef<Requirement> requirements, unsigned flags,
14581463 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) {
14591473 bool printParams = (flags & PrintParams);
14601474 bool printRequirements = (flags & PrintRequirements);
14611475 printRequirements &= Options.PrintGenericRequirements ;
@@ -1502,7 +1516,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
15021516 }
15031517
15041518 if (printRequirements || printInherited) {
1505- bool isFirstReq = true ;
15061519 for (const auto &req : requirements) {
15071520 if (!filter (req))
15081521 continue ;
@@ -1564,9 +1577,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
15641577 }
15651578 } else {
15661579 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.
15701580 printRequirement (req);
15711581 Printer.printStructurePost (PrintStructureKind::GenericRequirement);
15721582 }
@@ -1578,7 +1588,7 @@ void PrintAST::printSingleDepthOfGenericSignature(
15781588}
15791589
15801590void PrintAST::printRequirement (const Requirement &req) {
1581- printType (req.getFirstType ());
1591+ printTransformedType (req.getFirstType ());
15821592 switch (req.getKind ()) {
15831593 case RequirementKind::Layout:
15841594 Printer << " : " ;
@@ -1592,7 +1602,7 @@ void PrintAST::printRequirement(const Requirement &req) {
15921602 Printer << " == " ;
15931603 break ;
15941604 }
1595- printType (req.getSecondType ());
1605+ printTransformedType (req.getSecondType ());
15961606}
15971607
15981608bool PrintAST::shouldPrintPattern (const Pattern *P) {
@@ -2183,16 +2193,78 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
21832193 Ty->print (Printer, Options);
21842194}
21852195
2196+
21862197void PrintAST::printSynthesizedExtension (Type ExtendedType,
21872198 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+
21882242 if (Options.BracketOptions .shouldOpenExtension (ExtDecl)) {
21892243 printDocumentationComment (ExtDecl);
21902244 printAttributes (ExtDecl);
21912245 Printer << tok::kw_extension << " " ;
21922246
21932247 printExtendedTypeName (ExtendedType, Printer, Options);
21942248 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+
21962268 }
21972269 if (Options.TypeDefinitions ) {
21982270 printMembersOfDecl (ExtDecl, false ,
0 commit comments