Files
swift-mirror/test/SPI/spi-only-import-exportability.swift
Alexis Laferrière 2d339c1260 Sema: Custom diagnostic for var decls referencing a restricted type
Replace the `here` part of the generic exportability diagnostic for
variables with: `in a property declaration marked public or in a
'@frozen' or '@usableFromInline' context`.

The full diagnostic now looks like:
```
error: cannot use struct 'ImportedType' in a property declaration marked
public or in a '@frozen' or '@usableFromInline' context;
'HiddenDependency' has been imported as implementation-only
```

This should be improved further to support implicitly exported memory
layouts in non-library-evolution and embedded.
2025-10-21 11:30:52 -07:00

158 lines
6.5 KiB
Swift

/// Test @_spiOnly exportability type-checking
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
/// Generate dependencies.
// RUN: %target-swift-frontend -emit-module %t/PublicLib.swift \
// RUN: -module-name PublicLib -emit-module-path %t/PublicLib.swiftmodule \
// RUN: -swift-version 5 -enable-library-evolution
// RUN: %target-swift-frontend -emit-module %t/SPIOnlyImportedLib.swift \
// RUN: -module-name SPIOnlyImportedLib \
// RUN: -emit-module-path %t/SPIOnlyImportedLib.swiftmodule \
// RUN: -swift-version 5 -enable-library-evolution -I %t
/// Test the client.
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t -verify -verify-ignore-unrelated \
// RUN: -experimental-spi-only-imports
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t -verify -verify-ignore-unrelated \
// RUN: -experimental-spi-only-imports \
// RUN: -enable-library-evolution
/// Generate the swiftinterface of the working code and verify it.
// RUN: %target-swift-emit-module-interfaces(%t/Client.swiftinterface, %t/Client.private.swiftinterface) \
// RUN: %t/Client.swift -I %t -DSKIP_ERRORS \
// RUN: -experimental-spi-only-imports
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.swiftinterface) -I %t
// RUN: %target-swift-typecheck-module-from-interface(%t/Client.private.swiftinterface) -I %t
//--- PublicLib.swift
public struct PublicType {
public init() {}
}
public protocol PublicProtocol {}
public func conformanceUse(_ a: PublicProtocol) {}
@propertyWrapper
public struct PublicPropertyWrapper<T> {
public var wrappedValue: T
public init(wrappedValue value: T) { self.wrappedValue = value }
public init(_ value: T) { self.wrappedValue = value }
}
//--- SPIOnlyImportedLib.swift
import PublicLib
public func spiOnlyFunc() -> String { fatalError() }
public protocol SPIOnlyProto {
}
public struct SPIOnlyStruct {
public init() {}
public func structMethod() {}
}
public class SPIOnlyClass<P: PublicProtocol> {
public init(p: P) {}
public func classMethod() {}
}
public enum SPIOnlyEnum {
case A
case B
public func enumMethod() {}
}
extension PublicType {
public func spiOnlyExtensionMethod() {}
}
extension PublicType : PublicProtocol {}
@propertyWrapper
public struct SPIOnlyPropertyWrapper<T> {
public var wrappedValue: T
public init(wrappedValue value: T) { self.wrappedValue = value }
public init(_ value: T) { self.wrappedValue = value }
}
//--- Client.swift
import PublicLib
@_spiOnly import SPIOnlyImportedLib
#if !SKIP_ERRORS
public func publicUser<T: SPIOnlyProto>(_ a: SPIOnlyStruct, t: T) -> SPIOnlyStruct { fatalError() }
// expected-error @-1 2 {{cannot use struct 'SPIOnlyStruct' here; 'SPIOnlyImportedLib' was imported for SPI only}}
// expected-error @-2 {{cannot use protocol 'SPIOnlyProto' here; 'SPIOnlyImportedLib' was imported for SPI only}}
#endif
@_spi(X) public func spiUser(_ a: SPIOnlyStruct) -> SPIOnlyStruct { fatalError() }
internal func internalUser(_ a: SPIOnlyStruct) -> SPIOnlyStruct { fatalError() }
#if !SKIP_ERRORS
@inlinable
public func publicInlinableUser() {
_ = spiOnlyFunc() // expected-error {{global function 'spiOnlyFunc()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
var x: SPIOnlyStruct // expected-error {{struct 'SPIOnlyStruct' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
x = SPIOnlyStruct() // expected-error {{struct 'SPIOnlyStruct' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
// expected-error @-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
x.structMethod() // expected-error {{instance method 'structMethod()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
var c: SPIOnlyClass<PublicType> // expected-error {{generic class 'SPIOnlyClass' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
c = SPIOnlyClass(p: PublicType()) // expected-error {{generic class 'SPIOnlyClass' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
// expected-error @-1 {{initializer 'init(p:)' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
c.classMethod() // expected-error {{instance method 'classMethod()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
var e: SPIOnlyEnum // expected-error {{enum 'SPIOnlyEnum' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
e = .A // expected-error {{enum case 'A' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
e.enumMethod() // expected-error {{instance method 'enumMethod()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
let p: PublicType = PublicType()
p.spiOnlyExtensionMethod() // expected-error {{instance method 'spiOnlyExtensionMethod()' cannot be used in an '@inlinable' function because 'SPIOnlyImportedLib' was imported for SPI only}}
conformanceUse(p) // expected-error{{cannot use conformance of 'PublicType' to 'PublicProtocol' here; 'SPIOnlyImportedLib' was imported for SPI only}}
}
#endif
@inlinable @_spi(X)
public func spiInlinableUser() {
_ = spiOnlyFunc()
var x: SPIOnlyStruct
x = SPIOnlyStruct()
x.structMethod()
let p: PublicType = PublicType()
p.spiOnlyExtensionMethod()
conformanceUse(p)
}
public func implementationDetailsUser() {
_ = spiOnlyFunc()
var x: SPIOnlyStruct
x = SPIOnlyStruct()
x.structMethod()
let p: PublicType = PublicType()
p.spiOnlyExtensionMethod()
conformanceUse(p)
}
public struct ClientStruct {
#if !SKIP_ERRORS
public var a: SPIOnlyStruct // expected-error {{cannot use struct 'SPIOnlyStruct' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'SPIOnlyImportedLib' was imported for SPI only}}
// expected-error@+1 {{cannot use property 'wrappedValue' here; 'SPIOnlyImportedLib' was imported for SPI only}}
@SPIOnlyPropertyWrapper(42) public var aWrapped: Any // expected-error {{cannot use generic struct 'SPIOnlyPropertyWrapper' as property wrapper here; 'SPIOnlyImportedLib' was imported for SPI only}}
#endif
@PublicPropertyWrapper(SPIOnlyStruct()) public var bWrapped: Any
}