Skip to content

Commit e37070e

Browse files
authored
Merge pull request swiftlang#32883 from xymus/spi-req-in-spi-proto-5.3
[5.3][Sema] Only require a default implementation for SPI requirements in non-SPI protocols
2 parents e0df4ca + 2038b1a commit e37070e

File tree

3 files changed

+47
-50
lines changed

3 files changed

+47
-50
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -871,44 +871,6 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
871871
D->getDescriptiveKind());
872872
}
873873

874-
// If VD is a public protocol requirement it can be SPI only if there's
875-
// a default implementation.
876-
if (auto protocol = dyn_cast<ProtocolDecl>(D->getDeclContext())) {
877-
auto implementations = TypeChecker::lookupMember(
878-
D->getDeclContext(),
879-
protocol->getDeclaredType(),
880-
VD->createNameRef(),
881-
NameLookupFlags::ProtocolMembers);
882-
bool hasDefaultImplementation = llvm::any_of(implementations,
883-
[&](const LookupResultEntry &entry) {
884-
auto entryDecl = entry.getValueDecl();
885-
auto DC = entryDecl->getDeclContext();
886-
auto extension = dyn_cast<ExtensionDecl>(DC);
887-
888-
// The implementation must be defined in the same module in
889-
// an unconstrained extension.
890-
if (!extension ||
891-
extension->getParentModule() != protocol->getParentModule() ||
892-
extension->isConstrainedExtension())
893-
return false;
894-
895-
// For computed properties and subscripts, check that the default
896-
// implementation defines `set` if the protocol declares it.
897-
if (auto protoStorage = dyn_cast<AbstractStorageDecl>(VD))
898-
if (auto entryStorage = dyn_cast<AbstractStorageDecl>(entryDecl))
899-
if (protoStorage->getAccessor(AccessorKind::Set) &&
900-
!entryStorage->getAccessor(AccessorKind::Set))
901-
return false;
902-
903-
return true;
904-
});
905-
906-
if (!hasDefaultImplementation)
907-
diagnoseAndRemoveAttr(attr,
908-
diag::spi_attribute_on_protocol_requirement,
909-
VD->getName());
910-
}
911-
912874
// Forbid stored properties marked SPI in frozen types.
913875
if (auto property = dyn_cast<AbstractStorageDecl>(VD))
914876
if (auto DC = dyn_cast<NominalTypeDecl>(D->getDeclContext()))

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5764,7 +5764,15 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
57645764
if (!valueDecl->isProtocolRequirement())
57655765
continue;
57665766

5767-
checker.resolveWitnessViaLookup(valueDecl);
5767+
ResolveWitnessResult result = checker.resolveWitnessViaLookup(valueDecl);
5768+
5769+
if (result == ResolveWitnessResult::Missing &&
5770+
requirement->isSPI() &&
5771+
!proto->isSPI()) {
5772+
// SPI requirements need a default value, unless the protocol is SPI too.
5773+
valueDecl->diagnose(diag::spi_attribute_on_protocol_requirement,
5774+
valueDecl->getName());
5775+
}
57685776
}
57695777

57705778
// Find defaults for any associated conformances rooted on defaulted

test/SPI/protocol_requirement.swift

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
// Test limitations on SPI protocol requirements.
22

3-
// RUN: %target-typecheck-verify-swift
3+
// RUN: %target-typecheck-verify-swift -enable-library-evolution
44

55
// Reject SPI protocol requirements without a default implementation.
66
public protocol PublicProtoRejected {
7-
@_spi(Private) // expected-error{{protocol requirement 'reqWithoutDefault()' cannot be declared '@_spi' without a default implementation in a protocol extension}}
8-
func reqWithoutDefault()
7+
@_spi(Private)
8+
func reqWithoutDefault() // expected-error{{protocol requirement 'reqWithoutDefault()' cannot be declared '@_spi' without a default implementation in a protocol extension}}
99

10-
@_spi(Private) // expected-error{{protocol requirement 'property' cannot be declared '@_spi' without a default implementation in a protocol extension}}
11-
var property: Int { get set }
10+
@_spi(Private)
11+
func reqWithSharedName(_: Int) // expected-error{{protocol requirement 'reqWithSharedName' cannot be declared '@_spi' without a default implementation in a protocol extension}}
1212

13-
@_spi(Private) // expected-error{{protocol requirement 'propertyWithoutSetter' cannot be declared '@_spi' without a default implementation in a protocol extension}}
14-
var propertyWithoutSetter: Int { get set }
13+
@_spi(Private)
14+
var property: Int { get set } // expected-error{{protocol requirement 'property' cannot be declared '@_spi' without a default implementation in a protocol extension}}
1515

16-
@_spi(Private) // expected-error{{protocol requirement 'subscript(_:)' cannot be declared '@_spi' without a default implementation in a protocol extension}}
17-
subscript(index: Int) -> Int { get set }
16+
@_spi(Private)
17+
var propertyWithoutSetter: Int { get set } // expected-error{{protocol requirement 'propertyWithoutSetter' cannot be declared '@_spi' without a default implementation in a protocol extension}}
1818

19-
@_spi(Private) // expected-error{{protocol requirement 'init()' cannot be declared '@_spi' without a default implementation in a protocol extension}}
20-
init()
19+
@_spi(Private)
20+
subscript(index: Int) -> Int { get set } // expected-error{{protocol requirement 'subscript(_:)' cannot be declared '@_spi' without a default implementation in a protocol extension}}
21+
22+
@_spi(Private)
23+
init() // expected-error{{protocol requirement 'init()' cannot be declared '@_spi' without a default implementation in a protocol extension}}
2124

2225
@_spi(Private) // expected-error{{'@_spi' attribute cannot be applied to this declaration}}
2326
associatedtype T
@@ -26,6 +29,9 @@ public protocol PublicProtoRejected {
2629
extension PublicProtoRejected {
2730
@_spi(Private)
2831
public var propertyWithoutSetter: Int { get { return 42 } }
32+
33+
@_spi(Private)
34+
public func reqWithSharedName(_: String) {}
2935
}
3036

3137
extension PublicProtoRejected where Self : Equatable {
@@ -69,3 +75,24 @@ extension PublicProto {
6975
@_spi(Private)
7076
public init() { }
7177
}
78+
79+
@_spi(Private)
80+
public protocol SPIProtocol {
81+
@_spi(Private)
82+
func reqWithoutDefault()
83+
84+
@_spi(Private)
85+
var property: Int { get set }
86+
87+
@_spi(Private)
88+
var propertyWithoutSetter: Int { get set }
89+
90+
@_spi(Private)
91+
subscript(index: Int) -> Int { get set }
92+
93+
@_spi(Private)
94+
init()
95+
96+
@_spi(Private)
97+
static var staticProperty: Int { get }
98+
}

0 commit comments

Comments
 (0)