@@ -71,10 +71,6 @@ class BuilderClosureVisitor
7171
7272 ResultBuilder builder;
7373
74- // / The variable used as a base for all `build*` operations added
75- // / by this transform.
76- VarDecl *builderVar = nullptr ;
77-
7874 SkipUnhandledConstructInResultBuilder::UnhandledNode unhandledNode;
7975
8076 // / Whether an error occurred during application of the builder closure,
@@ -96,27 +92,7 @@ class BuilderClosureVisitor
9692 if (!cs)
9793 return nullptr ;
9894
99- SmallVector<Argument, 4 > args;
100- for (auto i : indices (argExprs)) {
101- auto *expr = argExprs[i];
102- auto label = argLabels.empty () ? Identifier () : argLabels[i];
103- auto labelLoc = argLabels.empty () ? SourceLoc () : expr->getStartLoc ();
104- args.emplace_back (labelLoc, label, expr);
105- }
106-
107- auto *baseExpr = new (ctx) DeclRefExpr ({builderVar}, DeclNameLoc (loc),
108- /* isImplicit=*/ true );
109-
110- auto memberRef = new (ctx) UnresolvedDotExpr (
111- baseExpr, loc, DeclNameRef (fnName), DeclNameLoc (loc),
112- /* implicit=*/ true );
113- memberRef->setFunctionRefKind (FunctionRefKind::SingleApply);
114-
115- auto openLoc = args.empty () ? loc : argExprs.front ()->getStartLoc ();
116- auto closeLoc = args.empty () ? loc : argExprs.back ()->getEndLoc ();
117-
118- auto *argList = ArgumentList::createImplicit (ctx, openLoc, args, closeLoc);
119- return CallExpr::createImplicit (ctx, memberRef, argList);
95+ return builder.buildCall (loc, fnName, argExprs, argLabels);
12096 }
12197
12298 // / Build an implicit variable in this context.
@@ -175,20 +151,9 @@ class BuilderClosureVisitor
175151public:
176152 BuilderClosureVisitor (ASTContext &ctx, ConstraintSystem *cs, DeclContext *dc,
177153 Type builderType, Type bodyResultType)
178- : cs(cs), dc(dc), ctx(ctx),
179- builder (dc, cs ? cs->simplifyType (builderType) : builderType) {
154+ : cs(cs), dc(dc), ctx(ctx), builder(cs, dc, builderType) {
180155 applied.builderType = builder.getType ();
181156 applied.bodyResultType = bodyResultType;
182-
183- // If we are about to generate constraints, let's establish builder
184- // variable for the base of `build*` calls.
185- if (cs) {
186- builderVar = new (ctx) VarDecl (
187- /* isStatic=*/ false , VarDecl::Introducer::Let,
188- /* nameLoc=*/ SourceLoc (), ctx.Id_builderSelf , dc);
189- builderVar->setImplicit ();
190- cs->setType (builderVar, MetatypeType::get (builder.getType ()));
191- }
192157 }
193158
194159 // / Apply the builder transform to the given statement.
@@ -2198,6 +2163,26 @@ void swift::printResultBuilderBuildFunction(
21982163 }
21992164}
22002165
2166+ ResultBuilder::ResultBuilder (ConstraintSystem *CS, DeclContext *DC,
2167+ Type builderType)
2168+ : DC(DC), BuilderType(CS ? CS->simplifyType (builderType) : builderType) {
2169+ auto &ctx = DC->getASTContext ();
2170+ // Use buildOptional(_:) if available, otherwise fall back to buildIf
2171+ // when available.
2172+ BuildOptionalId =
2173+ (supports (ctx.Id_buildOptional ) || !supports (ctx.Id_buildIf ))
2174+ ? ctx.Id_buildOptional
2175+ : ctx.Id_buildIf ;
2176+
2177+ if (CS) {
2178+ BuilderSelf = new (ctx) VarDecl (
2179+ /* isStatic=*/ false , VarDecl::Introducer::Let,
2180+ /* nameLoc=*/ SourceLoc (), ctx.Id_builderSelf , DC);
2181+ BuilderSelf->setImplicit ();
2182+ CS->setType (BuilderSelf, MetatypeType::get (BuilderType));
2183+ }
2184+ }
2185+
22012186bool ResultBuilder::supports (Identifier fnBaseName,
22022187 ArrayRef<Identifier> argLabels,
22032188 bool checkAvailability) {
@@ -2211,3 +2196,33 @@ bool ResultBuilder::supports(Identifier fnBaseName,
22112196 BuilderType, DC, fnBaseName, argLabels, /* allResults*/ {},
22122197 checkAvailability);
22132198}
2199+
2200+ Expr *ResultBuilder::buildCall (SourceLoc loc, Identifier fnName,
2201+ ArrayRef<Expr *> argExprs,
2202+ ArrayRef<Identifier> argLabels) const {
2203+ assert (BuilderSelf);
2204+
2205+ auto &ctx = DC->getASTContext ();
2206+
2207+ SmallVector<Argument, 4 > args;
2208+ for (auto i : indices (argExprs)) {
2209+ auto *expr = argExprs[i];
2210+ auto label = argLabels.empty () ? Identifier () : argLabels[i];
2211+ auto labelLoc = argLabels.empty () ? SourceLoc () : expr->getStartLoc ();
2212+ args.emplace_back (labelLoc, label, expr);
2213+ }
2214+
2215+ auto *baseExpr = new (ctx) DeclRefExpr ({BuilderSelf}, DeclNameLoc (loc),
2216+ /* isImplicit=*/ true );
2217+
2218+ auto memberRef = new (ctx)
2219+ UnresolvedDotExpr (baseExpr, loc, DeclNameRef (fnName), DeclNameLoc (loc),
2220+ /* implicit=*/ true );
2221+ memberRef->setFunctionRefKind (FunctionRefKind::SingleApply);
2222+
2223+ auto openLoc = args.empty () ? loc : argExprs.front ()->getStartLoc ();
2224+ auto closeLoc = args.empty () ? loc : argExprs.back ()->getEndLoc ();
2225+
2226+ auto *argList = ArgumentList::createImplicit (ctx, openLoc, args, closeLoc);
2227+ return CallExpr::createImplicit (ctx, memberRef, argList);
2228+ }
0 commit comments