我有点疑惑为什么解除引用&&str
似乎不适用于第二种情况:
use std::collections::HashSet;
fn main() {
let days = vec!["mon", "tue", "wed"];
let mut hs: HashSet<String> = HashSet::new();
for d in &days {
// works
hs.insert(String::from(*d));
// doesn't
hs.insert(*d.to_string());
}
println!("{:#?}", hs);
}
str
确实实现了ToString
特征,但它仍然给我错误:
error[E0308]: mismatched types
--> src/main.rs:12:19
|
12 | hs.insert(*d.to_string());
| ^^^^^^^^^^^^^^ expected struct `std::string::String`, found str
|
= note: expected type `std::string::String`
found type `str`
我在这里弄错了什么语法?
答案 0 :(得分:4)
to_string
在被解析之前被调用d
,因此您将对String
进行deref,从而产生str
。
将其更改为
hs.insert(d.to_string());
这是有效的,因为d
会自动解析为str
,之后会转换为String
。这称为Deref coercions。
如果您有
U
类型,并且它实现了Deref<Target=T>
,&U
的值将自动强制转换为&T
...
Deref也会在调用方法时启动
这是exactly the case here:impl Deref<Target = str> for String
。见here for an example:
类型
&&&&&&&&&&&&&&&&Foo
的值仍然可以在调用Foo
上定义方法,因为编译器将根据需要插入尽可能多的*
操作以使其正确。由于它正在插入*s
,因此使用Deref
。
这example证明了这一点:
struct Foo;
impl Foo {
fn foo(&self) { println!("Foo"); }
}
let f = &&Foo;
// prints "foo"
f.foo();
顺便说一下,
hs.insert((*d).to_string());
也会work,因为它首先是&str
。