Skip to content

Asynchronous Catching Result initializer - #88465

Merged
ktoso merged 14 commits into
swiftlang:mainfrom
mattmassicotte:result-async-catching
Jun 1, 2026
Merged

Asynchronous Catching Result initializer#88465
ktoso merged 14 commits into
swiftlang:mainfrom
mattmassicotte:result-async-catching

Conversation

@mattmassicotte

@mattmassicotte mattmassicotte commented Apr 14, 2026

Copy link
Copy Markdown
Contributor
  • Explanation:

Implementation of an async catching initializer for Result as part of swiftlang/swift-evolution#3234

  • Scope:

Details in proposal.

  • Issues:

  • Original PRs:

  • Risk:

  • Testing:

I've added two tests to cover some of functionality that was being exercised for the synchronous cases. It seems sufficient to me, but I'd like feedback on this.

  • Reviewers:

Would love for @ktoso to have a peek before finalizing.

@mattmassicotte mattmassicotte changed the title WIP - initial API Asynchronous Catching Result initializer Apr 14, 2026
Comment thread stdlib/public/core/Result.swift Outdated
@mattmassicotte

Copy link
Copy Markdown
Contributor Author

Arg. The body of this new initializer implementation is currently crashing the compiler.

1.	Swift version 6.4-dev (LLVM a63c015618d6123, Swift 339e8bc4595f8ce)
2.	Compiling with effective version 5.10
3.	While evaluating request ASTLoweringRequest(Lowering AST to SIL for module Swift)
4.	While silgen visitDecl extension of Result (at /Users/matt/Developer/swift-project/swift/stdlib/public/core/Result.swift:341:1)
5.	While silgen emitValueConstructor SIL function "@$ss6ResultOsRi_zrlE8catchingAByxq_GxyYaq_YKYCXE_tYacfC".
 for 'init(catching:)' (at /Users/matt/Developer/swift-project/swift/stdlib/public/core/Result.swift:361:34)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000106832f0c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x0000000106830ee8 llvm::sys::RunSignalHandlers() + 172
