@@ -73,6 +73,10 @@ class BuilderClosureVisitor
7373 Identifier buildOptionalId;
7474 llvm::SmallDenseMap<DeclName, bool > supportedOps;
7575
76+ // / The variable used as a base for all `build*` operations added
77+ // / by this transform.
78+ VarDecl *builderVar = nullptr ;
79+
7680 SkipUnhandledConstructInResultBuilder::UnhandledNode unhandledNode;
7781
7882 // / Whether an error occurred during application of the builder closure,
@@ -94,32 +98,6 @@ class BuilderClosureVisitor
9498 if (!cs)
9599 return nullptr ;
96100
97- // FIXME: Setting a base on this expression is necessary in order
98- // to get diagnostics if something about this builder call fails,
99- // e.g. if there isn't a matching overload for `buildBlock`.
100- TypeExpr *typeExpr;
101- auto simplifiedTy = cs->simplifyType (builderType);
102- if (!simplifiedTy->hasTypeVariable ()) {
103- typeExpr = TypeExpr::createImplicitHack (loc, simplifiedTy, ctx);
104- } else if (auto *decl = simplifiedTy->getAnyGeneric ()) {
105- // HACK: If there's not enough information to completely resolve the
106- // builder type, but we have the base available to us, form an *explicit*
107- // TypeExpr pointing at it. We cannot form an implicit base without
108- // a fully-resolved concrete type. Really, whatever we put here has no
109- // bearing on the generated solution because we're going to use this node
110- // to stash the builder type and hand it back to the ambient
111- // constraint system.
112- typeExpr = TypeExpr::createForDecl (DeclNameLoc (loc), decl, dc);
113- } else {
114- // HACK: If there's not enough information in the constraint system,
115- // create a garbage base type to force it to diagnose
116- // this as an ambiguous expression.
117- // FIXME: We can also construct an UnresolvedMemberExpr here instead of
118- // an UnresolvedDotExpr and get a slightly better diagnostic.
119- typeExpr = TypeExpr::createImplicitHack (loc, ErrorType::get (ctx), ctx);
120- }
121- cs->setType (typeExpr, MetatypeType::get (builderType));
122-
123101 SmallVector<Argument, 4 > args;
124102 for (auto i : indices (argExprs)) {
125103 auto *expr = argExprs[i];
@@ -128,8 +106,11 @@ class BuilderClosureVisitor
128106 args.emplace_back (labelLoc, label, expr);
129107 }
130108
109+ auto *baseExpr = new (ctx) DeclRefExpr ({builderVar}, DeclNameLoc (loc),
110+ /* isImplicit=*/ true );
111+
131112 auto memberRef = new (ctx) UnresolvedDotExpr (
132- typeExpr , loc, DeclNameRef (fnName), DeclNameLoc (loc),
113+ baseExpr , loc, DeclNameRef (fnName), DeclNameLoc (loc),
133114 /* implicit=*/ true );
134115 memberRef->setFunctionRefKind (FunctionRefKind::SingleApply);
135116
@@ -223,6 +204,16 @@ class BuilderClosureVisitor
223204 buildOptionalId = ctx.Id_buildOptional ;
224205 else
225206 buildOptionalId = ctx.Id_buildIf ;
207+
208+ // If we are about to generate constraints, let's establish builder
209+ // variable for the base of `build*` calls.
210+ if (cs) {
211+ builderVar = new (ctx) VarDecl (
212+ /* isStatic=*/ false , VarDecl::Introducer::Let,
213+ /* nameLoc=*/ SourceLoc (), ctx.Id_builderSelf , dc);
214+ builderVar->setImplicit ();
215+ cs->setType (builderVar, MetatypeType::get (cs->simplifyType (builderType)));
216+ }
226217 }
227218
228219 // / Apply the builder transform to the given statement.
0 commit comments