Skip to content

Conversation

@asl
Copy link
Contributor

@asl asl commented Nov 6, 2025

This is a proof-of-concept PR adding AST representation for coroutines

Further background at https://forums.swift.org/t/pitch-yield-once-functions-first-class-coroutines/77081

@asl
Copy link
Contributor Author

asl commented Nov 6, 2025

@tkremenek @rjmccall Following discussions on LLVM Dev Meeting, this is a stripped-down version of #78508:

  • No autodiff-related parts
  • No silgen (besides the "standard" special path used for coroutine accessors)
  • Some other fixes for SIL optimizer is omitted

Essentially the PR contains AST-related bits for coroutine declarations and coroutine function types as well as required boilerplate for AST mangling, dumping, serialization, etc.

@xedin comments from the original PR were addressed as well.

@asl
Copy link
Contributor Author

asl commented Nov 6, 2025

Please test with following pull request: swiftlang/llvm-project#11396
@swift-ci please test

@asl asl force-pushed the coro-ast-no-diff branch from 8805213 to 29ab221 Compare November 13, 2025 07:01
@asl
Copy link
Contributor Author

asl commented Nov 13, 2025

Please test with following pull request: swiftlang/llvm-project#11396
@swift-ci please test

@asl asl force-pushed the coro-ast-no-diff branch from 29ab221 to 28dadc4 Compare November 13, 2025 20:34
@asl
Copy link
Contributor Author

asl commented Nov 13, 2025

Please test with following pull request: swiftlang/llvm-project#11396
@swift-ci please test

@asl
Copy link
Contributor Author

asl commented Nov 14, 2025

Please test with following pull request: swiftlang/llvm-project#11396
@swift-ci please test windows platform

@asl asl force-pushed the coro-ast-no-diff branch from 28dadc4 to d5b8b73 Compare January 5, 2026 22:12
@asl asl requested a review from ktoso as a code owner January 5, 2026 22:12
@asl
Copy link
Contributor Author

asl commented Jan 5, 2026

swiftlang/swift-syntax#3225
@swift-ci please test

@asl
Copy link
Contributor Author

asl commented Jan 5, 2026

@slavapestov @rjmccall

The updated PR contains the support for yields w/o dedicated yield result type (I added them on top of the previous attempts to show the approach).

Things to note:

  1. There are no silgen changes here (as we discussed), though I have ported them separately and verified that removing special path for coroutine accessors and treating them as "ordinary coroutines" does not lead to any test breakage
  2. Function types support multiple yields (there was some initial boilerplate for this there), but I decided to postpone decision how we'd represent multiple yields for declarations (similar to error types), so declarations only support a single yield for now.
  3. It turned out that swift syntax parser treats function result arrow as a part of result clause, so to minimize amount of changes I decided to use for yields the syntax similar to the throws, so the yielded type uses contextual yields keyword that (if present) should be after after specifiers like throws or async
  4. Function type construction always requires yield types to be passed (even if empty), so they won't forgotten by accident. Though, the default implementation w/o yields could be added (I left it commented out for now)
  5. Everything is hidden behind dedicated experimental flag

Please let me know if there is something that should be changed / done differently in this approach.

@asl asl requested a review from rjmccall January 5, 2026 22:25
@asl asl force-pushed the coro-ast-no-diff branch from d5b8b73 to e336b6a Compare January 5, 2026 22:37
@asl
Copy link
Contributor Author

asl commented Jan 5, 2026

swiftlang/swift-syntax#3225
@swift-ci please test

@asl
Copy link
Contributor Author

asl commented Jan 6, 2026

@asl asl force-pushed the coro-ast-no-diff branch from e336b6a to 1c28062 Compare January 6, 2026 20:28
@asl
Copy link
Contributor Author

asl commented Jan 6, 2026

@asl
Copy link
Contributor Author

asl commented Jan 7, 2026

swiftlang/swift-syntax#3225 swiftlang/llvm-project#12064
@swift-ci please test macos platform

@asl
Copy link
Contributor Author

asl commented Jan 8, 2026

Looks like main is broken:

