用寿命参数动态建立结构

发布于 2025-01-23 05:34:52 字数 2559 浏览 3 评论 0原文

试图从Rust中的另一棵树结构中构建树结构 - 建造的树结构取决于终生参数。

下面的特征代表了我的搜索树结构的简化版本(我希望是动态构建的):

trait SPart {
  fn search<'b>(&'b self, queue: &mut Vec<Box<dyn SPart + 'b>>);
}
trait SubSPart<PP: SPart> {
  fn promote_search<'b>(&'b self, parent: &'b PP, queue: &mut Vec<Box<dyn SPart + 'b>>);
}

struct SP<'a>(pub Vec<Box<dyn SubSPart<Self> + 'a>>);
struct SSP(pub i32);

impl<'a> SPart for SP<'a> {
  fn search<'b>(&'b self, queue: &mut Vec<Box<dyn SPart + 'b>>) {
    for c in &self.0 {
      c.promote_search(self, queue);
    }
  }
}
impl<'a> SubSPart<SP<'a>> for SSP {
  fn promote_search<'b>(&'b self, parent: &'b SP, queue: &mut Vec<Box<dyn SPart + 'b>>) {
    queue.push(Box::new(SP(vec![])));
  }
}

零件和子部分可以包含对数据的参考,因此我认为寿命参数是必要的。 这些部分通常在递归函数中也短暂,可以动态地引用递归调用中早期帧的数据。

这一切都与颜色一起使用,所以现在我有兴趣通过单独的树结构动态构建此初始树结构:

trait BPart {
  fn build<'b>(&'b self, v: &mut Vec<Box<dyn SPart + 'b>>);
}
trait SubBPart<P, PP: SPart> {
  fn build<'b>(&'b self, parent: &'b P, v: &mut Vec<Box<dyn SubSPart<PP> + 'b>>);
}

struct BP<'a>(pub Vec<Box<dyn SubBPart<Self, SP<'a>>>>, pub i32);
struct SBP(pub i32);

impl<'a> BPart for BP<'a> {
  fn build<'b>(&'b self, v: &mut Vec<Box<dyn SPart + 'b>>) {
    let mut sv = vec![];
    for sp in &self.0 {
      sp.build(self, &mut sv);
    }
    let sp = SP(sv);
    v.push(Box::new(sp));
  }
}

impl<'a> SubBPart<BP<'a>, SP<'a>> for SBP {
  fn build<'b>(&'b self, parent: &'b BP<'a>, v: &mut Vec<Box<dyn SubSPart<SP> + 'b>>) {
    v.push(Box::new(SSP(self.0 + parent.1)));
  }
}

fn main() {
  let bp = BP(vec![Box::new(SBP(42))], 21);
  let mut v = vec![];
  bp.build(&mut v);
}

但是,这似乎是:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

看起来寿命与bpart('a)< /code>在创建Spartsubpart时,但我不知道如何在生锈中表达这一点。

a href =“ https://play.rust-lang.org/?version=stable&; mode = debug&;

< 强>编辑: 添加了特质方法和示例以及主要方法。

Trying to build a tree structure from another tree structure in Rust - where the the built tree structure are dependent on lifetimes parameters.

The traits below represents a simplified version of my search tree structure (the one I wish for to be build dynamically):

trait SPart {
  fn search<'b>(&'b self, queue: &mut Vec<Box<dyn SPart + 'b>>);
}
trait SubSPart<PP: SPart> {
  fn promote_search<'b>(&'b self, parent: &'b PP, queue: &mut Vec<Box<dyn SPart + 'b>>);
}

struct SP<'a>(pub Vec<Box<dyn SubSPart<Self> + 'a>>);
struct SSP(pub i32);

impl<'a> SPart for SP<'a> {
  fn search<'b>(&'b self, queue: &mut Vec<Box<dyn SPart + 'b>>) {
    for c in &self.0 {
      c.promote_search(self, queue);
    }
  }
}
impl<'a> SubSPart<SP<'a>> for SSP {
  fn promote_search<'b>(&'b self, parent: &'b SP, queue: &mut Vec<Box<dyn SPart + 'b>>) {
    queue.push(Box::new(SP(vec![])));
  }
}

The parts and subparts can contain references to data, hence I think the lifetime-parameter is necessary.
These parts are usually also short-lived in a recursive function, and can be created dynamically referring back to data from earlier frames in the recursive call.

This all works with flying colors, so now I'm interested in building this initial tree structure dynamically from a separate tree structure:

trait BPart {
  fn build<'b>(&'b self, v: &mut Vec<Box<dyn SPart + 'b>>);
}
trait SubBPart<P, PP: SPart> {
  fn build<'b>(&'b self, parent: &'b P, v: &mut Vec<Box<dyn SubSPart<PP> + 'b>>);
}

struct BP<'a>(pub Vec<Box<dyn SubBPart<Self, SP<'a>>>>, pub i32);
struct SBP(pub i32);

impl<'a> BPart for BP<'a> {
  fn build<'b>(&'b self, v: &mut Vec<Box<dyn SPart + 'b>>) {
    let mut sv = vec![];
    for sp in &self.0 {
      sp.build(self, &mut sv);
    }
    let sp = SP(sv);
    v.push(Box::new(sp));
  }
}

