Skip to content

Commit 8d1eebe

Browse files
committed
Fixing invalid swiftinterface in presence of an internal protocol
Private member witnessing a public constraint should be deprecated. If StrictTextualInterfaceChecking is set, compiler emits an error when access check is not passed. rdar://74904373
1 parent 83a9913 commit 8d1eebe

File tree

5 files changed

+45
-1
lines changed

5 files changed

+45
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,6 +3268,14 @@ WARNING(warn_protocol_witness_optionality,none,
32683268
" different optionality than expected by protocol %2",
32693269
(unsigned, const ValueDecl *, const ProtocolDecl *))
32703270

3271+
ERROR(err_private_member_witness_public_protocol,none,
3272+
"%0 is private and should not witness public protocol %1",
3273+
(const ValueDecl *,const ProtocolDecl *))
3274+
WARNING(warn_private_member_witness_public_protocol,none,
3275+
"%0 is private and should not witness public protocol %1; "
3276+
"this is deprecated and will become an error in future versions",
3277+
(const ValueDecl *,const ProtocolDecl *))
3278+
32713279
NOTE(protocol_witness_static_conflict,none,
32723280
"candidate operates on %select{a type|an instance}0, not "
32733281
"%select{an instance|a type}0 as required", (bool))

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ MIGRATABLE_UPCOMING_FEATURE(MemberImportVisibility, 444, 7)
302302
MIGRATABLE_UPCOMING_FEATURE(InferIsolatedConformances, 470, 7)
303303
MIGRATABLE_UPCOMING_FEATURE(NonisolatedNonsendingByDefault, 461, 7)
304304
UPCOMING_FEATURE(ImmutableWeakCaptures, 481, 7)
305+
UPCOMING_FEATURE(StrictTextualInterfaceChecking, 0, 7)
305306

306307
// Optional language features / modes
307308

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ UNINTERESTING_FEATURE(ExistentialAny)
7272
UNINTERESTING_FEATURE(InferSendableFromCaptures)
7373
UNINTERESTING_FEATURE(ImplicitOpenExistentials)
7474
UNINTERESTING_FEATURE(MemberImportVisibility)
75+
UNINTERESTING_FEATURE(StrictTextualInterfaceChecking)
7576

7677
// ----------------------------------------------------------------------------
7778
// MARK: - Experimental Features

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1762,11 +1762,14 @@ static bool checkWitnessAccess(DeclContext *dc,
17621762

17631763
auto actualScopeToCheck = requiredAccessScope.first;
17641764

1765+
// without StrictTextualInterfaceChecking feature forConformance is set true
1766+
bool forConformance = not dc->getASTContext().LangOpts.hasFeature
1767+
(Feature::StrictTextualInterfaceChecking);
17651768
// Setting the 'forConformance' flag means that we admit witnesses in
17661769
// protocol extensions that we can see, but are not necessarily as
17671770
// visible as the conforming type and protocol.
17681771
if (!witness->isAccessibleFrom(actualScopeToCheck.getDeclContext(),
1769-
/*forConformance=*/true)) {
1772+
forConformance)) {
17701773
// Special case: if we have `@testable import` of the witness's module,
17711774
// allow the witness to match if it would have matched for just this file.
17721775
// That is, if '@testable' allows us to see the witness here, it should
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-typecheck-verify-swift -enable-library-evolution -enable-upcoming-feature StrictTextualInterfaceChecking
3+
4+
public protocol P {
5+
func foo() -> Int
6+
}
7+
internal protocol Q: P {
8+
func fooImpl() -> Int32
9+
}
10+
extension Q {
11+
public func foo() -> Int { // expected-note {{mark the instance method as 'public' to satisfy the requirement}}
12+
return Int(self.fooImpl())
13+
}
14+
}
15+
public struct S: Q { // expected-error {{method 'foo()' must be declared public because it matches a requirement in public protocol 'P'}}
16+
internal func fooImpl() -> Int32 {
17+
return 42
18+
}
19+
}
20+
21+
public struct Foo {
22+
public init(value: Int) {}
23+
}
24+
public protocol PublicProtocol {
25+
init?(integer: Int)
26+
}
27+
protocol InternalProtocol: PublicProtocol {}
28+
extension InternalProtocol {
29+
public init(integer: Int) {} // expected-note {{mark the initializer as 'public' to satisfy the requirement}}
30+
}
31+
extension Foo: PublicProtocol, InternalProtocol {} // expected-error {{initializer 'init(integer:)' must be declared public because it matches a requirement in public protocol 'PublicProtocol'}}

0 commit comments

Comments
 (0)