Skip to content

Proc macro crash with the unquote crate #11130

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
lnicola opened this issue Dec 28, 2021 · 3 comments
Closed

Proc macro crash with the unquote crate #11130

lnicola opened this issue Dec 28, 2021 · 3 comments
Labels
A-macro macro expansion C-bug Category: bug S-actionable Someone could pick this issue up and work on it right now

Comments

@lnicola
Copy link
Member

lnicola commented Dec 28, 2021

Here's a smaller reproduction that builds on stable Rust 1.57.0:

[package]
name = "macro-test"
version = "0.0.0"
edition = "2021"
publish = false

[lib]
# Needed because `unquote`'s syn dependency isn't set up correctly. It's hopefully not relevant.
proc_macro = true

[dependencies]
quote = "1.0.10"
syn = "1.0.83"
unquote = "0.0.6"
use quote::quote;
use syn::parse::ParseStream;
use unquote::unquote;

#[allow(dead_code)]
fn parse(input: ParseStream) -> syn::Result<()> {
    unquote!(input, a); // <--
    Ok(())
}

Settings (not minimal):

{
    "rust-analyzer.cargo-watch.command": "clippy",
    "rust-analyzer.rainbowHighlightingOn": true,
    "rust-analyzer.procMacro.enabled": true,
    "rust-analyzer.procMacro.enable": true,
    "rust-analyzer.cargo.loadOutDirsFromCheck": true,
    "rust-analyzer.checkOnSave.command": "clippy",
    "rust-analyzer.experimental.procAttrMacros": true,
    "rust-analyzer.cargo.allFeatures": true,
    "rust-analyzer.checkOnSave.extraArgs": [
        "--locked"
    ],
    "rust-analyzer.updates.channel": "nightly"
}

cargo expand:

Probably not relevant, but it's a fairly simple macro:
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use quote::quote;
use syn::parse::ParseStream;
use unquote::unquote;
#[allow(dead_code)]
fn parse(input: ParseStream) -> syn::Result<()> {
    let input = input;
    let mut prev_span = input.cursor().span();
    if input.call(<syn::Ident as syn::ext::IdentExt>::parse_any)?
        != syn::parse::Parser::parse2(<syn::Ident as syn::ext::IdentExt>::parse_any, {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "a");
            _s
        })
        .unwrap()
    {
        return Err(syn::Error::new(input.cursor().span(), "Expected `a`"));
    };
    Ok(())
}
const _: () = {
    extern crate proc_macro;
    #[rustc_proc_macro_decls]
    #[allow(deprecated)]
    static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
};

Error:

[{
	"resource": "[project directory]/src/lib.rs",
	"owner": "rustc",
	"code": {
		"value": "macro-error",
		"target": {
			"$mid": 1,
			"external": "https://rust-analyzer.github.io/manual.html#macro-error",
			"path": "/manual.html",
			"scheme": "https",
			"authority": "rust-analyzer.github.io",
			"fragment": "macro-error"
		}
	},
	"severity": 8,
	"message": "called `Option::unwrap()` on a `None` value",
	"source": "rust-analyzer",
	"startLineNumber": 7,
	"startColumn": 5,
	"endLineNumber": 7,
	"endColumn": 23
}]

Rust Analyzer Client output (abbreviated):

INFO [25.12.2021, 18:38:34]: Extension version: 0.3.875
INFO [25.12.2021, 18:38:34]: Using configuration {
  […]
}
INFO [25.12.2021, 18:38:34]: PersistentState: { serverVersion: '0.3.875' }
INFO [25.12.2021, 18:38:34]: Using server binary at [~]\.vscode\extensions\matklad.rust-analyzer-0.3.875\server\rust-analyzer.exe

Rust Analyzer Language Server Trace appears to be empty.

Originally posted by @Tamschi in #10570 (comment)

@lnicola lnicola added A-macro macro expansion C-bug Category: bug S-actionable Someone could pick this issue up and work on it right now labels Dec 28, 2021
@brandondong
Copy link

I tried editing the unquote crate implementation and trimming down the code/dependencies to the bare minimum that reproduces the issue:

use proc_macro::{Span, TokenStream};

#[proc_macro]
pub fn unquote(_input: TokenStream) -> TokenStream {
	let span = Span::call_site();
	span.located_at(span);
	TokenStream::new()
}

The located_at line results in the Option.unwrap error. It doesn't seem to matter how you get the two Span's. The same thing happens for calling resolved_at.

Looking at https://github.com/rust-analyzer/rust-analyzer/blob/7409880a07803c34590ad162d7854061145c6eae/crates/proc_macro_srv/src/abis/abi_1_56/rustc_server.rs#L690, I'm really not sure why this happens.

@Tamschi
Copy link

Tamschi commented Mar 23, 2022

This may be fixed, or at least I'm now getting a stack overflow in the rust-analyzer language server instead of this error in my project.

@Veykril
Copy link
Member

Veykril commented Jun 1, 2024

This should be fixed as we changed the logic here to no longer be ID based

@Veykril Veykril closed this as completed Jun 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macro macro expansion C-bug Category: bug S-actionable Someone could pick this issue up and work on it right now
Projects
None yet
Development

No branches or pull requests

4 participants