2  swift-frontend           0x00000001068339b4 SignalHandler(int, __siginfo*, void*) + 308
3  libsystem_platform.dylib 0x000000018ec217a4 _sigtramp + 56
4  swift-frontend           0x00000001013e18c8 swift::SILType::getOpaqueIsolationType(swift::ASTContext const&) + 24
5  swift-frontend           0x00000001013e18c8 swift::SILType::getOpaqueIsolationType(swift::ASTContext const&) + 24
6  swift-frontend           0x0000000101086e68 swift::Lowering::SILGenFunction::emitActorInstanceIsolation(swift::SILLocation, swift::Lowering::ManagedValue, swift::CanType) + 64
7  swift-frontend           0x0000000101066b4c (anonymous namespace)::CallEmission::emitArgumentsForNormalApply(swift::Lowering::AbstractionPattern, swift::CanTypeWrapper<swift::SILFunctionType>, llvm::ArrayRef<swift::LifetimeDependenceInfo>, swift::ForeignInfo const&, llvm::SmallVectorImpl<swift::Lowering::ManagedValue>&, std::__1::optional<swift::SILLocation>&) + 1428
8  swift-frontend           0x0000000101051f0c (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) + 3732
9  swift-frontend           0x000000010104f53c swift::Lowering::SILGenFunction::emitApplyExpr(swift::ApplyExpr*, swift::Lowering::SGFContext) + 52
10 swift-frontend           0x00000001010aed24 swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*, swift::Lowering::Initialization*, std::__1::optional<swift::SILLocation>) + 472
11 swift-frontend           0x000000010101e02c swift::Lowering::ArgumentSource::forwardInto(swift::Lowering::SILGenFunction&, swift::Lowering::Initialization*) && + 160
12 swift-frontend           0x000000010101e7b8 swift::Lowering::ArgumentSource::forwardInto(swift::Lowering::SILGenFunction&, swift::Lowering::AbstractionPattern, swift::Lowering::Initialization*, swift::Lowering::TypeLowering const&) && + 164
13 swift-frontend           0x000000010104f010 emitEnumElementPayloads(swift::Lowering::SILGenFunction&, swift::SILLocation, swift::EnumElementDecl*, llvm::MutableArrayRef<swift::Lowering::ArgumentSource>, swift::Lowering::AbstractionPattern, swift::SILType, swift::Lowering::Initialization*) + 976
14 swift-frontend           0x0000000101068538 void llvm::function_ref<void (swift::SILValue)>::callback_fn<swift::Lowering::SILGenFunction::emitInjectEnum(swift::SILLocation, llvm::MutableArrayRef<swift::Lowering::ArgumentSource>, swift::SILType, swift::EnumElementDecl*, swift::Lowering::SGFContext)::$_2>(long, swift::SILValue) + 344
15 swift-frontend           0x0000000101077ad8 swift::Lowering::SILGenBuilder::bufferForExpr(swift::SILLocation, swift::SILType, swift::Lowering::TypeLowering const&, swift::Lowering::SGFContext, llvm::function_ref<void (swift::SILValue)>) + 252
16 swift-frontend           0x000000010104ea90 swift::Lowering::SILGenFunction::emitInjectEnum(swift::SILLocation, llvm::MutableArrayRef<swift::Lowering::ArgumentSource>, swift::SILType, swift::EnumElementDecl*, swift::Lowering::SGFContext) + 1040
17 swift-frontend           0x000000010105122c (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) + 436
18 swift-frontend           0x000000010104f53c swift::Lowering::SILGenFunction::emitApplyExpr(swift::ApplyExpr*, swift::Lowering::SGFContext) + 52
19 swift-frontend           0x00000001010aedf4 swift::Lowering::SILGenFunction::emitRValue(swift::Expr*, swift::Lowering::SGFContext) + 40
20 swift-frontend           0x00000001010fd468 swift::Lowering::SILGenFunction::emitAssignToLValue(swift::SILLocation, swift::Lowering::ArgumentSource&&, swift::Lowering::LValue&&) + 292
21 swift-frontend           0x00000001010c9140 (anonymous namespace)::RValueEmitter::visitAssignExpr(swift::AssignExpr*, swift::Lowering::SGFContext) + 892
22 swift-frontend           0x00000001010b2034 swift::Lowering::SILGenFunction::emitIgnoredExpr(swift::Expr*) + 1028
23 swift-frontend           0x0000000101147228 (anonymous namespace)::StmtEmitter::visitBraceStmt(swift::BraceStmt*) + 460
24 swift-frontend           0x00000001011435fc swift::ASTVisitor<(anonymous namespace)::StmtEmitter, void, void, void, void, void, void>::visit(swift::Stmt*) + 4988
25 swift-frontend           0x00000001011472a0 (anonymous namespace)::StmtEmitter::visitBraceStmt(swift::BraceStmt*) + 580
26 swift-frontend           0x0000000101142274 swift::Lowering::SILGenFunction::emitStmt(swift::Stmt*) + 24
27 swift-frontend           0x0000000101089ff8 swift::Lowering::SILGenFunction::emitValueConstructor(swift::ConstructorDecl*) + 6176
28 swift-frontend           0x000000010103d324 swift::Lowering::SILGenModule::emitFunctionDefinition(swift::SILDeclRef, swift::SILFunction*) + 5056
29 swift-frontend           0x000000010103e390 swift::Lowering::SILGenModule::emitOrDelayFunction(swift::SILDeclRef) + 256
30 swift-frontend           0x000000010103f4d4 swift::Lowering::SILGenModule::emitConstructor(swift::ConstructorDecl*) + 332
31 swift-frontend           0x0000000101156d98 swift::ASTVisitor<SILGenExtension, void, void, void, void, void, void>::visit(swift::Decl*) + 188
32 swift-frontend           0x0000000101153cf0 SILGenExtension::emitExtension(swift::ExtensionDecl*) + 156
33 swift-frontend           0x0000000101153c48 swift::Lowering::SILGenModule::visitExtensionDecl(swift::ExtensionDecl*) + 24
34 swift-frontend           0x0000000101040ff4 swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*) + 212
35 swift-frontend           0x00000001010415dc swift::ASTLoweringRequest::evaluate(swift::Evaluator&, swift::ASTLoweringDescriptor) const + 608
36 swift-frontend           0x0000000101141c88 swift::SimpleRequest<swift::ASTLoweringRequest, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>> (swift::ASTLoweringDescriptor), (swift::RequestFlags)17>::evaluateRequest(swift::ASTLoweringRequest const&, swift::Evaluator&) + 136
37 swift-frontend           0x0000000101045270 swift::ASTLoweringRequest::OutputType swift::Evaluator::getResultUncached<swift::ASTLoweringRequest, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'()>(swift::ASTLoweringRequest const&, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'())::'lambda'()::operator()() const + 84
38 swift-frontend           0x000000010104518c swift::ASTLoweringRequest::OutputType swift::Evaluator::getResultUncached<swift::ASTLoweringRequest, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'()>(swift::ASTLoweringRequest const&, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'()) + 316
39 swift-frontend           0x00000001010418a8 swift::performASTLowering(swift::ModuleDecl*, swift::Lowering::TypeConverter&, swift::SILOptions const&, swift::IRGenOptions const*) + 120
40 swift-frontend           0x00000001009b3900 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*, llvm::ArrayRef<char const*>) + 1312
41 swift-frontend           0x00000001009c401c withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
42 swift-frontend           0x00000001009b720c performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*, llvm::ArrayRef<char const*>) + 568
43 swift-frontend           0x00000001009b4d44 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2172
44 swift-frontend           0x00000001006e5ad4 swift::mainEntry(int, char const**) + 1864
45 dyld                     0x000000018e85bda4 start + 6992

@mattmassicotte
mattmassicotte force-pushed the result-async-catching branch from ece048f to 339e8bc Compare April 15, 2026 17:51
@mattmassicotte

Copy link
Copy Markdown
Contributor Author

I've narrowed the crash down slightly. Just making the existing initializer async causes the crash...

@mattmassicotte

Copy link
Copy Markdown
Contributor Author

The following reduced example, included in Result.swift also results in the same crash. It's something about the async init.

enum PhonyResult<Success, Failure: Error> {
  /// A success, storing a `Success` value.
  case success(Success)

  /// A failure, storing a `Failure` value.
  case failure(Failure)
}

extension PhonyResult {
  init(catching body: () throws(Failure) -> Success) async {
    do {
      self = .success(try body())
    } catch {
      self = .failure(error)
    }
  }
}

@mattmassicotte

Copy link
Copy Markdown
Contributor Author

Ok, this is now getting hard to believe. I have reduced this even further. Adding the following to the bottom of this same file produces the crash:

struct Wat {
  init() async {
  }
}

@ktoso ktoso self-assigned this Apr 15, 2026
@ktoso
ktoso self-requested a review April 15, 2026 21:41
@ktoso ktoso added the swift evolution pending discussion Flag → feature: A feature that has a Swift evolution proposal currently in review label Apr 15, 2026
@ktoso

ktoso commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

I'll have a look

@ktoso

ktoso commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso

ktoso commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

This may just be because this is in the core module which doesnt have any of the concurrency types -- move this extension into the concurrency module :)

Comment thread stdlib/public/core/Result.swift Outdated
@mattmassicotte

Copy link
Copy Markdown
Contributor Author

@swift-ci please smoke test

@mattmassicotte
mattmassicotte marked this pull request as ready for review April 16, 2026 14:58
@mattmassicotte
mattmassicotte requested a review from a team as a code owner April 16, 2026 14:58
@mattmassicotte
mattmassicotte force-pushed the result-async-catching branch from 4a36bce to c73c6a5 Compare April 16, 2026 17:43
@mattmassicotte

Copy link
Copy Markdown
Contributor Author

@swift-ci please smoke test macOS

@mattmassicotte

Copy link
Copy Markdown
Contributor Author

I'm having trouble understanding what is actually failing in CI...

@DougGregor

