I have a Block
that parses Elements
from chars: impl LikeIter
:
pub trait LikeIter: Iterator<Item = (usize, char)> + Clone + Debug {}
impl<T: Iterator<Item<Item = (usize, char)> + Clone + Debug> LikeIter for T {}
that is, from any iterator that has Item = (usize, char)
Elements
contains a Vec<Element>
within it
Element
has different variant constructions, including Block
:
#[derive(Debug, PartialEq)]
pub enum Element {
Block(Block),
AssignExpr(AssignExpr),
Ident(Ident),
}
When Elements
is parsed, a Block
is also parsed inside it, where its inner Elements
is parsed.
Recursion occurs and since the LikeIter
type may contain a type with lifetime, an error occurs:
error[E0275]: overflow evaluating the requirement Enumerate<Chars<'_>>: Iterator
|
= help: consider increasing the recursion limit by adding a #![recursion_limit = "20"] attribute to your crate (abstract_)
= note: required for TakeWhile<Enumerate<Chars<'_>>, ...> to implement Iterator
= note: 9 redundant requirements hidden
= note: required for TakeWhile<TakeWhile<..., ...>, ...> to implement Iterator
= note: required for TakeWhile<TakeWhile<..., ...>, ...> to implement IntoIterator
= note: the full name for the type has been written to 'C:\Users\letif\VS Code Projects\rust\abstract\target\debug\deps\abstract_-c86ab7040e388b79.long-type-13391386737842869171.txt'
= note: consider using --verbose to print the full type name to the console
= note: the full name for the type has been written to 'C:\Users\letif\VS Code Projects\rust\abstract\target\debug\deps\abstract_-c86ab7040e388b79.long-type-5479745382517321328.txt'
= note: consider using --verbose to print the full type name to the console
error[E0275]: overflow evaluating the requirement Chars<'_>: Sized
|
= help: consider increasing the recursion limit by adding a #![recursion_limit = "20"] attribute to your crate (abstract_)
= note: required for Enumerate<Chars<'_>> to implement Iterator
= note: 9 redundant requirements hidden
= note: required for TakeWhile<TakeWhile<..., ...>, ...> to implement Iterator
= note: required for TakeWhile<TakeWhile<..., ...>, ...> to implement IntoIterator
= note: the full name for the type has been written to 'C:\Users\letif\VS Code Projects\rust\abstract\target\debug\deps\abstract_-c86ab7040e388b79.long-type-15616929496332024509.txt'
= note: consider using --verbose to print the full type name to the console
= note: the full name for the type has been written to 'C:\Users\letif\VS Code Projects\rust\abstract\target\debug\deps\abstract_-c86ab7040e388b79.long-type-15616929496332024509.txt'
= note: consider using --verbose to print the full type name to the console
For more information about this error, try rustc --explain E0275.
warning: abstract_ (lib test) generated 11 warnings (5 duplicates)
error: could not compile abstract_ (lib test) due to 2 previous errors; 11 warnings emitted
How to solve it? How to get around it if it can't be solved? What I know for sure: the recursion_limit
attribute will not solve the problem.
Full code:
#[derive(PartialEq, Debug)]
pub struct Block(Elements);
impl Parse for Block {
fn parse(chars: impl LikeIter) -> Option<Self> {
let [mut start, mut end] = [{ None }; 2];
for (i, char) in chars.clone() {
if char == ' ' {
continue;
}
if char == '{' {
start = Some(i);
break;
}
return None;
}
let start = start?;
let chars = chars.clone().take_while(|&(i, _)| i < start);
let el = Elements::parse(chars.clone()).unwrap();
if !el.is_empty() {
end = Some(el.get_end());
}
for (i, char) in chars.take_while(|&(i, _)| i <= end.unwrap_or_default()) {
if char == ' ' {
continue;
}
if char == '}' {
end = Some(i);
break;
}
return None;
}
Some(Self(el))
}
}
#[derive(PartialEq, Debug, Deref)]
pub struct Elements(Vec<Element>);
impl Parse for Elements {
fn parse(chars: impl LikeIter) -> Option<Self> {
let mut elements = Vec::new();
let mut skip_index = 0;
while let Some(el) = Element::parse(chars.clone().skip_while(|&(i, _)| i <= skip_index)) {
skip_index = el.get_end();
elements.push(el);
}
Some(Self(elements))
}
}
#[derive(Debug, PartialEq)]
pub enum Element {
Block(Block),
AssignExpr(AssignExpr),
Ident(Ident),
}
impl Parse for Element {
fn parse(chars: impl LikeIter) -> Option<Self> {
[
Block::parse(chars.clone()).map(|v| Element::Block(v)),
AssignExpr::parse(chars.clone()).map(|v| Self::AssignExpr(v)),
Ident::parse(chars.clone()).map(|v| Self::Ident(v)),
]
.into_iter()
.flat_map(|v| v)
.nth(0)
}
}