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

rustc: Disallow modules and macros in expansions #50820

Merged
merged 1 commit into from
May 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 55 additions & 5 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use ext::placeholders::{placeholder, PlaceholderExpander};
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use fold;
use fold::*;
use parse::{DirectoryOwnership, PResult};
use parse::{DirectoryOwnership, PResult, ParseSess};
use parse::token::{self, Token};
use parse::parser::Parser;
use ptr::P;
Expand All @@ -31,7 +31,7 @@ use syntax_pos::{Span, DUMMY_SP, FileName};
use syntax_pos::hygiene::ExpnFormat;
use tokenstream::{TokenStream, TokenTree};
use util::small_vector::SmallVector;
use visit::Visitor;
use visit::{self, Visitor};

use std::collections::HashMap;
use std::fs::File;
Expand Down Expand Up @@ -532,7 +532,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
})).into();
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
self.parse_expansion(tok_result, kind, &attr.path, attr.span)
let res = self.parse_expansion(tok_result, kind, &attr.path, attr.span);
self.gate_proc_macro_expansion(attr.span, &res);
res
}
ProcMacroDerive(..) | BuiltinDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
Expand Down Expand Up @@ -591,6 +593,50 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
);
}

fn gate_proc_macro_expansion(&self, span: Span, expansion: &Option<Expansion>) {
if self.cx.ecfg.proc_macro_gen() {
return
}
let expansion = match expansion {
Some(expansion) => expansion,
None => return,
};

expansion.visit_with(&mut DisallowModules {
span,
parse_sess: self.cx.parse_sess,
});

struct DisallowModules<'a> {
span: Span,
parse_sess: &'a ParseSess,
}

impl<'ast, 'a> Visitor<'ast> for DisallowModules<'a> {
fn visit_item(&mut self, i: &'ast ast::Item) {
let name = match i.node {
ast::ItemKind::Mod(_) => Some("modules"),
ast::ItemKind::MacroDef(_) => Some("macro definitions"),
_ => None,
};
if let Some(name) = name {
emit_feature_err(
self.parse_sess,
"proc_macro_gen",
self.span,
GateIssue::Language,
&format!("procedural macros cannot expand to {}", name),
);
}
visit::walk_item(self, i);
}

fn visit_mac(&mut self, _mac: &'ast ast::Mac) {
// ...
}
}
}

/// Expand a macro invocation. Returns the result of expansion.
fn expand_bang_invoc(&mut self,
invoc: Invocation,
Expand Down Expand Up @@ -732,7 +778,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
});

let tok_result = expandfun.expand(self.cx, span, mac.node.stream());
self.parse_expansion(tok_result, kind, path, span)
let result = self.parse_expansion(tok_result, kind, path, span);
self.gate_proc_macro_expansion(span, &result);
result
}
}
};
Expand Down Expand Up @@ -814,7 +862,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
span: DUMMY_SP,
node: ast::MetaItemKind::Word,
};
Some(kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item)))
let items = ext.expand(self.cx, span, &dummy, item);
Some(kind.expect_from_annotatables(items))
}
BuiltinDerive(func) => {
expn_info.callee.allow_internal_unstable = true;
Expand Down Expand Up @@ -1491,6 +1540,7 @@ impl<'feat> ExpansionConfig<'feat> {
fn proc_macro_enabled = proc_macro,
fn macros_in_extern_enabled = macros_in_extern,
fn proc_macro_mod = proc_macro_mod,
fn proc_macro_gen = proc_macro_gen,
fn proc_macro_expr = proc_macro_expr,
fn proc_macro_non_items = proc_macro_non_items,
}
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ declare_features! (
(active, proc_macro_mod, "1.27.0", None, None),
(active, proc_macro_expr, "1.27.0", None, None),
(active, proc_macro_non_items, "1.27.0", None, None),
(active, proc_macro_gen, "1.27.0", None, None),

// #[doc(alias = "...")]
(active, doc_alias, "1.27.0", Some(50146), None),
Expand Down
56 changes: 56 additions & 0 deletions src/test/compile-fail-fulldeps/proc-macro/auxiliary/more-gates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2018 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.

// no-prefer-dynamic

#![crate_type = "proc-macro"]
#![feature(proc_macro)]

extern crate proc_macro;

use proc_macro::*;

#[proc_macro_attribute]
pub fn attr2mod(_: TokenStream, _: TokenStream) -> TokenStream {
"mod test {}".parse().unwrap()
}

#[proc_macro_attribute]
pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream {
"macro_rules! foo1 { (a) => (a) }".parse().unwrap()
}

#[proc_macro_attribute]
pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream {
"macro foo2(a) { a }".parse().unwrap()
}

#[proc_macro]
pub fn mac2mod(_: TokenStream) -> TokenStream {
"mod test2 {}".parse().unwrap()
}

#[proc_macro]
pub fn mac2mac1(_: TokenStream) -> TokenStream {
"macro_rules! foo3 { (a) => (a) }".parse().unwrap()
}

#[proc_macro]
pub fn mac2mac2(_: TokenStream) -> TokenStream {
"macro foo4(a) { a }".parse().unwrap()
}

#[proc_macro]
pub fn tricky(_: TokenStream) -> TokenStream {
"fn foo() {
mod test {}
macro_rules! foo { (a) => (a) }
}".parse().unwrap()
}
37 changes: 37 additions & 0 deletions src/test/compile-fail-fulldeps/proc-macro/more-gates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2018 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:more-gates.rs

#![feature(proc_macro)]

extern crate more_gates as foo;

use foo::*;

#[attr2mod]
//~^ ERROR: cannot expand to modules
pub fn a() {}
#[attr2mac1]
//~^ ERROR: cannot expand to macro definitions
pub fn a() {}
#[attr2mac2]
//~^ ERROR: cannot expand to macro definitions
pub fn a() {}

mac2mod!(); //~ ERROR: cannot expand to modules
mac2mac1!(); //~ ERROR: cannot expand to macro definitions
mac2mac2!(); //~ ERROR: cannot expand to macro definitions

tricky!();
//~^ ERROR: cannot expand to modules
//~| ERROR: cannot expand to macro definitions

fn main() {}
3 changes: 3 additions & 0 deletions src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// gate-test-proc_macro_mod line
// gate-test-proc_macro_expr
// gate-test-proc_macro_mod
// gate-test-proc_macro_gen

#![feature(proc_macro, stmt_expr_attributes)]

Expand All @@ -29,10 +30,12 @@ fn _test_inner() {
}

#[a] //~ ERROR: custom attributes cannot be applied to modules
//~| ERROR: procedural macros cannot expand to modules
mod _test2 {}

mod _test2_inner {
#![a] //~ ERROR: custom attributes cannot be applied to modules
//~| ERROR: procedural macros cannot expand to modules
}

#[a = y] //~ ERROR: must only be followed by a delimiter token
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-pass-fulldeps/macro-quote-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// aux-build:hello_macro.rs
// ignore-stage1

#![feature(use_extern_macros, proc_macro_non_items)]
#![feature(use_extern_macros, proc_macro_non_items, proc_macro_gen)]

extern crate hello_macro;

Expand Down