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

cmd! panics when string contains backslash followed by a line break #65

Open
Aloso opened this issue Feb 27, 2023 · 3 comments
Open

cmd! panics when string contains backslash followed by a line break #65

Aloso opened this issue Feb 27, 2023 · 3 comments

Comments

@Aloso
Copy link

Aloso commented Feb 27, 2023

This panics during macro expansion:

cmd!(
    sh,
    "grcov . --binary-path ./target/debug/deps -s . -t {fmt} --branch --ignore-not-existing \
    --ignore ../* --ignore /* --ignore xtask/* --ignore */src/tests/* -o {file}"
)
@ssmendon
Copy link

ssmendon commented May 6, 2023

Thought I'd add some extra information. I recompiled a sample on nightly -Z macro-backtrace enabled.

use xshell::{cmd, Shell};

fn main() -> anyhow::Result<()> {
    let sh = Shell::new()?;

    cmd!(
        sh,
        "scoop \
        --help"
    );

    Ok(())
}
error[E0765]: unterminated double quote string
   --> source\github\xshell\src\lib.rs:348:32
    |
343 |   macro_rules! cmd {
    |   ---------------- in this expansion of `cmd!` (#1)
...
348 |           let cmd: $crate::Cmd = $crate::__cmd!(f $cmd);
    |                                  ^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation (#2)
    |
   ::: source\github\xshell\xshell-macros\src\lib.rs:12:1
    |
12  |   pub fn __cmd(macro_arg: TokenStream) -> TokenStream {
    |   --------------------------------------------------- in this expansion of `$crate::__cmd!` (#2)
    |
   ::: examples\65.rs:6:5
    |
6   | /     cmd!(
7   | |         sh,
8   | |         "\
9   | |         --help"
10  | |     );
    | |_____- in this macro invocation (#1)

error: proc macro panicked
   --> source\github\xshell\src\lib.rs:348:32
    |
343 |   macro_rules! cmd {
    |   ---------------- in this expansion of `cmd!`
...
348 |           let cmd: $crate::Cmd = $crate::__cmd!(f $cmd);
    |                                  ^^^^^^^^^^^^^^^^^^^^^^
    |
   ::: examples\65.rs:6:5
    |
6   | /     cmd!(
7   | |         sh,
8   | |         "\
9   | |         --help"
10  | |     );
    | |_____- in this macro invocation

For more information about this error, try `rustc --explain E0765`.
error: could not compile `xshell` (example "65") due to 2 previous errors

@matklad
Copy link
Owner

matklad commented Jul 11, 2023

Yeah, this is a bug, will get to fixing this one day if no-one beats me to it.

The semantics we want here is the following:

  • macro argument is a string literal, thing like "hello '\u{1F600} !'", with " and all
  • string value of a string literal is computed, yielding "hello '😄 !'"
  • the value is lexed into array of arguments ["hello", "😄 !"]

That's the same semantics of escapes that println! uses:

fn main() {
    println!("{\x7d", 93)
}

The problem with implementing this is that the first step, parsing string literal into string value, is part of Rust semantics, and ideally should be implemented by the compiler. So the proper solution here is to go & RFC https://internals.rust-lang.org/t/getting-value-out-of-proc-macro-literal/14140.

While we are waiting for that to happen, we should approximate what rustc is doing. I don't think we need to aim to be 100% correct here, but we obviously should fix panics

@matklad
Copy link
Owner

matklad commented Jul 11, 2023

And see also #4 (comment), we need to figure out the correct semantics for quotes as well...

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

3 participants