1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rust ジェネリック関数で”the size for values of type `str` cannot be known at compilation time”エラー

Last updated at Posted at 2024-11-01

コンパイルエラー発生!

このコードを実装したら、コンパイルエラーになりました。
Rust初心者の私には、このエラーの理屈が分からなくて、悩んだので書き留めておきます。

    fn print_value<T: std::fmt::Debug>(s: &T) {
        println!("{:?}", s);
    }
    
    let s: &str = "Hello, world!";

    // エラーになった
    // the size for values of type `str` cannot be known at compilation time
    print_value(s);

なんでエラーになるの?

s&str型なのに、str型と認識される理由が分からなかったです。。。。

まずはstr型について

まずはstr型についておさらいです。

The Rust Programming Language 日本語版によると&strstr型の参照ですが、&strはスライス型です。
"Hello"などの文字列リテラルもスライス型になるようです。

let s: &str = "Hello";

ここで注意です。&String&strはまったく別の型です。

  • &String: String型の参照
  • &str: str型の参照

str型は変数、引数、戻り値の型として指定できません

この変数宣言はコンパイルエラーになります。

let s: str;

{8CD9E973-9975-4E90-97D7-96A01A0E3A22}.png
str型はコンパイル時点でデータサイズが未定なので使えません。

しかし、&strにすると、参照値(アドレス値)となりデータサイズが分かるので使えます。
下図はVSCODEのスクショです。
{4AE3CACB-C629-4A18-9684-58048C6BCE45}.png
size=16とデータサイズが16バイトであると分かります。

次にジェネリック型の型解決の動き

これを理解していなかったのでエラーの理由がわかりませんでした。

こちらのコードは、問題なくコンパイルできます。

let n:i32 = 10;
print_value(&n);    

では、ジェネリックがどのように型を解決(推論)してくか。です。

  1. T = i32 (まずはTの型を解決)
  2. &T = &i32

と型解決します。
この2段階解決だと知りませんでした。

私は

  1. &T = &i32

と一発で解決すると思っていました。

この解決の動きだと下記の&strの場合は

let s: &str = "Hello, world!";
print_value(s);    
  1. T = str
  2. &T = &str

となります。

そうです、1段階のT = strの時点で、Tstrとなり、strは引数の型としては使えないのでダメ!とエラーになるのです。

このエラーを回避するなら

let s: &str = "Hello, world!";
print_value(&s);    

とします。すると

  1. T = &str&sの型は&&strなので、Tの型は&strになる)
  2. &T = &&str

となり、1段階目のTが&strになるのでエラーになりません。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?