Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nightly compiler crash: Assertion `type->isTypeParameter() && "Expected a type parameter"' failed #73838

Open
dimitribouniol opened this issue May 23, 2024 · 1 comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler itself concurrency Feature: umbrella label for concurrency language features crash Bug: A crash, i.e., an abnormal termination of software swift 6.0

Comments

@dimitribouniol
Copy link
Contributor

dimitribouniol commented May 23, 2024

Description

I noticed the following crash on the nightlies, which compiled fine with Swift 5.9/5.10.

Reproduction

It seems like this is the code responsible, though I haven't had a chance to boil it down and try reproducing in isolation:

/// An internal type to assist kicking off work without primarily awaiting it, instead allowing that work to call into a continuation as needed.
 /// Use ``withCancellableFirstSuccessfulContinuation()`` instead of invoking this directly.
 actor CancellableContinuation<T: Sendable>: Sendable {
     private var bodyTask: Task<Void, Error>?
     private var continuation: CheckedContinuation<T, Error>?
     private var isCancelled = false

     private func cancelMainTask() {
         continuation?.resume(throwing: CancellationError())
         continuation = nil
         bodyTask?.cancel()
         isCancelled = true
     }

     private func isolatedResume(returning value: T) {
         continuation?.resume(returning: value)
         continuation = nil
         cancelMainTask()
     }

     nonisolated func cancel() {
         Task { await cancelMainTask() }
     }

     nonisolated func resume(returning value: T) {
         Task { await isolatedResume(returning: value) }
     }

     /// Wrap an asynchronous closure providing a continuation for when results are ready that can be called any number of times, but also allowing the closure to be cancelled at any time, including once the first successful value is provided.
     fileprivate func wrap(_ body: Body) async throws -> T {
         assert(bodyTask == nil, "A CancellableContinuationTask should only be used once.")
         /// Register a cancellation callback that will: a) immediately cancel the continuation if we have one, b) unset it so it doesn't get called a second time, and c) cancel the main task.
         return try await withTaskCancellationHandler {
             let response: T = try await withCheckedThrowingContinuation { localContinuation in
                 /// Synchronously a) check if we've been cancelled, stopping early, b) save the contnuation, and c) assign the task, which runs immediately.
                 /// This works since we are guaranteed to hear back from the cancellation handler either immediately, since Task.isCancelled is already set, or after task is set, since we are executing on the actor's executor.
                 guard !Task.isCancelled else {
                     localContinuation.resume(throwing: CancellationError())
                     return
                 }

                 self.continuation = localContinuation
                 self.bodyTask = Task { [unowned self] in
                     /// If the continuation doesn't exist at this point, it's because we've already been cancelled. This is guaranteed to run after the task has been set and potentially cancelled since it also runs on the task executor.
                     guard let continuation = self.continuation else { return }
                     do {
                         try await body(self)
                     } catch {
                         /// If the main body fails for any reason, pass along the error. This will be a no-op if the continuation was already resumed or cancelled.
                         continuation.resume(throwing: error)
                         self.continuation = nil
                     }
                 }
             }
             /// Wait for the body to finish cancelling before continuing, so it doesn't run into any data races.
             try? await bodyTask?.value
             return response
         } onCancel: {
             cancel()
         }
     }

     /// A wrapper for the body, which will ever only be called once, in a non-escaping manner before the continuation resumes.
     fileprivate struct Body: @unchecked Sendable {
         var body: (_ continuation: CancellableContinuation<T>) async throws -> ()

         func callAsFunction(_ continuation: CancellableContinuation<T>) async throws {
             try await body(continuation)
         }
     }
 }

 /// Execute an operation providing it a continuation for when results are ready that can be called any number of times, but also allowing the operation to be cancelled at any time, including once the first successful value is provided.
 func withCancellableFirstSuccessfulContinuation<T: Sendable>(_ body: (_ continuation: CancellableContinuation<T>) async throws -> ()) async throws -> T {
     try await withoutActuallyEscaping(body) { escapingBody in
         try await CancellableContinuation().wrap(.init { try await escapingBody($0) })
     }
 }

Stack dump

error: compile command failed due to signal 6 (use -v to see invocation)
swift-frontend: /home/build-user/swift/lib/AST/GenericSignature.cpp:381: bool swift::GenericSignatureImpl::requiresProtocol(swift::Type, swift::ProtocolDecl *) const: Assertion `type->isTypeParameter() && "Expected a type parameter"' failed.
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0.	Program arguments: /usr/bin/swift-frontend -frontend -c /code/Sources/WebAuthn/Authenticators/KeyPairAuthenticator.swift /code/Sources/WebAuthn/Authenticators/Protocol/AssertionAuthenticationRequest.swift /code/Sources/WebAuthn/Authenticators/Protocol/AttestationRegistrationRequest.swift /code/Sources/WebAuthn/Authenticators/Protocol/AuthenticatorCredentialSourceIdentifier.swift /code/Sources/WebAuthn/Authenticators/Protocol/AuthenticatorCredentialSourceProtocol.swift /code/Sources/WebAuthn/Authenticators/Protocol/AuthenticatorProtocol.swift /code/Sources/WebAuthn/Ceremonies/Authentication/AuthenticationCredential.swift /code/Sources/WebAuthn/Ceremonies/Authentication/AuthenticatorAssertionResponse.swift /code/Sources/WebAuthn/Ceremonies/Authentication/PublicKeyCredentialRequestOptions.swift /code/Sources/WebAuthn/Ceremonies/Authentication/VerifiedAuthentication.swift /code/Sources/WebAuthn/Ceremonies/Registration/AttestationConveyancePreference.swift /code/Sources/WebAuthn/Ceremonies/Registration/AttestationFormat.swift /code/Sources/WebAuthn/Ceremonies/Registration/AttestationObject.swift /code/Sources/WebAuthn/Ceremonies/Registration/AttestedCredentialData.swift /code/Sources/WebAuthn/Ceremonies/Registration/AuthenticatorAttestationResponse.swift /code/Sources/WebAuthn/Ceremonies/Registration/Credential.swift /code/Sources/WebAuthn/Ceremonies/Registration/Formats/PackedAttestation.swift /code/Sources/WebAuthn/Ceremonies/Registration/Formats/TPMAttestation+Structs.swift /code/Sources/WebAuthn/Ceremonies/Registration/Formats/TPMAttestation.swift /code/Sources/WebAuthn/Ceremonies/Registration/PublicKeyCredentialCreationOptions.swift /code/Sources/WebAuthn/Ceremonies/Registration/RegistrationCredential.swift /code/Sources/WebAuthn/Ceremonies/Shared/AuthenticatorAttachment.swift /code/Sources/WebAuthn/Ceremonies/Shared/AuthenticatorAttestationGloballyUniqueID.swift /code/Sources/WebAuthn/Ceremonies/Shared/AuthenticatorData.swift /code/Sources/WebAuthn/Ceremonies/Shared/AuthenticatorFlags.swift /code/Sources/WebAuthn/Ceremonies/Shared/COSE/CBOR+COSEHelpers.swift /code/Sources/WebAuthn/Ceremonies/Shared/COSE/COSEAlgorithmIdentifier.swift /code/Sources/WebAuthn/Ceremonies/Shared/COSE/COSECurve.swift /code/Sources/WebAuthn/Ceremonies/Shared/COSE/COSEKey.swift /code/Sources/WebAuthn/Ceremonies/Shared/COSE/COSEKeyType.swift -primary-file /code/Sources/WebAuthn/Ceremonies/Shared/CollectedClientData.swift -primary-file /code/Sources/WebAuthn/Ceremonies/Shared/CredentialPublicKey.swift -primary-file /code/Sources/WebAuthn/Ceremonies/Shared/CredentialType.swift -primary-file /code/Sources/WebAuthn/Helpers/Base64Utilities.swift -primary-file /code/Sources/WebAuthn/Helpers/ByteCasting.swift -primary-file /code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift /code/Sources/WebAuthn/Helpers/ChallengeGenerator.swift /code/Sources/WebAuthn/Helpers/Data+safeSubscript.swift /code/Sources/WebAuthn/Helpers/Duration+Milliseconds.swift /code/Sources/WebAuthn/Helpers/KeyedDecodingContainer+decodeURLEncoded.swift /code/Sources/WebAuthn/Helpers/UInt8+random.swift /code/Sources/WebAuthn/Helpers/UnreferencedStringEnumeration.swift /code/Sources/WebAuthn/WebAuthnClient.swift /code/Sources/WebAuthn/WebAuthnError.swift /code/Sources/WebAuthn/WebAuthnManager+Configuration.swift /code/Sources/WebAuthn/WebAuthnManager.swift -supplementary-output-file-map /tmp/TemporaryDirectory.NbixEc/supplementaryOutputs-6 -target x86_64-unknown-linux-gnu -disable-objc-interop -I /code/.build/x86_64-unknown-linux-gnu/debug/Modules -enable-testing -g -debug-info-format=dwarf -dwarf-version=4 -module-cache-path /code/.build/x86_64-unknown-linux-gnu/debug/ModuleCache -warnings-as-errors -swift-version 5 -Onone -D SWIFT_PACKAGE -D DEBUG -enable-experimental-feature StrictConcurrency=complete -empty-abi-descriptor -Xcc -working-directory -Xcc /code -resource-dir /usr/lib/swift -enable-anonymous-context-mangled-names -file-compilation-dir /code -Xcc -fmodule-map-file=/code/.build/checkouts/swift-crypto/Sources/CCryptoBoringSSLShims/include/module.modulemap -Xcc -I -Xcc /code/.build/checkouts/swift-crypto/Sources/CCryptoBoringSSLShims/include -Xcc -fmodule-map-file=/code/.build/checkouts/swift-crypto/Sources/CCryptoBoringSSL/include/module.modulemap -Xcc -I -Xcc /code/.build/checkouts/swift-crypto/Sources/CCryptoBoringSSL/include -Xcc -fPIC -Xcc -g -Xcc -fno-omit-frame-pointer -module-name WebAuthn -package-name code -plugin-path /usr/lib/swift/host/plugins -plugin-path /usr/local/lib/swift/host/plugins -parse-as-library -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/CollectedClientData.swift.o -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/CredentialPublicKey.swift.o -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/CredentialType.swift.o -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/Base64Utilities.swift.o -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/ByteCasting.swift.o -o /code/.build/x86_64-unknown-linux-gnu/debug/WebAuthn.build/CancellableContinuationTask.swift.o -index-store-path /code/.build/x86_64-unknown-linux-gnu/debug/index/store -index-system-modules
1.	Swift version 6.0-dev (LLVM cef183591317ec7, Swift 66e311074bff491)
2.	Compiling with effective version 5.10
3.	While evaluating request ASTLoweringRequest(Lowering AST to SIL for file "/code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift")
4.	While silgen emitFunction SIL function "@$s8WebAuthn23CancellableContinuationC4wrap33_8B8D8D6E76AA132C13FB74CECA909F2ELLyxAC4BodyAELLVyx_GYaKF".
 for 'wrap(_:)' (at /code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift:44:17)
