【发布时间】:2020-01-24 17:29:54
【问题描述】:
看了method-call expressions、dereference operator、method lookup和auto-dereferencing之后,我觉得我对这个主题有了很好的理解;但后来我遇到了一种情况,我希望自动取消引用会发生,而实际上它并没有发生。
示例如下。
#[derive(Clone, Copy, Debug)]
struct Foo();
impl Into<&'static str> for Foo {
fn into(self) -> &'static str {
"<Foo as Into>::into"
}
}
fn vec_into<F: Copy + Into<T>, T>(slice: &[F]) -> Vec<T> {
slice.iter().map(|x| (*x).into()).collect()
}
fn main() {
let array = [Foo(), Foo(), Foo()];
let vec = vec_into::<_, &'static str>(&array);
println!("{:?}", vec);
}
上面的代码有效,但我认为不需要在函数vec_into 中显式取消引用(*x).into()。我的推理是,既然x: &Foo,那么x.into() 会尝试找到接受类型&Foo、&&Foo、&mut &Foo、Foo、&Foo、&mut Foo 的方法。
这是因为存在取消引用&Foo → Foo 的链,并且对于此链中的每个U,我们还插入&U 和&mut U。
我的直觉得到以下事实的证实:以下代码也有效,无需任何明确的取消引用。
#[derive(Clone, Copy, Debug)]
struct Foo();
trait MyInto<T> {
fn my_into(self) -> T;
}
impl MyInto<&'static str> for Foo {
fn my_into(self) -> &'static str {
"<Foo as MyInto>::my_into"
}
}
fn vec_my_into<F: Copy + MyInto<T>, T>(slice: &[F]) -> Vec<T> {
slice.iter().map(|x| x.my_into()).collect()
}
fn main() {
let array = [Foo(), Foo(), Foo()];
let my_vec = vec_my_into(&array);
println!("{:?}", my_vec);
}
这里 x: &Foo 被隐式取消引用,以便调用方法 <Foo as MyInto<&'static str>>::my_into。
一个小例子
鉴于以上Foo和MyInto的定义,代码
let result: &str = (&Foo()).my_into()
有效,但是
let result: &str = (&Foo()).into()
编译失败
error[E0277]: the trait bound `&str: std::convert::From<&Foo>` is not satisfied
--> src/bin/into.rs:34:33
|
34 | let result: &str = (&Foo()).into();
| ^^^^ the trait `std::convert::From<&Foo>` is not implemented for `&str`
|
= note: required because of the requirements on the impl of `std::convert::Into<&str>` for `&Foo`
【问题讨论】:
-
再次与您的问题无关,但
struct Foo();和Foo()可以只是struct Foo;和Foo。有助于避免误以为这是常规功能。 -
@Shepmaster 谢谢,我不知道(现在我明白了:doc.rust-lang.org/book/…)
标签: rust traits implicit-conversion dereference