Copy link
Copy Markdown
Member

I'm having trouble understanding what is actually failing in CI...

Me too, it looks completely unrelated to your change. I'm going to kick off CI again

@DougGregor

Copy link
Copy Markdown
Member

@swift-ci please smoke test

@NotTheNHK

NotTheNHK commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Don’t forget to add the new file to the CMakeList file in the Runtimes/Core/Concurrency folder

Comment thread stdlib/public/Concurrency/Result+AsyncInit.swift Outdated
@ktoso

ktoso commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test macOS

@ktoso

ktoso commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

The extension is missing availability, I'll propose a fix.

Don't forget this comment from @NotTheNHK

Don’t forget to add the new file to the CMakeList file in the Runtimes/Core/Concurrency folder

Comment thread stdlib/public/Concurrency/Result+AsyncInit.swift
@ktoso

ktoso commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

Comment thread stdlib/public/Concurrency/Result+AsyncInit.swift Outdated

@ktoso ktoso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, just needs to get through evolution

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

I made a follow up issue about the wasm side of this -- #89155 @MaxDesiatov there's a few things going on here with ~Copyable and async... I'm not sure what's intended to be supported here on wasm already?

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

Okey so we can't just internal import without the rest of the files doing the same; let's do this separately.

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please test source compatibility

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

I prepared the 6.4 pick as well #89157

@mattmassicotte

Copy link
Copy Markdown
Contributor Author

Awesome thank you so much!

@ktoso

ktoso commented May 15, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please test windows

@MaxDesiatov

Copy link
Copy Markdown
Contributor

I'm not sure what's intended to be supported here on wasm already?

Everything is intended to be supported. I'm not aware of any limitations that could prevent this proposal from being supported on Wasm.

@ktoso

ktoso commented May 18, 2026

Copy link
Copy Markdown
Contributor

I see we need to look into it deeper then… I’ll catch up with you if I need any help with wasm then

Comment thread test/stdlib/Result.swift Outdated
Comment on lines +126 to +130
#if os(WASI)
// FIXME: https://github.com/swiftlang/swift/issues/89155
// wasi-wasm32 traps in Result<T, any Error>'s value-witness copy
// after returning from the new Result.init(catching:) async.
#else

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I really would like this exclusion not to end up in the final PR. This test possibly uncovered some runtime or stdlib bug, but I don't see why this should be temporarily excluded otherwise during development. IMO, fixing that bug, whatever that is, to enable it consistently on all platforms should be a pre-requisite before merging.

@ktoso ktoso May 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah I'll look into fixing this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The root cause and repro is tracked here, I'm looking into it #89320

Thanks for uncovering this bug!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems #89416 was merged so let's see if this passes now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Still failing on Wasm, I'll investigate

@ktoso
ktoso marked this pull request as draft May 21, 2026 12:53
@ktoso

ktoso commented May 21, 2026

Copy link
Copy Markdown
Contributor

Blocked on #89320

@ktoso

ktoso commented May 26, 2026

Copy link
Copy Markdown
Contributor

Depends on #89416

swiftlang#89416 was merged, so this should work now
@ktoso
ktoso marked this pull request as ready for review May 28, 2026 07:22
@ktoso

ktoso commented May 28, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso

ktoso commented May 30, 2026

Copy link
Copy Markdown
Contributor

Going to land this, the wasm fix is taking to long -- it can land later.

@ktoso

ktoso commented May 30, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso
ktoso enabled auto-merge (squash) May 30, 2026 00:47
@ktoso

ktoso commented May 30, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test macOS

1 similar comment
@ktoso

ktoso commented May 30, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test macOS

Comment thread test/stdlib/Result.swift Outdated
@ktoso

ktoso commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

@swift-ci please smoke test

@ktoso
ktoso merged commit a8020e4 into swiftlang:main Jun 1, 2026
3 checks passed
@mattmassicotte
mattmassicotte deleted the result-async-catching branch June 1, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

concurrency Feature: umbrella label for concurrency language features swift evolution approved Flag → feature: A feature that was approved through the Swift evolution process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants