Skip to content

Commit 6a17e38

Browse files
authored
Merge pull request #3002 from aschwaighofer/se-0496-edits
Minor edits to SE-0496
2 parents ae0d796 + d75b62d commit 6a17e38

File tree

1 file changed

+42
-18
lines changed

1 file changed

+42
-18
lines changed

proposals/0496-inline-always.md

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ determined dynamically at runtime:
133133
func a(c: C) {
134134
c.method()
135135
}
136+
- Calls through `class` methods on `class` types and the method referenced
137+
is not `final`
138+
```swift
139+
class C {
140+
@inline(always)
141+
class func method() {...}
142+
}
143+
func a(c: C.Type) {
144+
c.method()
145+
}
136146
```
137147

138148
In such cases, the compiler cannot determine at a call site which function is
@@ -144,8 +154,8 @@ function references in the following:
144154

145155
- Calls to free standing functions
146156
- Calls to methods of `actor`, `struct`, `enum` type
147-
- Calls to final methods of `class` type, and type (`static/class`) methods of
148-
`class` type
157+
- Calls to final methods, final `class` type methods of `class` type, and
158+
`static` type methods of `class` type
149159

150160
Therefore, in cases where the value of the function at a usage site is
151161
dynamically derived we don't emit an error even if the dynamic value of the
@@ -171,9 +181,10 @@ Listing the different scenarios that can occur for a function marked with
171181
### Direct function references
172182

173183
Calls to freestanding functions, methods of `enum`, `struct`, `actor` types,
174-
final methods of `class` types, and type methods of `class` types don't
175-
dynamically dispatch to different implementations. Calls to such methods can
176-
always be inlined barring the recursion limitation (see later). (case 1)
184+
final methods of `class` types, and `static` (but not `class`) type methods of
185+
`class` types don't dynamically dispatch to different implementations. Calls to
186+
such methods can always be inlined barring the recursion limitation (see later).
187+
(case 1)
177188

178189
```swift
179190
struct S {
@@ -191,7 +202,10 @@ class C {
191202
final func finalMethod() {}
192203

193204
@inline(always)
194-
class func method() {}
205+
static func method() {}
206+
207+
@inline(always)
208+
final class func finalTypeMethod()
195209
}
196210

197211
class Sub : C {}
@@ -202,6 +216,8 @@ func f2() {
202216
let c2: Sub = ..
203217
c2.finalMethod() // can definitely be inlined
204218
C.method() // can definitely be inlined
219+
let c: C.Type = ...
220+
c.finalTypeMethod() // can definitely be inlined
205221
}
206222

207223
@inline(always)
@@ -215,28 +231,36 @@ func f3() {
215231

216232
### Non final class methods
217233

218-
Swift performs dynamic dispatch for non-final methods of classes based on the
219-
dynamic receiver type of the class instance value at a use site. Inferring the
220-
value of that dynamic computation at compile time is not possible in many cases
221-
and the success of inlining cannot be ensured. We treat a non-final method
222-
declaration with `@inline(always)` as an declaration site error because we
223-
assume that the intention of the attribute is that the method will be inlined in
224-
most cases and this cannot be guaranteed (case 3).
234+
Swift performs dynamic dispatch for non-final methods of classes and non final
235+
`class` methods of classes based on the dynamic receiver type of the class
236+
instance/class type value at a use site. Inferring the value of that dynamic
237+
computation at compile time is not possible in many cases and the success of
238+
inlining cannot be ensured. We treat a non-final method declaration with
239+
`@inline(always)` as an declaration site error because we assume that the
240+
intention of the attribute is that the method will be inlined in most cases and
241+
this cannot be guaranteed (case 3).
225242

226243
```swift
227244
class C {
228245
@inline(always) // error: non-final method marked @inline(always)
229246
func method() {}
247+
248+
@inline(always) // error: non-final method marked @inline(always)
249+
class func class_method() {}
230250
}
231251

232252
class C2 : C {
233253
@inline(always) // error: non-final method marked @inline(always)
234254
override func method() {}
255+
256+
class func class_method() {}
235257
}
236258

237-
func f(c: C) {
259+
func f(c: C, c2: C.Type) {
238260
c.method() // dynamic type of c might be C or C2, could not ensure success
239261
// of inlining in general
262+
c2.class_method() // dynamic type of c2 might be C.self or C2.self, could not
263+
// ensure success of inlining in general
240264
}
241265
```
242266

@@ -357,13 +381,13 @@ to the client.
357381

358382
`@inline(always)` intention is to be able to guarantee that inlining will happen
359383
for any caller inside or outside the defining module therefore it makes sense to
360-
require the use of "@inlinable" attribute with them. This attribute could be
384+
require the use of an `@inlinable` attribute with them. This attribute could be
361385
required to be explicitly stated. And for it to be an error when the attribute
362386
is omitted.
363387

364388
```swift
365389
@inline(always)
366-
@inlinable // or @_alwaysEmitIntoClient
390+
@inlinable
367391
public func caller() { ... }
368392

369393
@inline(always) // error: a public function marked @inline(always) must be marked @inlinable
@@ -467,13 +491,13 @@ attribute in the future.
467491

468492
```swift
469493
@inlinable
470-
public caller() {
494+
public func caller() {
471495
if coldPath {
472496
callee()
473497
}
474498
}
475499

476-
public otherCaller() {
500+
public func otherCaller() {
477501
if hotPath {
478502
callee()
479503
}

0 commit comments

Comments
 (0)