Code Fix

上級

as によるダウンキャストは警告なしで値を切り捨てる

asによる整数の型変換(ダウンキャスト)は、変換先の型で表現できない値を警告もエラーもなく切り捨てます。300をu8にキャストすると、下位8ビットだけが残り44になります。

なぜエラーが出ないのか

出力: 44
(エラーなし)
Rustは何も報告しません。型としても借用としても正しいコードだからです
出力: 44
実際の出力 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  fn main() {
 2      let big: i32 = 300;
 3      let small = big as u8 ;
                            ^
 4      println!("{}", small);
 5  }
出力: 44

u8で表現できるのは0〜255までです。300をasでu8にキャストすると、警告もエラーも無く下位8ビットだけが残ります。

直し方: u8i16 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  fn main() {
 2      let value: i32 = 500;
 3      let result = value as u8 ;
                               ^
 4      println!("{}", result);
 5  }
出力: 244

asキャストは安全性チェックを行わない操作なので、範囲外の値は黙って切り捨てられます。

直し方: u8i16 にします。

この問題を解いてみる →

パターン3

 1  fn main() {
 2      let code: i32 = 1000;
 3      let byte_value = code as u8 ;
                                  ^
 4      println!("{}", byte_value);
 5  }
出力: 232

範囲外の値をエラーとして検出したい場合は、asではなくtry_into()を使う必要があります。

直し方: u8i16 にします。

この問題を解いてみる →

パターン4

 1  fn main() {
 2      let raw: i32 = 260;
 3      let converted = raw as u8 ;
                                ^
 4      println!("{}", converted);
 5  }
出力: 4

260をu8にキャストすると4になります。この静かな切り捨てはバグとして非常に見つけにくいです。

直し方: u8i16 にします。

この問題を解いてみる →

パターン5

 1  fn main() {
 2      let input: i32 = 400;
 3      let narrowed = input as u8 ;
                                 ^
 4      println!("{}", narrowed);
 5  }
出力: 144

ダウンキャストする前に、値が変換先の型の範囲に収まっているかを確認する習慣が必要です。

直し方: u8i16 にします。

この問題を解いてみる →

よくある誤解

「範囲外の値をキャストしようとすれば、エラーになるかパニックするはず」という思い込みは誤りです。asキャストは意図的に安全性チェックを行わない操作で、範囲外の値は黙って切り捨てられます。安全に変換したい場合はtry_into()を使う必要があります。

まとめ

as によるダウンキャストは警告なしで値を切り捨てるは上級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)