为什么一个接受&dyn Display trait对象的函数不能接受一个&str?

8

我正在阅读一本关于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 作为 trait 对象传递会失败:

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`

为什么第一次调用失败了,而第二次调用成功了?
1个回答

10
str 实现了 Display,但是不能将一个 &str 强制转换为 &dyn Display,因为对于 str 的实现可能会(并且确实)使用字符串的长度。长度是 &str 类型的一部分,但不是 &dyn Display 类型的一部分,而且你不能丢弃长度,因为这样将完全无法实现 Display
从另一个角度看,strDisplay 实现不存在虚方法表(vtable),因为 vtable 只能包含接受“瘦”指针的函数,而在 impl Display for str 中,&self 是“胖”指针。详情请参见为什么 `&(?Sized + Trait)` 不能强制转换为 `&dyn Trait`? 然而,&str 本身也实现了 Display,因此你可以通过添加另一层间接性来使 test 起作用:
fn main() {
    test(&"hello");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接