@@ -942,6 +942,8 @@ class ResultBuilderTransform
942
942
return castToStmt<BraceStmt>(newBody.get ());
943
943
}
944
944
945
+ VarDecl *getBuilderSelf () const { return builder.getBuilderSelf (); }
946
+
945
947
protected:
946
948
NullablePtr<Stmt> failTransform (UnsupportedElt unsupported) {
947
949
recordUnsupported (unsupported);
@@ -2426,6 +2428,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
2426
2428
Type bodyResultType,
2427
2429
ConstraintKind bodyResultConstraintKind,
2428
2430
ConstraintLocatorBuilder locator) {
2431
+ builderType = simplifyType (builderType);
2429
2432
auto builder = builderType->getAnyNominal ();
2430
2433
assert (builder && " Bad result builder type" );
2431
2434
assert (builder->getAttrs ().hasAttribute <ResultBuilderAttr>());
@@ -2477,58 +2480,72 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
2477
2480
return None;
2478
2481
}
2479
2482
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 ());
2484
2491
2485
- if (auto unsupported = transform.getUnsupportedElement ()) {
2486
- assert (!body);
2492
+ if (auto unsupported = transform.getUnsupportedElement ()) {
2493
+ assert (!body);
2487
2494
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
+ }
2492
2499
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
+ }
2499
2506
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
+ }
2505
2512
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 ();
2514
2525
}
2515
2526
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 );
2517
2531
}
2518
2532
2533
+ // Set the type of `$__builderSelf` variable before constraint generation.
2534
+ setType (transformedBody->first , MetatypeType::get (builderType));
2535
+
2519
2536
if (isDebugMode ()) {
2520
2537
auto &log = llvm::errs ();
2521
2538
auto indent = solverState ? solverState->depth * 2 : 0 ;
2522
2539
log.indent (indent) << " ------- Transfomed Body -------\n " ;
2523
- body ->dump (log);
2540
+ transformedBody-> second ->dump (log);
2524
2541
log << ' \n ' ;
2525
2542
}
2526
2543
2527
2544
AppliedBuilderTransform transformInfo;
2528
2545
2529
2546
transformInfo.builderType = builderType;
2530
2547
transformInfo.bodyResultType = bodyResultType;
2531
- transformInfo.transformedBody = body ;
2548
+ transformInfo.transformedBody = transformedBody-> second ;
2532
2549
2533
2550
// Record the transformation.
2534
2551
assert (
@@ -2541,7 +2558,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
2541
2558
resultBuilderTransformed.insert (
2542
2559
std::make_pair (fn, std::move (transformInfo)));
2543
2560
2544
- if (generateConstraints (fn, body ))
2561
+ if (generateConstraints (fn, transformInfo. transformedBody . get () ))
2545
2562
return getTypeMatchFailure (locator);
2546
2563
2547
2564
return getTypeMatchSuccess ();
0 commit comments