Skip to content

필사 모드: Dartマクロ取消しから1年半 — 約束された3つは実際に届いたか

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — I/O 2026から消えた言葉

2026年5月のGoogle I/Oに合わせて出たDart 3.12発表文には、「マクロ(macro)」という言葉が一度も出てきません。Dart 3.11発表文(2026年2月)にも、Dart 3.10発表文(2025年11月)にもありません。ちょうど2年前のI/O 2024で「何年もかけて設計に投資してきた」と、リリース発表文の大きな部分を割いて紹介していた機能にしては、完全な沈黙です。

何が起きたかは知られています — マクロは2025年1月に正式に取り消されました。本稿でやりたいのは、その出来事の振り返りではなく事後検証です。取消し文は「代わりにこれをやる」という約束を3つ残しており、そこから1年半が経った今(Flutter 3.44.6 + Dart 3.12.2、2026年7月9日リリース時点)は、その約束が守られたかを確認するのにちょうどよいタイミングです。検証には2次的な解説ではなく1次資料だけを使います — dart.devブログ原文(サイトリポジトリのMarkdown)、Dart SDKとbuild_runnerのチェンジログ、pub.devレジストリAPI、GitHub issueの状態。

タイムライン — 発表、警告音、取消し

2024年5月14日、Dart 3.4。 I/O 2024でマクロのプレビューが公開されます。最初のマクロは、JSONシリアライズのボイラープレートをなくす@JsonCodable()ひとつで、計画は3段階でした — JsonCodableのプレビュー → 反応が良ければJSONマクロをstableへ → 最終的にコミュニティが自分のマクロを定義できるよう開放。興味深いのは、この記事がデータクラスに直接言及している点です。データクラスはDart言語リポジトリで最も票を集めた機能要望ですが、チームは「何を標準にすべきかは意見が分かれる」として、言語に組み込む代わりにマクロシステムでコミュニティ各自に作らせる道を選んだと明かしています。マクロは最初からデータ問題の代理解決策だったのです。

2024年8月6日、Dart 3.5。 ロードマップ更新を兼ねた発表文には、すでに警告音が聞こえます。言語・コンパイラチームの時間の大半をマクロに使っているとしながらも、hot reloadのような中核的なユースケースに回帰を起こしかねないため慎重に進めており、「次のステップを共有できるまでにはさらに数四半期かかりそうだ」と記しています。プレビュー公開から3か月も経たないうちに、スケジュールが「数四半期先」へと後退していたわけです。

2025年1月29日、取消し。 DartチームのVijay Menon名義でAn update on Dart macros & data serializationが公開されます。核心となる文は2つです。「大きな技術的障害を1つ解決するたびに、新しい障害が現れた」、そして「we will not be shipping macros in the foreseeable future(近い将来にマクロを提供することはない)」。発表から取消しまで8か月半かかりました。

なぜ死んだのか — セマンティック・イントロスペクションとhot reloadの衝突

取消し文が明かした理由は、性能でも人員でもなく、設計目標そのものの衝突です。

DartチームはRustの手続き型マクロのように、プログラムの構文(syntax)しか見ないマクロでは目標(データシリアライズのような問題をきちんと解くこと)に足りないと判断し、コンパイル時に型や宣言構造まで参照する深いセマンティック・イントロスペクションを選びました。問題はその選択のコストです。マクロがプログラムの意味情報を参照するということは、コードが変わるたびに、その意味に依存するマクロの出力を再計算しなければならないということです。取消し文の表現を借りれば、このコストが「stateful hot reloadをhotに保つのを難しくして」おり、当時の実装は編集体験(静的解析、コード補完)と増分コンパイル(hot reloadの第一段階)の両方を退行させていました。

Flutterの開発者から見れば、このトレードは成立しません。DartチームはDartのアイデンティティを、取消し文の中で自ら2つに定義しています — 静的言語並みのAOT性能、そして動的言語並みの開発サイクル(hot reload)。マクロがどれだけボイラープレートをなくしてくれても、保存のたびにリロードがもたつくなら、FlutterがReact NativeやComposeに対して掲げる中核的なDX資産を蝕むことになります。機会費用を挙げて退いたのは、その意味で理解できる判断です。

