Rust 如何约束关联类型以接受任何引用生存期?

Rust 如何约束关联类型以接受任何引用生存期?,rust,borrow-checker,Rust,Borrow Checker,我有一个简单的特性,它有一个接受关联类型的函数 pub管道{ 类型项目; fn推送(&mut self,值:self::Item); } 现在我想用一个管道做一些事情,它接受引用而不是拥有的值 pub fn do\u something\u ref(特征说明:T) 哪里 T:管道 { 设val:usize=5; 特征仪器推送(&val); } 引用的生存期不会超过调用方上下文的生存期。 也许管道克隆了值。也许它会打印在上面。 但是不允许它存储它,因为这将违反调用方上下文生存期 但是,上面的代

我有一个简单的特性,它有一个接受关联类型的函数

pub管道{
类型项目;
fn推送(&mut self,值:self::Item);
}
现在我想用一个
管道
做一些事情,它接受引用而不是拥有的值

pub fn do\u something\u ref(特征说明:T)
哪里
T:管道
{
设val:usize=5;
特征仪器推送(&val);
}
引用的生存期不会超过调用方上下文的生存期。 也许管道克隆了值。也许它会打印在上面。 但是不允许它存储它,因为这将违反调用方上下文生存期

但是,上面的代码给出了一个错误:
错误[E0637]:`&`没有明确的生存期名称,不能在这里使用

我怎样才能做到这一点? 这是我的尝试


所以,在这里,它们似乎很有用。如果我可以说“
P:Pipe

您可以这样做,为您的函数添加一个通用生存期:

pub fn do_something_ref<'i, T>(mut trait_inst: T)
where
    T: Pipe<Item = &'i usize>
{
    let val: usize = 5;
    trait_inst.push(&val);
}

如果不保留引用是
push()
的一个属性,则可以通过修改trait来解决问题(关于是否允许这样做的问题尚不清楚):

pub管道,
{
设val:usize=5;
特征仪器推送(&val);
}
…并且它可以实现()


如果不修改trait,正如另一个答案所说,没有任何东西可以阻止
push()
保留该值。(类似的问题会阻止流式迭代器工作-除非您无法“修复”迭代器,因为修复会使常规迭代器停止工作。)

另一个选择是……放弃仿制药,只创造两个特性

这是有效的,也是我最终所做的

pub管道{
类型项目;
fn推送(&mut self,值:self::Item);
}
pub-RefPipe{
类型项目;
fn push(&mut self,value:&self::Item);//此处引用
}
(如果需要,
RefPipe
可以被视为
Pipe
s和接收的自有值)

P的impl管道{
类型Item=P::Item;

fn push(&mut self,item:self::item)->Result
for可能还有更好的方法,比如or。@trentcl-Ah它对类型参数(而不是相关类型)起作用的事实是,
fn
特性的参数类型是输入(参数)类型,而不是输出(相关)类型,因此大致相当于
fn(&'a X)
将是
管道,因为它对类型参数(而不是相关类型)有效是有见地的-我的理解是,将特征泛型化为
可以有效地为每个不同的
创建一个新的特征。有了生存期,编译器可以更自由地确定特定的特征可以做什么。据我所知,这就是为什么要将显式泛型生存期添加到当trait具有输出类型时,trait会有所帮助。
error[E0597]: `val` does not live long enough
  --> src/lib.rs:12:21
   |
7  | pub fn do_something_ref<'i, T>(mut trait_inst: T)
   |                         -- lifetime `'i` defined here
...
12 |     trait_inst.push(&val);
   |     ----------------^^^^-
   |     |               |
   |     |               borrowed value does not live long enough
   |     argument requires that `val` is borrowed for `'i`
13 | }
   | - `val` dropped here while still borrowed
pub fn do_something_ref<'i, T>(mut trait_inst: T, x: &'i usize)
where
    T: Pipe<Item = &'i usize>
{
    trait_inst.push(&x);
}
pub trait Pipe<'a> {
    type Item;

    fn push(&mut self, value: Self::Item);
}

pub fn do_something_ref<T>(mut trait_inst: T)
where
    T: for<'a> Pipe<'a, Item = &'a usize>,
{
    let val: usize = 5;
    trait_inst.push(&val);
}