提交 412f43ac 编写于 作者: B bors

Auto merge of #66647 - petrochenkov:nosynt, r=Centril

rustc_plugin: Remove support for syntactic plugins

This part of the plugin interface was successfully replaced by token-based procedural macros in theory and in practice.

cc https://github.com/rust-lang/rust/issues/29597
cc https://github.com/rust-lang/rust/pull/64675
r? @Centril
......@@ -3802,7 +3802,6 @@ dependencies = [
"rustc_error_codes",
"rustc_metadata",
"syntax",
"syntax_expand",
"syntax_pos",
]
......
......@@ -13,7 +13,7 @@ This feature is part of "compiler plugins." It will often be used with the
------------------------
`rustc` can load compiler plugins, which are user-provided libraries that
extend the compiler's behavior with new syntax extensions, lint checks, etc.
extend the compiler's behavior with new lint checks, etc.
A plugin is a dynamic library crate with a designated *registrar* function that
registers extensions with `rustc`. Other crates can load these extensions using
......@@ -35,134 +35,6 @@ The usual practice is to put compiler plugins in their own crate, separate from
any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
of a library.
# Syntax extensions
Plugins can extend Rust's syntax in various ways. One kind of syntax extension
is the procedural macro. These are invoked the same way as [ordinary
macros](../../book/macros.md), but the expansion is performed by arbitrary Rust
code that manipulates syntax trees at
compile time.
Let's write a plugin
[`roman_numerals.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/roman_numerals.rs)
that implements Roman numeral integer literals.
```rust,ignore
#![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)]
extern crate syntax;
extern crate syntax_pos;
extern crate rustc;
extern crate rustc_driver;
use syntax::parse::token::{self, Token};
use syntax::tokenstream::{TokenTree, TokenStream};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax_pos::Span;
use rustc_driver::plugin::Registry;
fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream)
-> Box<dyn MacResult + 'static> {
static NUMERALS: &'static [(&'static str, usize)] = &[
("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
("I", 1)];
if args.len() != 1 {
cx.span_err(
sp,
&format!("argument should be a single identifier, but got {} arguments", args.len()));
return DummyResult::any(sp);
}
let text = match args.into_trees().next().unwrap() {
TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(),
_ => {
cx.span_err(sp, "argument should be a single identifier");
return DummyResult::any(sp);
}
};
let mut text = &*text;
let mut total = 0;
while !text.is_empty() {
match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
Some(&(rn, val)) => {
total += val;
text = &text[rn.len()..];
}
None => {
cx.span_err(sp, "invalid Roman numeral");
return DummyResult::any(sp);
}
}
}
MacEager::expr(cx.expr_usize(sp, total))
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("rn", expand_rn);
}
```
Then we can use `rn!()` like any other macro:
```rust,ignore
#![feature(plugin)]
#![plugin(roman_numerals)]
fn main() {
assert_eq!(rn!(MMXV), 2015);
}
```
The advantages over a simple `fn(&str) -> u32` are:
* The (arbitrarily complex) conversion is done at compile time.
* Input validation is also performed at compile time.
* It can be extended to allow use in patterns, which effectively gives
a way to define new literal syntax for any data type.
In addition to procedural macros, you can define new
[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds
of extensions. See `Registry::register_syntax_extension` and the
`SyntaxExtension` struct. For a more involved macro example, see
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
## Tips and tricks
You can use `syntax::parse` to turn token trees into
higher-level syntax elements like expressions:
```rust,ignore
fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-> Box<MacResult+'static> {
let mut parser = cx.new_parser_from_tts(args);
let expr: P<Expr> = parser.parse_expr();
```
Looking through [`libsyntax` parser
code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs)
will give you a feel for how the parsing infrastructure works.
Keep the `Span`s of everything you parse, for better error reporting. You can
wrap `Spanned` around your custom data structures.
Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to
instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler
can continue and find further errors.
To print syntax fragments for debugging, you can use `span_note` together with
`syntax::print::pprust::*_to_string`.
# Lint plugins
Plugins can extend [Rust's lint
......
......@@ -322,7 +322,7 @@ pub fn run_compiler(
}
{
let (_, _, lint_store) = &*compiler.register_plugins()?.peek();
let (_, lint_store) = &*compiler.register_plugins()?.peek();
// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
......
......@@ -37,7 +37,7 @@
use rustc_typeck as typeck;
use syntax::{self, ast, visit};
use syntax::early_buffered_lints::BufferedEarlyLint;
use syntax_expand::base::{NamedSyntaxExtension, ExtCtxt};
use syntax_expand::base::ExtCtxt;
use syntax::mut_visit::MutVisitor;
use syntax::util::node_count::NodeCounter;
use syntax::symbol::Symbol;
......@@ -119,7 +119,6 @@ pub fn configure_and_expand(
metadata_loader: Box<MetadataLoaderDyn>,
krate: ast::Crate,
crate_name: &str,
plugin_info: PluginInfo,
) -> Result<(ast::Crate, BoxedResolver)> {
// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
......@@ -137,7 +136,6 @@ pub fn configure_and_expand(
&crate_name,
&resolver_arenas,
&*metadata_loader,
plugin_info,
);
let mut resolver = match res {
Err(v) => {
......@@ -164,17 +162,13 @@ pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutp
}
}
pub struct PluginInfo {
syntax_exts: Vec<NamedSyntaxExtension>,
}
pub fn register_plugins<'a>(
sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader,
register_lints: impl Fn(&Session, &mut lint::LintStore),
mut krate: ast::Crate,
crate_name: &str,
) -> Result<(ast::Crate, PluginInfo, Lrc<lint::LintStore>)> {
) -> Result<(ast::Crate, Lrc<lint::LintStore>)> {
krate = time(sess, "attributes injection", || {
syntax_ext::cmdline_attrs::inject(
krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr
......@@ -240,10 +234,9 @@ pub fn register_plugins<'a>(
}
});
let Registry { syntax_exts, llvm_passes, .. } = registry;
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
*sess.plugin_llvm_passes.borrow_mut() = registry.llvm_passes;
Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store)))
Ok((krate, Lrc::new(lint_store)))
}
fn configure_and_expand_inner<'a>(
......@@ -253,7 +246,6 @@ fn configure_and_expand_inner<'a>(
crate_name: &str,
resolver_arenas: &'a ResolverArenas<'a>,
metadata_loader: &'a MetadataLoaderDyn,
plugin_info: PluginInfo,
) -> Result<(ast::Crate, Resolver<'a>)> {
time(sess, "pre-AST-expansion lint checks", || {
lint::check_ast_crate(
......@@ -290,10 +282,6 @@ fn configure_and_expand_inner<'a>(
util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer());
syntax_ext::plugin_macro_defs::inject(
&mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
);
// Expand all macros
krate = time(sess, "expansion", || {
let _prof_timer = sess.prof.generic_activity("macro_expand_crate");
......
use crate::interface::{Compiler, Result};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt, PluginInfo};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};
use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc;
......@@ -79,7 +79,7 @@ pub(crate) struct Queries {
dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>,
crate_name: Query<String>,
register_plugins: Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>,
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
dep_graph: Query<DepGraph>,
lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>,
......@@ -111,7 +111,7 @@ pub fn parse(&self) -> Result<&Query<ast::Crate>> {
})
}
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>> {
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
self.queries.register_plugins.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let krate = self.parse()?.take();
......@@ -161,14 +161,13 @@ pub fn expansion(
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
self.queries.expansion.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let (krate, plugin_info, lint_store) = self.register_plugins()?.take();
let (krate, lint_store) = self.register_plugins()?.take();
passes::configure_and_expand(
self.sess.clone(),
lint_store.clone(),
self.codegen_backend().metadata_loader(),
krate,
&crate_name,
plugin_info,
).map(|(krate, resolver)| {
(krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
})
......
......@@ -14,6 +14,5 @@ doctest = false
rustc = { path = "../librustc" }
rustc_metadata = { path = "../librustc_metadata" }
syntax = { path = "../libsyntax" }
syntax_expand = { path = "../libsyntax_expand" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_error_codes = { path = "../librustc_error_codes" }
//! Infrastructure for compiler plugins.
//!
//! Plugins are Rust libraries which extend the behavior of `rustc`
//! in various ways.
//!
//! Plugin authors will use the `Registry` type re-exported by
//! this module, along with its methods. The rest of the module
//! is for use by `rustc` itself.
//!
//! To define a plugin, build a dylib crate with a
//! `#[plugin_registrar]` function:
//!
//! ```no_run
//! #![crate_name = "myplugin"]
//! #![crate_type = "dylib"]
//! #![feature(plugin_registrar)]
//! #![feature(rustc_private)]
//!
//! extern crate rustc_driver;
//! extern crate syntax;
//! extern crate syntax_pos;
//!
//! use rustc_driver::plugin::Registry;
//! use syntax_expand::base::{ExtCtxt, MacResult};
//! use syntax_pos::Span;
//! use syntax::tokenstream::TokenTree;
//!
//! #[plugin_registrar]
//! pub fn plugin_registrar(reg: &mut Registry) {
//! reg.register_macro("mymacro", expand_mymacro);
//! }
//!
//! fn expand_mymacro(cx: &mut ExtCtxt, span: Span, tt: &[TokenTree]) -> Box<MacResult> {
//! unimplemented!()
//! }
//!
//! # fn main() {}
//! ```
//!
//! WARNING: We currently don't check that the registrar function
//! has the appropriate type!
//!
//! To use a plugin while compiling another crate:
//!
//! ```rust
//! #![feature(plugin)]
//! #![plugin(myplugin)]
//! ```
//! Plugins are a deprecated way to extend the behavior of `rustc` in various ways.
//!
//! See the [`plugin`
//! feature](https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html)
//! of the Unstable Book for more examples.
//! of the Unstable Book for some examples.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
......
......@@ -2,10 +2,6 @@
use rustc::lint::LintStore;
use rustc::session::Session;
use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
use syntax_expand::base::MacroExpanderFn;
use syntax::symbol::Symbol;
use syntax::ast;
use syntax_pos::Span;
......@@ -33,9 +29,6 @@ pub struct Registry<'a> {
#[doc(hidden)]
pub krate_span: Span,
#[doc(hidden)]
pub syntax_exts: Vec<NamedSyntaxExtension>,
#[doc(hidden)]
pub llvm_passes: Vec<String>,
}
......@@ -48,7 +41,6 @@ pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -
lint_store,
args_hidden: None,
krate_span,
syntax_exts: vec![],
llvm_passes: vec![],
}
}
......@@ -67,24 +59,6 @@ pub fn args(&self) -> &[ast::NestedMetaItem] {
self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
}
/// Register a syntax extension of any kind.
///
/// This is the most general hook into `libsyntax`'s expansion behavior.
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
self.syntax_exts.push((name, extension));
}
/// Register a macro of the usual kind.
///
/// This is a convenience wrapper for `register_syntax_extension`.
/// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`,
/// and also takes care of interning the macro's name.
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander));
let ext = SyntaxExtension::default(kind, self.sess.edition());
self.register_syntax_extension(Symbol::intern(name), ext);
}
/// Register an LLVM pass.
///
/// Registration with LLVM itself is handled through static C++ objects with
......
......@@ -880,8 +880,8 @@ fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>
}
}
/// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined
/// extension partially or entirely for built-in macros and legacy plugin macros.
/// Compile the macro into a `SyntaxExtension` and possibly replace
/// its expander to a pre-defined one for built-in macros.
crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension {
let mut result = compile_declarative_macro(
&self.session.parse_sess, self.session.features_untracked(), item, edition
......@@ -890,14 +890,9 @@ fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>
if result.is_builtin {
// The macro was marked with `#[rustc_builtin_macro]`.
if let Some(ext) = self.builtin_macros.remove(&item.ident.name) {
if ext.is_builtin {
// The macro is a built-in, replace only the expander function.
// The macro is a built-in, replace its expander function
// while still taking everything else from the source code.
result.kind = ext.kind;
} else {
// The macro is from a plugin, the in-source definition is dummy,
// take all the data from the resolver.
result = ext;
}
} else {
let msg = format!("cannot find a built-in macro with name `{}`", item.ident);
self.session.span_err(item.span, &msg);
......
......@@ -825,8 +825,6 @@ pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnD
}
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
/// Result of resolving a macro invocation.
pub enum InvocationRes {
Single(Lrc<SyntaxExtension>),
......
......@@ -38,7 +38,6 @@
mod util;
pub mod cmdline_attrs;
pub mod plugin_macro_defs;
pub mod proc_macro_harness;
pub mod standard_library_imports;
pub mod test_harness;
......
//! Each macro must have a definition, so `#[plugin]` attributes
//! inject a dummy `macro_rules` item for each macro they define.
use syntax::ast::*;
use syntax::attr;
use syntax::edition::Edition;
use syntax::ptr::P;
use syntax::source_map::respan;
use syntax::symbol::sym;
use syntax::token;
use syntax::tokenstream::*;
use syntax_expand::base::{Resolver, NamedSyntaxExtension};
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::hygiene::{ExpnData, ExpnKind, AstPass};
use std::mem;
fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
let rustc_builtin_macro = attr::mk_attr_outer(
attr::mk_word_item(Ident::new(sym::rustc_builtin_macro, span)));
let parens: TreeAndJoint = TokenTree::Delimited(
DelimSpan::from_single(span), token::Paren, TokenStream::default()
).into();
let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
P(Item {
ident: Ident::new(name, span),
attrs: vec![rustc_builtin_macro],
id: DUMMY_NODE_ID,
kind: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }),
vis: respan(span, VisibilityKind::Inherited),
span: span,
tokens: None,
})
}
pub fn inject(
krate: &mut Crate,
resolver: &mut dyn Resolver,
named_exts: Vec<NamedSyntaxExtension>,
edition: Edition,
) {
if !named_exts.is_empty() {
let mut extra_items = Vec::new();
let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable(
ExpnKind::AstPass(AstPass::PluginMacroDefs), DUMMY_SP, edition,
[sym::rustc_attrs][..].into(),
));
for (name, ext) in named_exts {
resolver.register_builtin_macro(Ident::with_dummy_span(name), ext);
extra_items.push(plugin_macro_def(name, span));
}
// The `macro_rules` items must be inserted before any other items.
mem::swap(&mut extra_items, &mut krate.module.items);
krate.module.items.append(&mut extra_items);
}
}
......@@ -750,7 +750,6 @@ pub enum AstPass {
StdImports,
TestHarness,
ProcMacroHarness,
PluginMacroDefs,
}
impl AstPass {
......@@ -759,7 +758,6 @@ fn descr(self) -> &'static str {
AstPass::StdImports => "standard library imports",
AstPass::TestHarness => "test harness",
AstPass::ProcMacroHarness => "proc macro harness",
AstPass::PluginMacroDefs => "plugin macro definitions",
}
}
}
......
......@@ -4,17 +4,7 @@
#![feature(rustc_private)]
extern crate rustc_driver;
extern crate syntax;
extern crate syntax_expand;
use rustc_driver::plugin::Registry;
use syntax_expand::base::SyntaxExtension;
use syntax::feature_gate::AttributeType;
use syntax::symbol::Symbol;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition())
);
}
pub fn plugin_registrar(_: &mut Registry) {}
// force-host
#![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)]
extern crate syntax;
extern crate syntax_expand;
extern crate syntax_pos;
extern crate rustc;
extern crate rustc_driver;
use std::borrow::ToOwned;
use syntax::ast;
use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use syntax_expand::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager};
use syntax::print::pprust;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use syntax::tokenstream::TokenStream;
use rustc_driver::plugin::Registry;
struct Expander {
args: Vec<ast::NestedMetaItem>,
}
impl TTMacroExpander for Expander {
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt,
sp: Span,
_: TokenStream) -> Box<dyn MacResult+'cx> {
let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
.collect::<Vec<_>>().join(", ");
MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args)))
}
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
let args = reg.args().to_owned();
reg.register_syntax_extension(Symbol::intern("plugin_args"), SyntaxExtension::default(
SyntaxExtensionKind::LegacyBang(Box::new(Expander { args })), reg.sess.edition()
));
}
// WARNING WARNING WARNING WARNING WARNING
// =======================================
//
// This code also appears in src/doc/unstable-book/src/language-features/plugin.md.
// Please keep the two copies in sync! FIXME: have rustdoc read this file
// force-host
#![crate_type="dylib"]
#![feature(plugin_registrar, rustc_private)]
extern crate syntax;
extern crate syntax_expand;
extern crate syntax_pos;
extern crate rustc;
extern crate rustc_driver;
use syntax::token::{self, Token};
use syntax::tokenstream::{TokenTree, TokenStream};
use syntax_expand::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax_pos::Span;
use rustc_driver::plugin::Registry;
fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: TokenStream)
-> Box<dyn MacResult + 'static> {
static NUMERALS: &'static [(&'static str, usize)] = &[
("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
("I", 1)];
if args.len() != 1 {
cx.span_err(
sp,
&format!("argument should be a single identifier, but got {} arguments", args.len()));
return DummyResult::any(sp);
}
let text = match args.into_trees().next().unwrap() {
TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(),
_ => {
cx.span_err(sp, "argument should be a single identifier");
return DummyResult::any(sp);
}
};
let mut text = &*text;
let mut total = 0;
while !text.is_empty() {
match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
Some(&(rn, val)) => {
total += val;
text = &text[rn.len()..];
}
None => {
cx.span_err(sp, "invalid Roman numeral");
return DummyResult::any(sp);
}
}
}
MacEager::expr(cx.expr_usize(sp, total))
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("rn", expand_rn);
}
// aux-build:attr-plugin-test.rs
// aux-build:empty-plugin.rs
#![plugin(attr_plugin_test)]
#![plugin(empty_plugin)]
//~^ ERROR compiler plugins are deprecated
//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated
......
error[E0658]: compiler plugins are deprecated
--> $DIR/gated-plugin.rs:3:1
|
LL | #![plugin(attr_plugin_test)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #![plugin(empty_plugin)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29597
= help: add `#![feature(plugin)]` to the crate attributes to enable
......@@ -10,8 +10,8 @@ LL | #![plugin(attr_plugin_test)]
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/gated-plugin.rs:3:1
|
LL | #![plugin(attr_plugin_test)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
LL | #![plugin(empty_plugin)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
......
// run-pass
// aux-build:plugin-args.rs
// check-pass
// aux-build:empty-plugin.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(plugin_args)] //~ WARNING compiler plugins are deprecated
#![plugin(empty_plugin)] //~ WARNING compiler plugins are deprecated
fn main() {
assert_eq!(plugin_args!(), "");
}
fn main() {}
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/plugin-args-1.rs:6:1
|
LL | #![plugin(plugin_args)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
LL | #![plugin(empty_plugin)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
// run-pass
// aux-build:plugin-args.rs
// check-pass
// aux-build:empty-plugin.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(plugin_args())] //~ WARNING compiler plugins are deprecated
#![plugin(empty_plugin())] //~ WARNING compiler plugins are deprecated
fn main() {
assert_eq!(plugin_args!(), "");
}
fn main() {}
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/plugin-args-2.rs:6:1
|
LL | #![plugin(plugin_args())]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
LL | #![plugin(empty_plugin())]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
// run-pass
// aux-build:plugin-args.rs
// check-pass
// aux-build:empty-plugin.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(plugin_args(hello(there), how(are="you")))] //~ WARNING compiler plugins are deprecated
#![plugin(empty_plugin(hello(there), how(are="you")))] //~ WARNING compiler plugins are deprecated
fn main() {
assert_eq!(plugin_args!(), "hello(there), how(are = \"you\")");
}
fn main() {}
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/plugin-args-3.rs:6:1
|
LL | #![plugin(plugin_args(hello(there), how(are="you")))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
LL | #![plugin(empty_plugin(hello(there), how(are="you")))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
// aux-build:attr-plugin-test.rs
// aux-build:empty-plugin.rs
// ignore-cross-compile
//
// attr_plugin_test will not compile on a cross-compiled target because
// empty_plugin will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
#![deny(plugin_as_library)]
extern crate attr_plugin_test; //~ ERROR compiler plugin used as an ordinary library
extern crate empty_plugin; //~ ERROR compiler plugin used as an ordinary library
fn main() { }
error: compiler plugin used as an ordinary library
--> $DIR/plugin-as-extern-crate.rs:9:1
|
LL | extern crate attr_plugin_test;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | extern crate empty_plugin;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/plugin-as-extern-crate.rs:7:9
......
// edition:2018
// aux-build:attr-plugin-test.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(attr_plugin_test)]
//~^ WARN use of deprecated attribute `plugin`
pub use mac as reexport; //~ ERROR `mac` is private, and cannot be re-exported
fn main() {}
error[E0364]: `mac` is private, and cannot be re-exported
--> $DIR/plugin-reexport.rs:9:9
|
LL | pub use mac as reexport;
| ^^^^^^^^^^^^^^^
|
note: consider marking `mac` as `pub` in the imported module
--> $DIR/plugin-reexport.rs:9:9
|
LL | pub use mac as reexport;
| ^^^^^^^^^^^^^^^
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/plugin-reexport.rs:6:1
|
LL | #![plugin(attr_plugin_test)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
error: aborting due to previous error
For more information about this error, try `rustc --explain E0364`.
// run-pass
// aux-build:roman-numerals.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(roman_numerals)] //~ WARNING compiler plugins are deprecated
pub fn main() {
assert_eq!(rn!(MMXV), 2015);
assert_eq!(rn!(MCMXCIX), 1999);
assert_eq!(rn!(XXV), 25);
assert_eq!(rn!(MDCLXVI), 1666);
assert_eq!(rn!(MMMDCCCLXXXVIII), 3888);
assert_eq!(rn!(MMXIV), 2014);
}
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/roman-numerals-macro.rs:6:1
|
LL | #![plugin(roman_numerals)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
|
= note: `#[warn(deprecated)]` on by default
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册