rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.92k stars 1.57k forks source link

Allow macros to be used in literals and/or meta items #1516

Open erickt opened 8 years ago

erickt commented 8 years ago

In this reddit comment Perceptes mentioned one idea to cut down down on some of the syntex boilerplate would be to use the #[path = ...] attribute to point to one of the generated files, as in this:

#[path = concat!(env!("OUT_DIR"), "/generated_foo.rs")]
mod foo;

Unfortunately this is currently illegal, because macros cannot be used in the position of a literal. It would be nice if we supported this functionality.

steveklabnik commented 8 years ago

Talking about this on IRC, an alternate way to accomplish this would be to have mod foo also look for $OUT_DIR/foo.rs as well. A larger change, but also nicer looking and easier.

nikomatsakis commented 8 years ago

I'm in favor of having OUT_DIR conventions be something that the compiler itself understands. I'd like it if we searched both in the main directory and the OUT_DIR (but note that I would want full relative paths: so to find foo::bar we look in $OUT_DIR/foo/bar.rs). I've definitely hit this problem in LALRPOP as well (which currently generates code in src partly for this reason, though partly because I didn't know about $OUT_DIR :wink:).

alexcrichton commented 8 years ago

I would personally want to avoid literally using the OUT_DIR environment variable for lookup paths when parsing modules. An explicit argument to the compiler seems more reasonable to me (tougher to get wrong).

In general this may just mean, however, that the compiler's story for supporting code generation isn't the best. I think that C/C++ take care of this by having header include paths so it may be the case that parser lookup paths are just the same?

durka commented 8 years ago

There may be motivation for the original idea beyond OUT_DIR. For example, I could imagine a macro wanting to output #[doc=concat!(stringify!($a), $b)].

nikomatsakis commented 8 years ago

On Tue, Mar 01, 2016 at 08:10:52AM -0800, Alex Crichton wrote:

I would personally want to avoid literally using the OUT_DIR environment variable for lookup paths when parsing modules. An explicit argument to the compiler seems more reasonable to me (tougher to get wrong).

Yes, this is what I actually meant. Basically the ability to have more than one "root path" for finding modules. Many compilers offer a facility like this (e.g., javac has SOURCEPATH, etc)

In general this may just mean, however, that the compiler's story for supporting code generation isn't the best. I think that C/C++ take care of this by having header include paths so it may be the case that parser lookup paths are just the same?

Well the other big thing is of course #line-style directives...

tikue commented 8 years ago

Similar to what @durka pointed out, I have a macro that generates a trait, and I want to document some of the trait items by doing:

#[doc=concat!("The type of `Future` returned by ", stringify!($fn_name))]
type Fut: Future<Item=T, Error=E>;

As a workaround, I use a plugin that replaces {} in a doc comment with the expected ident.

Ericson2314 commented 8 years ago

Inside macro bodies eager expansion should work?

tikue commented 8 years ago

@Ericson2314 something like this doesn't work; is that what you meant?

durka commented 8 years ago

I think @Ericson2314 is referring to #1628, which creates new syntax for eager expansion within macro bodies. If that is accepted, then #[doc=stringify!!($foo)] ought to work, so it would supersede this RFC (in effect, eager expansion supersedes all "macros should be allowed in _ position" concerns).

durka commented 6 years ago

Update: You still cannot put a macro in #[doc]. You can put a macro in #[path] but it seems to cause the attribute to be dropped. Example:

fn foo() {
    #[path=env!("xyz")] mod foo;
}
error: Cannot declare a non-inline module inside a block unless it has a path attribute

This has been reported at rust-lang/rust#48250.