@@ -215,7 +215,21 @@ static Type inferResultBuilderType(ValueDecl *decl) {
215215 }
216216 }
217217
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+
218229 auto *dc = decl->getDeclContext ();
230+
231+ // Neither of the aforementioned inference sources apply to a protocol
232+ // requirement.
219233 if (isa<ProtocolDecl>(dc)) {
220234 return Type ();
221235 }
@@ -225,6 +239,29 @@ static Type inferResultBuilderType(ValueDecl *decl) {
225239 return Type ();
226240 }
227241
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.
228265 if (!funcDecl->hasBody () || !dc->getParentSourceFile () ||
229266 !TypeChecker::findReturnStatements (funcDecl).empty ()) {
230267 return Type ();
0 commit comments