具有从借到借的构造函数的特征无法推断使用的寿命
Trait with constructor that takes borrows to borrows cannot infer liftime on usage
我需要一个特征,它允许我构造一个借用对象的对象。在下面的示例中是 PaperBin。 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=78fb3f88b71bc226614912001ceca65b
trait GarbageBin<'a,'b>{
fn new(rubbish: &'b Paper<'a>) -> Self;
}
struct PaperBin<'a,'b> {
rubbish: &'b Paper<'a>
}
struct Paper<'a> {
matter: &'a [u8]
}
impl<'a,'b> GarbageBin<'a,'b> for PaperBin<'a,'b> {
fn new(rubbish: &'b Paper<'a>) -> Self{
Self {
rubbish: rubbish
}
}
}
fn create_bin_with_rubbish<'a,'b, T>()
where T: GarbageBin<'a,'b>
{
let matter = &[1][..];
let rubbish = Paper{matter};
This gives an error:
//let garbage_bin = T::new(&rubbish);
}
#[test]
fn run() {
create_bin_with_rubbish::<PaperBin>();
}
我需要创建一般在函数调用时确定的 GarbageBins,如示例中所示。对于 Trait 的 new() 关联函数中的固定类型 Paper,此示例看起来可能是不必要的。这应该成为真实代码中的 Trait 对象。
如何实现garbage_bin泛型T的创建?
这是我收到的错误消息,如果我取消注释该行:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src\reference_to_reference\mod.rs:23:23
|
23 | let garbage_bin = T::new(&rubbish);
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:28...
--> src\reference_to_reference\mod.rs:18:28
|
18 | fn create_bin_with_rubbish<'a,'b, T>()
| ^^
note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 18:31...
--> src\reference_to_reference\mod.rs:18:31
|
18 | fn create_bin_with_rubbish<'a,'b, T>()
| ^^
note: ...so that the types are compatible
--> src\reference_to_reference\mod.rs:23:23
|
23 | let garbage_bin = T::new(&rubbish);
| ^^^^^^
= note: expected `GarbageBin<'_, '_>`
found `GarbageBin<'a, 'b>`
您的直接问题是 T: GarbageBin<'a, 'b>
,其中 'a
和 'b
是 create_bin_with_rubbish
的参数,因此必须长于对该函数的调用——但传递给的实际生命周期T::new
仅在函数内部,因此不满足这些界限。
不是使用生命周期 'a
和 'b
来参数化 create_bin_with_rubbish
,解决这个问题的一种方法是使用 HRTB(更高级别的特征边界):
fn create_bin_with_rubbish<T>()
where
T: for<'a, 'b> GarbageBin<'a, 'b>,
但是,PaperBin
隐含地要求 'a: 'b
,并且 HRTB 当前不支持此类界限。但这本身就表明第二个生命周期参数是不必要的:记住,一个生命周期参数只意味着“生命至少与……一样长”,同一参数的多个实例可以代表不同的具体生命周期(只要它们各自满足相同的界限)。所以让我们简化一下:
struct PaperBin<'a> {
rubbish: &'a Paper<'a>,
}
最后,使用 HRTB 确实需要打破 GarbageBin
及其实现者 PaperBin
生命周期之间的直接关系 link——但这是有道理的,因为您正试图通过在不知道其生命周期参数的 PaperBin
类型中,然后在其上调用 GarbageBin
的构造函数方法以获得具有特定生命周期参数的 PaperBin
。所以现在我们实现了 GarbageBin<'a> for PaperBin<'_>
——但是我们仍然需要构造函数来 return 一个 PaperBin<'a>
的实例,为此我们添加了一个关联类型:
trait GarbageBin<'a> {
type Constructed: GarbageBin<'a>;
fn new(rubbish: &'a Paper<'a>) -> Self::Constructed;
}
struct Paper<'a> {
matter: &'a [u8]
}
struct PaperBin<'a> {
rubbish: &'a Paper<'a>
}
impl<'a> GarbageBin<'a> for PaperBin<'_> {
type Constructed = PaperBin<'a>;
fn new(rubbish: &'a Paper<'a>) -> PaperBin<'a> {
PaperBin { rubbish }
}
}
fn create_bin_with_rubbish<T>()
where
T: for<'a> GarbageBin<'a>,
{
let matter = &[1][..];
let rubbish = Paper { matter };
let garbage_bin = T::new(&rubbish);
}
fn main() {
create_bin_with_rubbish::<PaperBin>();
}
使用 GAT(通用关联类型),这是一个 currently 不稳定的功能,您可以将生命周期参数从特征推入关联类型,从而不需要 HRTB:
#![feature(generic_associated_types)]
trait GarbageBin {
type Constructed<'a>: GarbageBin;
fn new<'a>(rubbish: &'a Paper<'a>) -> Self::Constructed<'a>;
}
struct Paper<'a> {
matter: &'a [u8]
}
struct PaperBin<'a> {
rubbish: &'a Paper<'a>
}
impl GarbageBin for PaperBin<'_> {
type Constructed<'a> = PaperBin<'a>;
fn new<'a>(rubbish: &'a Paper<'a>) -> PaperBin<'a> {
PaperBin { rubbish }
}
}
fn create_bin_with_rubbish<T: GarbageBin>() {
let matter = &[1][..];
let rubbish = Paper { matter };
let garbage_bin = T::new(&rubbish);
}
fn main() {
create_bin_with_rubbish::<PaperBin>();
}
我需要一个特征,它允许我构造一个借用对象的对象。在下面的示例中是 PaperBin。 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=78fb3f88b71bc226614912001ceca65b
trait GarbageBin<'a,'b>{
fn new(rubbish: &'b Paper<'a>) -> Self;
}
struct PaperBin<'a,'b> {
rubbish: &'b Paper<'a>
}
struct Paper<'a> {
matter: &'a [u8]
}
impl<'a,'b> GarbageBin<'a,'b> for PaperBin<'a,'b> {
fn new(rubbish: &'b Paper<'a>) -> Self{
Self {
rubbish: rubbish
}
}
}
fn create_bin_with_rubbish<'a,'b, T>()
where T: GarbageBin<'a,'b>
{
let matter = &[1][..];
let rubbish = Paper{matter};
This gives an error:
//let garbage_bin = T::new(&rubbish);
}
#[test]
fn run() {
create_bin_with_rubbish::<PaperBin>();
}
我需要创建一般在函数调用时确定的 GarbageBins,如示例中所示。对于 Trait 的 new() 关联函数中的固定类型 Paper,此示例看起来可能是不必要的。这应该成为真实代码中的 Trait 对象。
如何实现garbage_bin泛型T的创建?
这是我收到的错误消息,如果我取消注释该行:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src\reference_to_reference\mod.rs:23:23
|
23 | let garbage_bin = T::new(&rubbish);
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:28...
--> src\reference_to_reference\mod.rs:18:28
|
18 | fn create_bin_with_rubbish<'a,'b, T>()
| ^^
note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 18:31...
--> src\reference_to_reference\mod.rs:18:31
|
18 | fn create_bin_with_rubbish<'a,'b, T>()
| ^^
note: ...so that the types are compatible
--> src\reference_to_reference\mod.rs:23:23
|
23 | let garbage_bin = T::new(&rubbish);
| ^^^^^^
= note: expected `GarbageBin<'_, '_>`
found `GarbageBin<'a, 'b>`
您的直接问题是 T: GarbageBin<'a, 'b>
,其中 'a
和 'b
是 create_bin_with_rubbish
的参数,因此必须长于对该函数的调用——但传递给的实际生命周期T::new
仅在函数内部,因此不满足这些界限。
不是使用生命周期 'a
和 'b
来参数化 create_bin_with_rubbish
,解决这个问题的一种方法是使用 HRTB(更高级别的特征边界):
fn create_bin_with_rubbish<T>()
where
T: for<'a, 'b> GarbageBin<'a, 'b>,
但是,PaperBin
隐含地要求 'a: 'b
,并且 HRTB 当前不支持此类界限。但这本身就表明第二个生命周期参数是不必要的:记住,一个生命周期参数只意味着“生命至少与……一样长”,同一参数的多个实例可以代表不同的具体生命周期(只要它们各自满足相同的界限)。所以让我们简化一下:
struct PaperBin<'a> {
rubbish: &'a Paper<'a>,
}
最后,使用 HRTB 确实需要打破 GarbageBin
及其实现者 PaperBin
生命周期之间的直接关系 link——但这是有道理的,因为您正试图通过在不知道其生命周期参数的 PaperBin
类型中,然后在其上调用 GarbageBin
的构造函数方法以获得具有特定生命周期参数的 PaperBin
。所以现在我们实现了 GarbageBin<'a> for PaperBin<'_>
——但是我们仍然需要构造函数来 return 一个 PaperBin<'a>
的实例,为此我们添加了一个关联类型:
trait GarbageBin<'a> {
type Constructed: GarbageBin<'a>;
fn new(rubbish: &'a Paper<'a>) -> Self::Constructed;
}
struct Paper<'a> {
matter: &'a [u8]
}
struct PaperBin<'a> {
rubbish: &'a Paper<'a>
}
impl<'a> GarbageBin<'a> for PaperBin<'_> {
type Constructed = PaperBin<'a>;
fn new(rubbish: &'a Paper<'a>) -> PaperBin<'a> {
PaperBin { rubbish }
}
}
fn create_bin_with_rubbish<T>()
where
T: for<'a> GarbageBin<'a>,
{
let matter = &[1][..];
let rubbish = Paper { matter };
let garbage_bin = T::new(&rubbish);
}
fn main() {
create_bin_with_rubbish::<PaperBin>();
}
使用 GAT(通用关联类型),这是一个 currently 不稳定的功能,您可以将生命周期参数从特征推入关联类型,从而不需要 HRTB:
#![feature(generic_associated_types)]
trait GarbageBin {
type Constructed<'a>: GarbageBin;
fn new<'a>(rubbish: &'a Paper<'a>) -> Self::Constructed<'a>;
}
struct Paper<'a> {
matter: &'a [u8]
}
struct PaperBin<'a> {
rubbish: &'a Paper<'a>
}
impl GarbageBin for PaperBin<'_> {
type Constructed<'a> = PaperBin<'a>;
fn new<'a>(rubbish: &'a Paper<'a>) -> PaperBin<'a> {
PaperBin { rubbish }
}
}
fn create_bin_with_rubbish<T: GarbageBin>() {
let matter = &[1][..];
let rubbish = Paper { matter };
let garbage_bin = T::new(&rubbish);
}
fn main() {
create_bin_with_rubbish::<PaperBin>();
}