5.	While silgen closureexpr SIL function "@$s8WebAuthn23CancellableContinuationC4wrap33_8B8D8D6E76AA132C13FB74CECA909F2ELLyxAC4BodyAELLVyx_GYaKFxyYaKXEfU_".
 for expression at [/code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift:47:54 - line:72:9] RangeText="{
            let response: T = try await withCheckedThrowingContinuation { localContinuation in
                /// Synchronously a) check if we've been cancelled, stopping early, b) save the contnuation, and c) assign the task, which runs immediately.
                /// This works since we are guaranteed to hear back from the cancellation handler either immediately, since Task.isCancelled is already set, or after task is set, since we are executing on the actor's executor.
                guard !Task.isCancelled else {
                    localContinuation.resume(throwing: CancellationError())
                    return
                }
                
                self.continuation = localContinuation
                self.bodyTask = Task { [unowned self] in
                    /// If the continuation doesn't exist at this point, it's because we've already been cancelled. This is guaranteed to run after the task has been set and potentially cancelled since it also runs on the task executor.
                    guard let continuation = self.continuation else { return }
                    do {
                        try await body(self)
                    } catch {
                        /// If the main body fails for any reason, pass along the error. This will be a no-op if the continuation was already resumed or cancelled.
                        continuation.resume(throwing: error)
                        self.continuation = nil
                    }
                }
            }
            /// Wait for the body to finish cancelling before continuing, so it doesn't run into any data races.
            try? await bodyTask?.value
            return response
        "
