Skip to content

"Failed to parse macro invocation" when using crate "proconio" #8171

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

Closed
baku1101 opened this issue Mar 23, 2021 · 4 comments · Fixed by #8201
Closed

"Failed to parse macro invocation" when using crate "proconio" #8171

baku1101 opened this issue Mar 23, 2021 · 4 comments · Fixed by #8201
Labels
A-macro macro expansion S-actionable Someone could pick this issue up and work on it right now

Comments

@baku1101
Copy link

baku1101 commented Mar 23, 2021

proconio is easy IO library for competitive programming.

Error occur when using input! macro.

I can compile and run it, but I get "Failed to parse macro invocation" in rust-analyzer.

This error was confirmed in both vim and vscode.

rust-analyzer is nightly version(0.3.528).

image

Complete repro

cargo.toml:

[package]
name = "repro"
version = "0.1.0"
authors = ["hogehoge"]
edition = "2018"
[dependencies]
proconio = "0.4.2"

main.rs

use proconio::*;
fn main() {
    input! {
        _n: isize,
    }
}

Thank you.

@jonas-schievink jonas-schievink added A-macro macro expansion S-actionable Someone could pick this issue up and work on it right now labels Mar 23, 2021
@statiolake
Copy link

Some additional information:

As for released versions of Rust Analyzer, version 2021-03-22 and 2021-03-15 both show the error for the repro code, but if input! is not the last expression of the main function, only 2021-03-22 can't correctly parse them. That is, 2021-03-15 can parse this code but 2021-03-22 cannot:

fn main() {
    input! {
        n: isize,
    }
    let _x = n;
}

As for versions of Visual Studio Code extension, I can confirm the same behavior with rust-analyzer 0.2.529 and 0.2.521. 0.2.529 behaves like 2021-03-22, 0.2.521 behaves like 2021-03-15. I'm not sure they are exactly the same version - I don't know how to check it.

image
image

image
image

The last one shows 0.2.521 can successfully parse the macro invocation (_x is correctly inferred to be of type isize).

@edwin0cheng
Copy link
Member

edwin0cheng commented Mar 24, 2021

Thanks for the report, It seem like there's still have some bugs related to statements after #8044. I am investigating on it right now, but need sometimes.

A no-deps version of reproducible example :

macro_rules! input {
    // terminator
    (@from [$source:expr] @rest) => {};

    // parse mutability
    (@from [$source:expr] @rest mut $($rest:tt)*) => {
        input! {
            @from [$source]
            @mut [mut]
            @rest $($rest)*
        }
    };
    (@from [$source:expr] @rest $($rest:tt)*) => {
        input! {
            @from [$source]
            @mut []
            @rest $($rest)*
        }
    };

    // parse variable pattern
    (@from [$source:expr] @mut [$($mut:tt)?] @rest $var:tt: $($rest:tt)*) => {
        input! {
            @from [$source]
            @mut [$($mut)*]
            @var $var
            @kind []
            @rest $($rest)*
        }
    };

    // parse kind (type)
    (@from [$source:expr] @mut [$($mut:tt)?] @var $var:tt @kind [$($kind:tt)*] @rest) => {
        let $($mut)* $var = 0;
    };
    (@from [$source:expr] @mut [$($mut:tt)?] @var $var:tt @kind [$($kind:tt)*] @rest, $($rest:tt)*) => {
        input!(@from [$source] @mut [$($mut)*] @var $var @kind [$($kind)*] @rest);
    };
    (@from [$source:expr] @mut [$($mut:tt)?] @var $var:tt @kind [$($kind:tt)*] @rest $tt:tt $($rest:tt)*) => {
        input!(@from [$source] @mut [$($mut)*] @var $var @kind [$($kind)* $tt] @rest $($rest)*);
    };

    ($($rest:tt)*) => {
        let mut _locked_stdin = "";
        input! {
            @from [&mut *locked_stdin]
            @rest $($rest)*
        }
        drop(_locked_stdin); // release the lock
    };
}

fn main() {    
    input! {
        n: isize,
    }
    let a = n;
}

@statiolake
Copy link

statiolake commented Mar 24, 2021

Smaller repro:

macro_rules! ng {
    ([$($tts:tt)*]) => {
        $($tts)*;
    };
    ([$($tts:tt)*] $head:tt $($rest:tt)*) => {
        ng! {
            [$($tts)* $head] $($rest)*
        }
    };
}

