我想知道为什么这样
fn main() {
let v: Vec<&str> = Vec::new();
let s: &str = v.get(0).unwrap();
let new_string = String::from(s);
println!("{}", new_string);
}
但不是这个:
fn main() {
let v: Vec<&str> = Vec::new();
let s = v.get(0).unwrap();
let new_string = String::from(s);
println!("{}", new_string);
}
第二个代码段出现以下错误:
let new_string = String::from(s);
^^^^^^^^^^^^ the trait `std::convert::From<&&str>` is not implemented for `std::string::String`
答案 0 :(得分:0)
Vec::<T>::get()
方法返回一个Option<&T>
,即对向量的引用选项。因为向量已经包含引用(&str
),所以在您的情况下,get()
返回Option<&&str>
。
现在,您的第一个示例进行编译的原因是,通过明确说明s
变量的类型,会导致deref coercion触发,也就是说,编译器将自动插入解引用运算符:
// You write this:
let s: &str = v.get(0).unwrap();
// Compiler actually does this:
let s: &str = *v.get(0).unwrap();
然后,因为存在exists的From<&str>
特性String
的实现,所以编译器接受String::from(s)
调用。
但是,在第二篇文章中,没有显式类型注释,则分配给s
的类型是&&str
:
let s: &&str = v.get(0).unwrap();
这通过String::from()
方法改变了情况:From<&&str>
没有String
实现,并且编译器无法编译代码。
这里的逻辑问题是,当将s
用作from()
的参数时,为什么在这种情况下不发生反引用强制?答案是通用方法不会发生反引用强制,而String::from
是通用方法,因为它依赖于From
特性的类型参数。编译器无法执行反强制,因为totally possible(原则上)同时具有From<&str>
和From<&&str>
方法,它们可能会做不同的事情。
即使From<&&str>
现在不存在,并且编译器将应用deref强制,它也会使代码对未来的发展变得脆弱:如果出于某种原因在将来的版本中添加了From<&&str>
在标准库中,您的代码可能会无声地中断,因为它现在将调用与以前不同的方法,并且逻辑可能不同。
(自然地,我并不是说在未来的libstd版本中确实会添加From<&&str>
;这是适用于任何特征,在任何代码库中的通用推理)。