gpt4 book ai didi

rust - 为什么在 (*x).into() 中需要显式取消引用,但在 x.my_into() 中不需要?

转载 作者:行者123 更新时间:2023-11-29 07:43:57 34 4
gpt4 key购买 nike

看完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);
}

上面的代码有效,但我认为显式取消引用 (*x).into()在函数中 vec_into不需要。我的推理是,因为 x: &Foo , 然后 x.into()会尝试找到接受类型 &Foo 的方法, &&Foo , &mut &Foo , Foo , &Foo , &mut Foo .

这是因为存在解引用链 &FooFoo ,并且对于每个 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`

最佳答案

Rust 完全按照您的描述执行方法查找,并立即找到 .into() 的候选者 – blanket implementation

impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}

此实现满足候选方法的所有要求 - 它是可见的,在范围内并为 &Foo 类型定义,因为它是为 any 类型 T 定义的。一旦编译器选择了这个候选者,它就会注意到 U 上的特征边界不满足,并发出您看到的错误。

MyInto 的情况完全不同,因为您没有提供基于From 的全面实现。如果这样做,您将遇到相同的错误。

有人可能会争辩说,如果不满足特征边界,编译器应该跳过一揽子实现,并继续处理候选类型列表,直到找到更合适的类型。语言规范实际上在这一点上并不完全清楚,但是从我们看到的错误中可以清楚地知道编译器实际上做了什么。

关于rust - 为什么在 (*x).into() 中需要显式取消引用,但在 x.my_into() 中不需要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58082860/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com