Rust &引用;参数`';a“从不使用”;当';在类型参数绑定中使用 使用std::iter::Iterator; 性状表项; fn-iter(&'a self)->self::iter; } 枚举术语值+大小+'a, { Str(LT), } 错误[E0392]:从未使用参数“%a” -->src/main.rs:8:16 | 8 | enum TermValue,但我认为在我的用例中没有任何机会这样做
Rust &引用;参数`';a“从不使用”;当';在类型参数绑定中使用 使用std::iter::Iterator; 性状表项; fn-iter(&'a self)->self::iter; } 枚举术语值+大小+'a, { Str(LT), } 错误[E0392]:从未使用参数“%a” -->src/main.rs:8:16 | 8 | enum TermValue,但我认为在我的用例中没有任何机会这样做,rust,Rust,'a显然正在使用 就编译器而言并非如此。它所关心的只是所有的泛型参数都在结构体或枚举中的某个地方使用。约束不起作用 您可能希望使用更高级别的终身限制: use std::iter::Iterator; trait ListTerm<'a> { type Iter: Iterator<Item = &'a u32>; fn iter(&'a self) -> Self::Iter; } enum TermValue<'a, L
'a
显然正在使用
就编译器而言并非如此。它所关心的只是所有的泛型参数都在结构体
或枚举
中的某个地方使用。约束不起作用
您可能希望使用更高级别的终身限制:
use std::iter::Iterator;
trait ListTerm<'a> {
type Iter: Iterator<Item = &'a u32>;
fn iter(&'a self) -> Self::Iter;
}
enum TermValue<'a, LT>
where
LT: ListTerm<'a> + Sized + 'a,
{
Str(LT),
}
需要明确的是:您可以在枚举中使用PhantomData
;将其放入其中一个变体中:
use std::marker::PhantomData;
struct Thing<'a> {
// Causes the type to function *as though* it has a `&'a ()` field,
// despite not *actually* having one.
_marker: PhantomData<&'a ()>,
}
enum TermValue),
}
如何规避这个问题(按照建议使用PhantomData
),并暗示问题是定义中未使用'a
,但编译器为什么会关心这个问题
'a
是一个生命周期标记。借用检查器使用它来标识不同对象的生存期之间的关系及其借用状态
借用对象时,您可以可变地借用它(&mut T
)或不可变地借用它(&T
),并且根据支持Rust内存安全的可变异或别名原则,它改变了一切:
- 您可以有多个并发的
&T
- 您只能有一个
&mut T
,它不包括并发&T
当您使用'a
参数化您的结构
或枚举
时,您会宣布您打算借用某个'a
的对象。然而,您并没有宣布您将以可变方式还是不变方式借款,这一细节至关重要
因此,编译器将查看您的数据类型的内部,并检查您是否使用可变引用或不可变引用来自行推断在使用该数据类型时将发生哪种借用
在这里,因为'a
未被使用,它找不到任何这样的用途,因此无法编译您的代码
编译器窥视数据类型内部是否是一件好事是有争议的,因为在不更改类型接口的情况下更改此数据类型的内部(从&T
更改为&mut T
)可能导致编译失败
因此,重要的是要记住,如何使用泛型参数(拥有、可变借用或不可变借用)不是一个实现细节。如果不使用关联类型(如
绑定,这样您就可以编写一个或多个fn
或一个impl
,它使用LT
作为列表项
。在这种情况下,您可以轻松地用
参数化类型,并将'a
泛型和特征绑定仅放在需要它的项上:
enum TermValue<'a, LT>
where
LT: 'a + ListTerm<'a> + Sized,
{
Str(LT, PhantomData<&'a ()>),
}
trait列表项;
fn-iter(&'a self)->self::iter;
}
枚举TermValue{//no'此处有一个参数。。。
Str(LT),
}
impl,
{
fn iter(&'a self)->LT::iter{
匹配自我{
TermValue::Str(ref term)=>term.iter(),
}
}
}
一些标准的库类型,如这样做的:K:Hash+Eq
绑定不在类型本身上。或者,在需要绑定的每个方法上都可以有一个where
子句。除非是impl,否则impl
上的where
子句与fn
上的子句之间的差异并不显著修正一个特征(参见)
使用PhantomData
的主要原因是您想表达一些编译器自己无法理解的约束。您不需要PhantomData
来表达“任何TermData
只有在其包含的LT
有效时才有效”,因为编译器已经执行了(通过“窥视内部”类型,如中).你的错误是说struct,你的代码是enum?@Neikos啊,这两种情况下都会发生错误,但是对于struct来说,添加一个phantomdata就不那么麻烦了,因为用户不一定直接与它交互。我想明确我的用例是一个enum,所以要求用户在任何时候都匹配一个phantomdata是非常糟糕的人机工程学他们打开了oneN…不。生命周期界限在枚举体中使用。事实上,它需要查看特征界限来找出这一点并不能解释为什么它没有得到它。这是一个有用的答案。看起来这两种技术对我的用例都不起作用。IRL,TermValue采用了另一种需要生命周期的类型我相当于另一个,而且
enum TermValue<'a, LT>
where
LT: 'a + ListTerm<'a> + Sized,
{
Str(LT, PhantomData<&'a ()>),
}
trait ListTerm<'a> {
type Iter: Iterator<Item = &'a u32>;
fn iter(&'a self) -> Self::Iter;
}
enum TermValue<LT> { // no 'a parameter here...
Str(LT),
}
impl<'a, LT> TermValue<LT> // ... just here
where
LT: ListTerm<'a>,
{
fn iter(&'a self) -> LT::Iter {
match *self {
TermValue::Str(ref term) => term.iter(),
}
}
}