为什么Rust无法识别变量是&str?

vit*_*ral 6 traits rust

下面的代码编译并运行正常:

use std::fmt::Display;

fn display(x: &str) {
    println!("{}", x);
}

fn main() {
    let s: &str = "hi there";
    display(s);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您将display功能更改为

fn display(x: &Display)
Run Code Online (Sandbox Code Playgroud)

它给出以下错误:

src/main.rs:9:13: 9:14 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
src/main.rs:9     display(s);
Run Code Online (Sandbox Code Playgroud)

通过改变display(s)display(&s)它再次工作.

这里发生了什么?显然类型是&str,但什么时候&Display是输入参数,它不能识别.

注意:&34也可以作为一个参数.难道这是因为Display实际的执行&str,而不是str

blu*_*uss 7

您正在请求&str应该被强制&Display(对特征对象的引用),这似乎是有意义的,因为类型str实现Display.

然而,作为防锈1.9(和改变这种没有目前的计划)的,转换到一个性状目的是只可能&T&Trait,如果类型T是" Sized".

原因是实施.特征对象&Display由两个字段组成,一个指向数据的指针,以及一个指向特征方法表(vtable)的指针.此表示仅适用于其引用为"精简"且正是类型的值where T: Sized.A &str是一个"胖"引用,它有一个指针和一个长度,因此a str不能是特征对象的数据.


为什么显示(&s)工作?我想这是对"肥胖"参考的引用?

对,就是这样.A &&str,是一个"瘦"引用,指向具有该&str值的变量.所以它可以转换为&Display.


Tat*_*ano 5

(推荐我对主要答案的编辑)

在编写时fn display(x: &Display),该函数采用可以通过解除引用来强制转换为特征对象的值.Rust函数还需要x在编译时知道参数的值大小.

&34(&u32类型)被解除引用并强制转换为特征对象时,它变为u32并且可以确定其大小.

&str取消引用时,它变为str并且其大小无法确定,因为字符串的长度可以是任何东西.

通过添加&&str(&&str),它被取消引用回来&str,这是一个指针,可以确定其大小.我相信这就是编译器只接受display(&s)你的代码的原因.