Please help me on main overflow stack error

use std::fmt;

#[derive(Debug)]
pub struct RuleOptions {
    pub keep_all_tokens: bool,
    pub expand1: bool,
    pub priority: Option<usize>,
    pub template_source: Option<String>,
    pub empty_indices: Vec<bool>
}

impl Default for RuleOptions {
    fn default() -> Self {
        RuleOptions {
            keep_all_tokens: false,
            expand1: false,
            priority: Some(0),
            template_source: Some("Some text".to_string()),
            empty_indices: vec![false]
        }
    }
}

impl fmt::Display for RuleOptions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "RuleOptions(keep_all_tokens: {}, expand1: {}, priority: {}, template_source: {})",
            self.keep_all_tokens, self.expand1, self.priority.unwrap(), self.template_source.is_some())
    }
}

impl RuleOptions {
    pub fn new (
        keep_all_tokens: bool, expand1: bool, priority: Option<usize>,
        template_source: Option<String>, empty_indices: Vec<bool>
    ) -> Self {
        RuleOptions {keep_all_tokens, expand1, priority, template_source, empty_indices}
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Symbol {
    pub name: String,
    pub is_term: bool,
    pub filter_out: Option<bool>
}

impl Default for Symbol {
    fn default() -> Self {
        Symbol {
            name: "symbol".to_string(),
            is_term: false,
            filter_out: None
        }
    }
}


impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Symbol(name: {}, is_term: {}, filter_out: {})", self.name, self.is_term, self.filter_out.is_some())
    }
}


#[derive(Debug)]
pub struct Rule {
    pub origin: Symbol,
    pub expansion: Vec<Symbol>,
    pub order: usize,
    pub alias: Option<String>,
    pub options: Option<RuleOptions>
}

impl Default for Rule {
    fn default() -> Self {
        Rule {
            origin: Symbol {..Default::default()},
            expansion: vec![Symbol {..Default::default()}],
            order: 0,
            alias: None,
            options: None
        }
    }
}

impl fmt::Display for Rule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self)
    }
}


fn main() {
    let s1 = Symbol {name: "symboltest".to_string(), is_term: false, filter_out: Some(false)};
    let s2 = Symbol {name: "symboltest1".to_string(), is_term: false, filter_out: Some(true)};
    let s3 = Symbol {name: "symboltest2".to_string(), is_term: true, filter_out: Some(false)};
    let mut vecsymb: Vec<Symbol> = Vec::new();
    vecsymb.push(s2);
    vecsymb.push(s3);

    let ro = RuleOptions {keep_all_tokens: true, expand1: false, priority: Some(1),
        template_source: None, empty_indices: Vec::from([false])};


    println!("symb: {}", s1);
    println!("Vec<symb>: {}", vecsymb[0]);
    println!("rule option: {}", ro);

    let rr = Rule {origin: s1, expansion: vecsymb, order: 1, alias: None,
        options: Some(ro)
    };

    println!("{}", rr);

}

(Playground)

Output:

symb: Symbol(name: symboltest, is_term: false, filter_out: true)
Vec<symb>: Symbol(name: symboltest1, is_term: false, filter_out: true)
rule option: RuleOptions(keep_all_tokens: true, expand1: false, priority: 1, template_source: false)

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.48s
     Running `target/debug/playground`

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

Above code compiled successfully, but when I try to run, it's get failed, please help me to know the actual issue with my code.

It seems to me that this function calls itself.

The write!() (and other similar macros) with "{}" as format string invoke the Display implementation of its argument, so your implementation ended up calling itself forever overflowing the stack.

You should probably implement it by descending into individual parts like you did for Symbol, for example (not tested):

impl fmt::Display for Rule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Rule(origin: {}, expansion: {}, ...)", self.origin, self.expansion);  // TODO: remaining parts
    }
}

alternatively you can use the derived Debug trait by using the "{:?}" like this (not tested):

impl fmt::Display for Rule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
        // TODO: write proper formatting
    }
}

or in your main function (not tested):

println!("{:?}", rr);
3 Likes

By the way, using Clippy can help a lot here:

error: using `self` as `Display` in `impl Display` will cause infinite recursion
  --> src/main.rs:88:9
   |
88 |         write!(f, "{}", self)
   |         ^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#recursive_format_impl
   = note: `#[deny(clippy::recursive_format_impl)]` on by default
   = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
5 Likes

Thanks @steffahn,

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.