Merge pull request #84630 from xymus/non-neic-funcs-are-fragile

Sema: In embedded, consider functions as fragile unless `@_neverEmitIntoClient`
This commit is contained in:
Alexis Laferrière
2025-10-16 13:31:48 -07:00
committed by GitHub
11 changed files with 517 additions and 26 deletions

View File

@@ -202,7 +202,7 @@ struct ConformanceDiagnostic {
ProtocolDecl *ExistingExplicitProtocol;
};
/// Used in diagnostic %selects.
/// Used in diagnostic %selects via FRAGILE_FUNC_KIND.
struct FragileFunctionKind {
enum Kind : unsigned {
Transparent,
@@ -211,6 +211,7 @@ struct FragileFunctionKind {
DefaultArgument,
PropertyInitializer,
BackDeploy,
EmbeddedAlwaysEmitIntoClient,
None
};

View File

@@ -7312,7 +7312,8 @@ ERROR(usable_from_inline_attr_in_protocol,none,
"an '@_alwaysEmitIntoClient' function|" \
"a default argument value|" \
"a property initializer in a '@frozen' type|" \
"a '@backDeployed' function'}"
"a '@backDeployed' function|" \
"an embedded function not marked '@_neverEmitIntoClient'}"
ERROR(local_type_in_inlinable_function,
none, "type %0 cannot be nested inside " FRAGILE_FUNC_KIND "1",

View File

@@ -488,6 +488,11 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
case FragileFunctionKind::PropertyInitializer:
case FragileFunctionKind::BackDeploy:
return ResilienceExpansion::Minimal;
/// Embedded functions are treated as fragile for diagnostics only.
/// For code gen they are treated as normal and optimized later.
case FragileFunctionKind::EmbeddedAlwaysEmitIntoClient:
case FragileFunctionKind::None:
return ResilienceExpansion::Maximal;
}
@@ -551,6 +556,23 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
if (AFD->getDeclContext()->isLocalContext())
continue;
// Delay checking the implicit conditions after explicit declarations.
auto checkEmbeddedAlwaysEmitIntoClient = [&](const ValueDecl *VD) {
if (!VD->getASTContext().LangOpts.hasFeature(Feature::Embedded))
return FragileFunctionKind::None;
bool funcIsNEIC = VD->isNeverEmittedIntoClient();
bool storageIsNEIC = false;
if (auto accessor = dyn_cast<AccessorDecl>(VD))
storageIsNEIC = accessor->getStorage()->isNeverEmittedIntoClient();
// Accessors are implicitly EmbeddedAlwaysEmitIntoClient if neither the
// accessor or starage is marked @_neverEmitIntoClient.
if (!funcIsNEIC && !storageIsNEIC)
return FragileFunctionKind::EmbeddedAlwaysEmitIntoClient;
return FragileFunctionKind::None;
};
auto funcAccess =
AFD->getFormalAccessScope(/*useDC=*/nullptr,
/*treatUsableFromInlineAsPublic=*/true);
@@ -558,7 +580,8 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
// If the function is not externally visible, we will not be serializing
// its body.
if (!funcAccess.isPublic()) {
return {FragileFunctionKind::None};
// For non-public decls, only check embedded mode correctness.
return {checkEmbeddedAlwaysEmitIntoClient(AFD)};
}
// If the function is public, @_transparent implies @inlinable.
@@ -592,6 +615,10 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
return {FragileFunctionKind::BackDeploy};
}
}
auto implicitKind = checkEmbeddedAlwaysEmitIntoClient(AFD);
if (implicitKind != FragileFunctionKind::None)
return {implicitKind};
}
}

View File

