为什么String :: from(* d)在&& str上给出了* d.to_string()的不同结果?

问题描述 投票:2回答:1

我有点疑惑为什么在第二种情况下解除引用&&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`

我在这里弄错了什么语法?

Rust Playground Link

rust
1个回答
4
投票

to_string在它被解雇之前被召唤到d,所以你将dez the String,这导致str

将其更改为

hs.insert(d.to_string());

这是有效的,因为d会自动解析为str,之后将转换为String。这叫做Deref coercions

如果你有一个类型U,它实现Deref<Target=T>&U的值将自动强制到&T

...

Deref也会在调用方法时启动

这是exactly the case hereimpl 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 deref'd。

© www.soinside.com 2019 - 2024. All rights reserved.