[2026-01-08T05:03:21.576Z] /Users/ec2-user/jenkins/workspace/swift-PR-macos/branch-main/swift/stdlib/public/core/StaticPrint.swift:866:29: error: expression uses unsafe constructs but is not marked with 'unsafe' [#]8;;https://docs.swift.org/compiler/documentation/diagnostics/strict-memory-safety\StrictMemorySafety]8;;\]
[2026-01-08T05:03:21.576Z] 864 |   let argumentClosures = message.interpolation.arguments.argumentClosures
[2026-01-08T05:03:21.576Z] 865 |   if Bool(_builtinBooleanLiteral: Builtin.ifdef_SWIFT_STDLIB_PRINT_DISABLED()) { return }
[2026-01-08T05:03:21.576Z] 866 |   let formatStringPointer = _getGlobalStringTablePointer(formatString)
[2026-01-08T05:03:21.576Z]     |                             |- error: expression uses unsafe constructs but is not marked with 'unsafe' [#]8;;https://docs.swift.org/compiler/documentation/diagnostics/strict-memory-safety\StrictMemorySafety]8;;\]
[2026-01-08T05:03:21.576Z]     |                             `- note: reference to global function '_getGlobalStringTablePointer' involves unsafe type 'UnsafePointer<CChar>' (aka 'UnsafePointer<Int8>')
[2026-01-08T05:03:21.576Z] 867 |   unsafe constant_vprintf_backend(
[2026-01-08T05:03:21.576Z] 868 |     fmt: formatStringPointer,
[2026-01-08T05:03:21.576Z] 
[2026-01-08T05:03:21.576Z] [#StrictMemorySafety]: <https://docs.swift.org/compiler/documentation/diagnostics/strict-memory-safety>
[2026-01-08T05:03:21.576Z] ninja: build stopped: subcommand failed.
[2026-01-08T05:03:21.576Z] ERROR: command `['env', '/usr/local/bin/cmake', '--build', '/Users/ec2-user/jenkins/workspace/swift-PR-macos/branch-main/build/buildbot_incremental/minimalstdlib-macosx-x86_64', '--config', 

@asl
Copy link
Contributor Author

asl commented Jan 8, 2026

swiftlang/swift-syntax#3225 swiftlang/llvm-project#12064
@swift-ci please test macos platform

Copy link
Contributor

@rjmccall rjmccall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just worrying about the AST part of this is fine for now, yeah. This seems like good progress.

HasSendingResult = 0x00000010U,

// Values if we have any yields
IsCoroutine = 0x00000020U,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need runtime metadata support? I don't think there's anything wrong with the code you're adding here, but I don't know if I'm happy about baking ABI support into the runtime for a feature we haven't actually added to the language.

Here (and many other places), I would like to avoid baking in that "coroutine" means this specific kind of coroutine. We do have other coroutine-like features, and I think we will probably add more. "YieldOnceCoroutine" is unambiguous.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, just to clarify – in other places you'd also want to have, say FunctionType::isYieldOnceCoroutine()? This looks different from e.g. SIL level when SILFunctionType::isCoroutine() means any coroutine (being it yield_once or yield_many).


public:
/// 'Constructor' Factory Function
#if 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor residue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, no. As I mentioned, I have not decided whether to keep or not yield-less ctors. As one one hand they are less verbose, but on other hand make it easy to forget about yields leading to subtle unintended differences

}

CanFunctionType substGenericArgs(SubstitutionMap subs) const;
#if 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Out << "\n";
abort();
}
if (FT->hasExtInfo() && FT->isCoroutine()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (FT->hasExtInfo() && FT->isCoroutine()) {
if (FT->isCoroutine()) {

_label("operation",
_sending(_function(_async(_throws(_thick)), _typeparam(0),
_parameters())))),
_parameters(), _yields())))),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to figure out a way to not need a builder for the yields when we don't have any.

FunctionType::ExtInfo info;
auto innerFunction =
FunctionType::get(params, linearFnResultGen.build(builder), info);
FunctionType::get(params, {}, linearFnResultGen.build(builder), info);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that we need this change in a million places. It was probably really nice for writing this patch that you had to fix a bunch of generic places to propagate and handle yields, but now that that's done, I wonder if we shouldn't just have a factory that defaults to not having any yields.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's exactly what I mentioned above. I do not know :) I'm worrying that the caller might forget about yields and it might lead to dropping yields should they present during various things here and there

@asl asl force-pushed the coro-ast-no-diff branch from 1c28062 to 4cdca9e Compare January 14, 2026 20:51
@asl
Copy link
Contributor Author

asl commented Jan 14, 2026

@swift-ci please test

@asl
Copy link
Contributor Author

asl commented Jan 15, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants