の実装はstd::mem::drop
次のように文書化されています。
pub fn drop<T>(_x: T) { }
そのため、クロージャー|_| ()
(通称、トイレクロージャー)drop
は、双方向での1対1の交換の可能性があると予想します。ただし、以下のコードdrop
は、これが関数のパラメーターにバインドされたより高いランクの特性と互換性がないことを示していますが、トイレのクロージャーは互換性があります。
fn foo<F, T>(f: F, x: T)
where
for<'a> F: FnOnce(&'a T),
{
dbg!(f(&x));
}
fn main() {
foo(|_| (), "toilet closure"); // this compiles
foo(drop, "drop"); // this does not!
}
コンパイラのエラーメッセージ:
error[E0631]: type mismatch in function arguments
--> src/main.rs:10:5
|
1 | fn foo<F, T>(f: F, x: T)
| ---
2 | where
3 | for<'a> F: FnOnce(&'a T),
| ------------- required by this bound in `foo`
...
10 | foo(drop, "drop"); // this does not!
| ^^^
| |
| expected signature of `for<'a> fn(&'a _) -> _`
| found signature of `fn(_) -> _`
error[E0271]: type mismatch resolving `for<'a> <fn(_) {std::mem::drop::<_>} as std::ops::FnOnce<(&'a _,)>>::Output == ()`
--> src/main.rs:10:5
|
1 | fn foo<F, T>(f: F, x: T)
| ---
2 | where
3 | for<'a> F: FnOnce(&'a T),
| ------------- required by this bound in `foo`
...
10 | foo(drop, "drop"); // this does not!
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
drop
任意のサイズのに関して一般的であると考えられることを考えるとT
、「より一般的な」シグネチャfn(_) -> _
がと互換性がないことは不合理に聞こえfor<'a> fn (&'a _) -> _
ます。コンパイラがdrop
ここの署名を認めないのはなぜですか?トイレのクロージャが代わりに配置されている場合、それは何が違うのですか?