motoko-compiler-warnings-fixes について
Motoko 開発者向けに、コンパイラー警告の確認と修正方法を案内するスキルです。DFX、MOPS、ICP-CLI のチェック手順と、修正時の型エラーを避ける注意点をまとめています。
主な機能
- 01DFX、MOPS、ICP-CLI のビルドチェック
- 02M0194 と M0244 の解説
- 03未使用識別子の安全な修正方法
- 04段階的な再チェックと回帰確認
活用シーン
- 01Motoko プロジェクトの警告確認
- 02未使用識別子や可変バインディングの修正
- 03パラメーターのレコード編集時の型エラー回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ research-ag/ motoko-skills --skill motoko-compiler-warnings-fixesインストール後、Claude Code で/motoko-compiler-warnings-fixesを入力して読み込まれたか確認します。
詳細
Motoko コンパイラーの警告を修正する
ビルドチェックの実行方法
DFX プロジェクトの場合(Motoko のキャニスターのみをビルド):
dfx build --check 2>&1 | tee /tmp/dfx_build_output.txt
デプロイせずに、すべてのキャニスターの型チェックを行います。警告を取得するには、標準エラー出力をリダイレクトしてください。大規模なプロジェクトでは、ビルドに数分かかります。
MOPS パッケージの場合:
find src -type f -name "*.mo" -print0 | xargs -0 -n1 $(mops toolchain bin moc) --check $(mops sources) 2>&1 | tee /tmp/moc_check_output.txt
各ファイルに対して個別に moc --check を実行し、過剰な警告を避けます。通常、完全な dfx build --check より速く、スタンドアロンの Motoko パッケージに最適です。
ICP-CLI プロジェクトの場合:
icp build 2>&1 | tee /tmp/icp_build_output.txt
最新の icp-cli ツールを使用して、プロジェクトの型チェックを行います。
警告を種類別に数えるには:
grep -o 'M[0-9][0-9][0-9][0-9]' /tmp/*_output.txt | sort | uniq -c | sort -rn
警告コードのリファレンス
M0194 — 未使用の識別子
意味: 変数、パラメーター、インポート、または束縛が宣言されていますが、使用されていません。
修正方法: 識別子の先頭に _ を付けます(例:caller → _caller)。catch の束縛には、単独の _ を使用してください(例:catch (e) → catch (_))。_e` は使用しないでください。
重大な注意点:
-
関数パラメーターの分解で未使用のレコードフィールドがある場合は、そのフィールドを完全に削除してください。 Motoko のレコード型は構造的で、幅部分型付けに対応しています。そのため、
{ response : ... }を要求する関数は、呼び出し元のレコードに必要なフィールドより多くのフィールドがあるため、{ context : Blob; response : ... }も受け入れます。したがって、正しい修正方法は、パラメーターレコードから未使用のフィールドを削除することです。// ❌ WRONG — renaming the field changes the record type, causes M0096 type errors public query func transform({ _context : Blob; response : { ... }; }) : async { ... } { ... } // ❌ ALSO WRONG — leaving it triggers M0194 warning public query func transform({ context : Blob; response : { ... }; }) : async { ... } { ... } // ✅ CORRECT — remove the unused field; subtyping accepts the extra field from callers public query func transform({ response : { ... }; }) : async { ... } { ... }
IC ランタイムは { context = <blob>; response = <http_response> } を渡します。Motoko は構造的部分型付けを使用するため、{ response : ... } のみを要求する関数でも、context フィールドを含むレコードを受け入れます。余分なフィールドは単に無視されます。
ルール: M0194 が関数パラメーターのレコードフィールドで発生した場合は、分解パターンからそのフィールドを削除してください。_ プレフィックスを付けて名前を変更してはいけません。
-
単語境界を使った正規表現では、メソッド呼び出しの名前も変更されることがあります。 同じ行に
poolActor.liquidity()があるときに、変数liquidityが未使用の場合、単純な\b正規表現では両方の名前が変更されてしまいます。ドットを除外する否定先読み/否定後読みを使用してください。# ❌ WRONG — also renames poolActor.liquidity() pattern = rf'\b{identifier}\b' # ✅ CORRECT — won't match after a dot pattern = rf'(?<![._a-zA-Z0-9]){re.escape(identifier)}(?![_a-zA-Z0-9])' -
未使用のインポートには安全に
_を付けられます(例:import Time "mo:base/Time"→import _Time "mo:base/Time")。ただし、本当に不要であれば、インポート自体を削除することも検討してください。
名前を変更しても安全なカテゴリ:
catch (e)→catch (_)(catch の束縛。単独の_を必ず使用し、_eや_errは使用しないでください)let foo = ...→let _foo = ...(let 束縛。本当に未使用の場合のみ)func bar(caller : Principal)→func bar(_caller : Principal)(単純な名前の関数パラメーター。レコードフィールドは対象外)- 関数パラメーターの分解で未使用のレコードフィールドがある場合 → フィールドを完全に削除する(部分型付けで対応できます)
import Foo "..."→import _Foo "..."(未使用のインポート。削除してもかまいません)
catch ブロックの規約: catch (_e) や catch (_err) ではなく、単独のワイルドカードを使って、必ず catch (_) としてください。エラー値は意図的に破棄されるため、_ はそのことを明確に示し、名前付き識別子も作りません。
一括修正の方法: ビルド出力からすべての M0194 警告を抽出し、file:line:identifier を解析して、Python スクリプトで修正します。例:
import re
def fix_m0194(filepath, line_num, identifier):
"""Prefix an unused identifier with _ on a specific line."""
with open(filepath, 'r') as f:
lines = f.readlines()
line = lines[line_num - 1] # 1-indexed
# Careful regex: don't match after dots (method calls)
pattern = rf'(?<![._a-zA-Z0-9]){re.escape(identifier)}(?![_a-zA-Z0-9])'
new_line = re.sub(pattern, f'_{identifier}', line, count=1)
lines[line_num - 1] = new_line
with open(filepath, 'w') as f:
f.writelines(lines)
M0244 — 変数を let にできる
意味: var 束縛は再代入されていないため、不変の let にできます。
修正方法: var を let に変更します:
// Before
var foo = computeSomething();
// After
let foo = computeSomething();
transient var → transient let と stable var → stable let にも適用されます(ただし、stable let には制約があります。値が定数である場合、またはアップグレード可能にする必要のない初期化子である場合にのみ使用してください)。
一括修正の方法: ビルド出力から警告(file:line:varname)を解析し、各行で \bvar\b を let に置き換えます(count=1)。コンパイラーが変数に再代入されないことをすでに確認しているため、これは安全です。
一括修正しても安全です。 将来の使用に備えて意図的に可変にしている場合を除き、常に安全に変更できます。
一般的な方針
重要なルール: コンパイラーが特定の行と問題について明示的な警告またはエラー(Mxxxx)を出していない限り、コードを変更しないでください。コンパイラーが実際には指摘していない、問題があると思われる箇所に対して「修正」を適用してはいけません。たとえば、コンパイラーがその行について明示的に警告またはエラーを報告していない限り、ドット記法をモジュール呼び出しに変更してはいけません。
重要:段階的に進めてください。 一度に1種類のエラー/警告だけを修正し、次の種類に進む前にテスト/ベンチマークを再実行してください。
- ビルドチェックを実行し(上記を参照)、出力を保存します。
- 優先順位を決めるため、コードごとに警告の数を数えます。
- 一度に1種類の警告だけを修正します(例:すべてのM0194を修正してから、すべてのM0244を修正します)。
- 修正の各段階の後は、必ず再ビルド/再チェックを行い、新しいエラーが発生していないことを確認します。
- 動作に関するリグレッションがないことを確認するため、テストとベンチマークを実行します。
- 名前を変更した後は、**型エラー(M0096)**に注意してください。型シグネチャを壊したことを示しています。
- IC インターフェイス関数のフィールド名を変更すると、型エラーが連鎖的に発生します。
環境に関する注意事項
- ビルド時間は、リポジトリの規模や canister の数によって異なります。
- リポジトリにコンパイラー警告とは無関係な既存のビルド失敗がある場合は、別途記録し、警告修正によるリグレッションとして扱わないでください。
- コンパイラー警告は
mocのバージョンによって異なる場合があるため、結果の再現やトリアージに関係する場合は、使用中のコンパイラーのバージョンを記録してください。