error[E0308]: mismatched types
期待された型と使用された型が異なっている。
単純に期待されるのと異なる型を使っているパターン。
以下では、i32
型が期待される箇所で、u32
型の値を使っている。
fn main() {
let mut _var1 = 42_i32;
let _var2 = 42_u32;
_var1 = _var2;
}
error[E0308]: mismatched types --> src\main.rs:4:13 | 2 | let mut _var1 = 42_i32; | ------ expected due to this value 3 | let _var2 = 42_u32; 4 | _var1 = _var2; | ^^^^^ expected `i32`, found `u32`
可能ならキャストするとよい。
fn main() {
let mut _var1 = 42_i32;
let _var2 = 42_u32;
_var1 = _var2 as i32;
}
クロージャの型はたとえ引数や戻り値の型が同じでもそれぞれ異なる。
そのため、それらに互換性があると想定するとエラーになる。
以下では、2 行目のクロージャの型に 3 行目のクロージャを代入しようとしている。
fn main() {
let mut _var = &(|| false);
_var = &(|| true);
}
error[E0308]: mismatched types --> src\main.rs:3:9 | 2 | let mut _var = &(|| false); | -- the expected closure 3 | _var = &(|| true); | ^^^^^^^^^^ expected `&{closure@main.rs:2:22}`, found `&{closure@main.rs:3:11}` | = note: expected reference `&{closure@src\main.rs:2:22: 2:24}` found reference `&{closure@src\main.rs:3:11: 3:13}` = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object
型を dyn
キーワードで抽象化するとよい。
fn main() {
let mut _var = &(|| false) as &dyn Fn() -> _;
_var = &(|| true);
}
関数アイテム型はたとえ引数や戻り値の型が同じでもそれぞれ異なる。
そのため、それらに互換性があると想定するとエラーになる。
以下では、f1
型の変数に f2
型を代入しようとしている。
fn main() {
let mut _var = f1;
_var = f2;
}
fn f1() {}
fn f2() {}
error[E0308]: mismatched types --> src\main.rs:3:9 | 2 | let mut _var = f1; | -- expected due to this value 3 | _var = f2; | ^^ expected fn item, found a different fn item | = note: expected fn item `fn() {f1}` found fn item `fn() {f2}` = note: different fn items have unique types, even if their signatures are the same = help: consider casting both fn items to fn pointers using `as fn()`
関数アイテム型を関数ポインタ型にキャストするとよい。
fn main() {
let mut _var = f1 as fn();
_var = f2;
}
fn f1() {}
fn f2() {}
関数アイテム型は関数ポインタ型を受け入れない (逆は可能)。
そのため、それらに互換性があると想定するとエラーになる。
以下では、関数アイテム型の変数に関数ポインタ型を代入しようとしている。
fn main() {
let mut _var = f1;
_var = f2 as fn();
}
fn f1() {}
fn f2() {}
error[E0308]: mismatched types --> src\main.rs:3:12 | 2 | let mut _var = f1; | -- expected due to this value 3 | _var = f2 as fn(); | ^^^^^^^^^^ expected fn item, found fn pointer | = note: expected fn item `fn() {f1}` found fn pointer `fn()` = help: consider casting the fn item to a fn pointer: `f1 as fn()`
関数アイテム型を関数ポインタ型にキャストするとよい。
fn main() {
let mut _var = f1 as fn();
_var = f2 as fn();
}
fn f1() {}
fn f2() {}
HRTB を扱える型を期待していたが、特定のライフタイムのみ扱える型が使用された。
以下では、任意のライフタイム引数を扱える関数ポインタに、'static
のみしか扱えない関数ポインタを代入しようとしている。
fn main() {
let mut _var = with_hrtb as fn(&_);
_var = with_static as fn(&'static _);
}
fn with_hrtb(s: & str) {
println!("{s}");
}
fn with_static(s: &'static str) {
println!("{s}");
}
error[E0308]: mismatched types --> src\main.rs:3:11 | 3 | var = with_static as fn(&'static _); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected fn pointer `for<'a> fn(&'a _)` found fn pointer `fn(&'static _)`
『HRTB - 型推論』で紹介する通り、HRTB を含んだ型は型推論できない。
そのため、関連型にそれらを含んだ型を期待していてもエラーになる。
以下では、関数 callback
の型パラメタ F
の境界、そしてその実引数 identity
の型から、Fn::Output
である O
が HRTB
によるライフタイム 'a
を含むと期待している。
use std::fmt::Display;
fn main() {
callback(identity, &42);
}
fn callback<F, I, O>(f: F, input: &I)
where
F: for<'a> Fn(&'a I) -> O,
I: Display,
O: Display,
{
println!("input: {}", input);
println!("result: {}", f(input))
}
fn identity(x: &i32) -> &i32 {
x
}
error[E0308]: mismatched types --> src\main.rs:4:5 | 4 | callback(identity, &42); | ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected reference `&'a _` found reference `&_` note: the lifetime requirement is introduced here --> src\main.rs:9:29 | 9 | F: for<'a> Fn(&'a I) -> O, | ^
以下では、推論すべき箇所を型パラメタではなく関連型で表現している。なお、FnHelper
は Fn
トレイトを通常のトレイトとして扱えるようにするためのヘルパトレイトである。
use std::fmt::Display;
fn main() {
let input = &42;
callback(identity, input);
}
fn callback<F, I>(f: F, input: &I)
where
for<'a> F: FnHelper<&'a I>,
for<'a> <F as FnHelper<&'a I>>::Output: Display,
I: Display,
{
println!("input: {}", input);
println!("result: {}", f(input))
}
fn identity(x: &i32) -> &i32 {
x
}
trait FnHelper<I>: Fn(I) -> <Self as FnHelper<I>>::Output {
type Output;
}
impl<F, I, O> FnHelper<I> for F
where
F: Fn(I) -> O,
{
type Output = F::Output;
}
以下でも、推論すべき箇所を型パラメタではなく関連型で表現している。ただし、前の解決策における FnHelper
の代わりに、まだ不安定な機能 (unboxed_closures
) を利用している。
#![feature(unboxed_closures)]
use std::fmt::Display;
fn main() {
let input = &42;
callback(identity, input);
}
fn callback<F, I>(f: F, input: &I)
where
for<'a> F: Fn<(&'a I,)>,
for<'a> <F as FnOnce<(&'a I,)>>::Output: Display,
I: Display,
{
println!("input: {}", input);
println!("result: {}", f(input))
}
fn identity(x: &i32) -> &i32 {
x
}