You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Implementation: Already implemented as a pair of underscored attributes `@_inlineable` and `@_versioned`
9
9
10
-
**Note: the original review ran to January 5, 2018. The review is now running for another week to discuss the spelling of `@abiPublic`. Please see the [review thread](https://forums.swift.org/t/se-0193-cross-module-inlining-and-specialization/7310) to read the discussion and join in.**
10
+
**Note: the original review ran to January 5, 2018. The review is now running for another week to discuss the spelling of `@usableFromInline`. Please see the [review thread](https://forums.swift.org/t/se-0193-cross-module-inlining-and-specialization/7310) to read the discussion and join in.**
11
11
12
12
## Introduction
13
13
14
-
We propose introducing a pair of new attributes, `@inlinable` and `@abiPublic`. The `@inlinable` attribute exports the body of a function as part of a module's interface, making it available to the optimizer when referenced from other modules. The `@abiPublic` attribute marks an internal declaration as being part of the binary interface of a module, allowing it to be used from `@inlinable` code without exposing it as part of the module's source interface.
14
+
We propose introducing a pair of new attributes, `@inlinable` and `@usableFromInline`. The `@inlinable` attribute exports the body of a function as part of a module's interface, making it available to the optimizer when referenced from other modules. The `@usableFromInline` attribute marks an internal declaration as being part of the binary interface of a module, allowing it to be used from `@inlinable` code without exposing it as part of the module's source interface.
15
15
16
16
## Motivation
17
17
@@ -73,24 +73,28 @@ The `@inlinable` attribute can be applied to the following kinds of declarations
73
73
74
74
The attribute can only be applied to ABI-public declarations (which are defined in the following section).
75
75
76
-
The attribute cannot be applied to local declarations, that is, declarations nested inside functions or statements. However, local functions and closure expressions defined inside public `@inlinable` functions are always implicitly `@inlinable`.
76
+
The attribute cannot be applied to local declarations, that is, declarations nested inside functions or statements. However, local functions and closure expressions defined inside public `@inlinable` functions are always implicitly `@inlinable`.
77
77
78
-
When applied to a subscript or computed property, the attribute applies to all of the getter, setter, `didSet`and `willSet`, if present.
78
+
When applied to a subscript or computed property, the attribute applies to both the getterand setter.
79
79
80
-
The compiler will enforce certain restrictions on bodies of inlinable declarations:
80
+
Note that only delegating initializers (those that assign to `self` or call another initializer via `self.init`) can be inlinable. Root initializers which initialize the stored properties of a struct or class directly cannot be inlinable. For motivation, see [SE-0189 Restrict Cross-module Struct Initializers](https://github.com/apple/swift-evolution/blob/master/proposals/0189-restrict-cross-module-struct-initializers.md).
81
+
82
+
### Inlinable contexts
83
+
84
+
The body of an inlinable declaration is an example of an _inlinable context_. The compiler enforces certain restrictions within inlinable contexts:
81
85
82
86
***Inlinable declarations cannot define local types.** This is because all types have a unique identity in the Swift runtime, visible to the language in the form of the `==` operator on metatype values. It is not clear what it would mean if two different libraries inline the same local type from a third library, with all three libraries linked together into the same binary. This becomes even worse if two _different_ versions of the same inlinable function appear inside the same binary.
83
87
84
88
***Inlinable declarations can only reference ABI-public declarations.** This is because they can be emitted into the client binary, and are therefore limited to referencing symbols that the client binary can reference.
85
89
86
-
**Note:**The restrictions enforced on the bodies of `@inlinable` declarations are exactly those that we have in place on default argument expressions of `public` functions in Swift 4. In particular, default argument expressions of public functions can now reference internal declarations, as long as those declarations are annotated with `@abiPublic`.
90
+
**Note:**As of Swift 4.0, the above restrictions are already enforced on default argument expressions of ABI-public functions. This means that default argument expressions are inlinable contexts. Future evolution porposals may add new kinds of inlinable contexts.
87
91
88
-
### The `@abiPublic` attribute
92
+
### The `@usableFromInline` attribute
89
93
90
-
This attribute allows us to introduce the notion of _ABI visibility_. A declaration is _ABI-public_ if both of the following conditions hold:
94
+
This attribute allows us to introduce a notion of an _ABI-public_ declaration. A declaration is _ABI-public_ if both of the following conditions hold:
91
95
92
96
- The declaration is a top-level declaration, or it is nested inside an ABI-public type.
93
-
- The declaration is `public`, or is `internal` and annotated with the `@abiPublic` attribute.
97
+
- The declaration is `public`, or is `internal` and annotated with the `@usableFromInline` attribute.
94
98
95
99
In the following example, the method `C.f` is ABI-public:
96
100
@@ -104,29 +108,29 @@ Another example of an ABI-public declaration is the method `C.D.f` below:
104
108
105
109
```swift
106
110
publicclassC {
107
-
@abiPublicinternalclassD {
108
-
@abiPublicinternalfuncf() {}
111
+
@usableFromInlineinternalclassD {
112
+
@usableFromInlineinternalfuncf() {}
109
113
}
110
114
}
111
115
```
112
116
113
-
In the following, the method `C.f` is **not** ABI-public, because it is nested inside a type that is not `@abiPublic` or `public`:
117
+
In the following, the method `C.f` is **not** ABI-public, because it is nested inside a type that is not `@usableFromInline` or `public`:
114
118
115
119
```swift
116
120
internalclassC {
117
121
publicfuncf() {}
118
122
}
119
123
```
120
124
121
-
The `@abiPublic` attribute can be applied to all declarations which support access control modifiers. This includes almost all kinds of declarations, except for the following, which always have the same effective visibility as their containing declaration:
125
+
The `@usableFromInline` attribute can be applied to all declarations which support access control modifiers. This includes almost all kinds of declarations, except for the following, which always have the same effective visibility as their containing declaration:
122
126
123
127
* Protocol requirements
124
128
* Enum cases
125
129
* Class destructors
126
130
127
-
When applied to a subscript or computed property, the attribute applies to all of the getter, setter, `didSet`and `willSet`, if present.
131
+
When applied to a subscript or computed property, the attribute applies to both the getterand setter, if present.
128
132
129
-
The `@abiPublic` attribute can be applied to `internal` declarations, and not `private`, `fileprivate` or `public` declarations. The `@abiPublic` attribute does not affect source-level visibility of a declaration; it only results in the entry point being exported at the ABI level, allowing it to be referenced from `@inlinable` functions.
133
+
The `@usableFromInline` attribute can only be applied to `internal` declarations. It does not make sense on `public` declarations, which are already ABI-public. It also cannot be applied to `private`and `fileprivate` declarations. and not `private`, `fileprivate` or `public` declarations. The `@usableFromInline` attribute does not affect source-level visibility of a declaration; it only results in the entry point being exported at the ABI level, allowing it to be referenced from `@inlinable` functions.
130
134
131
135
### Future directions
132
136
@@ -138,13 +142,13 @@ This versioning capability will also be required for non-exhaustive enums and fi
138
142
139
143
## Source compatibility
140
144
141
-
The introduction of the `@inlinable` and `@abiPublic` attributes is an additive change to the language and has no impact on source compatibility.
145
+
The introduction of the `@inlinable` and `@usableFromInline` attributes is an additive change to the language and has no impact on source compatibility.
142
146
143
147
## Effect on ABI stability
144
148
145
149
Adding or removing `@inlinable` on an existing declaration does not change the ABI of that declaration.
146
150
147
-
Adding `@abiPublic` to an existing declaration does not change the ABI of that declaration. Removing `@abiPublic` does however, and therefore is a binary-incompatible change.
151
+
Adding `@usableFromInline` to an existing declaration does not change the ABI of that declaration. Removing `@usableFromInline` does however, and therefore is a binary-incompatible change.
148
152
149
153
## Effect on API resilience
150
154
@@ -158,11 +162,11 @@ The closest language feature to the `@inlinable` attribute is found in C and C++
158
162
159
163
Header files mostly contain declarations without bodies, but can also declare `inline` functions with bodies. Such functions are not part of the binary interface of the library, and are instead emitted into client code when referenced. As with `@inlinable` declarations, `inline` functions can only reference other "public" declarations, that is, those that are defined in other header files. Note that while `static inline` is the most commonly-used incarnation of this feature in C, our proposed `@inlinable` attribute is most similar to `extern inline`, were that easier to use.
160
164
161
-
The closest analogue in C to `@abiPublic` is a non-`static` function that is not declared in a framework's header file. External clients cannot see it directly, but they can call it if they provide a local `extern` declaration.
165
+
The closest analogue in C to `@usableFromInline` is a non-`static` function that is not declared in a framework's header file. External clients cannot see it directly, but they can call it if they provide a local `extern` declaration.
162
166
163
167
## Alternatives considered
164
168
165
-
One possible alterative would be to add a new compiler mode where _all_ declarations become implicitly `@inlinable`, and _all_ private and internal declarations become `@abiPublic`.
169
+
One possible alterative would be to add a new compiler mode where _all_ declarations become implicitly `@inlinable`, and _all_ private and internal declarations become `@usableFromInline`.
166
170
167
171
However, such a compilation mode would not solve the problem of delivering a stable ABI and standard library which can be deployed separately from user code. We _don't want_ all declaration bodies in the standard library to be available to the optimizer when building user code.
0 commit comments