Forbid '#[macro_use] extern crate' outside the crate root

This commit is contained in:
Keegan McAllister 2015-01-02 22:21:28 -08:00
parent c2e26972e3
commit bbbb85a4ec
3 changed files with 40 additions and 3 deletions

View file

@ -20,6 +20,7 @@ use std::dynamic_lib::DynamicLibrary;
use std::collections::HashSet;
use syntax::ast;
use syntax::attr;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::ptr::P;
use syntax::visit;
@ -45,6 +46,7 @@ pub struct Plugins {
struct PluginLoader<'a> {
sess: &'a Session,
span_whitelist: HashSet<Span>,
reader: CrateReader<'a>,
plugins: Plugins,
}
@ -54,6 +56,7 @@ impl<'a> PluginLoader<'a> {
PluginLoader {
sess: sess,
reader: CrateReader::new(sess),
span_whitelist: HashSet::new(),
plugins: Plugins {
macros: vec!(),
registrars: vec!(),
@ -66,6 +69,14 @@ impl<'a> PluginLoader<'a> {
pub fn load_plugins(sess: &Session, krate: &ast::Crate,
addl_plugins: Option<Plugins>) -> Plugins {
let mut loader = PluginLoader::new(sess);
// We need to error on `#[macro_use] extern crate` when it isn't at the
// crate root, because `$crate` won't work properly. Identify these by
// spans, because the crate map isn't set up yet.
for vi in krate.module.view_items.iter() {
loader.span_whitelist.insert(vi.span);
}
visit::walk_crate(&mut loader, krate);
let mut plugins = loader.plugins;
@ -158,6 +169,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
};
let load_registrar = plugin_attr.is_some();
if load_macros && !self.span_whitelist.contains(&vi.span) {
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
the crate root");
}
if load_macros || load_registrar {
let pmd = self.reader.read_plugin_metadata(vi);
if load_macros {

View file

@ -19,13 +19,14 @@
#![deny(experimental)]
#![allow(dead_code)]
#[macro_use]
extern crate lint_stability; //~ ERROR: use of unmarked item
mod cross_crate {
extern crate stability_cfg1;
extern crate stability_cfg2; //~ ERROR: use of experimental item
#[macro_use]
extern crate lint_stability; //~ ERROR: use of unmarked item
use self::lint_stability::*;
use lint_stability::*;
fn test() {
let foo = MethodTester;

View file

@ -0,0 +1,20 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:macro_crate_nonterminal.rs
// ignore-stage1
mod foo {
#[macro_use]
extern crate macro_crate_nonterminal; //~ ERROR must be at the crate root
}
fn main() {
}