@@ -210,44 +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 conformances = evaluateOrDefault (
218- dc->getASTContext ().evaluator ,
219- LookupAllConformancesInContextRequest{dc}, { });
220-
221213 // Find all of the potentially inferred function builder types.
222214 struct Match {
223- ProtocolConformance *conformance;
224- 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+
225229 Type functionBuilderType;
226- };
227- SmallVector<Match, 2 > matches;
228- for (auto conformance : conformances) {
229- auto protocol = conformance->getProtocol ();
230- for (auto found : protocol->lookupDirect (lookupDecl->getName ())) {
231- if (!isa<ProtocolDecl>(found->getDeclContext ()))
232- continue ;
233230
234- auto requirement = dyn_cast<ValueDecl>(found);
235- if (!requirement)
236- 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+ }
237242
238- Type functionBuilderType = requirement->getFunctionBuilderType ();
239- if (!functionBuilderType)
240- 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+ }
241251
242- auto witness = conformance->getWitnessDecl (requirement);
243- if (witness != lookupDecl)
244- continue ;
252+ DeclName getSourceName () const {
253+ switch (kind) {
254+ case Conformance:
255+ return conformanceMatch.conformance ->getProtocol ()->getName ();
245256
246- // Substitute into the function builder type.
247- auto subs = conformance->getSubstitutions (decl->getModuleContext ());
248- 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;
249265
250- 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{dc}, { });
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);
251316 }
252317 }
253318
@@ -273,7 +338,8 @@ static Type inferFunctionBuilderType(ValueDecl *decl) {
273338 decl->diagnose (
274339 diag::function_builder_infer_pick_specific,
275340 match.functionBuilderType ,
276- match.conformance ->getProtocol ()->getName ())
341+ static_cast <unsigned >(match.kind ),
342+ match.getSourceName ())
277343 .fixItInsert (
278344 lookupDecl->getAttributeInsertionLoc (false ),
279345 " @" + match.functionBuilderType .getString () + " " );
0 commit comments