@@ -689,6 +689,9 @@ void swift::simple_display(llvm::raw_ostream &out,
case FragileFunctionKind::BackDeploy:
out << "backDeploy";
return;
case FragileFunctionKind::EmbeddedAlwaysEmitIntoClient:
out << "embeddedAlwaysEmitIntoClient";
return;
case FragileFunctionKind::None:
out << "none";
return;

View File

@@ -5223,7 +5223,8 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info,
// restriction, macros would need to either be expanded when printed in
// swiftinterfaces or be parsable as macros by module clients.
auto fragileKind = DC->getFragileFunctionKind();
if (fragileKind.kind != FragileFunctionKind::None) {
if (fragileKind.kind != FragileFunctionKind::None &&
fragileKind.kind != FragileFunctionKind::EmbeddedAlwaysEmitIntoClient) {
for (auto availSpec : info->getQueries()) {
if (availSpec->getMacroLoc().isValid()) {
diags.diagnose(availSpec->getMacroLoc(),

View File

@@ -97,6 +97,14 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
return false;
}
// Embedded functions can reference non-public decls as they are visible
// to clients. Still report references to decls imported non-publicly
// to enforce access-level on imports.
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient &&
!problematicImport)
return false;
DowngradeToWarning downgradeToWarning = DowngradeToWarning::No;
// Swift 4.2 did not perform any checks for type aliases.
@@ -127,7 +135,6 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D);
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
if (problematicImport.has_value() &&
problematicImport->accessLevel < D->getFormalAccess()) {
Context.Diags.diagnose(problematicImport->importLoc,

View File

@@ -2946,7 +2946,8 @@ public:
// We don't allow nested types inside inlinable contexts.
auto kind = DC->getFragileFunctionKind();
if (kind.kind != FragileFunctionKind::None) {
if (kind.kind != FragileFunctionKind::None &&
kind.kind != FragileFunctionKind::EmbeddedAlwaysEmitIntoClient) {
NTD->diagnose(diag::local_type_in_inlinable_function, NTD->getName(),
kind.getSelector());
}

View File

@@ -0,0 +1,182 @@
/// Test @_implementationOnly internal import exportability diagnostics in embedded mode.
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule \
// RUN: %S/Inputs/implementation-only-imports/indirects.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t \
// RUN: %S/Inputs/implementation-only-imports/directs.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unrelated %s -I %t \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// REQUIRES: swift_feature_Embedded
// REQUIRES: embedded_stdlib_cross_compiling
@_implementationOnly internal import directs
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
// expected-note @-2 19 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
// expected-note @-3 12 {{initializer 'init()' imported as 'internal' from 'directs' here}}
import indirects
internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}
@inlinable
public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
}
nested()
localInternalFunc() // expected-error {{global function 'localInternalFunc()' is internal and cannot be referenced from an '@inlinable' function}}
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
explicitNonInliable()
}
public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
@_neverEmitIntoClient
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect()
if (true) {
_ = StructFromDirect()
}
@_neverEmitIntoClient
func nested() {
_ = StructFromDirect()
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
@_neverEmitIntoClient
internal func explicitNonInliableInternal(arg: StructFromDirect = StructFromDirect()) {
_ = StructFromDirect()
if (true) {
_ = StructFromDirect()
}
@_neverEmitIntoClient
func nested() {
_ = StructFromDirect()
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()) {
_ = StructFromIndirect()
if (true) {
_ = StructFromIndirect()
}
func nested() {
_ = StructFromIndirect()
}
nested()
}
public struct ExposedLayoutPublic {
public var publicField: StructFromDirect // expected-error {{property cannot be declared public because its type uses an internal type}}
// expected-error @-1 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
// expected-note @-2 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
private var privateField: StructFromDirect
}
private struct ExposedLayoutPrivate {
private var privateField: StructFromDirect
}

View File

@@ -0,0 +1,210 @@
/// Test @_implementationOnly import exportability diagnostics in embedded mode.
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule \
// RUN: %S/Inputs/implementation-only-imports/indirects.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t\
// RUN: %S/Inputs/implementation-only-imports/directs.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unrelated %s -I %t \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -define-availability "availMacro:macOS 26.0, iOS 26.0" \
// RUN: -enable-experimental-feature Embedded
// REQUIRES: swift_feature_Embedded
// REQUIRES: embedded_stdlib_cross_compiling
@_implementationOnly import directs
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
import indirects
internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}
@inlinable
public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-2 {{struct 'StructFromDirect' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-3 {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
}
nested()
localInternalFunc() // expected-error {{global function 'localInternalFunc()' is internal and cannot be referenced from an '@inlinable' function}}
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
explicitNonInliable()
}
public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-2 {{struct 'StructFromDirect' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-3 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
if #available(availMacro, *) { }
}
private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
@_neverEmitIntoClient
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-2 {{struct 'StructFromDirect' cannot be used in a default argument value because 'directs' was imported implementation-only}}
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
_ = StructFromDirect()
if (true) {
_ = StructFromDirect()
}
func nested() {
_ = StructFromDirect()
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}
@_neverEmitIntoClient
internal func explicitNonInliableInternal(arg: StructFromDirect = StructFromDirect()) {
_ = StructFromDirect()
if (true) {
_ = StructFromDirect()
}
func nested() {
_ = StructFromDirect()
}
nested()
localInternalFunc()
explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
struct NestedStruct {}
}
struct Accessors {
public var var1: Int {
get {
globalFunctionFromDirect() // expected-error {{global function 'globalFunctionFromDirect()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
return 0
}
}
@_alwaysEmitIntoClient
public var var2: Int {
get {
globalFunctionFromDirect() // expected-error {{global function 'globalFunctionFromDirect()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
return 0
}
}
@_neverEmitIntoClient
public var var3: Int {
get {
globalFunctionFromDirect()
return 0
}
}
public var var4: Int {
@_neverEmitIntoClient
get {
globalFunctionFromDirect()
return 0
}
}
}
public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()) {
_ = StructFromIndirect()
if (true) {
_ = StructFromIndirect()
}
func nested() {
_ = StructFromIndirect()
}
nested()
}
public struct ExposedLayoutPublic {
public var publicField: StructFromDirect // expected-error {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
private var privateField: StructFromDirect // FIXME should error
}
private struct ExposedLayoutPrivate {
private var privateField: StructFromDirect // FIXME should error
}

View File

@@ -0,0 +1,66 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule \
// RUN: %S/../Sema/Inputs/implementation-only-imports/indirects.swift \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t\
// RUN: %S/../Sema/Inputs/implementation-only-imports/directs.swift \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -emit-sil %s -I %t \
// RUN: -enable-experimental-feature Embedded
// REQUIRES: swift_feature_Embedded
// REQUIRES: embedded_stdlib_cross_compiling
@_implementationOnly import directs
import indirects
internal func localInternalFunc() {}
public func implicitlyInlinablePublic() {
localInternalFunc()
}
private func implicitlyInlinablePrivate() {
localInternalFunc()
}
@_neverEmitIntoClient
public func explicitNonInliable() {
_ = StructFromDirect()
if (true) {
_ = StructFromDirect()
}
@_neverEmitIntoClient
func nested() {
_ = StructFromDirect()
}
nested()
localInternalFunc()
}
@_alwaysEmitIntoClient
public func legalAccessToIndirect() {
_ = StructFromIndirect()
if (true) {
_ = StructFromIndirect()
}
func nested() {
_ = StructFromIndirect()
}
nested()
}
extension Array {
@_alwaysEmitIntoClient
public var myMutableSpan: Int {
get {
return 0
}
}
}

View File

@@ -12,7 +12,7 @@
// RUN: cp %S/Inputs/CHeader.h %t/Dependencies/
// RUN: cp %S/Inputs/module.modulemap %t/Dependencies/
// RUN: split-file %s %t/Files
// RUN: split-file %s %t/Files --leading-lines
// Compile the Swift dependencies into that same location.
// RUN: %target-swift-frontend -parse-as-library -emit-module %t/Dependencies/SwiftDependency.swift -enable-experimental-feature Embedded -o %t/Dependencies/SwiftDependency.swiftmodule
@@ -21,6 +21,9 @@
// against the dependencies.
// RUN: %target-swift-frontend -parse-as-library -emit-module %t/Files/Library.swift -enable-experimental-feature Embedded -I %t/Dependencies/ -o %t/Modules/Library.swiftmodule
// Building the library with invalid uses trigger errors.
// RUN: %target-swift-frontend -parse-as-library -typecheck -verify %t/Files/Library.swift -enable-experimental-feature Embedded -I %t/Dependencies/ -o %t/Modules/Library.swiftmodule -DBAD_IOI_USAGE
// Remove the dependencies so there is no way we can find them later.
// RUN: rm -rf %t/Dependencies
@@ -28,19 +31,12 @@
// @_neverEmitIntoClient hides the body of test().
// RUN: %target-swift-frontend -emit-ir -parse-as-library %t/Files/Application.swift -enable-experimental-feature Embedded -I %t/Modules -o %t/Application.ir
// Build the application against the library, but intentionally trigger
// deserialization of some serialized SIL that refers to an implementation-only
// dependency. Right now, these fail spectacularly. Over time, we want them to
// become compile-time errors or start working.
// RUN: not --crash %target-swift-frontend -emit-ir -parse-as-library %t/Files/Application.swift -enable-experimental-feature Embedded -I %t/Modules -o %t/Application.ir -DBAD_C_USAGE
// RUN: not --crash %target-swift-frontend -emit-ir -parse-as-library %t/Files/Application.swift -enable-experimental-feature Embedded -I %t/Modules -o %t/Application.ir -DBAD_SWIFT_USAGE
// REQUIRES: swift_in_compiler
// REQUIRES: swift_feature_Embedded
//--- Library.swift
@_implementationOnly import CDependency
@_implementationOnly import SwiftDependency
@_implementationOnly import CDependency // expected-warning {{using '@_implementationOnly' without enabling library evolution for 'Library' may lead to instability during execution}}
@_implementationOnly import SwiftDependency // expected-warning {{using '@_implementationOnly' without enabling library evolution for 'Library' may lead to instability during execution}}
@_neverEmitIntoClient
public func test() {
@@ -48,13 +44,17 @@ public func test() {
A().doSomething()
}
#if BAD_IOI_USAGE
public func badCLibraryUsage() {
_ = getPoint(3.14159, 2.71828)
_ = getPoint(3.14159, 2.71828) // expected-error {{global function 'getPoint' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'CDependency' was imported implementation-only}}
}
public func badSwiftLibraryUsage() {
A().doSomething()
A().doSomething() // expected-error {{struct 'A' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'SwiftDependency' was imported implementation-only}}
// expected-error @-1 {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'SwiftDependency' was imported implementation-only}}
// expected-error @-2 {{instance method 'doSomething()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'SwiftDependency' was imported implementation-only}}
}
#endif
//--- Application.swift
@@ -62,12 +62,4 @@ import Library
public func useTest() {
test()
#if BAD_C_USAGE
badCLibraryUsage()
#endif
#if BAD_SWIFT_USAGE
badSwiftLibraryUsage()
#endif
}