mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
182
test/Sema/access-level-import-embedded.swift
Normal file
182
test/Sema/access-level-import-embedded.swift
Normal 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
|
||||
}
|
||||
210
test/Sema/implementation-only-import-embedded.swift
Normal file
210
test/Sema/implementation-only-import-embedded.swift
Normal 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
|
||||
}
|
||||
66
test/embedded/implementation-only-import-build.swift
Normal file
66
test/embedded/implementation-only-import-build.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user