Skip to content

Commit 7d3e78e

Browse files
authored
Merge pull request #17738 from slavapestov/optional-witness-visibility-hackaround-4.2
Sema: Fix source compatibility break from relaxed witness matching rules [4.2]
2 parents 8b9f19d + 829664b commit 7d3e78e

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,6 +2763,21 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
27632763

27642764
case CheckKind::Access:
27652765
case CheckKind::AccessOfSetter: {
2766+
// Swift 4.2 relaxed some rules for protocol witness matching.
2767+
//
2768+
// This meant that it was possible for an optional protocol requirement
2769+
// to have a witness where previously in Swift 4.1 it did not.
2770+
//
2771+
// Since witnesses must be as visible as the protocol, this caused a
2772+
// source compatibility break if the witness was not sufficiently
2773+
// visible.
2774+
//
2775+
// Work around this by discarding the witness if its not sufficiently
2776+
// visible.
2777+
if (!TC.Context.isSwiftVersionAtLeast(5))
2778+
if (requirement->getAttrs().hasAttribute<OptionalAttr>())
2779+
return ResolveWitnessResult::Missing;
2780+
27662781
// Avoid relying on the lifetime of 'this'.
27672782
const DeclContext *DC = this->DC;
27682783
diagnoseOrDefer(requirement, false,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -swift-version 4
2+
3+
@objc protocol Opt {
4+
@objc optional func f(callback: @escaping () -> ())
5+
}
6+
7+
class Conforms : Opt {
8+
private func f(callback: () -> ()) {} // expected-note {{'f' declared here}}
9+
}
10+
11+
func g(x: Conforms) {
12+
_ = x.f(callback: {}) // expected-error {{'f' is inaccessible due to 'private' protection level}}
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -swift-version 5
2+
3+
@objc protocol Opt {
4+
@objc optional func f(callback: @escaping () -> ())
5+
}
6+
7+
class Conforms : Opt {
8+
private func f(callback: () -> ()) {}
9+
// expected-error@-1 {{method 'f(callback:)' must be declared internal because it matches a requirement in internal protocol 'Opt'}}
10+
// expected-note@-2 {{mark the instance method as 'internal' to satisfy the requirement}}
11+
}
12+
13+
func g(x: Conforms) {
14+
_ = x.f(callback: {})
15+
}

0 commit comments

Comments
 (0)