Avatar
omochimetaru 7/16/2020 9:40 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
💯 1
9:41 AM
1. TextOutputStreamable かつ CustomStringConvertibleの場合 2. TextOutputStreamableの場合 3. CustomStringConvertibleの場合 4. 任意の<T> 5. Any.Type の場合 の5つのオーバーロードがあるっぽい
9:42 AM
4のケースは _print_unlocked っていう謎の関数に転送されていて
9:43 AM
Mirror.swift において定義されている String.init<T>(describing: T) の実装も、 _print_unlocked への転送だった。
9:43 AM
_print_unlocked の実装は結構面白くて
9:46 AM
6-1 最初の分岐が魔法関数 _openExistential を使ってる if _openExistential(type(of: value as Any), do: _isOptional) { let debugPrintable = value as! CustomDebugStringConvertible debugPrintable.debugDescription.write(to: &target) return }
9:47 AM
_isOptionalは<T> を受けるので必ずopenできるがその先でoptionalかチェックするから、これでAnyの中に入ってるOptionalとかをおそらく必ず展開できて、 OptionalだからCustomDebugStringConvertibleが通る
9:49 AM
その先は 6-2: String分岐, 6-3: TextOutputStreamable分岐, 6-4: CustomSTringConvertible分岐, 6-5: CustomDebugStringConvertible分岐, で、最後のelseが 6-6: Mirror(reflecting: value)
9:50 AM
1が定義されているのは、もし1が無かった場合、2と3のオーバーロード解決が曖昧になるからだと思う。 で、1の実装は2と同じで、 2の実装と3の実装は6-3と6-4と同じになってる
9:51 AM
ということは、2と3は4からの6-Xに対する最適化ショートカットで、1は2と3の都合で必要になった関数
9:51 AM
気になるのは6-5のショートカットが無いことだけど
9:52 AM
もしそれを実装してしまうと(7とする)、 2と3と7の重複組合せを順序付けするためには、 1に相当するやつの(2,7)版、(3,7)版、(2,3,7)版が必要になって
9:52 AM
組合せ爆発するからあきらめたんじゃなかろうか。
9:54 AM
ちなみに、foo はオプショナルの場合の fix-itが2つ出るが、片方は、 String(describing: foo) への書き換えだから、 String.init(describing:) の実装と 4の実装が同じ( _print_unlocked )なのは暗黙的な規約っぽい。
9:56 AM
_print_unlocked は第二引数でStreamを取れるけどstdlib internalなので、 これはユーザーに提供されていない事になる。 String.init(describing:) を使ってエミュレートできるけど、ストリーム処理可能な場合にパフォーマンスロスが出ちゃう。