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

include! macro fails if included file has top-level inner attributes #18810

Closed
dwrensha opened this issue Nov 9, 2014 · 5 comments
Closed

include! macro fails if included file has top-level inner attributes #18810

dwrensha opened this issue Nov 9, 2014 · 5 comments

Comments

@dwrensha
Copy link
Contributor

dwrensha commented Nov 9, 2014

// test.rs

pub mod included {
    include!("test_included.rs")
}

fn main() {}
// test_included.rs

#![allow(dead_code)]

pub fn foo() {}
$ rustc test.rs
test_included.rs:3:3: 3:4 error: an inner attribute is not permitted in this context
test_included.rs:3 #![allow(dead_code)]
                     ^
error: aborting due to previous error

I at first thought that the problem was due to the implicit insert of the prelude in the included module. However, adding a #[no_implicit_prelude] attribute does not help.

@SimonSapin
Copy link
Contributor

I’ve written a syntax extension (below) to work around this.

mod_path! foo (concat!(env!("OUT_DIR"), "/hello.rs"))

Expands to:

#[path = "path/to/OUT_DIR/hello.rs"]
mod foo;

@alexcrichton I suggest adding this to libsyntax and making it the recommended way to use generated code in Cargo. (#824) Should it go through the RFC process?

#![crate_type="dylib"]
#![feature(plugin_registrar, quote)]

extern crate syntax;
extern crate rustc;

use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ast::{TokenTree, Ident};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacItems, IdentTT, get_single_str_from_tts};
use rustc::plugin::Registry;

fn expand_mod_path<'a>(cx: &'a mut ExtCtxt, sp: Span, ident: Ident, tts: Vec<TokenTree>)
            -> Box<MacResult + 'a> {
    let path = match get_single_str_from_tts(cx, sp, tts.as_slice(), "mod_path!") {
        Some(string) => string,
        None => return DummyResult::expr(sp),
    };

    MacItems::new(vec![quote_item!(cx,

        #[path = $path]
        mod $ident;

    ).unwrap()].into_iter())
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("mod_path"), IdentTT(box expand_mod_path, None));
}

@alexcrichton
Copy link
Member

Something like that would definitely need to go through the RFC process, but that seems great to me!

@SimonSapin
Copy link
Contributor

#18849 might be a better solution.

@steveklabnik
Copy link
Member

I'm pulling a massive triage effort to get us ready for 1.0. As part of this, I'm moving stuff that's wishlist-like to the RFCs repo, as that's where major new things should get discussed/prioritized.

This issue has been moved to the RFCs repo: rust-lang/rfcs#752

@SimonSapin
Copy link
Contributor

I’ve published the plugin above as a mod_path crate on crates.io

Marwes added a commit to Marwes/lalrpop that referenced this issue Mar 17, 2018
Due to rust-lang/rust#18810 (rust-lang/rfcs#752)
it is not possible to have an inner attribute in a file that gets
used with `include!`.

Specifying the attribute on each parser module is less precise and more
duplication but it will at least work for that case. If a user wants to
apply the rustfmt on the whole module they can still add an outer
attribute manually as well.
antialize added a commit to scalgo/scalgoproto that referenced this issue Nov 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants