Skip to content

Commit 93d07c6

Browse files
authored
_isOptional(type(of: value)) Does Not Do What You Think It Does (#28994)
In particular, if value is `Any` in a generic context, then `type(of: value)` is `Any.Protocol` which is never considered optional. As a result, the first clause here was never actually being used for `print()` or other similar paths. (Curiously, it _was_ used for string interpolation.) This changes how we test for an optional type so that the first clause is consistently used for all optionals, even when they are wrapped in `Any` containers. Fortunately? `print()` was producing the right results for optionals because of a dynamic cast bug that failed to unwrap optionals in these same contexts. <sigh>
1 parent f0a1fb5 commit 93d07c6

File tree

1 file changed

+3
-1
lines changed

1 file changed

+3
-1
lines changed

stdlib/public/core/OutputStream.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ internal func _print_unlocked<T, TargetStream: TextOutputStream>(
384384
// string. Check for Optional first, before checking protocol
385385
// conformance below, because an Optional value is convertible to a
386386
// protocol if its wrapped type conforms to that protocol.
387-
if _isOptional(type(of: value)) {
387+
// Note: _isOptional doesn't work here when T == Any, hence we
388+
// use a more elaborate formulation:
389+
if _openExistential(type(of: value as Any), do: _isOptional) {
388390
let debugPrintable = value as! CustomDebugStringConvertible
389391
debugPrintable.debugDescription.write(to: &target)
390392
return

0 commit comments

Comments
 (0)