在Self上分类不同的生存期和方法

在Self上分类不同的生存期和方法

本文介绍了在Self上分类不同的生存期和方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发布了类似的问题(铁锈寿命错误预期混凝土寿命,但昨晚找到了约束寿命),但现在仍不知道如何将其应用于这种情况.再次,下面是一个简化的示例:

struct Ref;

struct Container<'a> {
  r : &'a Ref
}

struct ContainerB<'a> {
  c : Container<'a>
}

trait ToC {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> Self;
}

impl<'b> ToC for ContainerB<'b> {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
    ContainerB{c:c}
  }
}

出现错误消息:

test.rs:16:3: 18:4 error: method `from_c` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
test.rs:16:67: 18:4 note: expected concrete lifetime is the lifetime 'b as defined on the block at 16:66
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
error: aborting due to previous error

我认为需要发生的是,我需要某种方式来等同于/子类型寿命'a和寿命'b.与前面的示例不同,没有&self可以使用.我想我可以通过向我的trait(trait ToC<'a> ...)添加一个生命周期类型参数来做到这一点,但是我不希望这样做,因为它在我想将trait用作类型绑定的任何地方都添加了额外的<'a>. /p>

如果有人好奇(AKA可以忽略这一点),我可能会在库中使用它在rust和python类型之间进行转换.特质是此处.一切正常,但是我正在尝试围绕PyObject类型(例如numpy ndarray)实现包装,并能够以此与PyObject进行相互转换.

再次感谢!

解决方案

这归结为与您上一个问题大致相同的问题.

Self是指您要为其实现特征的类型.在这种情况下,它是ContainerB<'b>,因此,关于它的全部不同之处适用.这次,这一次也没有将'b'a绑定在一起的情况;生存期是并且必须由编译器假定是可能不相交的. (这与保证'b ≥ 'a&'a ContainerB<'b>不同.)

一旦使用了在方法上定义的生存期,就不可能在Self上绑定生存期.最好的解决方案是将生命周期参数从方法转移到特征上:

trait ToC<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> Self;
}

impl<'a> ToC<'a> for ContainerB<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> ContainerB<'a> {
        ContainerB { c: c }
    }
}

I posted a similar question (Rust lifetime error expected concrete lifetime but found bound lifetime) last night, but still can't figure out how to apply it to this case now. Once again, a simplified example bellow:

struct Ref;

struct Container<'a> {
  r : &'a Ref
}

struct ContainerB<'a> {
  c : Container<'a>
}

trait ToC {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> Self;
}

impl<'b> ToC for ContainerB<'b> {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
    ContainerB{c:c}
  }
}

With the error message:

test.rs:16:3: 18:4 error: method `from_c` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
test.rs:16:67: 18:4 note: expected concrete lifetime is the lifetime 'b as defined on the block at 16:66
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
error: aborting due to previous error

What I think needs to happen is I need some way to equate / sub-type lifetime 'a, and lifetime 'b. Unlike the previous example there is no &self to use. I am guessing I can do this by adding a lifetime type argument to my trait(trait ToC<'a> ...), but I would prefer not to do this as it adds extra <'a> everywhere I want to use the trait as a type bound.

If anybody is curious(AKA can ignore this) where this might actually come up, I am using it in a library to convert between rust and python types. The trait is here. Everything works fine, but I am trying to implement a wrapper around the PyObject type (such as a numpy ndarray) and be able to convert it to and from a PyObject with this.

Thanks again!

解决方案

This boils down to much the same problem as in your previous question.

Self refers to the type you are implementing the trait for. In this case it is ContainerB<'b>, and so the whole thing about its not being the same applies; this time this time there is nothing to tie 'b and 'a together, either; the lifetimes are and must be assumed by the compiler to be potentially disjoint. (This is as distinct to the &'a ContainerB<'b> which guaranteed 'b ≥ 'a.)

Once you are using a lifetime defined on the method, tying that in with a lifetime on Self is not possible. The solution that is probably best is to shift the lifetime parameter from the method onto the trait:

trait ToC<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> Self;
}

impl<'a> ToC<'a> for ContainerB<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> ContainerB<'a> {
        ContainerB { c: c }
    }
}

这篇关于在Self上分类不同的生存期和方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 04:23