Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
441 views
in Technique[技术] by (71.8m points)

rust - Lifetimes for generalizing trait implementation from &T to AsRef<T>

I have some problems generalizing a trait working for &str to other string types (e.g. Rc<str>, Box<str>,String).

First of all my example function should work for:

assert_eq!(count("ababbc", 'a'), 2);                // already working
assert_eq!(count(Rc::from("ababbc"), 'a'), 2);      // todo
assert_eq!(count("ababbc".to_string(), 'a'), 2);    // todo

This is the working code, which makes the first test run:

pub trait Atom: Copy + Eq + Ord + Display + Debug {}
impl Atom for char {}

pub trait Atoms<A, I>
where
  I: Iterator<Item = A>,
  A: Atom,
{
  fn atoms(&self) -> I;
}

impl<'a> Atoms<char, std::str::Chars<'a>> for &'a str {
  fn atoms(&self) -> std::str::Chars<'a> {
    self.chars()
  }
}

pub fn count<I, A, T>(pattern: T, item: A) -> usize
where
  A: Atom,
  I: Iterator<Item = A>,
  T: Atoms<A, I>,
{
  pattern.atoms().filter(|i| *i == item).count()
}

To make the next tests run, I changed the signature of count and Atoms in following way:

pub trait Atoms<'a, A, I>
where
  I: Iterator<Item = A> + 'a,
  A: Atom,
{
  fn atoms<'b>(&'b self) -> I
  where
    'b: 'a;
}

impl<'a, S> Atoms<'a, char, std::str::Chars<'a>> for S
where
  S: AsRef<str> + 'a,
{
  fn atoms<'b>(&'b self) -> std::str::Chars<'b>
  where
    'b: 'a,
  {
    self.as_ref().chars()
  }
}

but now the function count does not compile any more:

pub fn count<'a, I, A, T>(pattern: T, item: A) -> usize
where
  A: Atom,
  I: Iterator<Item = A> + 'a,
  T: Atoms<'a, A, I>,
{
  pattern.atoms().filter(|i| *i == item).count()
}

Playground-Link

The compiler error is: the parameter type 'T' may not live long enough ... consider adding an explicit lifetime bound...: 'T: 'a'. This is not completely understandable for me, so I tried to apply the help T: Atoms<'a, A, I> + 'a. Now the error is: 'pattern' does not live long enough ... 'pattern' dropped here while still borrowed.

Since the latter error also occurs without implementations of Atoms and by just replacing the function body by pattern.atoms();return 1; I suspect that the type signature of Atoms is not suitable for my purpose.

Has anybody a hint what could be wrong with the type signature of Atoms or count?

question from:https://stackoverflow.com/questions/65625748/lifetimes-for-generalizing-trait-implementation-from-t-to-asreft

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
trait Atoms<'a, A, I> where I: Iterator<Item = A> + 'a ...

By writing this, you're requiring the iterator to outlive the lifetime 'a. Since 'a is part of the trait's generic parameters, it must be a lifetime that extends before you start using (implicitly) <String?as?Atoms<'a,?char,?std::str::Chars>>::atoms. This directly contradicts the idea of returning a new iterator object, since that object did not exist before the call to atoms().

Unfortunately, I'm not sure how to rewrite this so that it will work, without generic associated types (a feature not yet stabilized), but I hope that at least this explanation of the problem helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...