@@ -210,45 +210,109 @@ static Type inferFunctionBuilderType(ValueDecl *decl) {
210210 lookupDecl = accessor->getStorage ();
211211 }
212212
213- // Determine all of the conformances within the same context as
214- // this declaration. If this declaration is a witness to any
215- // requirement within one of those protocols that has a function builder
216- // attached, use that function builder type.
217- auto idc = cast<IterableDeclContext>(dc->getAsDecl ());
218- auto conformances = evaluateOrDefault (
219- dc->getASTContext ().evaluator ,
220- LookupAllConformancesInContextRequest{idc}, { });
221-
222213 // Find all of the potentially inferred function builder types.
223214 struct Match {
224- ProtocolConformance *conformance;
225- ValueDecl *requirement;
215+ enum Kind {
216+ Conformance,
217+ DynamicReplacement,
218+ } kind;
219+
220+ union {
221+ struct {
222+ ProtocolConformance *conformance;
223+ ValueDecl *requirement;
224+ } conformanceMatch;
225+
226+ ValueDecl *dynamicReplacement;
227+ };
228+
226229 Type functionBuilderType;
227- };
228- SmallVector<Match, 2 > matches;
229- for (auto conformance : conformances) {
230- auto protocol = conformance->getProtocol ();
231- for (auto found : protocol->lookupDirect (lookupDecl->getName ())) {
232- if (!isa<ProtocolDecl>(found->getDeclContext ()))
233- continue ;
234230
235- auto requirement = dyn_cast<ValueDecl>(found);
236- if (!requirement)
237- continue ;
231+ static Match forConformance (
232+ ProtocolConformance *conformance,
233+ ValueDecl *requirement,
234+ Type functionBuilderType) {
235+ Match match;
236+ match.kind = Conformance;
237+ match.conformanceMatch .conformance = conformance;
238+ match.conformanceMatch .requirement = requirement;
239+ match.functionBuilderType = functionBuilderType;
240+ return match;
241+ }
238242
239- Type functionBuilderType = requirement->getFunctionBuilderType ();
240- if (!functionBuilderType)
241- continue ;
243+ static Match forDynamicReplacement (
244+ ValueDecl *dynamicReplacement, Type functionBuilderType) {
245+ Match match;
246+ match.kind = DynamicReplacement;
247+ match.dynamicReplacement = dynamicReplacement;
248+ match.functionBuilderType = functionBuilderType;
249+ return match;
250+ }
242251
243- auto witness = conformance->getWitnessDecl (requirement);
244- if (witness != lookupDecl)
245- continue ;
252+ DeclName getSourceName () const {
253+ switch (kind) {
254+ case Conformance:
255+ return conformanceMatch.conformance ->getProtocol ()->getName ();
246256
247- // Substitute into the function builder type.
248- auto subs = conformance->getSubstitutions (decl->getModuleContext ());
249- Type subFunctionBuilderType = functionBuilderType.subst (subs);
257+ case DynamicReplacement:
258+ return dynamicReplacement->getName ();
259+ }
260+ }
261+ };
262+
263+ // The set of matches from which we can infer function builder types.
264+ SmallVector<Match, 2 > matches;
250265
251- matches.push_back ({conformance, requirement, subFunctionBuilderType});
266+ // Determine all of the conformances within the same context as
267+ // this declaration. If this declaration is a witness to any
268+ // requirement within one of those protocols that has a function builder
269+ // attached, use that function builder type.
270+ auto addConformanceMatches = [&matches](ValueDecl *lookupDecl) {
271+ DeclContext *dc = lookupDecl->getDeclContext ();
272+ auto idc = cast<IterableDeclContext>(dc->getAsDecl ());
273+ auto conformances = evaluateOrDefault (
274+ dc->getASTContext ().evaluator ,
275+ LookupAllConformancesInContextRequest{idc}, { });
276+
277+ for (auto conformance : conformances) {
278+ auto protocol = conformance->getProtocol ();
279+ for (auto found : protocol->lookupDirect (lookupDecl->getName ())) {
280+ if (!isa<ProtocolDecl>(found->getDeclContext ()))
281+ continue ;
282+
283+ auto requirement = dyn_cast<ValueDecl>(found);
284+ if (!requirement)
285+ continue ;
286+
287+ Type functionBuilderType = requirement->getFunctionBuilderType ();
288+ if (!functionBuilderType)
289+ continue ;
290+
291+ auto witness = conformance->getWitnessDecl (requirement);
292+ if (witness != lookupDecl)
293+ continue ;
294+
295+ // Substitute into the function builder type.
296+ auto subs =
297+ conformance->getSubstitutions (lookupDecl->getModuleContext ());
298+ Type subFunctionBuilderType = functionBuilderType.subst (subs);
299+
300+ matches.push_back (
301+ Match::forConformance (
302+ conformance, requirement, subFunctionBuilderType));
303+ }
304+ }
305+ };
306+
307+ addConformanceMatches (lookupDecl);
308+
309+ // Look for function builder types inferred through dynamic replacements.
310+ if (auto replaced = lookupDecl->getDynamicallyReplacedDecl ()) {
311+ if (auto functionBuilderType = replaced->getFunctionBuilderType ()) {
312+ matches.push_back (
313+ Match::forDynamicReplacement (replaced, functionBuilderType));
314+ } else {
315+ addConformanceMatches (replaced);
252316 }
253317 }
254318
@@ -274,7 +338,8 @@ static Type inferFunctionBuilderType(ValueDecl *decl) {
274338 decl->diagnose (
275339 diag::function_builder_infer_pick_specific,
276340 match.functionBuilderType ,
277- match.conformance ->getProtocol ()->getName ())
341+ static_cast <unsigned >(match.kind ),
342+ match.getSourceName ())
278343 .fixItInsert (
279344 lookupDecl->getAttributeInsertionLoc (false ),
280345 " @" + match.functionBuilderType .getString () + " " );
0 commit comments