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

Show rustdoc of proc macros #14772

Open
Tracked by #14079
peter-lyons-kehl opened this issue May 10, 2023 · 4 comments
Open
Tracked by #14079

Show rustdoc of proc macros #14772

peter-lyons-kehl opened this issue May 10, 2023 · 4 comments
Labels
A-ide general IDE features C-bug Category: bug

Comments

@peter-lyons-kehl
Copy link

peter-lyons-kehl commented May 10, 2023

Thank you for rust-analyzer.

  • Please, consider showing rustdoc of attribute macros (on mouse over in VS Code...).
  • And, if you do choose to implement it, please also carry rustdoc if a macro is imported through use ... as ...; under an alias.

Example: Attribute macros aliased on purpose from https://docs.rs/allow_prefixed/latest/allow_prefixed (or from https://docs.rs/allow_prefixed/latest/allow):

Crrent rust-analyzer version v0.3.1506 in current VS Code:

Version: 1.78.1
Commit: 6a995c4f4cc2ced6e3237749973982e751cb0bf9
Date: 2023-05-04T09:46:23.602Z
Electron: 22.5.1
Chromium: 108.0.5359.215
Node.js: 16.17.1
V8: 10.8.168.25-electron.0
OS: Linux x64 6.3.0-1-MANJARO
Sandboxed: No

Thank you in advance.

@peter-lyons-kehl peter-lyons-kehl added the C-feature Category: feature request label May 10, 2023
@lowr
Copy link
Contributor

lowr commented May 15, 2023

This is a really unfortunate consequence of #12603. We do show rustdoc of proc macros, but we fail to expand your internal macros to generate the attribute macros in the first place.

The problem is that your internal macro prefixed_lint! takes a path, which rustc would wrap in an opaque AST fragment upon macro expansion (see the Rust reference for details), but rust-analyzer does not (yes, it's a bug). So while your proc macros in allow_internal receive paths wrapped in TokenTree::Group when they're run by rustc, they receive plain paths when they're run by rust-analyzer.

One thing you can do to workaround this is to have prefixed_lint! and other helper macros take paths as tt fragment type, because rustc special-cases it and wouldn't wrap it in the said opaque fragment. This requires changing other internal proc macros like generate_allow_attribute_macro_definition_prefixed but should work properly with both rustc and rust-analyzer.

I hate to suggest a workaround instead of fixing the bug, but we've been failing to figure out how to resolve it properly, so this should be the quickest way to make your crate work in rust-analyzer. Sorry for the inconvenience.

@lowr lowr added A-macro macro expansion A-proc-macro proc macro C-bug Category: bug and removed C-feature Category: feature request labels May 15, 2023
@peter-lyons-kehl
Copy link
Author

peter-lyons-kehl commented May 18, 2023

Hi Ryo,

Thank you so mach for deep insight. Workarounds are fine.

Only for reference, or for anyone curious or with a similar problem: Unfortunately, and to my surprise, paths (or some paths, at least: like clippy::alloc_instead_of_core, and any clippy:: or rustdoc:: valid lint paths) cannot be matched by tt macro variables. (As https://veykril.github.io/tlborm/decl-macros/minutiae/fragment-specifiers.html#tt says, tt "can match nearly anything" - but it doesn't say what correct/paired tokens tt can't match).

That's with 1.71.0-nightly (e9e1bbc7a 2023-05-17), and even if the macro by example takes only one parameter (while in my crate I need two parameters, or more). Example is at https://github.com/peter-kehl/macro_rules_path_as_tt:

❯ cargo check
    Checking macro_rules_path_as_tt v0.1.0 (/share/pkehl/GIT/macro_rules_path_as_tt)
error: no rules expected the token `::`
  --> src/lib.rs:12:41
   |
1  | macro_rules! prefixed_lint_versioned {
   | ------------------------------------ when calling this macro
...
12 |     prefixed_lint_versioned!(1.2, clippy::alloc_instead_of_core);
   |                                         ^^ no rules expected this token in macro call
   |
note: while trying to match meta-variable `$lint_path:tt`
  --> src/lib.rs:2:23
   |
2  |     ($major_minor:tt, $lint_path:tt) => {
   |                       ^^^^^^^^^^^^^

error: no rules expected the token `::`
  --> src/lib.rs:14:30
   |
6  | macro_rules! consume_path_only {
   | ------------------------------ when calling this macro
...
14 |     consume_path_only!(clippy::alloc_instead_of_core);
   |                              ^^ no rules expected this token in macro call
   |
note: while trying to match meta-variable `$lint_path:tt`
  --> src/lib.rs:7:6
   |
7  |     ($lint_path:tt) => {

Update: The above is even more strange, because I do have $lint_path:tt working with macro_rules. It's at

Anyway, I am exploring a different workaround: Since all prefixed lints have only one path level (either rustdoc:: or clippy:: prefix), I'll take the prefix and the lint name as two separate tt parameters, and I'll join them together into a tt (either with paste crate or manually). I'll post here.

peter-lyons-kehl added a commit to peter-lyons-kehl/macro_rules_path_as_tt that referenced this issue May 18, 2023
@peter-lyons-kehl
Copy link
Author

Another surprise: If a macro (by example) accepts a path fragment (like $lint_path:path), then such a macro CAN invoke another macro (by example) passing that meta variable, even if that other macro accepts it as tt (like $lint_path:tt):

macro_rules! consume_path_only_as_path_then_pass_down_as_tt {
    ($lint_path:path) => {
        consume_tt_only!($lint_path);
    };
}

macro_rules! consume_tt_only {
    ($lint_path:tt) => {};
}

pub fn test_macro() {
    // ...
    // the following does compile!
    consume_path_only_as_path_then_pass_down_as_tt!(clippy::alloc_instead_of_core);
}

(Updated https://github.com/peter-kehl/macro_rules_path_as_tt.)

@peter-lyons-kehl
Copy link
Author

peter-lyons-kehl commented May 25, 2023

Thank you. I confirm that using tt all the way from the top level macro_rules! is a good enough workaround. I'm lucky - I have a small number of macro_rules! combinations/"paths" to handle. Otherwise this would not be feasible.

(Then my only problem was that rust-analyzer doesn't show rustdoc coming from stringify! in #[doc = stringify!()] - #8092. I've worked around by generating that from (another) proc macro, from another crate, of course - luckily I already had to use two levels of proc_macro crates.)

Feel free to close this issue (since it can be worked around), or keep open, as you see fit.

@Veykril Veykril added A-ide general IDE features and removed A-macro macro expansion A-proc-macro proc macro labels Jun 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ide general IDE features C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

3 participants