use std::pin::Pin;
fn main() {
let val: i32 = 3;
let val_pin = Pin::new(&val);
f(val_pin);
f(Pin::new(&val));
}
fn f(_val: Pin<&dyn TestTrait>) {}
trait TestTrait {}
impl TestTrait for i32 {}
第 9 行 f(Pin::new(&val));
抛出编译器错误,但第 6 行 let val_pin = Pin::new(&val);
确实如此不是。编译器错误是:
error[E0277]: `dyn TestTrait` cannot be unpinned
--> src/main.rs:9:7
|
9 | f(Pin::new(&val));
| ^^^^^^^^ the trait `Unpin` is not implemented for `dyn TestTrait`
|
= note: consider using `Box::pin`
note: required by a bound in `Pin::<P>::new`
--> /usr/lib/rustlib/src/rust/library/core/src/pin.rs:482:23
|
482 | impl<P: Deref<Target: Unpin>> Pin<P> {
| ^^^^^ required by this bound in `Pin::<P>::new`
因此,似乎特征 Unpin
是在第 6 行中为 &val
实现的,而不是在第 9 行中实现的。这是为什么?
最佳答案
这与类型推断的一些微妙之处有关。
第 6 行的变量被推断为 Pin<&i32>
随后会自动向上转换为 Pin<&dyn TestTrait>
在第 7 行。您可以通过在第 6 行之后插入以下赋值来检查这一点,这会强制出现编译时错误,显示 my_val
的类型:
let _: () = my_val;
= note: expected unit type `()`
found struct `Pin<&i32>`
(附注:如果 my_val
的类型为 ()
,则此方法不起作用 - 那么分配将会成功!)
相反,当您创建Pin
时作为第 9 行的临时值,推断为 Pin<&dyn TestTrait>
而不是Pin<&i32>
,和&dyn TestTrait
没有实现Unpin
默认情况下。
您可以通过显式指定类型参数 T
来解决此问题的Pin<T>
成为&i32
第 9 行:
f(Pin::<&i32>::new(&val));
您还可以通过指定 TypeTrait
上的界限来解决此问题的Unpin
,这将导致&dyn TestTrait
实现Unpin
还有:
trait TestTrait: Unpin {}
最后,您还可以通过更改 f
来解决该问题接受Pin<&impl TestTrait>
而不是Pin<&dyn TestTrait>
:
fn f(_val: Pin<&impl TestTrait>) {}
正如 @KevinReid 所指出的,您还可以指示特征对象必须实现 Unpin
,这是允许的,因为 Unpin
没有方法:
fn f(_val: Pin<&(dyn TestTrait + Unpin)>) {}
关于rust - 为什么 &i32 有时实现 Unpin,有时不实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73395507/