mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Consider functions in embedded mode to be fragile unless marked with `@_neverEmitIntoClient`. Basically treating them as if they were `@_alwaysEmitIntoClient` by default. A fragile function cannot reference restricted imports such as `@_implementationOnly`, `internal import`, etc. We consider them as fragile only for type-checking, at the SIL level they remain treated as normal functions like before. This allows the later optimization to work as expected. We may want to likely align both ends of the compiler once this is properly supported in sema. This is enabled only in embedded. Fragile functions in library-evolution are marked with attributes and are already checked. We do not need this is non-embedded non-library-evolution as CMO handles inlining and already takes into consideration `@_implementationOnly` imports. Note: We'll need a similar check for memory layouts exposed to clients. We can still see compiler crashes and miscompiles in this scenario. This will apply to both embedded and non-library-evolution modes. That will likely need to extend the `@_neverEmitIntoClient` attribute and may require a staged deployment. rdar://161365361
172 lines
8.2 KiB
Swift
172 lines
8.2 KiB
Swift
/// 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-macosx15.0 \
|
|
// 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-macosx15.0 \
|
|
// RUN: -enable-experimental-feature Embedded
|
|
|
|
// RUN: %target-swift-frontend -typecheck -verify %s -I %t \
|
|
// RUN: -swift-version 5 -target arm64-apple-macosx15.0 \
|
|
// RUN: -enable-experimental-feature Embedded
|
|
|
|
// REQUIRES: swift_feature_Embedded
|
|
|
|
@_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()
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
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
|
|
}
|