7

我正在读一本 Rust 书,我对这个例子感到困惑:

use std::fmt::Display;

fn main() {
    test("hello");
    test2("hello")
}

fn test(s: &dyn Display) {
    println!("{}", s);
}

fn test2(s: &str) {
    println!("{}", s);
}

&'static str作为特征对象传递失败:

error[E0277]: the size for values of type `str` cannot be known at compilation time
 --> src/main.rs:4:10
  |
4 |     test("hello");
  |          ^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `str`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: required for the cast to the object type `dyn std::fmt::Display`

为什么这会失败并且第二次调用有效?

4

1 回答 1

10

str确实实现Display了,但不可能将 a 强制&str转换为 a,&dyn Display因为 for 的实现Display可能str(并且确实)使用了字符串的长度。Length 是 type 的一部分,&str但不是 type 的一部分&dyn Display,并且您不能丢弃该长度,因为这将使其根本无法实现Display

另一种看待这个的方式是,不存在用于实现Displayfor的 vtable(虚拟方法表) str,因为 vtables 可能只包含接受瘦指针的函数,self但 in是一个胖指针。另请参阅为什么不能将 `&(?Sized + Trait)` 强制转换为 `&dyn Trait`?impl Display for str&self

但是,&str它本身也实现了Display,因此您可以test通过简单地添加另一层间接来完成工作:

fn main() {
    test(&"hello");
}
于 2019-09-06T16:29:07.537 回答