Compare the package names of the accessing module and the decl's defining module.

Update tests.
This commit is contained in:
Ellie Shin
2024-02-08 20:08:46 -08:00
parent f5150e7265
commit 7d4e5678c7
7 changed files with 52 additions and 43 deletions

View File

@@ -480,8 +480,8 @@ public:
return Identifier(); return Identifier();
} }
bool inPackage(std::string packageName) { bool inSamePackage(ModuleDecl *other) {
return !getPackageName().empty() && getPackageName().str() == packageName; return !getPackageName().empty() && getPackageName() == other->getPackageName();
} }
/// Get the package associated with this module /// Get the package associated with this module

View File

@@ -2957,14 +2957,16 @@ bool AbstractStorageDecl::isResilient() const {
if (getAttrs().hasAttribute<FixedLayoutAttr>()) if (getAttrs().hasAttribute<FixedLayoutAttr>())
return false; return false;
// If we're an instance property of a nominal type, query the type.
if (!isStatic()) if (!isStatic())
if (auto *nominalDecl = getDeclContext()->getSelfNominalTypeDecl()) if (auto *nominalDecl = getDeclContext()->getSelfNominalTypeDecl())
return nominalDecl->isResilient(); return nominalDecl->isResilient();
// Non-public global and static variables always have a // Non-public global and static variables always have a
// fixed layout. // fixed layout.
if (!getFormalAccessScope(/*useDC=*/nullptr, auto accessScope = getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true).isPublicOrPackage()) /*treatUsableFromInlineAsPublic=*/true);
if (!accessScope.isPublicOrPackage())
return false; return false;
if (!getModuleContext()->isResilient()) if (!getModuleContext()->isResilient())
@@ -2973,8 +2975,7 @@ bool AbstractStorageDecl::isResilient() const {
// Allows bypassing resilience checks for package decls // Allows bypassing resilience checks for package decls
// at use site within a package if opted in, whether the // at use site within a package if opted in, whether the
// loaded module was built resiliently or not. // loaded module was built resiliently or not.
return !getDeclContext()->bypassResilienceInPackage(getFormalAccessScope(/*useDC=*/nullptr, return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
/*treatUsableFromInlineAsPublic=*/true).isPackage());
} }
bool AbstractStorageDecl::isResilient(ModuleDecl *M, bool AbstractStorageDecl::isResilient(ModuleDecl *M,
@@ -5050,8 +5051,9 @@ bool NominalTypeDecl::isResilient() const {
// Allows bypassing resilience checks for package decls // Allows bypassing resilience checks for package decls
// at use site within a package if opted in, whether the // at use site within a package if opted in, whether the
// loaded module was built resiliently or not. // loaded module was built resiliently or not.
return !getDeclContext()->bypassResilienceInPackage(getFormalAccessScope(/*useDC=*/nullptr, auto accessScope = getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true).isPackage()); /*treatUsableFromInlineAsPublic=*/true);
return !getDeclContext()->bypassResilienceInPackage(accessScope.isPackage());
} }
DestructorDecl *NominalTypeDecl::getValueTypeDestructor() { DestructorDecl *NominalTypeDecl::getValueTypeDestructor() {

View File

@@ -302,12 +302,12 @@ PackageUnit *DeclContext::getPackageContext(bool lookupIfNotCurrent) const {
bool DeclContext::bypassResilienceInPackage(bool isForPackageDecl) const { bool DeclContext::bypassResilienceInPackage(bool isForPackageDecl) const {
// Bypassing resilience checks only applies to package types (and possibly // Bypassing resilience checks only applies to package types (and possibly
// public types in a package in the future). Allowed only if opted-in for // public types in the same package in the future). Allowed only if opted-in
// bypassing checks, client and defining module are in the same package, // for bypassing optimization, client and defining module are in the same
// and defining module is a binary module. // package, and defining module is a binary module.
return isForPackageDecl && return isForPackageDecl &&
getASTContext().LangOpts.EnableBypassResilienceInPackage && getASTContext().LangOpts.EnableBypassResilienceInPackage &&
getParentModule()->inPackage(getASTContext().LangOpts.PackageName) && getParentModule()->inSamePackage(getASTContext().MainModule) &&
!getParentModule()->isBuiltFromInterface(); !getParentModule()->isBuiltFromInterface();
} }

View File

@@ -349,6 +349,7 @@ bool NormalProtocolConformance::isResilient() const {
// individual witnesses. // individual witnesses.
if (!getDeclContext()->getSelfNominalTypeDecl()->isResilient()) if (!getDeclContext()->getSelfNominalTypeDecl()->isResilient())
return false; return false;
return getDeclContext()->getParentModule()->isResilient(); return getDeclContext()->getParentModule()->isResilient();
} }

View File

@@ -762,7 +762,7 @@ void UnboundImport::validateInterfaceWithPackageName(ModuleDecl *topLevelModule,
// If source file is .swift or non-interface, show diags when importing an interface file // If source file is .swift or non-interface, show diags when importing an interface file
ASTContext &ctx = topLevelModule->getASTContext(); ASTContext &ctx = topLevelModule->getASTContext();
if (topLevelModule->inPackage(ctx.LangOpts.PackageName) && if (topLevelModule->inSamePackage(ctx.MainModule) &&
topLevelModule->isBuiltFromInterface() && topLevelModule->isBuiltFromInterface() &&
!topLevelModule->getModuleSourceFilename().endswith(".package.swiftinterface")) { !topLevelModule->getModuleSourceFilename().endswith(".package.swiftinterface")) {
ctx.Diags.diagnose(import.module.getModulePath().front().Loc, ctx.Diags.diagnose(import.module.getModulePath().front().Loc,

View File

@@ -221,7 +221,7 @@ public func memoryLayoutDotSizeWithResilientStruct() -> Int {
// CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience40memoryLayoutDotStrideWithResilientStructSiyF"() // CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience40memoryLayoutDotStrideWithResilientStructSiyF"()
public func memoryLayoutDotStrideWithResilientStruct() -> Int { public func memoryLayoutDotStrideWithResilientStruct() -> Int {
// CHECK: ret [[INT]] [[#WORDSIZE + WORDSIZE]] // CHECK: ret [[INT]] [[#WORDSIZE + WORDSIZE]]
return MemoryLayout<Size>.size return MemoryLayout<Size>.stride
} }
// CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience43memoryLayoutDotAlignmentWithResilientStructSiyF"() // CHECK-LABEL: define{{.*}} swiftcc {{i32|i64}} @"$s18package_resilience43memoryLayoutDotAlignmentWithResilientStructSiyF"()

View File

@@ -13,6 +13,17 @@
//--- Utils.swift //--- Utils.swift
package enum PkgEnum {
case one
case two(Int)
}
@usableFromInline
package enum UfiPkgEnum {
case one
case two(Int)
}
public enum PublicEnum { public enum PublicEnum {
case one case one
case two(Int) case two(Int)
@@ -24,31 +35,6 @@ public enum FrozenPublicEnum {
case two(Int) case two(Int)
} }
package enum PkgEnum {
case one
case two(Int)
}
public struct PublicStruct {
public var publicVar: Int
}
package enum PkgEnumWithPublicCase {
case one
case two(PublicStruct)
}
package enum PkgEnumWithExistentialCase {
case one
case two(any StringProtocol)
}
@usableFromInline
package enum UfiPkgEnum {
case one
case two(Int)
}
//--- ClientDefault.swift //--- ClientDefault.swift
import Utils import Utils
@@ -61,7 +47,16 @@ func f(_ arg: PkgEnum) -> Int {
} }
} }
public func g(_ arg: PublicEnum) -> Int { func g(_ arg: UfiPkgEnum) -> Int {
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
case .one:
return 1
case .two(let val):
return 2 + val
}
}
public func h(_ arg: PublicEnum) -> Int {
switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}} switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
case .one: case .one:
return 1 return 1
@@ -70,7 +65,7 @@ public func g(_ arg: PublicEnum) -> Int {
} }
} }
public func h(_ arg: FrozenPublicEnum) -> Int { public func k(_ arg: FrozenPublicEnum) -> Int {
switch arg { // no-warning switch arg { // no-warning
case .one: case .one:
return 1 return 1
@@ -92,8 +87,19 @@ func f(_ arg: PkgEnum) -> Int {
} }
} }
// Warning still shows up for usableFromInline package enum as the optimization is targeted for
// decls with package access, not the elevated public access. This might be allowed later.
func g(_ arg: UfiPkgEnum) -> Int {
switch arg { // expected-warning {{switch covers known cases, but 'UfiPkgEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
case .one:
return 1
case .two(let val):
return 2 + val
}
}
// Warning still shows up for public enum as the optimization is targeted for package types. // Warning still shows up for public enum as the optimization is targeted for package types.
public func g(_ arg: PublicEnum) -> Int { public func h(_ arg: PublicEnum) -> Int {
switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}} switch arg { // expected-warning {{switch covers known cases, but 'PublicEnum' may have additional unknown values}} {{none}} expected-note {{handle unknown values using "@unknown default"}}
case .one: case .one:
return 1 return 1
@@ -102,7 +108,7 @@ public func g(_ arg: PublicEnum) -> Int {
} }
} }
public func h(_ arg: FrozenPublicEnum) -> Int { public func k(_ arg: FrozenPublicEnum) -> Int {
switch arg { // no-warning switch arg { // no-warning
case .one: case .one:
return 1 return 1