Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
901d2c7b
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
901d2c7b
编写于
2月 16, 2015
作者:
M
Manish Goregaokar
浏览文件
操作
浏览文件
下载
差异文件
Rollup merge of #22241 - kmcallister:macro-plugin-cleanup, r=sfackler
上级
02fb58af
b7683fc0
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
396 addition
and
243 deletion
+396
-243
src/doc/trpl/plugins.md
src/doc/trpl/plugins.md
+10
-0
src/librustc/lint/builtin.rs
src/librustc/lint/builtin.rs
+43
-1
src/librustc/lint/context.rs
src/librustc/lint/context.rs
+1
-0
src/librustc/metadata/creader.rs
src/librustc/metadata/creader.rs
+29
-47
src/librustc/metadata/macro_import.rs
src/librustc/metadata/macro_import.rs
+186
-0
src/librustc/metadata/mod.rs
src/librustc/metadata/mod.rs
+1
-0
src/librustc/plugin/load.rs
src/librustc/plugin/load.rs
+21
-190
src/librustc_driver/driver.rs
src/librustc_driver/driver.rs
+6
-4
src/test/auxiliary/plugin_with_plugin_lib.rs
src/test/auxiliary/plugin_with_plugin_lib.rs
+22
-0
src/test/compile-fail-fulldeps/macro-crate-rlib.rs
src/test/compile-fail-fulldeps/macro-crate-rlib.rs
+1
-1
src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
+22
-0
src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs
src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs
+27
-0
src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs
src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs
+26
-0
src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
+1
-0
未找到文件。
src/doc/trpl/plugins.md
浏览文件 @
901d2c7b
...
...
@@ -39,6 +39,16 @@ If present, arguments passed as `#![plugin(foo(... args ...))]` are not
interpreted by rustc itself. They are provided to the plugin through the
`Registry`
's
[
`args` method
](
../rustc/plugin/registry/struct.Registry.html#method.args
)
.
In the vast majority of cases, a plugin should
*only*
be used through
`#![plugin]`
and not through an
`extern crate`
item. Linking a plugin would
pull in all of libsyntax and librustc as dependencies of your crate. This is
generally unwanted unless you are building another plugin. The
`plugin_as_library`
lint checks these guidelines.
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
...
...
src/librustc/lint/builtin.rs
浏览文件 @
901d2c7b
...
...
@@ -26,7 +26,7 @@
//! a `pub fn new()`.
use
self
::
MethodContext
::
*
;
use
metadata
::
csearch
;
use
metadata
::
{
csearch
,
decoder
}
;
use
middle
::
def
::
*
;
use
middle
::
subst
::
Substs
;
use
middle
::
ty
::{
self
,
Ty
};
...
...
@@ -1964,6 +1964,48 @@ fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}
declare_lint!
{
PLUGIN_AS_LIBRARY
,
Warn
,
"compiler plugin used as ordinary library in non-plugin crate"
}
#[derive(Copy)]
pub
struct
PluginAsLibrary
;
impl
LintPass
for
PluginAsLibrary
{
fn
get_lints
(
&
self
)
->
LintArray
{
lint_array!
[
PLUGIN_AS_LIBRARY
]
}
fn
check_item
(
&
mut
self
,
cx
:
&
Context
,
it
:
&
ast
::
Item
)
{
if
cx
.sess
()
.plugin_registrar_fn
.get
()
.is_some
()
{
// We're compiling a plugin; it's fine to link other plugins.
return
;
}
match
it
.node
{
ast
::
ItemExternCrate
(
..
)
=>
(),
_
=>
return
,
};
let
md
=
match
cx
.sess
()
.cstore
.find_extern_mod_stmt_cnum
(
it
.id
)
{
Some
(
cnum
)
=>
cx
.sess
()
.cstore
.get_crate_data
(
cnum
),
None
=>
{
// Probably means we aren't linking the crate for some reason.
//
// Not sure if / when this could happen.
return
;
}
};
if
decoder
::
get_plugin_registrar_fn
(
md
.data
())
.is_some
()
{
cx
.span_lint
(
PLUGIN_AS_LIBRARY
,
it
.span
,
"compiler plugin used as an ordinary library"
);
}
}
}
declare_lint!
{
pub
UNUSED_IMPORTS
,
Warn
,
...
...
src/librustc/lint/context.rs
浏览文件 @
901d2c7b
...
...
@@ -214,6 +214,7 @@ pub fn register_builtin(&mut self, sess: Option<&Session>) {
Stability
,
UnconditionalRecursion
,
InvalidNoMangleItems
,
PluginAsLibrary
,
);
add_builtin_with_new!
(
sess
,
...
...
src/librustc/metadata/creader.rs
浏览文件 @
901d2c7b
...
...
@@ -121,12 +121,10 @@ fn register_native_lib(sess: &Session,
sess
.cstore
.add_used_library
(
name
,
kind
);
}
pub
struct
PluginMetadata
<
'a
>
{
sess
:
&
'a
Session
,
// Extra info about a crate loaded for plugins or exported macros.
struct
ExtensionCrate
{
metadata
:
PMDSource
,
dylib
:
Option
<
Path
>
,
info
:
CrateInfo
,
vi_span
:
Span
,
target_only
:
bool
,
}
...
...
@@ -451,21 +449,7 @@ fn resolve_crate_deps(&mut self,
})
.collect
()
}
pub
fn
read_plugin_metadata
<
'b
>
(
&
'b
mut
self
,
krate
:
CrateOrString
<
'b
>
)
->
PluginMetadata
<
'b
>
{
let
(
info
,
span
)
=
match
krate
{
CrateOrString
::
Krate
(
c
)
=>
{
(
self
.extract_crate_info
(
c
)
.unwrap
(),
c
.span
)
}
CrateOrString
::
Str
(
sp
,
s
)
=>
{
(
CrateInfo
{
name
:
s
.to_string
(),
ident
:
s
.to_string
(),
id
:
ast
::
DUMMY_NODE_ID
,
should_link
:
false
,
},
sp
)
}
};
fn
read_extension_crate
(
&
mut
self
,
span
:
Span
,
info
:
&
CrateInfo
)
->
ExtensionCrate
{
let
target_triple
=
&
self
.sess.opts.target_triple
[];
let
is_cross
=
target_triple
!=
config
::
host_triple
();
let
mut
should_link
=
info
.should_link
&&
!
is_cross
;
...
...
@@ -517,30 +501,21 @@ pub fn read_plugin_metadata<'b>(&'b mut self,
PMDSource
::
Owned
(
library
.metadata
)
};
PluginMetadata
{
sess
:
self
.sess
,
ExtensionCrate
{
metadata
:
metadata
,
dylib
:
dylib
.map
(|
p
|
p
.0
),
info
:
info
,
vi_span
:
span
,
target_only
:
target_only
,
}
}
}
#[derive(Copy)]
pub
enum
CrateOrString
<
'a
>
{
Krate
(
&
'a
ast
::
Item
),
Str
(
Span
,
&
'a
str
)
}
/// Read exported macros.
pub
fn
read_exported_macros
(
&
mut
self
,
krate
:
&
ast
::
Item
)
->
Vec
<
ast
::
MacroDef
>
{
let
ci
=
self
.extract_crate_info
(
krate
)
.unwrap
();
let
ekrate
=
self
.read_extension_crate
(
krate
.span
,
&
ci
);
impl
<
'a
>
PluginMetadata
<
'a
>
{
/// Read exported macros
pub
fn
exported_macros
(
&
self
)
->
Vec
<
ast
::
MacroDef
>
{
let
imported_from
=
Some
(
token
::
intern
(
&
self
.info.ident
[])
.ident
());
let
source_name
=
format!
(
"<{} macros>"
,
&
self
.info.ident
[]);
let
source_name
=
format!
(
"<{} macros>"
,
krate
.ident
);
let
mut
macros
=
vec!
[];
decoder
::
each_exported_macro
(
self
.metadata
.as_slice
(),
decoder
::
each_exported_macro
(
ekrate
.metadata
.as_slice
(),
&*
self
.sess.cstore.intr
,
|
name
,
attrs
,
body
|
{
// NB: Don't use parse::parse_tts_from_source_str because it parses with
...
...
@@ -558,7 +533,7 @@ pub fn exported_macros(&self) -> Vec<ast::MacroDef> {
attrs
:
attrs
,
id
:
ast
::
DUMMY_NODE_ID
,
span
:
span
,
imported_from
:
imported_from
,
imported_from
:
Some
(
krate
.ident
)
,
// overridden in plugin/load.rs
export
:
false
,
use_locally
:
false
,
...
...
@@ -572,28 +547,35 @@ pub fn exported_macros(&self) -> Vec<ast::MacroDef> {
}
/// Look for a plugin registrar. Returns library path and symbol name.
pub
fn
plugin_registrar
(
&
self
)
->
Option
<
(
Path
,
String
)
>
{
if
self
.target_only
{
pub
fn
find_plugin_registrar
(
&
mut
self
,
span
:
Span
,
name
:
&
str
)
->
Option
<
(
Path
,
String
)
>
{
let
ekrate
=
self
.read_extension_crate
(
span
,
&
CrateInfo
{
name
:
name
.to_string
(),
ident
:
name
.to_string
(),
id
:
ast
::
DUMMY_NODE_ID
,
should_link
:
false
,
});
if
ekrate
.target_only
{
// Need to abort before syntax expansion.
let
message
=
format!
(
"plugin
crate
`{}` is not available for triple `{}`
\
let
message
=
format!
(
"plugin `{}` is not available for triple `{}`
\
(only found {})"
,
self
.info.ident
,
name
,
config
::
host_triple
(),
self
.sess.opts.target_triple
);
self
.sess
.span_err
(
s
elf
.vi_s
pan
,
&
message
[]);
self
.sess
.span_err
(
span
,
&
message
[]);
self
.sess
.abort_if_errors
();
}
let
registrar
=
decoder
::
get_plugin_registrar_fn
(
self
.metadata
.as_slice
())
.map
(|
id
|
decoder
::
get_symbol
(
self
.metadata
.as_slice
(),
id
));
let
registrar
=
decoder
::
get_plugin_registrar_fn
(
ekrate
.metadata
.as_slice
())
.map
(|
id
|
decoder
::
get_symbol
(
ekrate
.metadata
.as_slice
(),
id
));
match
(
self
.dylib
.as_ref
(),
registrar
)
{
match
(
ekrate
.dylib
.as_ref
(),
registrar
)
{
(
Some
(
dylib
),
Some
(
reg
))
=>
Some
((
dylib
.clone
(),
reg
)),
(
None
,
Some
(
_
))
=>
{
let
message
=
format!
(
"plugin
crate
`{}` only found in rlib format,
\
let
message
=
format!
(
"plugin `{}` only found in rlib format,
\
but must be available in dylib format"
,
self
.info.ident
);
self
.sess
.span_err
(
s
elf
.vi_s
pan
,
&
message
[]);
name
);
self
.sess
.span_err
(
span
,
&
message
[]);
// No need to abort because the loading code will just ignore this
// empty dylib.
None
...
...
src/librustc/metadata/macro_import.rs
0 → 100644
浏览文件 @
901d2c7b
// Copyright 2012-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.
//! Used by `rustc` when loading a crate with exported macros.
use
session
::
Session
;
use
metadata
::
creader
::
CrateReader
;
use
std
::
collections
::{
HashSet
,
HashMap
};
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
parse
::
token
;
use
syntax
::
visit
;
use
syntax
::
visit
::
Visitor
;
use
syntax
::
attr
::
AttrMetaMethods
;
struct
MacroLoader
<
'a
>
{
sess
:
&
'a
Session
,
span_whitelist
:
HashSet
<
Span
>
,
reader
:
CrateReader
<
'a
>
,
macros
:
Vec
<
ast
::
MacroDef
>
,
}
impl
<
'a
>
MacroLoader
<
'a
>
{
fn
new
(
sess
:
&
'a
Session
)
->
MacroLoader
<
'a
>
{
MacroLoader
{
sess
:
sess
,
span_whitelist
:
HashSet
::
new
(),
reader
:
CrateReader
::
new
(
sess
),
macros
:
vec!
[],
}
}
}
/// Read exported macros.
pub
fn
read_macro_defs
(
sess
:
&
Session
,
krate
:
&
ast
::
Crate
)
->
Vec
<
ast
::
MacroDef
>
{
let
mut
loader
=
MacroLoader
::
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
item
in
&
krate
.module.items
{
if
let
ast
::
ItemExternCrate
(
_
)
=
item
.node
{
loader
.span_whitelist
.insert
(
item
.span
);
}
}
visit
::
walk_crate
(
&
mut
loader
,
krate
);
loader
.macros
}
pub
type
MacroSelection
=
HashMap
<
token
::
InternedString
,
Span
>
;
// note that macros aren't expanded yet, and therefore macros can't add macro imports.
impl
<
'a
,
'v
>
Visitor
<
'v
>
for
MacroLoader
<
'a
>
{
fn
visit_item
(
&
mut
self
,
item
:
&
ast
::
Item
)
{
// We're only interested in `extern crate`.
match
item
.node
{
ast
::
ItemExternCrate
(
_
)
=>
{}
_
=>
{
visit
::
walk_item
(
self
,
item
);
return
;
}
}
// Parse the attributes relating to macros.
let
mut
import
=
Some
(
HashMap
::
new
());
// None => load all
let
mut
reexport
=
HashMap
::
new
();
for
attr
in
&
item
.attrs
{
let
mut
used
=
true
;
match
&
attr
.name
()[]
{
"phase"
=>
{
self
.sess
.span_err
(
attr
.span
,
"#[phase] is deprecated"
);
}
"plugin"
=>
{
self
.sess
.span_err
(
attr
.span
,
"#[plugin] on `extern crate` is deprecated"
);
self
.sess
.span_help
(
attr
.span
,
&
format!
(
"use a crate attribute instead,
\
i.e. #![plugin({})]"
,
item
.ident
.as_str
())[]);
}
"macro_use"
=>
{
let
names
=
attr
.meta_item_list
();
if
names
.is_none
()
{
// no names => load all
import
=
None
;
}
if
let
(
Some
(
sel
),
Some
(
names
))
=
(
import
.as_mut
(),
names
)
{
for
attr
in
names
{
if
let
ast
::
MetaWord
(
ref
name
)
=
attr
.node
{
sel
.insert
(
name
.clone
(),
attr
.span
);
}
else
{
self
.sess
.span_err
(
attr
.span
,
"bad macro import"
);
}
}
}
}
"macro_reexport"
=>
{
let
names
=
match
attr
.meta_item_list
()
{
Some
(
names
)
=>
names
,
None
=>
{
self
.sess
.span_err
(
attr
.span
,
"bad macro reexport"
);
continue
;
}
};
for
attr
in
names
{
if
let
ast
::
MetaWord
(
ref
name
)
=
attr
.node
{
reexport
.insert
(
name
.clone
(),
attr
.span
);
}
else
{
self
.sess
.span_err
(
attr
.span
,
"bad macro reexport"
);
}
}
}
_
=>
used
=
false
,
}
if
used
{
attr
::
mark_used
(
attr
);
}
}
self
.load_macros
(
item
,
import
,
reexport
)
}
fn
visit_mac
(
&
mut
self
,
_
:
&
ast
::
Mac
)
{
// bummer... can't see macro imports inside macros.
// do nothing.
}
}
impl
<
'a
>
MacroLoader
<
'a
>
{
fn
load_macros
<
'b
>
(
&
mut
self
,
vi
:
&
ast
::
Item
,
import
:
Option
<
MacroSelection
>
,
reexport
:
MacroSelection
)
{
if
let
Some
(
sel
)
=
import
.as_ref
()
{
if
sel
.is_empty
()
&&
reexport
.is_empty
()
{
return
;
}
}
if
!
self
.span_whitelist
.contains
(
&
vi
.span
)
{
self
.sess
.span_err
(
vi
.span
,
"an `extern crate` loading macros must be at
\
the crate root"
);
return
;
}
let
macros
=
self
.reader
.read_exported_macros
(
vi
);
let
mut
seen
=
HashSet
::
new
();
for
mut
def
in
macros
{
let
name
=
token
::
get_ident
(
def
.ident
);
seen
.insert
(
name
.clone
());
def
.use_locally
=
match
import
.as_ref
()
{
None
=>
true
,
Some
(
sel
)
=>
sel
.contains_key
(
&
name
),
};
def
.export
=
reexport
.contains_key
(
&
name
);
self
.macros
.push
(
def
);
}
if
let
Some
(
sel
)
=
import
.as_ref
()
{
for
(
name
,
span
)
in
sel
.iter
()
{
if
!
seen
.contains
(
name
)
{
self
.sess
.span_err
(
*
span
,
"imported macro not found"
);
}
}
}
for
(
name
,
span
)
in
reexport
.iter
()
{
if
!
seen
.contains
(
name
)
{
self
.sess
.span_err
(
*
span
,
"reexported macro not found"
);
}
}
}
}
src/librustc/metadata/mod.rs
浏览文件 @
901d2c7b
...
...
@@ -18,3 +18,4 @@
pub
mod
csearch
;
pub
mod
loader
;
pub
mod
filesearch
;
pub
mod
macro_import
;
src/librustc/plugin/load.rs
浏览文件 @
901d2c7b
...
...
@@ -8,24 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Used by `rustc` when loading a plugin
, or a crate with exported macros
.
//! Used by `rustc` when loading a plugin.
use
session
::
Session
;
use
metadata
::
creader
::
{
CrateOrString
,
CrateReader
}
;
use
metadata
::
creader
::
CrateReader
;
use
plugin
::
registry
::
Registry
;
use
std
::
mem
;
use
std
::
env
;
use
std
::
dynamic_lib
::
DynamicLibrary
;
use
std
::
collections
::{
HashSet
,
HashMap
};
use
std
::
borrow
::
ToOwned
;
use
syntax
::
ast
;
use
syntax
::
attr
;
use
syntax
::
codemap
::{
Span
,
COMMAND_LINE_SP
};
use
syntax
::
parse
::
token
;
use
syntax
::
ptr
::
P
;
use
syntax
::
visit
;
use
syntax
::
visit
::
Visitor
;
use
syntax
::
attr
::
AttrMetaMethods
;
/// Pointer to a registrar function.
...
...
@@ -37,51 +32,17 @@ pub struct PluginRegistrar {
pub
args
:
Vec
<
P
<
ast
::
MetaItem
>>
,
}
/// Information about loaded plugins.
pub
struct
Plugins
{
/// Imported macros.
pub
macros
:
Vec
<
ast
::
MacroDef
>
,
/// Registrars, as function pointers.
pub
registrars
:
Vec
<
PluginRegistrar
>
,
}
pub
struct
PluginLoader
<
'a
>
{
struct
PluginLoader
<
'a
>
{
sess
:
&
'a
Session
,
span_whitelist
:
HashSet
<
Span
>
,
reader
:
CrateReader
<
'a
>
,
pub
plugins
:
Plugins
,
}
impl
<
'a
>
PluginLoader
<
'a
>
{
fn
new
(
sess
:
&
'a
Session
)
->
PluginLoader
<
'a
>
{
PluginLoader
{
sess
:
sess
,
reader
:
CrateReader
::
new
(
sess
),
span_whitelist
:
HashSet
::
new
(),
plugins
:
Plugins
{
macros
:
vec!
(),
registrars
:
vec!
(),
},
}
}
plugins
:
Vec
<
PluginRegistrar
>
,
}
/// Read plugin metadata and dynamically load registrar functions.
pub
fn
load_plugins
(
sess
:
&
Session
,
krate
:
&
ast
::
Crate
,
addl_plugins
:
Option
<
Vec
<
String
>>
)
->
Plugins
{
addl_plugins
:
Option
<
Vec
<
String
>>
)
->
Vec
<
PluginRegistrar
>
{
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
item
in
&
krate
.module.items
{
if
let
ast
::
ItemExternCrate
(
_
)
=
item
.node
{
loader
.span_whitelist
.insert
(
item
.span
);
}
}
visit
::
walk_crate
(
&
mut
loader
,
krate
);
for
attr
in
&
krate
.attrs
{
if
!
attr
.check_name
(
"plugin"
)
{
continue
;
...
...
@@ -102,156 +63,34 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
}
let
args
=
plugin
.meta_item_list
()
.map
(
ToOwned
::
to_owned
)
.unwrap_or_default
();
loader
.load_plugin
(
CrateOrString
::
Str
(
plugin
.span
,
&*
plugin
.name
()),
args
);
loader
.load_plugin
(
plugin
.span
,
&*
plugin
.name
(),
args
);
}
}
if
let
Some
(
plugins
)
=
addl_plugins
{
for
plugin
in
plugins
{
loader
.load_plugin
(
CrateOrString
::
Str
(
COMMAND_LINE_SP
,
&
plugin
),
vec!
[]);
}
}
return
loader
.plugins
;
}
pub
type
MacroSelection
=
HashMap
<
token
::
InternedString
,
Span
>
;
// note that macros aren't expanded yet, and therefore macros can't add plugins.
impl
<
'a
,
'v
>
Visitor
<
'v
>
for
PluginLoader
<
'a
>
{
fn
visit_item
(
&
mut
self
,
item
:
&
ast
::
Item
)
{
// We're only interested in `extern crate`.
match
item
.node
{
ast
::
ItemExternCrate
(
_
)
=>
{}
_
=>
{
visit
::
walk_item
(
self
,
item
);
return
;
}
}
// Parse the attributes relating to macro loading.
let
mut
import
=
Some
(
HashMap
::
new
());
// None => load all
let
mut
reexport
=
HashMap
::
new
();
for
attr
in
&
item
.attrs
{
let
mut
used
=
true
;
match
&
attr
.name
()[]
{
"phase"
=>
{
self
.sess
.span_err
(
attr
.span
,
"#[phase] is deprecated"
);
}
"plugin"
=>
{
self
.sess
.span_err
(
attr
.span
,
"#[plugin] on `extern crate` is deprecated"
);
self
.sess
.span_help
(
attr
.span
,
&
format!
(
"use a crate attribute instead,
\
i.e. #![plugin({})]"
,
item
.ident
.as_str
())[]);
}
"macro_use"
=>
{
let
names
=
attr
.meta_item_list
();
if
names
.is_none
()
{
// no names => load all
import
=
None
;
}
if
let
(
Some
(
sel
),
Some
(
names
))
=
(
import
.as_mut
(),
names
)
{
for
attr
in
names
{
if
let
ast
::
MetaWord
(
ref
name
)
=
attr
.node
{
sel
.insert
(
name
.clone
(),
attr
.span
);
}
else
{
self
.sess
.span_err
(
attr
.span
,
"bad macro import"
);
}
}
}
}
"macro_reexport"
=>
{
let
names
=
match
attr
.meta_item_list
()
{
Some
(
names
)
=>
names
,
None
=>
{
self
.sess
.span_err
(
attr
.span
,
"bad macro reexport"
);
continue
;
}
};
for
attr
in
names
{
if
let
ast
::
MetaWord
(
ref
name
)
=
attr
.node
{
reexport
.insert
(
name
.clone
(),
attr
.span
);
}
else
{
self
.sess
.span_err
(
attr
.span
,
"bad macro reexport"
);
}
}
}
_
=>
used
=
false
,
}
if
used
{
attr
::
mark_used
(
attr
);
}
loader
.load_plugin
(
COMMAND_LINE_SP
,
&
plugin
,
vec!
[]);
}
self
.load_macros
(
item
,
import
,
reexport
)
}
fn
visit_mac
(
&
mut
self
,
_
:
&
ast
::
Mac
)
{
// bummer... can't see plugins inside macros.
// do nothing.
}
loader
.plugins
}
impl
<
'a
>
PluginLoader
<
'a
>
{
pub
fn
load_macros
<
'b
>
(
&
mut
self
,
vi
:
&
ast
::
Item
,
import
:
Option
<
MacroSelection
>
,
reexport
:
MacroSelection
)
{
if
let
Some
(
sel
)
=
import
.as_ref
()
{
if
sel
.is_empty
()
&&
reexport
.is_empty
()
{
return
;
}
}
if
!
self
.span_whitelist
.contains
(
&
vi
.span
)
{
self
.sess
.span_err
(
vi
.span
,
"an `extern crate` loading macros must be at
\
the crate root"
);
return
;
}
let
pmd
=
self
.reader
.read_plugin_metadata
(
CrateOrString
::
Krate
(
vi
));
let
mut
seen
=
HashSet
::
new
();
for
mut
def
in
pmd
.exported_macros
()
{
let
name
=
token
::
get_ident
(
def
.ident
);
seen
.insert
(
name
.clone
());
def
.use_locally
=
match
import
.as_ref
()
{
None
=>
true
,
Some
(
sel
)
=>
sel
.contains_key
(
&
name
),
};
def
.export
=
reexport
.contains_key
(
&
name
);
self
.plugins.macros
.push
(
def
);
}
if
let
Some
(
sel
)
=
import
.as_ref
()
{
for
(
name
,
span
)
in
sel
.iter
()
{
if
!
seen
.contains
(
name
)
{
self
.sess
.span_err
(
*
span
,
"imported macro not found"
);
}
}
}
for
(
name
,
span
)
in
reexport
.iter
()
{
if
!
seen
.contains
(
name
)
{
self
.sess
.span_err
(
*
span
,
"reexported macro not found"
);
}
fn
new
(
sess
:
&
'a
Session
)
->
PluginLoader
<
'a
>
{
PluginLoader
{
sess
:
sess
,
reader
:
CrateReader
::
new
(
sess
),
plugins
:
vec!
[],
}
}
pub
fn
load_plugin
<
'b
>
(
&
mut
self
,
c
:
CrateOrString
<
'b
>
,
args
:
Vec
<
P
<
ast
::
MetaItem
>>
)
{
let
registrar
=
{
let
pmd
=
self
.reader
.read_plugin_metadata
(
c
);
pmd
.plugin_registrar
()
};
fn
load_plugin
(
&
mut
self
,
span
:
Span
,
name
:
&
str
,
args
:
Vec
<
P
<
ast
::
MetaItem
>>
)
{
let
registrar
=
self
.reader
.find_plugin_registrar
(
span
,
name
);
if
let
Some
((
lib
,
symbol
))
=
registrar
{
let
fun
=
self
.dylink_registrar
(
c
,
lib
,
symbol
);
self
.plugins.
registrars
.
push
(
PluginRegistrar
{
let
fun
=
self
.dylink_registrar
(
span
,
lib
,
symbol
);
self
.plugins
.push
(
PluginRegistrar
{
fun
:
fun
,
args
:
args
,
});
...
...
@@ -259,8 +98,8 @@ pub fn load_plugin<'b>(&mut self,
}
// Dynamically link a registrar function into the compiler process.
fn
dylink_registrar
<
'b
>
(
&
mut
self
,
c
:
CrateOrString
<
'b
>
,
fn
dylink_registrar
(
&
mut
self
,
span
:
Span
,
path
:
Path
,
symbol
:
String
)
->
PluginRegistrarFun
{
// Make sure the path contains a / or the linker will search for it.
...
...
@@ -272,11 +111,7 @@ fn dylink_registrar<'b>(&mut self,
// inside this crate, so continue would spew "macro undefined"
// errors
Err
(
err
)
=>
{
if
let
CrateOrString
::
Krate
(
cr
)
=
c
{
self
.sess
.span_fatal
(
cr
.span
,
&
err
[])
}
else
{
self
.sess
.fatal
(
&
err
[])
}
self
.sess
.span_fatal
(
span
,
&
err
[])
}
};
...
...
@@ -288,11 +123,7 @@ fn dylink_registrar<'b>(&mut self,
}
// again fatal if we can't register macros
Err
(
err
)
=>
{
if
let
CrateOrString
::
Krate
(
cr
)
=
c
{
self
.sess
.span_fatal
(
cr
.span
,
&
err
[])
}
else
{
self
.sess
.fatal
(
&
err
[])
}
self
.sess
.span_fatal
(
span
,
&
err
[])
}
};
...
...
src/librustc_driver/driver.rs
浏览文件 @
901d2c7b
...
...
@@ -12,11 +12,11 @@
use
rustc
::
session
::
config
::{
self
,
Input
,
OutputFilenames
};
use
rustc
::
session
::
search_paths
::
PathKind
;
use
rustc
::
lint
;
use
rustc
::
metadata
;
use
rustc
::
metadata
::
creader
::
CrateReader
;
use
rustc
::
middle
::{
stability
,
ty
,
reachable
};
use
rustc
::
middle
::
dependency_format
;
use
rustc
::
middle
;
use
rustc
::
plugin
::
load
::
Plugins
;
use
rustc
::
plugin
::
registry
::
Registry
;
use
rustc
::
plugin
;
use
rustc
::
util
::
common
::
time
;
...
...
@@ -409,10 +409,12 @@ pub fn phase_2_configure_and_expand(sess: &Session,
syntax
::
std_inject
::
maybe_inject_crates_ref
(
krate
,
sess
.opts.alt_std_name
.clone
()));
let
macros
=
time
(
time_passes
,
"macro loading"
,
(),
|
_
|
metadata
::
macro_import
::
read_macro_defs
(
sess
,
&
krate
));
let
mut
addl_plugins
=
Some
(
addl_plugins
);
let
Plugins
{
macros
,
registrars
}
=
time
(
time_passes
,
"plugin loading"
,
(),
|
_
|
plugin
::
load
::
load_plugins
(
sess
,
&
krate
,
addl_plugins
.take
()
.unwrap
()));
let
registrars
=
time
(
time_passes
,
"plugin loading"
,
(),
|
_
|
plugin
::
load
::
load_plugins
(
sess
,
&
krate
,
addl_plugins
.take
()
.unwrap
()));
let
mut
registry
=
Registry
::
new
(
sess
,
&
krate
);
...
...
src/test/auxiliary/plugin_with_plugin_lib.rs
0 → 100644
浏览文件 @
901d2c7b
// 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.
// force-host
#![feature(plugin_registrar)]
#![deny(plugin_as_library)]
// should have no effect in a plugin crate
extern
crate
macro_crate_test
;
extern
crate
rustc
;
use
rustc
::
plugin
::
Registry
;
#[plugin_registrar]
pub
fn
plugin_registrar
(
_
:
&
mut
Registry
)
{
}
src/test/compile-fail-fulldeps/macro-crate-rlib.rs
浏览文件 @
901d2c7b
...
...
@@ -16,6 +16,6 @@
#![feature(plugin)]
#![plugin(rlib_crate_test)]
//~^ ERROR: plugin
crate
`rlib_crate_test` only found in rlib format, but must be available in dylib format
//~^ ERROR: plugin `rlib_crate_test` only found in rlib format, but must be available in dylib format
fn
main
()
{}
src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
0 → 100644
浏览文件 @
901d2c7b
// Copyright 2013-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_test.rs
// ignore-stage1
// ignore-cross-compile
//
// macro_crate_test will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
#![deny(plugin_as_library)]
extern
crate
macro_crate_test
;
//~ ERROR compiler plugin used as an ordinary library
fn
main
()
{
}
src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs
0 → 100644
浏览文件 @
901d2c7b
// Copyright 2013-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_test.rs
// ignore-stage1
// ignore-cross-compile
//
// macro_crate_test will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
#![deny(plugin_as_library)]
#![feature(plugin)]
#![plugin(macro_crate_test)]
extern
crate
macro_crate_test
;
//~ ERROR compiler plugin used as an ordinary library
fn
main
()
{
assert_eq!
(
1
,
make_a_1!
());
macro_crate_test
::
foo
();
}
src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs
0 → 100644
浏览文件 @
901d2c7b
// Copyright 2013-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_test.rs
// aux-build:plugin_with_plugin_lib.rs
// ignore-stage1
// ignore-cross-compile
//
// macro_crate_test will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
#![deny(plugin_as_library)]
#![feature(plugin)]
#![plugin(macro_crate_test)]
#![plugin(plugin_with_plugin_lib)]
fn
main
()
{
assert_eq!
(
1
,
make_a_1!
());
}
src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
浏览文件 @
901d2c7b
...
...
@@ -15,6 +15,7 @@
// macro_crate_test will not compile on a cross-compiled target because
// libsyntax is not compiled for it.
#![allow(plugin_as_library)]
#![feature(plugin)]
#![plugin(macro_crate_test)]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录