diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index e1f93c5c5f928..446eed89db868 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1688,6 +1688,14 @@ bool TypeChecker::isAvailabilitySafeForConformance( assert(dc->getSelfNominalTypeDecl() && "Must have a nominal or extension context"); + AvailabilityContext contextForConformingDecl = + availabilityForDeclSignature(dc->getAsDecl()); + + // If the conformance is unavailable then it's irrelevant whether the witness + // is potentially unavailable. + if (contextForConformingDecl.isUnavailable()) + return true; + // Make sure that any access of the witness through the protocol // can only occur when the witness is available. That is, make sure that // on every version where the conforming declaration is available, if the @@ -1703,7 +1711,7 @@ bool TypeChecker::isAvailabilitySafeForConformance( requirementInfo = AvailabilityInference::availableRange(requirement); AvailabilityRange infoForConformingDecl = - overApproximateAvailabilityAtLocation(dc->getAsDecl()->getLoc(), dc); + contextForConformingDecl.getPlatformRange(); // Relax the requirements for @_spi witnesses by treating the requirement as // if it were introduced at the deployment target. This is not strictly sound diff --git a/test/Sema/availability_scopes.swift b/test/Sema/availability_scopes.swift index 69d1d672fb754..aba23d053038c 100644 --- a/test/Sema/availability_scopes.swift +++ b/test/Sema/availability_scopes.swift @@ -373,6 +373,12 @@ extension SomeEnum { func neverAvailable() {} } +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=unavailableOnMacOSAndIntroduced() + +@available(macOS, unavailable, introduced: 52) +func unavailableOnMacOSAndIntroduced() { +} + // CHECK-NEXT: {{^}} (decl version=50 unavailable=* decl=NeverAvailable // CHECK-NEXT: {{^}} (decl version=50 unavailable=* decl=unavailableOnMacOS() diff --git a/test/Sema/conformance_availability.swift b/test/Sema/conformance_availability.swift index c73adabcddce3..ead1d41f89d8e 100644 --- a/test/Sema/conformance_availability.swift +++ b/test/Sema/conformance_availability.swift @@ -466,6 +466,14 @@ extension Bike : Vehicle { func move() {} } +@available(macOS, introduced: 100) +struct Wagon {} + +@available(macOS, introduced: 100) +extension Wagon : Vehicle { + func move() {} +} + class Car {} class ClownCar : Car {} @@ -478,6 +486,63 @@ extension Car { extension ClownCar : Vehicle {} // expected-error@-1 {{protocol 'Vehicle' requires 'move()' to be available in macOS 100 and newer}} +@available(macOS, unavailable) +struct Truck : Vehicle { + func move() {} +} + +struct Scooter {} + +@available(macOS, unavailable) +extension Scooter : Vehicle { + func move() {} +} + +struct Motorcycle {} + +@available(macOS, unavailable) +extension Motorcycle : Vehicle { + @available(macOS, introduced: 100) + func move() {} +} + +@available(macOS, unavailable) +struct AircraftCarrier { + struct Jet : Vehicle { + @available(macOS, introduced: 100) + func move() {} + } +} + +struct Unicycle { + @available(macOS, introduced: 100) + func move() {} +} + +@available(macOS, unavailable) +extension Unicycle : Vehicle {} + +@available(macOS, unavailable, introduced: 100) +struct Train : Vehicle { + func move() {} +} + +struct Blimp {} + +@available(macOS, unavailable, introduced: 100) +extension Blimp : Vehicle { + func move() {} +} + +@available(macOS, unavailable, introduced: 100) +struct Spaceship { +} + +@available(macOS, unavailable, introduced: 100) +extension Spaceship : Vehicle { + func move() {} +} + // rdar://problem/75430966 - Allow using unavailable conformances from unavailable contexts. @available(*, unavailable) public enum UnavailableEnum {