Files
swift-mirror/test/LiteralExpressions/VisibilityRestriction.swift
Artem Chikin d327f3401b [Literal Expressions] Prohibit references to @usableFromInline internal declaration values
Although a `@usableFromInline` variable cannot be named directly by a client, its value can still reach a client binary: an `@inlinable` function may fold the variable into an integer generic argument, and that folded value is then serialized into the function body that the client inlines.
e.g.
```swift
@usableFromInline let x = 8, y = 8, z = 8

@usableFromInline func bar(_ zs: [z of Int]) {}

@inlinable public func foo() {
  let xs: [x of Int] = [1, 2, 3, 4, 5, 6, 7, 8]
  let ys: [y of Int] = xs
  bar(ys)
}
```
A subsequent change to the folded value would leave already-compiled clients inconsistent with the evolved module, so the variable's value is, in effect, part of the ABI.
2026-06-08 10:35:06 +01:00

51 lines
2.7 KiB
Swift

// Literal expressions may not reference `let` bindings that are part of the
// module's ABI surface: publicly visible bindings, or `@usableFromInline` ones.
// REQUIRES: swift_feature_LiteralExpressions
// RUN: %target-swift-frontend -typecheck %s -verify \
// RUN: -package-name myPkg \
// RUN: -disable-availability-checking \
// RUN: -enable-experimental-feature LiteralExpressions
public let publicPageSize = 4096
package let packagePageSize = 4096
internal let internalPageSize = 4096
@usableFromInline internal let usableFromInlinePageSize = 4096
fileprivate let filePrivatePageSize = 4096
private let privatePageSize = 4096
// =============================================================================
// @section initializer position: public and package bindings are rejected.
// `open` is not exercised here because it cannot apply to a top-level `let`;
// the diagnostic's `%select` branch for `open` is preserved for completeness.
// =============================================================================
@section("mysection") let a = 2 * publicPageSize
// expected-error@-1 {{reference to a public 'let' binding is not permitted in a literal expression}}
@section("mysection") let b = 2 * packagePageSize
// expected-error@-1 {{reference to a package 'let' binding is not permitted in a literal expression}}
@section("mysection") let bUFI = 2 * usableFromInlinePageSize
// expected-error@-1 {{reference to a '@usableFromInline' 'let' binding is not permitted in a literal expression}}
// Internal, fileprivate, and private bindings are allowed.
@section("mysection") let c = 2 * internalPageSize
@section("mysection") let d = 2 * filePrivatePageSize
@section("mysection") let e = 2 * privatePageSize
// =============================================================================
// Integer generic argument position: same restriction applies.
// =============================================================================
let f: InlineArray<(2 * publicPageSize), UInt8> = .init(repeating: 0)
// expected-error@-1 {{reference to a public 'let' binding is not permitted in a literal expression}}
// expected-error@-2 {{generic value must be an integer literal expression}}
let g: InlineArray<(2 * packagePageSize), UInt8> = .init(repeating: 0)
// expected-error@-1 {{reference to a package 'let' binding is not permitted in a literal expression}}
// expected-error@-2 {{generic value must be an integer literal expression}}
let gUFI: InlineArray<(2 * usableFromInlinePageSize), UInt8> = .init(repeating: 0)
// expected-error@-1 {{reference to a '@usableFromInline' 'let' binding is not permitted in a literal expression}}
// expected-error@-2 {{generic value must be an integer literal expression}}