fn main() {
    ng!([] let _a = 3);
}

This causes failed to parse macro invocation error. let statement may be related: ng!([] String::new()) doesn't cause the error.

I'm not sure but recursive macro invocation with braces may be a part of cause: two macros below are both OK.

macro_rules! ok1 {
    ([$($tts:tt)*]) => {
        $($tts)*;
    };
    ([$($tts:tt)*] $head:tt $($rest:tt)*) => {
        // OK: using parens + semicolons instead of braces
        ok1! (
            [$($tts)* $head] $($rest)*
        );
    };
}
macro_rules! ok2 {
    ([$($tts:tt)*]) => {
        $($tts)*;
    };
    ([$($tts:tt)*] $($rest:tt)+) => {
        // OK: no recursive macro calls
        ok2! {
            [$($tts)* $($rest)*]
        }
    };
}

Note: I have a lot of trouble trying them anyway. I need to restart rust-analyzer to get latest diagnostics (error highlights, semantic highlightings, type hints, diagnostics etc won't be updated) every time I change macro invocation (delete or change params, comment-out, etc). I think rust-analyzer enters some erroneous state when something goes wrong.

Among them, ok1! is nearly perfectly parsed: rust-analyzer knows the type of declared variable so type hints and completions are usable.
image

ok2! does not cause parse error but rust-analyzer seems it doesn't know the type of the variable (perhaps it doesn't know the variable a exists.) Japanese text inside the intellisense popup in this screenshot means "loading..." or the like.

image

@lnicola
Copy link
Member

lnicola commented Mar 25, 2021

_ok2 gives:

thread '<unnamed>' panicked at 'cannot create item tree from [email protected] let_a=3', crates/hir_def/src/item_tree.rs:123:21
stack backtrace:
   0: rust_begin_unwind
             at /rustc/45b3c28518e4c45dfd12bc2c4400c0d0e9639927/library/std/src/panicking.rs:493:5
   1: std::panicking::begin_panic_fmt
             at /rustc/45b3c28518e4c45dfd12bc2c4400c0d0e9639927/library/std/src/panicking.rs:435:5
   2: hir_def::item_tree::ItemTree::file_item_tree_query
   3: salsa::runtime::Runtime::execute_query_implementation
   4: salsa::derived::slot::Slot<Q,MP>::read_upgrade
   5: salsa::derived::slot::Slot<Q,MP>::read
   6: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::try_fetch
   7: <DB as hir_def::db::DefDatabase>::file_item_tree::__shim
   8: hir_def::nameres::collector::DefCollector::collect_macro_expansion
   9: hir_def::nameres::collector::ModCollector::collect
  10: hir_def::nameres::collector::DefCollector::collect_macro_expansion
  11: hir_def::nameres::collector::ModCollector::collect
  12: hir_def::nameres::collector::collect_defs
  13: hir_def::nameres::DefMap::block_def_map_query
  14: salsa::runtime::Runtime::execute_query_implementation
  15: salsa::derived::slot::Slot<Q,MP>::read_upgrade
  16: salsa::derived::slot::Slot<Q,MP>::read
  17: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::try_fetch
  18: <DB as hir_def::db::DefDatabase>::block_def_map::__shim
  19: hir_def::body::lower::ExprCollector::collect_block
  20: hir_def::body::lower::ExprCollector::maybe_collect_expr
  21: hir_def::body::lower::ExprCollector::collect_expr_opt
  22: hir_def::body::lower::lower
  23: hir_def::body::Body::body_with_source_map_query
  24: salsa::runtime::Runtime::execute_query_implementation
  25: salsa::derived::slot::Slot<Q,MP>::read_upgrade
  26: salsa::derived::slot::Slot<Q,MP>::read
  27: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::try_fetch
  28: <DB as hir_def::db::DefDatabase>::body_with_source_map::__shim
  29: hir_def::diagnostics::validate_body
  30: hir::Function::diagnostics
  31: hir::Module::diagnostics
  32: ide::diagnostics::diagnostics
  33: std::panicking::try
  34: ide::Analysis::diagnostics
  35: rust_analyzer::handlers::handle_code_action
  36: <F as threadpool::FnBox>::call_box
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macro macro expansion S-actionable Someone could pick this issue up and work on it right now
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants