世界を動かす技術を、日本語で。

Swiftの導入を追求しないため、これを終了します

概要

Swift 6.0の正式サポートへの移行を妨げる主な問題点を一覧化 LLVMやC++インターロップ、CMake、Ladybird関連の課題を網羅 各問題の詳細、回避策、修正状況を明記 一部問題は既にmainブランチやリリースブランチで修正済みだが、安定版には未反映 未解決・未調査の問題や「nice-to-have」項目も記載

Swift 6.0正式サポート移行を妨げる主な問題一覧

  • LLVM関連の修正未反映

    • SwiftのLLVMバージョンに[Clang] ICE修正が未反映
      • PR: swiftlang/llvm-project#8998
      • 詳細: decltype(lambda)利用時にアサートビルドが失敗
      • 回避策: LinuxでLLVMアサート無効化ビルド、またはmacOS利用
      • 修正: swiftlang/llvm-project#9038(Swift 6.0.0で修正済)
  • C++インターロップのABI不一致

    • Optional<CxxValueType>返却時のABI不一致
      • PR: swiftlang/swift#75593
      • 詳細: Swift Optionalの小さなC++型返却が不可能
      • 回避策: Optionalを使わず、ヒープ確保型やArrayで代用
  • libstdc++のヘッダー依存性サイクル

    • Ubuntu 22.04でC++17以上利用時にサイクル発生
      • PR: swiftlang/swift#75661
      • 詳細: <execution>インクルード時にモジュール依存サイクル
      • 回避策: libstdcxx.hの<execution>行をコメントアウト
      • 修正: swiftlang/swift#75971(main/release/6.0で修正、6.0.0/6.0.1未反映)
  • Optional/Swift.StringのC++関数返却非対応

    • swiftlang/swift#76024
    • 詳細: swift::Optional<T>やswift::Stringの返却が未サポート
    • 回避策: std::型で返却
  • libstdc++-13 <chrono> ヘッダーのC++23モード未対応

    • swiftlang/swift#76809
    • 詳細: Ubuntu 24.04 LTSでデフォルトのlibstdc++-13に未対応
    • 回避策: libc++または旧libstdc++利用
    • 修正: swiftlang/swift:main(2024年10月18日以降)
  • SIL verifierクラッシュ(SWIFT_UNSAFE_REFERENCE関連)

    • swiftlang/swift#80065, #80182
    • 詳細: Unmanaged.passUnretained()やbitfield getter/setterでクラッシュ
    • 回避策: SIL検証無効化、またはSWIFT_UNSAFE_REFERENCE非利用
    • 修正: swiftlang/swift#81614, #80197
  • CxxConvertibleToContainerのiterator operator==未合成

    • swiftlang/swift#77607
    • 詳細: Vector<u32,2>等が認識されず
    • 回避策: Sequence扱い、手動コピー
  • Arch + GCC 15でcxx interop有効時に大量エラー

    • swiftlang/swift#81774
    • 詳細: <math.h>インクルード時にモジュールインポート失敗
    • 回避策: なし

CMake関連の問題

  • CMAKE_OSX_DEPLOYMENT_TARGET未反映

    • https://gitlab.kitware.com/cmake/cmake/-/issues/26174
    • 詳細: Swift+Ninja利用時にターゲット未適用
    • 回避策: set(CMAKE_Swift_COMPILER_TARGET ...)で明示指定
  • CMP0157有効時のinstall_name問題

    • https://gitlab.kitware.com/cmake/cmake/-/issues/26175
    • 詳細: swiftcが@rpathを正しく設定せず
    • 回避策: add_custom_commandでinstall_name_tool適用
    • 修正: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/9692(CMake 3.29, 3.30へバックポート予定)
  • INTERFACE_COMPILE_OPTIONS等の未対応フラグ

    • https://gitlab.kitware.com/cmake/cmake/-/issues/26195
    • 詳細: 依存ライブラリのフラグをswiftcが理解できず
    • 回避策: インポート後に手動でフラグ除去

