Skip to content

Commit d60d75a

Browse files
committed
Check the containing context when checking access for operators
This might help eliminate operators from overload sets sooner, if they weren't supposed to be accessed from the current context at all. Or it might not make any noticeable difference. No functionality change; the tests added did not change behavior.
1 parent cd22c5d commit d60d75a

File tree

4 files changed

+48
-10
lines changed

4 files changed

+48
-10
lines changed

lib/AST/Decl.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,6 +2480,7 @@ static bool checkAccessUsingAccessScopes(const DeclContext *useDC,
24802480
static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
24812481
AccessLevel access, bool forConformance) {
24822482
auto *sourceDC = VD->getDeclContext();
2483+
bool canUseFastPath = true;
24832484

24842485
if (!forConformance) {
24852486
if (auto *proto = sourceDC->getAsProtocolOrProtocolExtensionContext()) {
@@ -2496,9 +2497,16 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD,
24962497
}
24972498
}
24982499

2499-
// Skip the fast path below and just compare access scopes.
2500-
return checkAccessUsingAccessScopes(useDC, VD, access);
2500+
canUseFastPath = false;
25012501
}
2502+
2503+
if (VD->isOperator())
2504+
canUseFastPath = false;
2505+
}
2506+
2507+
if (!canUseFastPath) {
2508+
// Skip the fast path below and just compare access scopes.
2509+
return checkAccessUsingAccessScopes(useDC, VD, access);
25022510
}
25032511

25042512
// Fast path: assume that the client context already has access to our parent
@@ -2534,15 +2542,10 @@ bool ValueDecl::isAccessibleFrom(const DeclContext *useDC,
25342542
auto access = getFormalAccess();
25352543
bool result = checkAccess(useDC, this, access, forConformance);
25362544

2537-
// For everything outside of protocols and operators, we should get the same
2538-
// result using either implementation of checkAccess, because useDC must
2539-
// already have access to this declaration's DeclContext.
2540-
// FIXME: Arguably, we're doing the wrong thing for operators here too,
2541-
// because we're finding internal operators within private types. Fortunately
2542-
// we have a requirement that a member operator take the enclosing type as an
2543-
// argument, so it won't ever match.
2545+
// For everything outside of protocols, we should get the same result using
2546+
// either implementation of checkAccess, because useDC must already have
2547+
// access to this declaration's DeclContext.
25442548
assert(getDeclContext()->getAsProtocolOrProtocolExtensionContext() ||
2545-
isOperator() ||
25462549
result == checkAccessUsingAccessScopes(useDC, this, access));
25472550

25482551
return result;

test/SILGen/witness_accessibility.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
// RUN: %target-swift-emit-silgen -Xllvm -sil-full-demangle -enable-sil-ownership %s | %FileCheck %s
22

3+
prefix operator ^
4+
prefix operator ^^
5+
prefix operator ^^^
6+
37
public protocol P {
48
func publicRequirement()
9+
static prefix func ^(_: Self)
510
}
611

712
protocol Q : P {
813
func internalRequirement()
14+
static prefix func ^^(_: Self)
915
}
1016

1117
fileprivate protocol R : Q {
1218
func privateRequirement()
19+
static prefix func ^^^(_: Self)
1320
}
1421

1522
extension R {
1623
public func publicRequirement() {}
1724
func internalRequirement() {}
1825
func privateRequirement() {}
26+
27+
public static prefix func ^(_: Self) {}
28+
static prefix func ^^(_: Self) {}
29+
static prefix func ^^^(_: Self) {}
1930
}
2031

2132
public struct S : R {}

test/attr/Inputs/attr_usableFromInline_protocol_hole_helper.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1+
prefix operator ^
2+
prefix operator ^^
3+
prefix operator ^^^
4+
15
public protocol PublicProtocol {
26
}
37
extension PublicProtocol {
48
public func publicExtensionMethod() {}
59
@usableFromInline internal func ufiExtensionMethod() {}
610
internal func internalExtensionMethod() {}
11+
12+
public static prefix func ^(_: Self) {}
13+
@usableFromInline internal static prefix func ^^(_: Self) {}
14+
internal static prefix func ^^^(_: Self) {}
715
}
816

917
public struct PublicImpl: PublicProtocol {}
@@ -15,6 +23,10 @@ extension UFIProtocol {
1523
public func publicExtensionMethod() {}
1624
@usableFromInline internal func ufiExtensionMethod() {}
1725
internal func internalExtensionMethod() {}
26+
27+
public static prefix func ^(_: Self) {}
28+
@usableFromInline internal static prefix func ^^(_: Self) {}
29+
internal static prefix func ^^^(_: Self) {}
1830
}
1931

2032
public struct UFIImpl: PublicProtocol {}

test/attr/attr_usableFromInline_protocol_hole.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,28 @@ func test(_ obj: PublicProtocol) {
88
obj.publicExtensionMethod()
99
obj.ufiExtensionMethod() // expected-error {{inaccessible}}
1010
obj.internalExtensionMethod() // expected-error {{inaccessible}}
11+
12+
_ = ^obj // expected-error {{}} expected-note {{}}
13+
_ = ^^obj // expected-error {{}}
14+
_ = ^^^obj // expected-error {{}}
1115
}
1216

1317
func test(_ obj: PublicImpl) {
1418
obj.publicExtensionMethod()
1519
obj.ufiExtensionMethod() // expected-error {{inaccessible}}
1620
obj.internalExtensionMethod() // expected-error {{inaccessible}}
21+
22+
_ = ^obj
23+
_ = ^^obj // expected-error {{}}
24+
_ = ^^^obj // expected-error {{}}
1725
}
1826

1927
func test(_ obj: UFIImpl) {
2028
obj.publicExtensionMethod() // This being accessible is the "hole".
2129
obj.ufiExtensionMethod() // expected-error {{inaccessible}}
2230
obj.internalExtensionMethod() // expected-error {{inaccessible}}
31+
32+
_ = ^obj // This being accessible is the "hole".
33+
_ = ^^obj // expected-error {{}}
34+
_ = ^^^obj // expected-error {{}}
2335
}

0 commit comments

Comments
 (0)