@@ -215,7 +215,21 @@ static Type inferResultBuilderType(ValueDecl *decl) {
215
215
}
216
216
}
217
217
218
+ // Below is a list of supported inference sources (in relation to the function
219
+ // in question), followed by a list of inference rules.
220
+ //
221
+ // (a): Its dynamically replaced function.
222
+ // (b): Protocol requirements that it witnesses.
223
+ // (c): Protocol requirements that its dynamically replaced function
224
+ // witnesses.
225
+ //
226
+ // (r1): (a) and (b) are always attempted.
227
+ // (r2): (c) is attempted only if (a) has no result builder.
228
+
218
229
auto *dc = decl->getDeclContext ();
230
+
231
+ // Neither of the aforementioned inference sources apply to a protocol
232
+ // requirement.
219
233
if (isa<ProtocolDecl>(dc)) {
220
234
return Type ();
221
235
}
@@ -225,6 +239,29 @@ static Type inferResultBuilderType(ValueDecl *decl) {
225
239
return Type ();
226
240
}
227
241
242
+ // A potentially inferred result builder will not be used to transform
243
+ // the body in the following cases:
244
+ // - The function has no body.
245
+ // - The function was deserialized (has no parent source file) and, thus,
246
+ // is already type-checked.
247
+ // - The body has an explicit 'return' statement, which disables the result
248
+ // builder transform.
249
+ //
250
+ // In these cases, inference can be skipped as an optimization.
251
+ //
252
+ // To demostrate that skipping inference here will not affect result builder
253
+ // inference for other functions, suppose that the function at hand ('x') is
254
+ // an inference source for another function ('y'). Since 'x' is not a protocol
255
+ // requirement, the only inference source it can assume is (a). Consequently,
256
+ // the only inference source available to 'x' is (b) because a dynamically
257
+ // replaced declaration cannot itself be '@_dynamicReplacement'.
258
+ //
259
+ // This implies that inferring a result builder for 'x' is equivalent to
260
+ // attempting (b) for 'x', which in turn is equivalent to attempting (c) for
261
+ // 'y'. Now, recall that 'x' is (a) for 'y'. According to rule (r2), skipping
262
+ // inference for 'x' will cause (c) to be attempted for 'y'. We see that
263
+ // the result of inferring for 'x' will be considered when inferring for 'y'
264
+ // either way.
228
265
if (!funcDecl->hasBody () || !dc->getParentSourceFile () ||
229
266
!TypeChecker::findReturnStatements (funcDecl).empty ()) {
230
267
return Type ();
0 commit comments