6.	While silgen closureexpr SIL function "@$s8WebAuthn23CancellableContinuationC4wrap33_8B8D8D6E76AA132C13FB74CECA909F2ELLyxAC4BodyAELLVyx_GYaKFxyYaKXEfU_yScCyxs5Error_pGXEfU_".
 for expression at [/code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift:48:73 - line:68:13] RangeText="{ localContinuation in
                /// Synchronously a) check if we've been cancelled, stopping early, b) save the contnuation, and c) assign the task, which runs immediately.
                /// This works since we are guaranteed to hear back from the cancellation handler either immediately, since Task.isCancelled is already set, or after task is set, since we are executing on the actor's executor.
                guard !Task.isCancelled else {
                    localContinuation.resume(throwing: CancellationError())
                    return
                }
                
                self.continuation = localContinuation
                self.bodyTask = Task { [unowned self] in
                    /// If the continuation doesn't exist at this point, it's because we've already been cancelled. This is guaranteed to run after the task has been set and potentially cancelled since it also runs on the task executor.
                    guard let continuation = self.continuation else { return }
                    do {
                        try await body(self)
                    } catch {
                        /// If the main body fails for any reason, pass along the error. This will be a no-op if the continuation was already resumed or cancelled.
                        continuation.resume(throwing: error)
                        self.continuation = nil
                    }
                }
            "
