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

Rustc passes syntactically invalid input to attribute macros #90256

Open
dtolnay opened this issue Oct 25, 2021 · 6 comments
Open

Rustc passes syntactically invalid input to attribute macros #90256

dtolnay opened this issue Oct 25, 2021 · 6 comments
Labels
A-proc-macros Area: Procedural macros P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@dtolnay
Copy link
Member

dtolnay commented Oct 25, 2021

It used to be the case that attribute macros would only ever be invoked with syntactically valid input. Rustc would snip out or otherwise fix up invalid syntax prior to dispatching the macro invocation. This ensures that rustc's recovery from the invalid syntax, and any diagnostics emitted by rustc to that effect, are consistent with any subsequent diagnostics emitted by the macro, rather than requiring both to perform independent and inconsistent heuristics to recover from the invalid input.

However, it looks like recent rustc versions (1.51+) have begun invoking attribute macros on invalid syntax. Can we find out whether this behavior is intended or a regression from recent Span-related work (#43081@Aaron1011)? IMO the newfangled behavior is not necessarily desirable so I have filed this as a regression.

// src/lib.rs

use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn repro(_args: TokenStream, input: TokenStream) -> TokenStream {
    eprintln!("{:#?}", input);
    TokenStream::new()
}
// src/main.rs

#[repro::repro]
trait T {
    fn run(&);
}

fn main() {}
# Cargo.toml

[package]
name = "repro"
version = "0.0.0"
edition = "2018"
publish = false

[lib]
proc-macro = true
  • 1.31 through 1.39: macro is invoked with trait T {} as input. Invalid syntax has been snipped out.
  • 1.40 through 1.50: macro is invoked with trait T { fn run(); } as input, invalid syntax snipped out with finer granularity.
  • 1.51+: macro is invoked with trait T { fn run(&); } which is invalid syntax and not necessarily desirable.
@dtolnay dtolnay added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Oct 25, 2021
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Oct 25, 2021
@dtolnay dtolnay added A-proc-macros Area: Procedural macros regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Oct 25, 2021
@Aaron1011
Copy link
Member

This is probably due to parser recovery - in all of the affected versions, the parser was able to parse an Item despite the invalid syntax. In the past, we relied on pretty-printing and preparing in many cases, and pretty-printing a parsed item should always produce valid syntax. The output produced would depend on the precise way in which recovery was performed (e.g do we ignore the parameter, or the entire method?).

Now, we no longer rely on pretty-printing when incoming macros. The original (syntactically invalid) tokenstream is passed to the macro, without any kind of modification.

@Aaron1011
Copy link
Member

See #76360 (comment) for a previous discussion of this kind of issue.

@dtolnay
Copy link
Member Author

dtolnay commented Oct 25, 2021

Thanks for the link! The behavior I would expect is for the attribute macro to be run on the prettyprinted recovered input, iow the invalid node is snipped out or otherwise fixed up prior to the macro expansion. I think this is described as option 1 in your post. I left a comment on the other issue to that effect.

@apiraino
Copy link
Contributor

Assigning priority as discussed in the Zulip thread of the Prioritization Working Group.

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Nov 18, 2021
@pnkfelix
Copy link
Member

Discussed at P-high review

This seems like a real problem. I'm asking @estebank and @compiler-errors to try to dedicate some brain cycles to looking over the suggestions here and trying to drive progress towards a solution.

@pnkfelix
Copy link
Member

Discussed at 2023 Q1 P-high review

Arguably this is folded in with #76360, which has already (also) been handed off to WG-diagnostics, specifically @estebank and @compiler-errors , for some dedicated brain cycle time.

@pnkfelix pnkfelix added the WG-diagnostics Working group: Diagnostics label Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-proc-macros Area: Procedural macros P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

5 participants