Ladybird関連の問題

  • AK+LibGfx: clang module mapの明示化必要

    • #965
    • 詳細: umbrellaディレクトリエントリがlibcヘッダーと衝突
    • 回避策: 各ライブラリごとに個別module map生成
  • AKインポート後の型プロパティ参照でクラッシュ

    • #1101, #1102
    • 詳細: Debugビルドやunnamespaced String利用でswift-frontendクラッシュ
    • 回避策: Releaseビルド利用、String参照をAK.String/Swift.Stringに限定
    • Upstreamバグ: swiftlang/swift#82108
  • swift-testing利用時のコンパイラフロントエンドクラッシュ

    • #1201
    • 詳細: AKコンテナのCxxSequenceプロトコル適合テストでクラッシュ
    • 回避策: カスタムテストランナー利用
  • AK::StringViewのCxxSequenceType非適合

    • #2168
    • 詳細: swift/mainでStringViewがコンテナ扱いされず
    • 回避策: bytesUnsafe()で手動イテレート
  • Optional<CxxType>返却時のアプリクラッシュ

    • swiftlang/swift#79767
    • 詳細: Swift関数からC++呼び出し時にクラッシュ
    • 回避策: [MyCxx.CxxType]型(配列)で返却
  • CMakeプロジェクトでcompile_commands.json必須

    • swiftlang/vscode-swift#1449
    • 詳細: SourceKit-LSPやvscode-swift用にルート直下へ必要
    • 回避策: シンボリックリンク作成
  • <swift/bridging>のinclude path自動追加未対応

    • swiftlang/swift#80142
    • 詳細: Linuxで追加パスが必要
    • 回避策: swiftc -print-target-infoでパス取得

未解決・未調査の課題・Nice-to-have

  • view型やbyte sliceをコピーせずにSwiftへ渡す方法不明

    • 詳細: C++所有のStringやSpan<byte>をSwiftへ安全に受け渡す方法の模索
    • CxxConvertibleToContainerやCxxRandomAccessContainer型として認識させるのが困難
    • 型がimmutableなためかSwift標準のstd::型のように扱えず
  • AK::Optional, AK::HashTable/HashMap, AK::Time等のサポート未確立

    • 詳細: 独自型のSwift連携やガベージコレクタ統合方法の検討
    • 参考: https://forums.swift.org/t/ladybird-browser-and-swift-garbage-collection/76084

この一覧は、Swift 6.0の安定利用に向けて現状クリティカルな障壁となっている問題の全体像を把握し、対応・検討を進めるためのリファレンスとして活用可能

Hackerたちの意見

面白いね、何があったの?そこでは説明されてないみたい。ちなみに、私はこの件には関係ないよ。Linuxで動くなら、準備ができたら試してみるつもり。

私には、繰り返しのビルド問題が原因に見えたよ。「swiftはこれらの競合するC++バージョンのライブラリを同時にインポートできない」とか「バージョンやビルドの競合のためにいくつかの演算子が使えない」とかね。要するに、プロジェクトにSwiftを追加しようとしたら、あまりにも多くの問題が起きて、やる価値がないと判断したみたい。残念だけど、Swiftは過小評価されてる言語だと思う。でも、彼らの理由は理解できる。最初からSwiftを使おうとしたら、あまりにも野心的だっただろうし、壊れやすくて大規模なプロジェクトにSwiftを追加するのは複雑すぎたんじゃないかな。

あんまり驚かないな。SwiftはAppleに縛られすぎてるし、現代のメモリ安全なプラクティスで書かれたC++のサブセットと比べて、どんなメリットがあるのかもよく分からない。実績のある選択だし、実際に使われているブラウザはほとんどC++で書かれてるからね。

まあ、どちらにしても高レベルなコードだけのためならともかく、ひどいアイデアだったね。Swiftは一般的にC++と比べて生のパフォーマンスでは競争できないから(Javaと同じようにね。速いベンチマークもあるけど、実際のプログラムではほとんど起こらない)。

