Skip to content

Commit c80477b

Browse files
authored
Clarify the behavior of _SwiftValue (without naming it) (#33951)
Clarify the function of `__SwiftValue` (used when casting to AnyObject) but remove the actual name. The name and layout of this type is an internal implementation detail that is not guaranteed and should not be relied on by any code outside of the runtime.
1 parent 38db485 commit c80477b

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

docs/DynamicCasting.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ Note that although this mechanism was explicitly designed to simplify Swift inte
104104

105105
The `_ObjectiveCBridgeable` protocol defines an associated reference type `_ObjectiveCType`, along with a collection of methods that support casting to and from the associated `_ObjectiveCType`.
106106
This protocol allows library code to provide tailored mechanisms for casting Swift types to reference types.
107-
When casting to `AnyObject`, the casting logic prefers this tailored mechanism to the general `_SwiftValue` container mentioned above.
108107

109108
Note: The associated `_ObjectiveCType` is constrained to be a subtype of `AnyObject`; it is not limited to being an actual Objective-C type.
110109
In particular, this mechanism is equally available to the Swift implementation of Foundation on non-Apple platforms and the Objective-C Foundation on Apple platforms.
@@ -344,14 +343,22 @@ Invariants
344343

345344
Any class, enum, struct, tuple, function, metatype, or existential metatype instance can be cast to `AnyObject`.
346345

347-
XXX TODO The runtime logic has code to cast protocol types to `AnyObject` only if they are compatible with `__SwiftValue`. What is the practical effect of this logic? Does it mean that casting a protocol type to `AnyObject` will sometimes unwrap (if the protocol is incompatible) and sometimes not? What protocols are affected by this?
348-
349346
The contents of an `AnyObject` container can be accessed by casting to another type:
350347
* Weak existential invariant: If `t` is any instance, `U` is any type, `t is AnyObject`, and `t is U`, then `(t as! AnyObject) as? U` will produce the same result as `t as? U`
351348

352-
Implementation Note: `AnyObject` is represented in memory as a pointer to a refcounted object. The dynamic type of the object can be recovered from the "isa" field of the object. The optional form `AnyObject?` is the same except that it allows null. Reference types (class, metatype, or existential metatype instances) can be directly assigned to an `AnyObject` without any conversion. For non-reference types -- including struct, enum, and tuple types -- the casting logic will first look for an `_ObjectiveCBridgeable` conformance that it can use to convert the source into a tailored reference type. If that fails, the value will be copied into an opaque `_SwiftValue` container.
349+
#### Implementation Notes
350+
351+
`AnyObject` is represented in memory as a pointer to a reference-counted object. The dynamic type of the object can be recovered from the "isa" field of the object. The optional form `AnyObject?` is the same except that it allows null.
352+
353+
Reference types (class, metatype, or existential metatype instances) can be directly assigned to an `AnyObject` without any conversion.
353354

354-
(See "The _ObjectiveCBridgeable Protocol" below for more details.)
355+
For non-reference types -- including struct, enum, and tuple types -- the casting logic will first look for an `_ObjectiveCBridgeable` conformance that it can use to convert the source into a tailored reference type. (See "The _ObjectiveCBridgeable Protocol" below for more details.)
356+
357+
If bridging fails, the value will be copied into an opaque heap-allocated container that is compatible with Objective-C memory management. The sole purpose of this container is to allow arbitrary Swift types to be cast to and from `AnyObject` so they may be shared with Objective-C functions that need to call Swift code. The Objective-C code cannot use the contents of this container; it can only store the reference and pass it back into Swift functions.
358+
359+
For platforms that do not support an Objective-C runtime, there is an alternate implementation of the internal container type that supports the same casting operations with `AnyObject`.
360+
361+
XXX TODO The runtime logic has code to cast protocol types to `AnyObject` only if they are compatible with `__SwiftValue`. What is the practical effect of this logic? Does it mean that casting a protocol type to `AnyObject` will sometimes unwrap (if the protocol is incompatible) and sometimes not? What protocols are affected by this?
355362

356363
### Error (SE-0112)
357364

@@ -613,7 +620,7 @@ print(b is P)
613620
struct S {}
614621
let s = S()
615622
// Swift 5.3: Compiler crash (in asserts build)
616-
// Specification: Succeeds via _SwiftValue boxing
623+
// Specification: Succeeds via __SwiftValue boxing
617624
s as? AnyObject
618625
```
619626

0 commit comments

Comments
 (0)