impl<'a> SubBPart<BP<'a>, SP<'a>> for SBP {
  fn build<'b>(&'b self, parent: &'b BP<'a>, v: &mut Vec<Box<dyn SubSPart<SP> + 'b>>) {
    v.push(Box::new(SSP(self.0 + parent.1)));
  }
}

fn main() {
  let bp = BP(vec![Box::new(SBP(42))], 21);
  let mut v = vec![];
  bp.build(&mut v);
}

However, this fails with:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

It seems like the lifetime is tied to the BPart ('a) where I wish for the lifetime to be valid for any lifetime ('b) at the time of creation of the SPart and SubSPart, but I'm unaware of how to express this in Rust.

Link to rust playground

Edit:
Added trait methods and examples, and main method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为人所爱 2025-01-30 05:34:52

这是终生约束的意大利面条,因此我将尝试分解局限性:

  1. Lifetime 'B由于其在&amp; mut Vec&lt box&lt; box&lt;中而不变。 Dyn Spart +'B&gt;。大多数终身注释都是协变量的,这意味着可以根据需要缩短其与其他约束。但是编译器不能在这里这样做,因为如果缩短,该值可以变异或分配到比其所需的短的值。

  2. Lifetime 'a由于其在vec&lt; box&lt; dyn subbpart&lt; self,sp&lt;'a&gt;&gt;&gt;&gt;&gt;而不变。 特质&lt;'a&gt;的实施者可以使用内部的突变性,因此,出于上述相同的原因,不能是协变量的。

  3. 'a:'b - 使用&amp;'b self暗示bp&lt;'a&gt;:'b,因此意味着'a:'b意味着'b的寿命不能超过'a的寿命。

  4. 'b:'a - 使用dyn subpart&lt; pp&gt; +'b通常意味着特征对象可以从'b借用,但是因为ppsp&lt;'a&gt;还允许它从'a借用。这意味着为了'Bsubbpart ::构建bpart :: build对齐,然后'a 'a < /code>不能超越'b


  5. 要满足上述约束,必须是'a =='b。但是'b是特征函数签名作为通用参数的一部分,因此必须允许它是任何东西。

我对您如何修复它没有很好的建议,因为您的代码对这些生命和特质抽象的目的非常困惑。

This is quite the spaghetti of lifetime constraints so I'll try to break down the limitations:

  1. The lifetime 'b is invariant due to its use in &mut Vec<Box<dyn SPart + 'b>>. Most lifetime annotations are covariant, meaning it can be shortened as necessary to align with other constraints. But the compiler cannot do so here because, if shortened, the value could be mutated or assigned to a value that lives shorter than it needs to.

  2. The lifetime 'a is invariant due to its use in Vec<Box<dyn SubBPart<Self, SP<'a>>>>. An implementor of Trait<'a> can use inner mutability and thus, for the same reasons above, cannot be covariant.

  3. 'a: 'b - The use of &'b self implies BP<'a>: 'b and thus implies 'a: 'b meaning that the lifetime of 'b cannot outlive the life of 'a.

  4. 'b: 'a - The use of dyn SubSPart<PP> + 'b normally means that the trait object is allowed to borrow from 'b but because PP is SP<'a> it is also allowed to borrow from 'a. This means that in order for 'b from SubBPart::build to line up with BPart::build, then 'a cannot outlive 'b.

  5. To satisfy the above constraints, it must be that 'a == 'b. But 'b is part of a trait's function signature as a generic parameter, so it must be allowed to be anything.

I don't have a good recommendation for you for how to fix it since your code is very obfuscated as to what these lifetimes and trait abstractions are for.

冷了相思 2025-01-30 05:34:52

确实需要更高的寿命。而不是锁定特定的生命周期,而是将'a作为struct bp中的通用参数,可以指定较高友善的寿命如下

struct BP(pub Vec<Box<dyn for<'a> SubBPart<Self, SP<'a>>>>, pub i32);

:答案:在我的情况下,Spartsubpart可以包含来自其构建器bpart bpart 或subbpart的数据引用。这需要改变特征:

trait BPart<'a> {
  fn build(&'a self, v: &mut Vec<Box<dyn SPart + 'a>>);
}
trait SubBPart<'a, P, PP: SPart> {
  fn build(&'a self, parent: &'a P, v: &mut Vec<Box<dyn SubSPart<PP> + 'a>>);
}

然后对IMPS进行相应调整。

This is indeed a case where a higher kinded lifetime is needed. Instead of locking in on a specific lifetime, giving 'a as a generic parameter in the struct BP, the use of a higher kinded lifetime can be specified as follows:

struct BP(pub Vec<Box<dyn for<'a> SubBPart<Self, SP<'a>>>>, pub i32);

To complete the answer: In my case, a SPart or SubSPart can contain references to data from its builder BPart or SubBPart. This required changes to the traits:

trait BPart<'a> {
  fn build(&'a self, v: &mut Vec<Box<dyn SPart + 'a>>);
}
trait SubBPart<'a, P, PP: SPart> {
  fn build(&'a self, parent: &'a P, v: &mut Vec<Box<dyn SubSPart<PP> + 'a>>);
}

and then adjusting the impls accordingly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文