実績のある選択だし、実際に使われているブラウザはほとんどC++で書かれてる。 実際に使われているブラウザは、もうC++に深く関わりすぎてるから、抜け出せないけど、ChromiumとFirefoxは少しずつそれを削減して、安全な代替品に置き換えようとしてるよ。Chromiumは、安全な実装が出るまでJPEG-XLの採用をブロックしてたし、C++のリファレンスデコーダーを大きな負担と見なしてたからね。私の意見では、これらのブラウザはたくさんのC++を使っていて、これからもずっと使うだろうけど、彼らが得た教訓から、使わなくて済むならそうしたいと思ってるし、C++で新しいブラウザを書くのは、同じ間違いを無駄に繰り返すことになるだけだよ。ChromiumがC++を使ってるのは、WebkitがC++を使ってたからで、WebkitがC++を使ってたのはKHTMLが1998年にC++を使ってたからなんだ。今は振り返ることができる利点があるね。

現代のメモリ安全なプラクティスで書かれたC++のサブセット その神話のようなC++のサブセットって何?現代のSTL機能、例えばstring_viewを使うことが含まれてるの?(誤解しないでほしいけど、現代のSTLはかなり改善されてるけど、メモリ安全には程遠いよ。)

RustはMozillaのために特別に開発されたんじゃなかったっけ?MozillaはRustで書かれてるんだよね?

Swiftを削除するコミットにはもう少し詳しいことが書いてあるよ。「どこでも: Swiftの採用を放棄。長い間進展がなかったので、もうこれ以上進まないことを認めて、コードベースから削除しましょう。」 https://github.com/LadybirdBrowser/ladybird/commit/e87f889e3...

ああ、それは残念だね。つまり、彼らの独自のプログラミング言語Jaktは再び検討されるってこと?

彼らのためにも、そうなってほしくないな。外部からの寄付で資金調達してるプロジェクトが、こんなにADD(注意欠陥障害)を抱えて長続きするとは思えない。話すのもイライラする。エンジニアリングマネジメントの決定をどうしないかの素晴らしいケーススタディだけど、時間が経つにつれてそういうことが起こって、原因も魅力的だから、全体を声に出して話すのは難しいよね、軽蔑的な奴みたいに聞こえちゃうし。

Ladybirdはしばらく前にSerenityOSから分かれたし、Jaktは「彼ら」の言語じゃないよ。それに、ニッチなプログラミング言語が選択肢に入るとは思わない。

あの時、Swiftへの移行をバカにしてたのを覚えてる。Swiftは設計が悪くて、コンパイルも遅いし、主要なシステム言語になる道筋が見えないし、チームに専門家もいなかった。損失を減らす方向に進んでるのは良いことだね。

Swiftは本当にオープンソースって感じがしなかったな。進化ポイントを提案できるって言っても、Appleが全ての権限を握ってて、必要な優先事項を押し通すのは変わらないからね(例えば、ConcurrencyやSwift Testingとか)。それに、クロスプラットフォームの作業は小さなグループでやってるし、資金を探してるところもあるし…まあ、なんだかんだで。

Swiftには問題があるし、Appleプラットフォームの開発以外には使わないけど、チームに専門家がいなかったっていうのはちょっと言い過ぎだよ。Swiftのリーダーたちは、Chris Lattnerを除いても、C++の世界では高く評価されているメンバーが多かったし。

どの言語をおすすめする?

Swiftのポイントは、言語そのものじゃなくて、動的コードのための標準ABIなんだよね。Rustの人たちは、少なくとも標準のSwift実装があるプラットフォームでは、Cと並行して外部FFI/相互運用性をサポートすることにコミットすべきだと思う。

Goも同じなのかな?今のところのベストな選択は何だろう、C#なのかな?

LadybirdはなんでSwiftでこれを試みたのか、でも(推測だけど)Rustでは試さなかったのか?別の言語を追加する手間をかけるなら、Rustの方がC++との相互運用性が良いんじゃない?それに、SwiftのGCはブラウザのパフォーマンスにはあまり良くなさそうだし。

