Rust编译器chokes在以下代码上:
#![feature(ptr_metadata)]
use core::ptr::Pointee;
struct TypedHandle<E: ?Sized, H> {
handle: H,
metadata: <E as Pointee>::Metadata,
}
type NodeHandle<T, H> = TypedHandle<Node<T, H>, H>;
struct Node<T, H> {
element: T,
next: NodeHandle<T, H>,
prev: NodeHandle<T, H>,
}
似乎有一个类型推断/类型解析问题,但是注解到处都是奇怪的看似不相关的建议:
error[E0284]: type annotations needed
--> src/lib.rs:14:11
|
14 | next: NodeHandle<T, H>,
| ^^^^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `<Node<T, H> as Pointee>::Metadata == _`
note: required because it appears within the type `TypedHandle<Node<T, H>, H>`
--> src/lib.rs:5:8
|
5 | struct TypedHandle<E: ?Sized, H> {
| ^^^^^^^^^^^
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
14 | next: &NodeHandle<T, H>,
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
14 | next: Box<NodeHandle<T, H>>,
| ++++ +
对代码的各种更改“解决”了错误(但中断了功能):
- 使用
NonNull<E>
代替<E as Pointee>::Metadata
。这表明类型的递归性质并不是唯一的问题。 - 删除
TypedHandle
中E
上的?Sized
绑定。 - 删除
next
或prev
之一。这表明,关于next
不能同时是unsized和non-last字段的注解实际上是“严重的”,尽管TypedHandle
总是被调整大小。
对代码的各种更改没有帮助:
- 将
NodeHandle
从类型别名切换到元组结构。它对错误消息也没有帮助。
到目前为止,我找到的唯一解决方案是将where NodeHandle<T, H>: Sized
绑定到Node
,这是 * 相当 * 笨拙的,因为这个绑定必须在之后 * 到处 * 复制。
- 这是编译器的已知限制吗?
- 有没有更好的方法来解决这个问题?
- 注意:当我探索一个新的分配API时,这个问题出现在a custom implementation of
LinkedList
中,我通过将TypedHandle
复制/粘贴到SizedHandle
并删除E
上的?Sized
绑定来解决它,这让我感到很不舒服,但比到处复制/粘贴绑定更容易修复。
1条答案
按热度按时间vmdwslir1#
这是一个每晚的回归,@lukas-code在这个github评论中提到了我的问题。
在同一条评论中,他还提出了一个更轻量级的解决方案:添加一个
_tail: ()
字段,使编译器意识到一个类型的大小。特别是,
TypedHandle
定义可以更改为:以使解决方法的范围尽可能大。