rust - Rust 如何处理将 &SizedType 转换为 &UnsizedType?

标签 rust

struct MaybeSized<T: ?Sized> {
    v: T,
}

fn main() {
    let sized = MaybeSized {
        v: "sized".to_string(),
    };

    use std::fmt::Display;

    {
        // what exactly happens here?
        let ref1: &MaybeSized<Display> = &sized;
    }
    {
        // why this fails to compile?
        let ref2: &MaybeSized<str> = &sized;
    }
}

MaybeSize<String>是一个大小的类型; ref1 : &MaybeSized<Display>时堆栈和堆上有什么) 被 build ?为什么这种“魔法”不适用于另一种未确定大小的类型,如 MaybeSized<str>

最佳答案

来自 &MaybeSized<String> 的转换至 &MaybeSized<dyn Display>称为 unsized coercion .具体类型可以针对它们实现的特征强制转换为特征对象,并且这种强制在特定条件下扩展到通用结构:

Foo<..., T, ...> to Foo<..., U, ...>, when:

  • Foo is a struct.
  • T implements Unsize<U>.
  • The last field of Foo has a type involving T.
  • If that field has type Bar<T>, then Bar<T> implements Unsized<Bar<U>>.
  • T is not part of the type of any other fields.

(有关完整详细信息,请点击上面语言引用的链接。)

变量sized存储在堆栈中,但是String的数据分配在堆上。引用ref1胖指针的形式存储在堆栈中——一个指向sized的指针连同指向 String as dyn Display 的虚拟方法表的指针允许在必要时动态调用正确的方法。

这不适用于 MaybeSized<str>因为没有转换为 str 的未定大小的强制转换.您可以转换和 &String&str使用 deref 强制转换,但这不是我们在这里需要的——取消大小类型需要一个未调整大小的强制转换。未定尺寸的类型 MaybeSized<str>实际字符串数据组成,而MaybeSized<String>由长度、容量和指向堆的指针组成,因此无法使内存布局匹配。

不过,还有其他一些情况可行,例如

let a = MaybeSized { v: [65u8, 66, 67]};
let b: &MaybeSized<[u8]> = &a;

工作正常,因为有来自 [u8; 3] 的未定大小的强制转换至 [u8] .使用不安全代码,您可以将其转换为 &MaybeSized<str>如果你真的想:

let c: &MaybeSized<str> = unsafe { &*(b as *const _ as *const _) };

我想不出创建 &MaybeSized<str> 的安全方法.

( Code on the playground )

关于rust - Rust 如何处理将 &SizedType 转换为 &UnsizedType?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55988573/

相关文章:

rust - 为什么即使我没有设置default-features = false,rand::Rng 也能够在无std 环境中工作?

rust - 为什么可变引用没有移到这里?

reference - 如何将 `&b` 中的 `&A` 的引用 `b: B` 强制转换为 `let a: &A = &b;` ?

rust - 将可变实例方法传递给函数

rust - rust 交叉编译 ARM : skylake is not a recognized processor for this target

rust - 如何将网站内容下载到字符串中?

reference - 我什么时候应该使用引用而不是转让所有权?

rust - 我如何确定为什么已编译的 Rust 二进制文件需要特定符号?

rust - 当 ref 和所有权转移都不起作用时如何返回

rust - 如何选择退出运行文档测试?