@@ -942,6 +942,8 @@ class ResultBuilderTransform
942942 return castToStmt<BraceStmt>(newBody.get ());
943943 }
944944
945+ VarDecl *getBuilderSelf () const { return builder.getBuilderSelf (); }
946+
945947protected:
946948 NullablePtr<Stmt> failTransform (UnsupportedElt unsupported) {
947949 recordUnsupported (unsupported);
@@ -2426,6 +2428,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
24262428 Type bodyResultType,
24272429 ConstraintKind bodyResultConstraintKind,
24282430 ConstraintLocatorBuilder locator) {
2431+ builderType = simplifyType (builderType);
24292432 auto builder = builderType->getAnyNominal ();
24302433 assert (builder && " Bad result builder type" );
24312434 assert (builder->getAttrs ().hasAttribute <ResultBuilderAttr>());
@@ -2477,58 +2480,72 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
24772480 return None;
24782481 }
24792482
2480- if (Context.TypeCheckerOpts .ResultBuilderASTTransform ) {
2481- ResultBuilderTransform transform (*this , fn.getAsDeclContext (), builderType,
2482- bodyResultType);
2483- auto *body = transform.apply (fn.getBody ());
2483+ if (Context.LangOpts .hasFeature (Feature::ResultBuilderASTTransform)) {
2484+ auto transformedBody = getBuilderTransformedBody (fn, builder);
2485+ // If this builder transform has not yet been applied to this function,
2486+ // let's do it and cache the result.
2487+ if (!transformedBody) {
2488+ ResultBuilderTransform transform (*this , fn.getAsDeclContext (),
2489+ builderType, bodyResultType);
2490+ auto *body = transform.apply (fn.getBody ());
24842491
2485- if (auto unsupported = transform.getUnsupportedElement ()) {
2486- assert (!body);
2492+ if (auto unsupported = transform.getUnsupportedElement ()) {
2493+ assert (!body);
24872494
2488- // If we aren't supposed to attempt fixes, fail.
2489- if (!shouldAttemptFixes ()) {
2490- return getTypeMatchFailure (locator);
2491- }
2495+ // If we aren't supposed to attempt fixes, fail.
2496+ if (!shouldAttemptFixes ()) {
2497+ return getTypeMatchFailure (locator);
2498+ }
24922499
2493- // If we're solving for code completion and the body contains the code
2494- // completion location, skipping it won't get us to a useful solution so
2495- // just bail.
2496- if (isForCodeCompletion () && containsCodeCompletionLoc (fn.getBody ())) {
2497- return getTypeMatchFailure (locator);
2498- }
2500+ // If we're solving for code completion and the body contains the code
2501+ // completion location, skipping it won't get us to a useful solution so
2502+ // just bail.
2503+ if (isForCodeCompletion () && containsCodeCompletionLoc (fn.getBody ())) {
2504+ return getTypeMatchFailure (locator);
2505+ }
24992506
2500- // Record the first unhandled construct as a fix.
2501- if (recordFix (SkipUnhandledConstructInResultBuilder::create (
2502- *this , unsupported, builder, getConstraintLocator (locator)))) {
2503- return getTypeMatchFailure (locator);
2504- }
2507+ // Record the first unhandled construct as a fix.
2508+ if (recordFix (SkipUnhandledConstructInResultBuilder::create (
2509+ *this , unsupported, builder, getConstraintLocator (locator)))) {
2510+ return getTypeMatchFailure (locator);
2511+ }
25052512
2506- if (auto *closure = getAsExpr<ClosureExpr>(fn.getAbstractClosureExpr ())) {
2507- auto closureTy = getClosureType (closure);
2508- simplifyType (closureTy).visit ([&](Type componentTy) {
2509- if (auto *typeVar = componentTy->getAs <TypeVariableType>()) {
2510- assignFixedType (typeVar,
2511- PlaceholderType::get (getASTContext (), typeVar));
2512- }
2513- });
2513+ if (auto *closure =
2514+ getAsExpr<ClosureExpr>(fn.getAbstractClosureExpr ())) {
2515+ auto closureTy = getClosureType (closure);
2516+ simplifyType (closureTy).visit ([&](Type componentTy) {
2517+ if (auto *typeVar = componentTy->getAs <TypeVariableType>()) {
2518+ assignFixedType (typeVar,
2519+ PlaceholderType::get (getASTContext (), typeVar));
2520+ }
2521+ });
2522+ }
2523+
2524+ return getTypeMatchSuccess ();
25142525 }
25152526
2516- return getTypeMatchSuccess ();
2527+ transformedBody = std::make_pair (transform.getBuilderSelf (), body);
2528+ // Record the transformation so it could be re-used if needed.
2529+ setBuilderTransformedBody (fn, builder, transformedBody->first ,
2530+ transformedBody->second );
25172531 }
25182532
2533+ // Set the type of `$__builderSelf` variable before constraint generation.
2534+ setType (transformedBody->first , MetatypeType::get (builderType));
2535+
25192536 if (isDebugMode ()) {
25202537 auto &log = llvm::errs ();
25212538 auto indent = solverState ? solverState->depth * 2 : 0 ;
25222539 log.indent (indent) << " ------- Transfomed Body -------\n " ;
2523- body ->dump (log);
2540+ transformedBody-> second ->dump (log);
25242541 log << ' \n ' ;
25252542 }
25262543
25272544 AppliedBuilderTransform transformInfo;
25282545
25292546 transformInfo.builderType = builderType;
25302547 transformInfo.bodyResultType = bodyResultType;
2531- transformInfo.transformedBody = body ;
2548+ transformInfo.transformedBody = transformedBody-> second ;
25322549
25332550 // Record the transformation.
25342551 assert (
@@ -2541,7 +2558,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
25412558 resultBuilderTransformed.insert (
25422559 std::make_pair (fn, std::move (transformInfo)));
25432560
2544- if (generateConstraints (fn, body ))
2561+ if (generateConstraints (fn, transformInfo. transformedBody . get () ))
25452562 return getTypeMatchFailure (locator);
25462563
25472564 return getTypeMatchSuccess ();
0 commit comments