Skip to content

Commit c346c4f

Browse files
committed
Sema: Relax witness availability check
We were checking that the witness is at least as available as the intersection of the protocol and the conforming type. In the case where the conformance is defined in an extension, this should actually be the intersection of the protocol and the _availability of the extension_. Fixes <rdar://problem/74114880>.
1 parent 4769f21 commit c346c4f

File tree

3 files changed

+38
-8
lines changed

3 files changed

+38
-8
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,8 +1670,8 @@ bool TypeChecker::isAvailabilitySafeForConformance(
16701670
return true;
16711671

16721672
auto &Context = proto->getASTContext();
1673-
NominalTypeDecl *conformingDecl = dc->getSelfNominalTypeDecl();
1674-
assert(conformingDecl && "Must have conforming declaration");
1673+
assert(dc->getSelfNominalTypeDecl() &&
1674+
"Must have a nominal or extension context");
16751675

16761676
// Make sure that any access of the witness through the protocol
16771677
// can only occur when the witness is available. That is, make sure that
@@ -1688,8 +1688,7 @@ bool TypeChecker::isAvailabilitySafeForConformance(
16881688
requirementInfo = AvailabilityInference::availableRange(requirement, Context);
16891689

16901690
AvailabilityContext infoForConformingDecl =
1691-
overApproximateAvailabilityAtLocation(conformingDecl->getLoc(),
1692-
conformingDecl);
1691+
overApproximateAvailabilityAtLocation(dc->getAsDecl()->getLoc(), dc);
16931692

16941693
// Constrain over-approximates intersection of version ranges.
16951694
witnessInfo.constrainWith(infoForConformingDecl);

test/Sema/availability_versions.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ protocol ProtocolWithRequirementMentioningUnavailable {
13881388

13891389
protocol HasMethodF {
13901390
associatedtype T
1391-
func f(_ p: T) // expected-note 5{{protocol requirement here}}
1391+
func f(_ p: T) // expected-note 4{{protocol requirement here}}
13921392
}
13931393

13941394
class TriesToConformWithFunctionIntroducedOn10_51 : HasMethodF {
@@ -1439,7 +1439,8 @@ extension HasNoMethodF1 : HasMethodF {
14391439
class HasNoMethodF2 { }
14401440
@available(OSX, introduced: 10.51)
14411441
extension HasNoMethodF2 : HasMethodF {
1442-
func f(_ p: Int) { } // expected-error {{protocol 'HasMethodF' requires 'f' to be available in macOS 10.50.0 and newer}}
1442+
// This is OK, because the conformance was introduced by an extension.
1443+
func f(_ p: Int) { }
14431444
}
14441445

14451446
@available(OSX, introduced: 10.51)
@@ -1453,7 +1454,7 @@ extension HasNoMethodF3 : HasMethodF {
14531454

14541455
@available(OSX, introduced: 10.51)
14551456
protocol HasMethodFOn10_51 {
1456-
func f(_ p: Int) // expected-note {{protocol requirement here}}
1457+
func f(_ p: Int)
14571458
}
14581459

14591460
class ConformsToUnavailableProtocolWithUnavailableWitness : HasMethodFOn10_51 {
@@ -1465,7 +1466,8 @@ class ConformsToUnavailableProtocolWithUnavailableWitness : HasMethodFOn10_51 {
14651466
class HasNoMethodF4 { }
14661467
@available(OSX, introduced: 10.52)
14671468
extension HasNoMethodF4 : HasMethodFOn10_51 {
1468-
func f(_ p: Int) { } // expected-error {{protocol 'HasMethodFOn10_51' requires 'f' to be available in macOS 10.51 and newer}}
1469+
// This is OK, because the conformance was introduced by an extension.
1470+
func f(_ p: Int) { }
14691471
}
14701472

14711473
@available(OSX, introduced: 10.51)

test/Sema/conformance_availability.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,32 @@ func usesUnavailableHashable(_ c: UnavailableHashable) {
322322
// expected-error@-1 2 {{conformance of 'UnavailableHashable' to 'Hashable' is only available in macOS 100 or newer}}
323323
// expected-note@-2 2 {{add 'if #available' version check}}
324324
}
325+
326+
// Actually make sure we check witness availability correctly.
327+
protocol Vehicle {
328+
func move() // expected-note {{protocol requirement here}}
329+
}
330+
331+
@available(macOS 100, *)
332+
struct Pony : Vehicle {
333+
func move() {}
334+
}
335+
336+
struct Bike {}
337+
338+
@available(macOS 100, *)
339+
extension Bike : Vehicle {
340+
func move() {}
341+
}
342+
343+
class Car {}
344+
class ClownCar : Car {}
345+
346+
@available(macOS 200, *)
347+
extension Car {
348+
func move() {} // expected-note {{'move()' declared here}}
349+
}
350+
351+
@available(macOS 100, *)
352+
extension ClownCar : Vehicle {}
353+
// expected-error@-1 {{protocol 'Vehicle' requires 'move()' to be available in macOS 100 and newer}}

0 commit comments

Comments
 (0)