gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 08:15:31 25 4
gpt4 key购买 nike

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com