7.	While silgen closureexpr SIL function "@$s8WebAuthn23CancellableContinuationC4wrap33_8B8D8D6E76AA132C13FB74CECA909F2ELLyxAC4BodyAELLVyx_GYaKFxyYaKXEfU_yScCyxs5Error_pGXEfU_yyYaYbcfU_".
 for expression at [/code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift:57:38 - line:67:17] RangeText="{ [unowned self] in
                    /// If the continuation doesn't exist at this point, it's because we've already been cancelled. This is guaranteed to run after the task has been set and potentially cancelled since it also runs on the task executor.
                    guard let continuation = self.continuation else { return }
                    do {
                        try await body(self)
                    } catch {
                        /// If the main body fails for any reason, pass along the error. This will be a no-op if the continuation was already resumed or cancelled.
                        continuation.resume(throwing: error)
                        self.continuation = nil
                    }
                "
8.	While verifying SIL function "@$s8WebAuthn23CancellableContinuationC4wrap33_8B8D8D6E76AA132C13FB74CECA909F2ELLyxAC4BodyAELLVyx_GYaKFxyYaKXEfU_yScCyxs5Error_pGXEfU_yyYaYbcfU_".
 for expression at [/code/Sources/WebAuthn/Helpers/CancellableContinuationTask.swift:57:38 - line:67:17] RangeText="{ [unowned self] in
                    /// If the continuation doesn't exist at this point, it's because we've already been cancelled. This is guaranteed to run after the task has been set and potentially cancelled since it also runs on the task executor.
                    guard let continuation = self.continuation else { return }
                    do {
                        try await body(self)
                    } catch {
                        /// If the main body fails for any reason, pass along the error. This will be a no-op if the continuation was already resumed or cancelled.
                        continuation.resume(throwing: error)
                        self.continuation = nil
                    }
                "
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 0x000055e75b040bb7
1  swift-frontend 0x000055e75b03e90e
2  swift-frontend 0x000055e75b04122a
3  libc.so.6      0x00007f7caf749520
4  libc.so.6      0x00007f7caf79d9fc pthread_kill + 300
5  libc.so.6      0x00007f7caf749476 raise + 22
6  libc.so.6      0x00007f7caf72f7f3 abort + 211
7  libc.so.6      0x00007f7caf72f71b
8  libc.so.6      0x00007f7caf740e96
9  swift-frontend 0x000055e755fd4b4f
10 swift-frontend 0x000055e7555b1001
11 swift-frontend 0x000055e7555abdc6
12 swift-frontend 0x000055e754a6632e
13 swift-frontend 0x000055e754a64cbf
14 swift-frontend 0x000055e754a6e936
15 swift-frontend 0x000055e7554fd4bf
16 swift-frontend 0x000055e754a67df5
17 swift-frontend 0x000055e754addc12
18 swift-frontend 0x000055e754add674
19 swift-frontend 0x000055e754add31c
20 swift-frontend 0x000055e754add293
21 swift-frontend 0x000055e754ad1f2d
22 swift-frontend 0x000055e754ac9299
23 swift-frontend 0x000055e754abcf4c
24 swift-frontend 0x000055e754a9ac42
25 swift-frontend 0x000055e754a9ae4c
26 swift-frontend 0x000055e754a9ab73
27 swift-frontend 0x000055e754a9ad1a
28 swift-frontend 0x000055e754ad4dc2
29 swift-frontend 0x000055e754ac93a2
30 swift-frontend 0x000055e754abcf4c
31 swift-frontend 0x000055e754a9ac42
32 swift-frontend 0x000055e754b7b1d7
33 swift-frontend 0x000055e754bb0095
34 swift-frontend 0x000055e754b9aaa9
35 swift-frontend 0x000055e754badf15
36 swift-frontend 0x000055e754bbbb9b
37 swift-frontend 0x000055e754bbb121
38 swift-frontend 0x000055e754b9fe47
39 swift-frontend 0x000055e754b9d9fd
40 swift-frontend 0x000055e754ac9104
41 swift-frontend 0x000055e754abcf4c
42 swift-frontend 0x000055e754a979b7
43 swift-frontend 0x000055e754ad6f15
44 swift-frontend 0x000055e754ac9456
45 swift-frontend 0x000055e754abcf4c
46 swift-frontend 0x000055e754bafc0d
47 swift-frontend 0x000055e754b9aaa9
48 swift-frontend 0x000055e754badf15
49 swift-frontend 0x000055e754bbbb9b
50 swift-frontend 0x000055e754bbb121
51 swift-frontend 0x000055e754b9fe47
52 swift-frontend 0x000055e754ba8f04
53 swift-frontend 0x000055e754b0aa49
54 swift-frontend 0x000055e754ada529
55 swift-frontend 0x000055e754ac9583
56 swift-frontend 0x000055e754abd721
57 swift-frontend 0x000055e754b5d0c1
58 swift-frontend 0x000055e754b5bbbd
59 swift-frontend 0x000055e754aeb717
60 swift-frontend 0x000055e754a64c99
61 swift-frontend 0x000055e754a6e936
62 swift-frontend 0x000055e7554fd4bf
63 swift-frontend 0x000055e754a67df5
64 swift-frontend 0x000055e754addc12
65 swift-frontend 0x000055e754add9b1
66 swift-frontend 0x000055e754ac913b
67 swift-frontend 0x000055e754abcf4c
68 swift-frontend 0x000055e754bafc0d
69 swift-frontend 0x000055e754b9aaa9
70 swift-frontend 0x000055e754badf15
71 swift-frontend 0x000055e754bbbb9b
72 swift-frontend 0x000055e754bbb121
73 swift-frontend 0x000055e754b9fe47
74 swift-frontend 0x000055e754b9d9fd
75 swift-frontend 0x000055e754ac9104
76 swift-frontend 0x000055e754ab9a46
77 swift-frontend 0x000055e754aa26eb
78 swift-frontend 0x000055e754aaa542
79 swift-frontend 0x000055e754b5d010
80 swift-frontend 0x000055e754b5bbbd
81 swift-frontend 0x000055e754aeb717
82 swift-frontend 0x000055e754a64c99
83 swift-frontend 0x000055e754a6e936
84 swift-frontend 0x000055e7554fd4bf
85 swift-frontend 0x000055e754a67df5
86 swift-frontend 0x000055e754addc12
87 swift-frontend 0x000055e754add9b1
88 swift-frontend 0x000055e754ac913b
89 swift-frontend 0x000055e754abcf4c
90 swift-frontend 0x000055e754bafc0d
91 swift-frontend 0x000055e754b9aaa9
92 swift-frontend 0x000055e754badf15
93 swift-frontend 0x000055e754bbbb9b
94 swift-frontend 0x000055e754bbb121
95 swift-frontend 0x000055e754b9fe47
96 swift-frontend 0x000055e754b9d9fd
97 swift-frontend 0x000055e754ac9104
98 swift-frontend 0x000055e754ab9a46
99 swift-frontend 0x000055e754b60726
100 swift-frontend 0x000055e754b5e888
101 swift-frontend 0x000055e754b5d139
102 swift-frontend 0x000055e754b5bbbd
103 swift-frontend 0x000055e754aeb3df
104 swift-frontend 0x000055e754a65937
105 swift-frontend 0x000055e754a66b92
106 swift-frontend 0x000055e754a63cf3
107 swift-frontend 0x000055e754b77ff2
108 swift-frontend 0x000055e754b73f74
109 swift-frontend 0x000055e754b73e38
110 swift-frontend 0x000055e754a69f0f
111 swift-frontend 0x000055e754b5b4e4
112 swift-frontend 0x000055e754a6f862
113 swift-frontend 0x000055e754a6acbc
114 swift-frontend 0x000055e7542d8d9d
115 swift-frontend 0x000055e7542efb65
116 swift-frontend 0x000055e7542dccf7
117 swift-frontend 0x000055e7542db07c
118 swift-frontend 0x000055e75408eaee
119 libc.so.6      0x00007f7caf730d90
120 libc.so.6      0x00007f7caf730e40 __libc_start_main + 128
121 swift-frontend 0x000055e75408db95
error: fatalError

Expected behavior

This should compile fine. Swift 5.10 log: https://ci.swiftserver.group/job/webauthn-swift510-prb/40/console

Environment

6.0-dev (LLVM cef183591317ec7, Swift 66e3110)

Additional information

Original commit snapshot: https://github.com/swift-server/webauthn-swift/tree/090c9093812f8fe38d19a3c4cc59360a195292ae
Original PR: swift-server/webauthn-swift#70
Original crash log: https://ci.swiftserver.group/job/webauthn-swift-nightly-prb/137/console
Successful build log for 5.10: https://ci.swiftserver.group/job/webauthn-swift510-prb/40/console

@dimitribouniol dimitribouniol added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. crash Bug: A crash, i.e., an abnormal termination of software triage needed This issue needs more specific labels labels May 23, 2024
@ktoso ktoso added concurrency Feature: umbrella label for concurrency language features compiler The Swift compiler itself triage needed This issue needs more specific labels swift 6.0 and removed triage needed This issue needs more specific labels labels May 23, 2024
@ktoso
Copy link
Contributor

ktoso commented May 23, 2024

Thanks for the report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler itself concurrency Feature: umbrella label for concurrency language features crash Bug: A crash, i.e., an abnormal termination of software swift 6.0
Projects
None yet
Development

No branches or pull requests

2 participants