Skip to content

Commit 7d4e567

Browse files
committed
Compare the package names of the accessing module and the decl's defining module.
Update tests.
1 parent f5150e7 commit 7d4e567

File tree

7 files changed

+47
-38
lines changed

7 files changed

+47
-38
lines changed

include/swift/AST/Module.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,8 @@ class ModuleDecl
480480
return Identifier();
481481
}
482482

483-
bool inPackage(std::string packageName) {
484-
return !getPackageName().empty() && getPackageName().str() == packageName;
483+
bool inSamePackage(ModuleDecl *other) {
484+
return !getPackageName().empty() && getPackageName() == other->getPackageName();
485485
}
486486

487487
/// Get the package associated with this module

lib/AST/Decl.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,14 +2957,16 @@ bool AbstractStorageDecl::isResilient() const {
29572957
if (getAttrs().hasAttribute<FixedLayoutAttr>())
29582958
return false;
29592959

2960+
// If we're an instance property of a nominal type, query the type.
29602961
if (!isStatic())
29612962
if (auto *nominalDecl = getDeclContext()->getSelfNominalTypeDecl())
29622963
return nominalDecl->isResilient();
29632964

29642965
// Non-public global and static variables always have a
29652966
// fixed layout.
2966-
if (!getFormalAccessScope(/*useDC=*/nullptr,
2967-
/*treatUsableFromInlineAsPublic=*/true).isPublicOrPackage())
2967+
auto accessScope = getFormalAccessScope(/*useDC=*/nullptr,
2968+
/*treatUsableFromInlineAsPublic=*/true);
2969+
if (!accessScope.isPublicOrPackage())
29682970
return false;
29692971

29702972
if (!getModuleContext()->isResilient())
@@ -2973,8 +2975,7 @@ bool AbstractStorageDecl::isResilient() const {
29732975
// Allows bypassing resilience checks for package decls
29742976
// at use site within a package if opted in, whether the
29752977
// loaded module was built resiliently or not.
2976-
return !getDeclContext()->bypassResilienceInPackage(getFormalAccessScope(/*useDC=*/nullptr,
2977-
/*treatUsableFromInlineAsPublic=*/true).isPackage());
2978+
return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
29782979
}
29792980

29802981
bool AbstractStorageDecl::isResilient(ModuleDecl *M,
@@ -5050,8 +5051,9 @@ bool NominalTypeDecl::isResilient() const {
50505051
// Allows bypassing resilience checks for package decls
50515052
// at use site within a package if opted in, whether the
50525053
// loaded module was built resiliently or not.
5053-
return !getDeclContext()->bypassResilienceInPackage(getFormalAccessScope(/*useDC=*/nullptr,
5054-
/*treatUsableFromInlineAsPublic=*/true).isPackage());
5054+
auto accessScope = getFormalAccessScope(/*useDC=*/nullptr,
5055+
/*treatUsableFromInlineAsPublic=*/true);
5056+
return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
50555057
}
50565058

50575059
DestructorDecl *NominalTypeDecl::getValueTypeDestructor() {

lib/AST/DeclContext.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,12 @@ PackageUnit *DeclContext::getPackageContext(bool lookupIfNotCurrent) const {
302302

303303
bool DeclContext::bypassResilienceInPackage(bool isForPackageDecl) const {
304304
// Bypassing resilience checks only applies to package types (and possibly
305-
// public types in a package in the future). Allowed only if opted-in for
306-
// bypassing checks, client and defining module are in the same package,
307-
// and defining module is a binary module.
305+
// public types in the same package in the future). Allowed only if opted-in
306+
// for bypassing optimization, client and defining module are in the same
307+
// package, and defining module is a binary module.
308308
return isForPackageDecl &&
309309
getASTContext().LangOpts.EnableBypassResilienceInPackage &&
310-
getParentModule()->inPackage(getASTContext().LangOpts.PackageName) &&
310+
getParentModule()->inSamePackage(getASTContext().MainModule) &&
311311
!getParentModule()->isBuiltFromInterface();
312312
}
313313

lib/AST/ProtocolConformance.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ bool NormalProtocolConformance::isResilient() const {
349349
// individual witnesses.
350350
if (!getDeclContext()->getSelfNominalTypeDecl()->isResilient())
351351
return false;
352+
352353
return getDeclContext()->getParentModule()->isResilient();
353354
}
354355

lib/Sema/ImportResolution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ void UnboundImport::validateInterfaceWithPackageName(ModuleDecl *topLevelModule,
762762

763763
// If source file is .swift or non-interface, show diags when importing an interface file
764764
ASTContext &ctx = topLevelModule->getASTContext();
765-
if (topLevelModule->inPackage(ctx.LangOpts.PackageName) &&
765+
if (topLevelModule->inSamePackage(ctx.MainModule) &&
766766
topLevelModule->isBuiltFromInterface() &&
767767
!topLevelModule->getModuleSourceFilename().endswith(".package.swiftinterface")) {
768768
ctx.Diags.diagnose(import.module.getModulePath().front().Loc,

test/IRGen/package_resilience.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public func memoryLayoutDotSizeWithResilientStruct() -> Int {
221221
// CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience40memoryLayoutDotStrideWithResilientStructSiyF"()
222222
public func memoryLayoutDotStrideWithResilientStruct() -> Int {
223223
// CHECK: ret [[INT]] [[#WORDSIZE + WORDSIZE]]
224-
return MemoryLayout<Size>.size
224+
return MemoryLayout<Size>.stride
225225
}
226226

227227
// CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience43memoryLayoutDotAlignmentWithResilientStructSiyF"()

test/Sema/package_resilience_bypass_exhaustive_switch.swift

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,24 @@
1313

1414
//--- Utils.swift
1515

16-
public enum PublicEnum {
16+
package enum PkgEnum {
1717
case one
1818
case two(Int)
1919
}
2020

21-
@frozen
22-
public enum FrozenPublicEnum {
21+
@usableFromInline
22+
package enum UfiPkgEnum {
2323
case one
2424
case two(Int)
2525
}
2626

27-
package enum PkgEnum {
27+
public enum PublicEnum {
2828
case one
2929
case two(Int)
3030
}
3131

32-
public struct PublicStruct {
33-
public var publicVar: Int
34-
}
35-
36-
package enum PkgEnumWithPublicCase {
37-
case one
38-
case two(PublicStruct)
39-
}
40-
41-
package enum PkgEnumWithExistentialCase {
42-
case one
43-
case two(any StringProtocol)
44-
}
45-
46-
@usableFromInline
47-
package enum UfiPkgEnum {
32+
@frozen
33+
public enum FrozenPublicEnum {
4834
case one
4935
case two(Int)
5036
}
@@ -61,7 +47,16 @@ func f(_ arg: PkgEnum) -> Int {
6147
}
6248
}
6349

64-
public func g(_ arg: PublicEnum) -> Int {
50+
func g(_ arg: UfiPkgEnum) -> Int {
51+
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
52+
case .one:
53+
return 1
54+
case .two(let val):
55+
return 2 + val
56+
}
57+
}
58+
59+
public func h(_ arg: PublicEnum) -> Int {
6560
switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
6661
case .one:
6762
return 1
@@ -70,7 +65,7 @@ public func g(_ arg: PublicEnum) -> Int {
7065
}
7166
}
7267

73-
public func h(_ arg: FrozenPublicEnum) -> Int {
68+
public func k(_ arg: FrozenPublicEnum) -> Int {
7469
switch arg { // no-warning
7570
case .one:
7671
return 1
@@ -92,8 +87,19 @@ func f(_ arg: PkgEnum) -> Int {
9287
}
9388
}
9489

90+
// Warning still shows up for usableFromInline package enum as the optimization is targeted for
91+
// decls with package access, not the elevated public access. This might be allowed later.
92+
func g(_ arg: UfiPkgEnum) -> Int {
93+
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
94+
case .one:
95+
return 1
96+
case .two(let val):
97+
return 2 + val
98+
}
99+
}
100+
95101
// Warning still shows up for public enum as the optimization is targeted for package types.
96-
public func g(_ arg: PublicEnum) -> Int {
102+
public func h(_ arg: PublicEnum) -> Int {
97103
switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
98104
case .one:
99105
return 1
@@ -102,7 +108,7 @@ public func g(_ arg: PublicEnum) -> Int {
102108
}
103109
}
104110

105-
public func h(_ arg: FrozenPublicEnum) -> Int {
111+
public func k(_ arg: FrozenPublicEnum) -> Int {
106112
switch arg { // no-warning
107113
case .one:
108114
return 1

0 commit comments

Comments
 (0)