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

proc_macro_derive(attributes(path::to)) both does and doesn't work #55168

Closed
CAD97 opened this Issue Oct 18, 2018 · 7 comments

Comments

Projects
None yet
5 participants
@CAD97
Copy link
Contributor

CAD97 commented Oct 18, 2018

// crate `derive`
// lib.proc-macro = true
#[proc_macro_derive(WellThen, attributes(well::then))]
pub fn derive(i: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
    i
}

// crate `user`
use derive::WellThen;
#[derive(WellThen)]
#[well::then]
struct A;
error[E0433]: failed to resolve. Use of undeclared type or module `well`
  --> user\main.rs:3:3
   |
 3 | #[well::then]
   |   ^^^^ Use of undeclared type or module `well`

I would expect either for this to work or for #[proc_macro_derive(attributes(..))] to reject a path and only accept an ident, as specifying a path here doesn't work.

@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Oct 18, 2018

This may be an accidental regression from #50030, similarly to #53489.

This cannot work without significant work and introducing an entirely new entity into name resolution ("derive helper modules" or something), so #[proc_macro_derive(attributes(..))] needs to validate its arguments harder and reject non-identifier paths.

@shepmaster

This comment has been minimized.

Copy link
Member

shepmaster commented Feb 27, 2019

reject non-identifier paths

I don't think you can do this, as these work for attributes within the type on stable 1.32:

use repro_derive::Example;

#[derive(Example)]
#[example::attr]     // Does not work
struct Demo {
    #[example::attr] // Works
    field: i32,
}

fn main() {}
extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(Example, attributes(example::attr))]
pub fn example_derive(_input: TokenStream) -> TokenStream {
    TokenStream::new()
}
@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Feb 27, 2019

Oh god.
If not reject, then issue a deprecation warning immediately.

Self-assigning, I should be able to fix it this weekend.

@shepmaster

This comment has been minimized.

Copy link
Member

shepmaster commented Feb 27, 2019

Is there any suggested way to have my desired syntax of

#[derive(Example)]
#[example::attr]
struct Demo {
    #[example::attr]
    field: i32,
}
@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Feb 27, 2019

@shepmaster
Not right now, but something like #57921 may help.

Actually, the derive macro itself could be able to introduce "tool modules" into scope (like rustfmt in rustfmt::skip, but not global to the whole crate).
#[proc_macro_derive(Example, tools(example))] or something.
Right now this is almost trivial to add for "macro expanded" attribute targets, like the item itself, but some additional work is needed to support it for other targets, e.g. fields (as you can see #[rustfmt::skip] doesn't work on fields yet).

@Centril

This comment has been minimized.

Copy link
Contributor

Centril commented Feb 28, 2019

@petrochenkov Is there a reason we cannot let #[proc_macro_derive(Example, attributes(example::attr))] mean #[proc_macro_derive(Example, tools(example))] plus some validation for the ::attr part? handwave

From a user facing perspective at least, @shepmaster's #55168 (comment) example seems reasonable and "expected".

@petrochenkov

This comment has been minimized.

Copy link
Contributor

petrochenkov commented Mar 3, 2019

Fixed in #58899

Is there a reason we cannot let #[proc_macro_derive(Example, attributes(example::attr))] ...

I'd prefer to see crater results first.

bors added a commit that referenced this issue Mar 3, 2019

Auto merge of #58899 - petrochenkov:derval2, r=<try>
Do not accidentally treat multi-segment meta-items as single-segment

Fixes #55168 and many other regressions from #50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

@petrochenkov petrochenkov removed their assignment Mar 9, 2019

Centril added a commit to Centril/rust that referenced this issue Mar 10, 2019

Rollup merge of rust-lang#58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment

Fixes rust-lang#55168 and many other regressions from rust-lang#50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

Centril added a commit to Centril/rust that referenced this issue Mar 13, 2019

Rollup merge of rust-lang#58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment

Fixes rust-lang#55168 and many other regressions from rust-lang#50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

bors added a commit that referenced this issue Mar 16, 2019

Auto merge of #58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment

Fixes #55168 and many other regressions from #50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

bors added a commit that referenced this issue Mar 16, 2019

Auto merge of #58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment

Fixes #55168 and many other regressions from #50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

bors added a commit that referenced this issue Mar 16, 2019

Auto merge of #58899 - petrochenkov:derval2, r=estebank
Do not accidentally treat multi-segment meta-items as single-segment

Fixes #55168 and many other regressions from #50030

Basically, attributes like `#[any::prefix::foo]` were commonly interpreted as `#[foo]` due to `name()` successfully returning the last segment (this applies to nested things as well `#[attr(any::prefix::foo)]`).

@bors bors closed this in #58899 Mar 17, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.