取消し文は代わりに3つを約束しました。(1) データ処理のための「より専用(bespoke)の言語機能群」、(2) build_runnerの改善、(3) マクロの副産物としてプロトタイプされたaugmentationsの独立提供。ここから1つずつ採点していきます。

成績表1 — データ用言語機能: 部分提供

取消し以降のリリースで、小さな言語機能が実際に登場しました。いずれもSDKのチェンジログとリリース発表文で確認できます。

  • null-aware elementsDart 3.8(2025年5月20日)で提供。コレクションリテラルの中で、nullなら丸ごと除外される要素を書けるようにします。
  • dot shorthandsDart 3.10(2025年11月12日)で提供。文脈から型が推論できるとき、LogLevel.errorの代わりに.errorと書ける短縮構文です。
  • private named parametersDart 3.12(2026年5月20日)で提供。privateフィールドをnamedパラメータで初期化する際に強制されていた、イニシャライザリストのボイラープレートをなくします。
  • primary constructors — Dart 3.12でexperimentalとして公開(--enable-experiment=primary-constructorsフラグが必要)。そしてまだリリースされていない3.13のSDKチェンジログには、すでに正式な言語機能として記載されています。

primary constructorsが、この系譜の本題です。フィールド宣言とコンストラクタのパラメータを、クラスヘッダーの1行にまとめます。

// これまでのDart — フィールド2つのクラスに5行
class Point {
  final int x;
  final int y;
  Point(this.x, this.y);
}

// primary constructor — 3.12 experimental、3.13で正式化予定
class Point(final int x, final int y);

ただし、正直に採点すれば「部分提供」です。マクロがそもそも解こうとしていた問題 — toJson/fromJson==/hashCode/copyWithが自動で生成されるデータクラス — は、依然として言語にありません。dart-lang/language#314(Add data classes)は2017年10月に開かれて以来、本稿執筆時点でもopenのままで、1,552件の支持を集める今も最上位クラスの要望です。ここまでに提供されたのはボイラープレートを減らす文法であって、シリアライズコードを生成してくれる何かではありません。その仕事は以下のコード生成が引き続き担います。

成績表2 — build_runner: 最も確実な提供

マクロの代替が結局のところ「build_runnerを速くする」だったので、ここが最も重要な項目です。そしてここは数字で確認できます。

pub.devレジストリAPIの公開履歴をそのまま持ってくると、取消し前のbuild_runnerは事実上メンテナンスモードでした。2.4.0(2023年1月18日)から2.4.15(2025年2月11日)まで、25か月間でリリース16件、全部パッチバージョンで、マイナーバンプは1件もありません。取消し後が変曲点です — 2.5.0(2025年6月16日)から2.15.2(2026年7月13日)まで、13か月間でリリース30件、マイナーラインだけで11件が出ました。取消し文が公言した投資が、レジストリデータにそのまま刻まれているわけです。

