代表的な面接トピック

コーディング面接:Rust 1.96 の Range 型と assert_matches への移行

コーディング普通
Offer.cc 編集チーム公開日 更新日

質問

Rust ライブラリにおいて、コピー可能なスライス範囲を保持し、テストでパターン一致に失敗した際に実際の値を表示する必要があります。古い範囲型や互換性の落とし穴を避けつつ、Rust 1.96 の範囲型と assert_matches をどのように導入しますか?

プロンプトとコンテキスト

インデックス範囲が複数の軽量ハンドルによってコピーされ、テストでパターン不一致時に値を出力する必要があるパーサーライブラリを保守しています。このプロジェクトは現在、レガシーな core::ops 範囲と matches! を使用しており、Rust 1.96 へのアップグレードを進めています。新しい範囲型、イテレーションのセマンティクス、パブリック API、アサーションマクロ、およびリリース計画について説明してください。

面接官が評価するポイント

  • レガシーな Range が Iterator を実装しているのに対し、新しい core::range 型が IntoIterator を使用し Copy になり得ることを理解しているか。
  • 0..n 構文がすでに新しい型に切り替わっていると誤認していないか。
  • assert_matches! はプレリュードに含まれておらず、診断のために明示的なインポートが必要であることを知っているか。
  • MSRV、ドキュメント、マクロ展開、Wasm リンクの変更、およびロールバックを適切に扱えるか。

確認すべき明確化のための質問

  1. ライブラリの MSRV は Rust 1.96 ですか、それとも古いコンパイラを引き続きサポートする必要がありますか?
  2. 範囲は保存して後でイテレートする必要がありますか、それとも1つのループで消費されますか?
  3. パブリック API は任意の RangeBounds を受け入れるべきですか、それとも具体的な範囲型を公開すべきですか?
  4. Wasm ビルドは未定義のインポートに意図的に依存していますか、また Rust 1.96 では明示的なリンカー引数が必要ですか?

30秒の回答フレームワーク

コピー可能なインターバルハンドルを core::range 型で保存し、明示的な IntoIterator 変換を通じてイテレートします。ジェネリック API では、呼び出し元を1つの実装に固定しないように RangeBounds を優先します。テストでは core::assert_matches を明示的にインポートし、パターンチェックを維持しつつ実際の値を出力させます。移行前に MSRV を固定し、0..n が依然としてレガシー型を生成することを確認し、型テストと動作テストを追加し、Wasm リンク時における Rust 1.96 の厳格化された未定義シンボルの扱いを個別に検証します。

ステップバイステップの詳細解説

1. 2つの範囲セマンティクスを分離する

Rust 1.96 では core::range::RangeRangeFromRangeInclusive、およびそれらに関連するイテレータが安定化されます。新しい型は IntoIterator を実装しているため、Copy 構造体に保存できます。既存の範囲構文は現時点では依然としてレガシー型を生成し、将来のエディションで変更される予定です。コードレビューでは、0..n から型を推論するのではなく、型シグネチャを精査する必要があります。

2. ライブラリ API とライフタイムの設計

API が境界を読み取るだけであれば、レガシー範囲と新しい範囲の両方をサポートするために RangeBounds を受け入れます。範囲を保存およびコピーする場合は、新しい型を使用し、境界でイテレータに変換します。スライスアクセスは引き続き位置と文字境界を検証します。Copy は境界チェックを排除しません。ダウンストリームのユーザーが古いツールチェーンで予期せず失敗しないように、MSRV を文書化します。

3. 診断のためのパターンアサーションの使用

assert_matches! および debug_assert_matches! は、失敗時に値を表示するパターンアサーションです。これらはプレリュードに含まれていないため、テストモジュールでインポートしてください。リリースビルドではデバッグアサーションが削除されるため、debug_assert_matches! を本番環境の安全性チェックとして使用しないでください。機密性の高いペイロードの出力を避けるため、エラー enum の特定のフィールドにマッチさせます。

4. アップグレードリスクの評価

Rust 1.96 では、Wasm ターゲットのリンクも厳格化され、--allow-undefined がデフォルトで渡されなくなります。プロジェクトが意図的にインポートに依存している場合は、リンカー引数を明示的に設定するか、インポートモジュールに注釈を付け、CI で Wasm をビルドします。古いツールチェーンのマトリックス、ドキュメントの例、テスト、およびバイナリアーティファクトのチェックを実行し、コンパイラとロックファイルのロールバックパスを準備しておきます。

質の高い模範回答

MSRV とサポート対象のターゲットをリリースコントラクトに明記します。保持されるハンドルには、コピー可能であり IntoIterator を介してイテレートできる Rust 1.96 の core::range::Range を使用します。ジェネリック関数は RangeBounds を受け入れることで、呼び出し元が特定の具体的な型に縛られないようにします。コードは 0..n がすでに新しい型であるとは想定しません。型チェックと動作テストによって意図したセマンティクスを証明します。テストモジュールは、単純なブール値には matches! を維持しつつ、詳細なパターン診断のために core::assert_matches を明示的にインポートします。また、移行では Wasm の未定義シンボルも検証します。デフォルトのリンクが失敗するようになった場合、意図的なインポートにのみ明示的な --allow-undefined と import-module 注釈を付与します。CI では MSRV、最新の安定版、Wasm ビルド、およびドキュメントの例を実行し、いずれかの失敗があればリリースをブロックします。

よくある間違い

  • Rust 1.96 において 0..n が自動的に core::range 型を生成すると想定すること。
  • 新しい範囲を Iterator として扱い、その IntoIterator 設計を無視して直接呼び出すこと。
  • assert_matches! がプレリュードからインポートされることに依存すること。
  • デバッグアサーションを本番環境の安全性チェックとして使用すること。
  • 範囲が Copy であるからといって、境界、オーバーフロー、または文字境界の検証を省略すること。
  • Wasm の未定義シンボルリンクに関する Rust 1.96 の変更を無視すること。

フォローアップの質問と回答

なぜすべての API を新しい Range 型に変更しないのですか?

具体的な型を使用すると、MSRV と互換性の圧力が高まります。RangeBounds は呼び出し元の柔軟性を維持します。新しい型は、内部構造体がそれを保存してコピーする必要がある場合にのみ使用します。

assert_matches はどのような場合に matches と異なりますか?

ブール値の結果には matches! を使用します。テスト失敗時に実際の値とパターンを表示したい場合は assert_matches! を使用します。どちらもビジネスエラー処理やセキュリティ検証の代替にはなりません。

Wasm のインポートを維持する必要がある場合はどうしますか?

まず、そのインポートがリンカー設定の不足ではなく、意図的なコントラクトであることを証明します。次に、明示的な --allow-undefined および wasm_import_module 注釈を付けて復元し、CI でシンボルリストとランタイム動作をテストします。

公開情報ソース

関連する質問

関連面接ツール

コーディング問題にはスクリーンショットを使用

問題をキャプチャし、制約条件、解法アプローチ、コード、エッジケース、計算量の順に進めます。

ツールを見る