https://x.com/awesomekling/status/1822236888188498031 https://x.com/awesomekling/status/1822239138038382684 「結局、Swift対Rustになって、SwiftはOOサポートとC++との相互運用性で圧倒的に優れている。」

Swiftは実際、C++との相互運用性が優れてるよ[1](他の言語と比べてだけど、でもLadybirdには十分じゃなかったのかな)。[1] https://www.swift.org/documentation/cxx-interop/

本当にその通りだと思う。新しいウェブブラウザを作るのに、まるで新しいOSみたいに、みんなのためにオープンソースにしたいのに、Swiftを選ぶなんて、Rustじゃなくて?

Ladybirdの開発者たちは、RustとSwiftの両方を試して、Swiftを採用することに投票したんだ。

さらなる理由付けを見るのが楽しみだね。Rustは以前、DOM階層やOOPのせいで却下されたと思うけど、正確かどうかは分からない。20240810 https://news.ycombinator.com/item?id=41208836 Ladybirdブラウザが今秋Swift言語を使い始める

Andreas Klingは、RustにはOOが欠けていると言っていて、それがGUIコーディングには役立つらしい。彼はSerenityOSの下で自分の言語Jaktを作ろうとしたけど、LadybirdにはC++(最初はSwiftあり、今はなし)が実用的な選択だと感じたのかもしれない。

確か、LadyBirdの主要な開発者の一人は、WebKitでSwiftを使っていた元Apple社員だったと思うよ。

「LadybirdはなぜSwiftでこれを試みたのか、Rustではないのか?」 多分、Rustがゲーム開発で問題があるのと同じ理由だと思う。借用チェッカーとイディオマティックなRustは、循環依存や参照を必要とするものとは相性が良くないからね。もちろん、回避策はあるけど、あまり使いやすくないし生産的でもないよ。

どの言語で書かれていても、Ladybirdが将来的にユーザーを尊重したJavascript実装に焦点を当ててほしいと思ってる。ウェブ標準が何を言おうと、ウェブサイトがユーザーを監視したり、ペーストを無効にしたり、必要以上のデバイス情報を引き出したりするのは許されないよね。ユーザーベース全体で標準化された(偽装された)値を報告するアプローチも考えられるけど、そうすればLadybirdのユーザーは基本的にお互いに区別がつかなくなる(発信元IPを除いて)。これはTorが取っているアプローチに近いし、Ladybirdのようなプロジェクトが本当に違いを生むことができるところだと思う。

人気のあるウェブサイトには、Ladybirdをボットとしてフラグ付けして、サイトが使えなくなるような防御機構が多すぎるんだよね。これと通常の動作を切り替えるトグルがあればいいけど、デフォルトでそれだと広く普及するのは難しいと思う。

彼らのMac UIはAppKitの薄いレイヤーなんだって。今のところObjective-C++を使っているみたいで、Swiftじゃないみたいだよ。https://github.com/LadybirdBrowser/ladybird/tree/master/UI/A...

2021年にSwiftを使い始めた者として、C#/.NETでほぼ10年いた後だったから、C#がどれだけ複雑かにちょっとイライラしてたんだよね。(その時点でC#は21年経ってたし)でもSwiftに来たら、C#と比べてSwiftがどれだけ複雑か信じられなかった。Swiftは2014年にリリースされたから、2022年には8歳だったのに。C#の半分の年齢の言語が、C#よりも複雑ってどういうこと?データアクセスレイヤーとバックエンドのWeb APIにSwiftを使おうとしてたんだけど、バックエンドAPIにSwiftを使うためのガイダンスや既存の知識がほとんどないんだよね。ましてや、ウェブブラウザのプロジェクトなんて。参考にできる前例や実装がないし、SwiftのベストプラクティスはほとんどAppleプラットフォームのAPIと一緒に使うことに特化してるから、言語自体の使い方に関する知識はAppleハードウェア向けのクライアントアプリを作る以外にはほとんど適用できないんだ。通常の領域外でSwiftを使うのは、まさに先駆者になって、真に未検証なことに挑戦することになる。いつも長い道のりだったよ。