内容もパッチレベルではありません。build_runnerのチェンジログ基準で、2026年上半期だけでも:

  • 2.13.0(2026年3月) — 「小さな初回ビルドで1.4倍、大きな増分ビルドで4倍という範囲の速度向上」。ベンチマークの全文はリリースPR(dart-lang/build#4405)で公開されています。
  • 2.14.0(2026年4月) — 解析用ファイル管理の改善による「増分ビルドがさらに2倍向上」。ビルダーのコンパイルがJITからAOTがデフォルトへと変わり(dart:mirrorsを使うビルダーはJITにフォールバック)、初回起動は遅くなる代わりにその後のビルドが速くなるというトレードを明示しています。
  • 2.15.0(2026年4月) — ベースのメモリ使用量が改善されたとして、--low-resources-modeフラグ自体を廃止。

数字にはラベルを付ける必要があります。上の1.4倍・4倍・2倍は、すべてDartチーム自身のベンチマークの数値です。測定条件は当該リリースPRのベンチマークスイートであり、皆さんのコードベース — ビルダーの組み合わせ、パッケージ数、ワークスペース構成 — で同じ倍率が出る保証はありません。4倍という上限は「大きな増分ビルド」という条件付きの値です。独立に再現されたベンチマークはまだ見たことがありません。それでも方向性自体はチェンジログの数十項目が一貫して指し示しており、改善そのものの存在まで疑う理由はありません。

成績表3 — augmentations: 未提供

取消し文が「マクロでプロトタイプした機能のうち独自に価値があり、独立提供を目指す」としていたaugmentations(1つの宣言を別ファイルから拡張する機能 — コード生成の出力物をpartファイルより滑らかに結合するための基盤)は、本稿執筆時点でどのリリースにも収録されていません。追跡issuedart-lang/language#4154は依然openで(2026年2月に最終更新)、未リリースの3.13区間までのSDKチェンジログにもaugmentation関連の項目はありません。3つの約束のうち、唯一何も届いていない項目です。

参考までに、build_runner改善の親追跡issue(dart-lang/build#3800、"Faster dev cycle")も依然openです — 提供が進行中という意味であって、終わったという意味ではありません。

死んだ機能が残した痕跡

取消しがどれほど徹底していたかは、副産物の整理ぶりに表れています。すべて今すぐ確認できる状態です。

  • pub.devのmacrosパッケージ(0.0.1で止まっている)と、JsonCodableを収めていたjsonパッケージ(0.20.4、2024年12月が最終更新)は、いずれもdiscontinuedマークが付いています。
  • ドキュメントページだったdart.dev/language/macrosは、今では取消しブログ記事へ301リダイレクトされます。機能ドキュメントのURLがその機能の訃報記事につながる、珍しい光景です。

一方で、マクロが置き換えようとしていたものたちは、ぴんぴんと生き続けています。pub.dev基準で、json_serializableは6.14.0(2026年5月15日)、freezedは3.2.5(2026年2月3日)で、いずれもリリースを続けています。2026年のDartのデータシリアライズは依然としてコード生成であり、変わったのはそのコード生成を動かすエンジンが速くなったという点だけです。

では今、何をすべきか

マクロを待って先送りにしてきた決定があるなら、終わらせてください。 公式な立場は「foreseeable futureにはない」であり、直近3回のリリース発表文(3.10・3.11・3.12)ではマクロは言及すらされていません。長期的なメタプログラミング探索issue(#1482)は開いていますが、ロードマップに載っているものは何もありません。

build_runnerを最新へ上げるのは安上がりな得です。 2.4.xに留まっているプロジェクトなら、2.15.xまでの間に性能改善が何層も積み重なっています。ただし2.14.0からAOTコンパイルがデフォルトになったため初回起動が遅くなる可能性があること、dart:mirrorsに依存するビルダーがあるとJITフォールバックが起きることは、知った上で上げるのがよいでしょう。

primary constructorsは、まだ有効化しないでください。 3.12ではexperimentalフラグ扱いであり、experimental機能はリリース間で文法が変わることがあります。3.13のチェンジログに正式に記載されているのは事実ですが、3.13はまだリリースされていません — 未リリースのチェンジログは計画であって、約束ではありません。

freezed/json_serializableのスタックを取り除く理由はありません。 言語がデータクラスを組み込む日が来るまで(#314は2017年から開いたままです)、コード生成はDartのデータストーリーそのものです。Flutterエコシステム全体でこのスタックが占める位置は、React Native vs Flutter 2025:クロスプラットフォームモバイル開発の全てで扱った通りです。

おわりに

機能の取消しは、たいてい静かに起こります。issueが何年も放置されたあげく閉じられ、ドキュメントがひっそり消える、というように。Dartマクロの取消しが振り返る価値を持つのは、その逆だったからです — 理由(セマンティック・イントロスペクションのコンパイル時コストがhot reloadと両立できないこと)を技術的に説明し、代替案を3つ明示し、そのうち2つは1年半後の今、リリースとレジストリデータで確認できる形で提供され続けています。

同時に、採点表は未完成です。augmentationsは届いておらず、データクラスは依然としてissueトラッカーの1位要望であり、build_runnerの速度数値もまだチーム自身の測定にとどまっています。マクロの死が残した教訓があるとすれば、これでしょう — hot reloadは、Dartがどんな言語機能とも引き換えにしない不可侵の資産であること、そしてその制約の下では、Dartのメタプログラミングは当面「より速いコード生成」という答えにとどまるということ。

参考資料

현재 단락 (1/55)

2026年5月のGoogle I/Oに合わせて出た[Dart 3.12発表文](https://dart.dev/blog/announcing-dart-3-12)には、「マクロ(macro)」とい...

작성 글자: 0원문 글자: 8,710작성 단락: 0/55