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

Comments

Projects
None yet
4 participants
@dwrensha
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

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Nov 10, 2014

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));
}
Contributor

SimonSapin commented Nov 10, 2014

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

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Nov 10, 2014

Member

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

Member

alexcrichton commented Nov 10, 2014

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

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Nov 10, 2014

Contributor

#18849 might be a better solution.

Contributor

SimonSapin commented Nov 10, 2014

#18849 might be a better solution.

@steveklabnik

This comment has been minimized.

Show comment
Hide comment
@steveklabnik

steveklabnik Jan 27, 2015

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

Member

steveklabnik commented Jan 27, 2015

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

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jan 28, 2015

Contributor

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

Contributor

SimonSapin commented Jan 28, 2015

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

fix: Allow lalrpop parsers to be used with include!
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment