diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index cd275d64fd184..b20bc9280ef38 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -6195,7 +6195,11 @@ bool swift::checkSendableConformance( return false; // If this is an always-unavailable conformance, there's nothing to check. - if (auto ext = dyn_cast(conformanceDC)) { + // We always use the root conformance for this check, because inherited + // conformances need to walk back to the original declaration for the + // superclass conformance to find an unavailable attribute. + if (auto ext = dyn_cast( + conformance->getRootConformance()->getDeclContext())) { if (AvailableAttr::isUnavailable(ext)) return false; } diff --git a/test/Concurrency/concurrent_value_checking.swift b/test/Concurrency/concurrent_value_checking.swift index 7d0f4c2ae22a6..57b0b6dfe79ed 100644 --- a/test/Concurrency/concurrent_value_checking.swift +++ b/test/Concurrency/concurrent_value_checking.swift @@ -380,6 +380,14 @@ final class C7: Sendable { } class C9: Sendable { } // expected-warning{{non-final class 'C9' cannot conform to 'Sendable'; use '@unchecked Sendable'}} +@available(*, unavailable) +extension HasUnavailableSendable : @unchecked Sendable { } + +class HasUnavailableSendable { +} + +class NoRestated: HasUnavailableSendable {} // okay + @globalActor struct SomeActor { static let shared = A1()