"参数`'a`永远不会被使用"'a'用于类型参数绑定时出错

mak*_*ako 7 rust

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),
}
Run Code Online (Sandbox Code Playgroud)
error[E0392]: parameter `'a` is never used
 --> src/main.rs:8:16
  |
8 | enum TermValue<'a, LT>
  |                ^^ unused type parameter
  |
  = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`
Run Code Online (Sandbox Code Playgroud)

'a显然正在被使用.这是一个错误,还是参数枚举还没有真正完成?rustc --explain E0392建议使用PhantomData<&'a _>,但我认为在我的用例中没有任何机会这样做.

DK.*_*DK. 13

'a 显然正在被使用.

不就编译器而言.所有它关心的是你的所有通用参数都在structor 的主体中的某个地方使用enum.限制不计算在内.

可能想要的是使用更高级别的生命周期界限:

enum TermValue<LT>
where
    for<'a> LT: 'a + ListTerm<'a> + Sized,
{
    Str(LT),
}
Run Code Online (Sandbox Code Playgroud)

在其他情况下,您可能希望使用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 ()>,
}
Run Code Online (Sandbox Code Playgroud)

而仅仅是明确的:你可以使用PhantomDataenum; 把它放在其中一个变种中:

enum TermValue<'a, LT>
where
    LT: 'a + ListTerm<'a> + Sized,
{
    Str(LT, PhantomData<&'a ()>),
}
Run Code Online (Sandbox Code Playgroud)


Mat*_* M. 6

@DK.回答了如何规避问题(只是PhantomData按建议使用),并暗示问题是'a在定义中没有使用,但为什么编译器会关心这个?

'a 是一个生命周期标记,借用检查器系统使用它来识别不同对象的生命周期之间的关系,以及它们的借用状态.

借用一个对象时,你可以可变地(&mut T)或不可变地(&T)借用它,并根据支持Rust的内存安全性的Mutability XOR Aliasing原则改变一切:

  • 你可以有多个并发 &T
  • 你只能有一个&mut T,它排除了并发&T

当你参与你struct或你的参数enum'a,你宣布你打算借用一些人的生命'a.但是,您不会宣布您是否会以可变或不可变的方式借款,而这一细节至关重要.

因此,编译器将在您的数据类型的内部进行对等,并检查您是否使用可变或不可变引用来自行推断在使用数据类型时将发生哪种借用.

在这里,因为'a未使用,它找不到任何此类用途,因此无法编译您的代码.


这是有争议的编译器的数据类型里面窥视是否是好事还是坏事,因为改变这种数据类型的内部(从&T&mut T)可能会导致编译失败不改变接口类型.

因此,重要的是要记住,如何使用通用参数(拥有,可变借用或不可变地借用)不是实现细节.