@@ -210,45 +210,109 @@ static Type inferFunctionBuilderType(ValueDecl *decl) {
210
210
lookupDecl = accessor->getStorage ();
211
211
}
212
212
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
-
222
213
// Find all of the potentially inferred function builder types.
223
214
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
+
226
229
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 ;
234
230
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
+ }
238
242
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
+ }
242
251
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 ();
246
256
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;
250
265
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);
252
316
}
253
317
}
254
318
@@ -274,7 +338,8 @@ static Type inferFunctionBuilderType(ValueDecl *decl) {
274
338
decl->diagnose (
275
339
diag::function_builder_infer_pick_specific,
276
340
match.functionBuilderType ,
277
- match.conformance ->getProtocol ()->getName ())
341
+ static_cast <unsigned >(match.kind ),
342
+ match.getSourceName ())
278
343
.fixItInsert (
279
344
lookupDecl->getAttributeInsertionLoc (false ),
280
345
" @" + match.functionBuilderType .getString () + " " );
0 commit comments