Skip to content

Commit bf44341

Browse files
committed
Sema: Fix superfluous error about private decls in internal memory layouts
Don't consider implicitly exposed memory layouts when checking for usable from inline correctness. That check applies only to memory layouts marked as exposed explicitly. Consider the implict state only at the general availability checking.
1 parent 4883212 commit bf44341

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6727,7 +6727,10 @@ class VarDecl : public AbstractStorageDecl {
67276727
///
67286728
/// From the standpoint of access control and exportability checking, this
67296729
/// var will behave as if it was public, even if it is internal or private.
6730-
bool isLayoutExposedToClients() const;
6730+
///
6731+
/// If \p applyImplicit, consider implicitly exposed layouts as well.
6732+
/// This applies to non-resilient modules.
6733+
bool isLayoutExposedToClients(bool applyImplicit = false) const;
67316734

67326735
/// Is this a special debugger variable?
67336736
bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; }

lib/AST/Availability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ bool swift::isExported(const ValueDecl *VD) {
10061006

10071007
// Is this a stored property in a @frozen struct or class?
10081008
if (auto *property = dyn_cast<VarDecl>(VD))
1009-
if (property->isLayoutExposedToClients())
1009+
if (property->isLayoutExposedToClients(/*applyImplicit=*/true))
10101010
return true;
10111011

10121012
return false;

lib/AST/Decl.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,7 +2753,7 @@ bool VarDecl::isInitExposedToClients() const {
27532753
return hasInitialValue() && isLayoutExposedToClients();
27542754
}
27552755

2756-
bool VarDecl::isLayoutExposedToClients() const {
2756+
bool VarDecl::isLayoutExposedToClients(bool applyImplicit) const {
27572757
auto parent = dyn_cast<NominalTypeDecl>(getDeclContext());
27582758
if (!parent) return false;
27592759
if (isStatic()) return false;
@@ -2763,9 +2763,11 @@ bool VarDecl::isLayoutExposedToClients() const {
27632763
parent->getFormalAccessScope(/*useDC=*/nullptr,
27642764
/*treatUsableFromInlineAsPublic=*/true);
27652765

2766-
// Resilient modules hide layouts by default.
2767-
if (!getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) ||
2768-
M->getResilienceStrategy() == ResilienceStrategy::Resilient) {
2766+
// Resilient modules and classes hide layouts by default.
2767+
bool layoutIsHiddenByDefault = !applyImplicit ||
2768+
!getASTContext().LangOpts.hasFeature(Feature::CheckImplementationOnly) ||
2769+
M->getResilienceStrategy() == ResilienceStrategy::Resilient;
2770+
if (layoutIsHiddenByDefault) {
27692771
if (!nominalAccess.isPublic())
27702772
return false;
27712773

test/Sema/hidden-memory-layout.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ public struct ExposedLayoutPublic {
6262
public init() { fatalError() }
6363
}
6464

65+
internal struct ExposedLayoutInternal {
66+
}
67+
6568
private struct ExposedLayoutPrivate {
6669
// expected-note @-1 2 {{struct 'ExposedLayoutPrivate' is not '@usableFromInline' or public}}
67-
// expected-opt-in-note @-2 {{type declared here}}
6870
init() { fatalError() } // expected-note {{initializer 'init()' is not '@usableFromInline' or public}}
6971
}
7072

@@ -74,7 +76,7 @@ private struct HiddenLayout {
7476
// expected-opt-in-note @-1 2 {{struct 'HiddenLayout' is not '@usableFromInline' or public}}
7577
// expected-opt-in-note @-2 1 {{initializer 'init()' is not '@usableFromInline' or public}}
7678
// expected-opt-in-note @-3 2 {{struct declared here}}
77-
// expected-opt-in-note @-4 {{type declared here}}
79+
// expected-opt-in-note @-4 {{struct declared here}}
7880
}
7981
#else
8082
private struct HiddenLayout {
@@ -163,12 +165,26 @@ public struct ExposedLayoutPublicUser {
163165
// expected-opt-in-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
164166

165167
private var a: ExposedLayoutPublic
168+
private var aa: ExposedLayoutInternal
166169
private var b: ExposedLayoutPrivate
167-
// expected-opt-in-error @-1 {{type referenced from a stored property in a '@frozen' struct must be '@usableFromInline' or public}}
168170

169171
private var c: HiddenLayout
170172
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; it is a struct marked '@_implementationOnly'}}
171-
// expected-opt-in-error @-2 {{type referenced from a stored property in a '@frozen' struct must be '@usableFromInline' or public}}
173+
174+
private func privateFunc(h: HiddenLayout) {}
175+
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because it is a struct marked '@_implementationOnly'}}
176+
}
177+
178+
private struct ExposedLayoutInternalUser {
179+
180+
private var privateField: StructFromDirect
181+
// expected-opt-in-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
182+
183+
private var a: ExposedLayoutPublic
184+
private var aa: ExposedLayoutInternal
185+
private var b: ExposedLayoutPrivate
186+
private var c: HiddenLayout
187+
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; it is a struct marked '@_implementationOnly'}}
172188

173189
private func privateFunc(h: HiddenLayout) {}
174190
// expected-embedded-opt-in-error @-1 {{struct 'HiddenLayout' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because it is a struct marked '@_implementationOnly'}}
@@ -180,6 +196,7 @@ private struct ExposedLayoutPrivateUser {
180196
// expected-opt-in-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
181197

182198
private var a: ExposedLayoutPublic
199+
private var aa: ExposedLayoutInternal
183200
private var b: ExposedLayoutPrivate
184201
private var c: HiddenLayout
185202
// expected-opt-in-error @-1 {{cannot use struct 'HiddenLayout' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; it is a struct marked '@_implementationOnly'}}
@@ -194,6 +211,7 @@ private struct HiddenLayoutUser {
194211
public var publicField: StructFromDirect
195212
private var privateField: StructFromDirect
196213
private var a: ExposedLayoutPublic
214+
private var aa: ExposedLayoutInternal
197215
private var b: ExposedLayoutPrivate
198216
private var c: HiddenLayout
199217

0 commit comments

Comments
 (0)