我怎样才能在结构中有一个未使用的类型参数?

How can I have an unused type parameter in a struct?

我正在尝试更新我写的一些旧代码,基本上看起来像:

trait Foo<T>{}

struct Bar<A, B: Foo<A>>{
  b: B
}

这过去工作得很好,但现在我遇到编译错误:

src/test.rs:19:12: 19:13 error: parameter `A` is never used
src/test.rs:19 struct Bar<A, B: Foo<A>> {
                          ^
src/test.rs:19:12: 19:13 help: consider removing `A` or using a marker such as `core::marker::PhantomData`

所以我可以尝试删除类型参数并得到如下内容:

struct Bar<A>{
  b: Foo<A>
}

然而这并不是我真正想要的。在我的原始代码中 B 解析为大小类型,但现在 Foo<A> 未调整大小。

另一个建议的解决方案是尝试使用错误提到的这个 PhantomData,导致:

struct Bar<A, B: Foo<A>> {
  b: B,
  marker: PhantomData<A>
}

但这对我来说真的很乱。阅读 PhantomData 的文档似乎表明这是要与不安全代码一起使用,但我在这里的任何地方都没有使用不安全代码。我想要的只是 Bar 包含一个实现 Foo.

的某种类型的实例

这真的是现在处理这种情况的唯一方法吗,还是我遗漏了什么?

根据您的真实 Foo 情况,您也许可以使用关联类型,例如:

trait Foo{ type T; }

struct Bar<B: Foo> {
  b: B,
}

否则(如果您确实需要 Foo 上的类型参数),PhantomData 确实是可行的方法。

您不是唯一发现 PhantomData 的文档令人困惑的人(参见 PhantomData is incomprehensible). As a result, the documentation for PhantomData has been recently improved by Steve Klabnik,现在它确实明确提到了这种情况(而不仅仅是不安全的代码)。

看来您想要的是以下内容:对于 any 类型 AB 必须实现 Foo<A>。这表明您依赖 Foo 的功能而不依赖于 A 的值,这意味着您可以将 Foo 更改为具有关联类型而不是类型参数。

trait Foo<T> { }

会变成

trait Foo {
    type T;
}

然后你可以删除所有地方的 A 类型参数并且只需要 B: Foo.

详细说明PhantomData,它与不安全代码无关,它用于在编译器无法推断类型参数时确定类型参数的变化。有关方差和 PhantomData.

的更多信息,请参阅 RFC 738