Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a4a249fc
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,发现更多精彩内容 >>
提交
a4a249fc
编写于
2月 02, 2016
作者:
B
bors
浏览文件
操作
浏览文件
下载
差异文件
Auto merge of #31279 - DanielJCampbell:MacroReferencing, r=nrc
r? @nrc
上级
b94cd7a5
1d326419
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
221 addition
and
11 deletion
+221
-11
src/librustc/session/mod.rs
src/librustc/session/mod.rs
+7
-1
src/librustc_metadata/common.rs
src/librustc_metadata/common.rs
+2
-0
src/librustc_metadata/creader.rs
src/librustc_metadata/creader.rs
+5
-3
src/librustc_metadata/decoder.rs
src/librustc_metadata/decoder.rs
+12
-3
src/librustc_metadata/encoder.rs
src/librustc_metadata/encoder.rs
+5
-0
src/librustc_trans/save/dump_csv.rs
src/librustc_trans/save/dump_csv.rs
+54
-2
src/librustc_trans/save/mod.rs
src/librustc_trans/save/mod.rs
+63
-0
src/librustc_trans/save/recorder.rs
src/librustc_trans/save/recorder.rs
+25
-0
src/librustc_trans/save/span_utils.rs
src/librustc_trans/save/span_utils.rs
+27
-2
src/libsyntax/codemap.rs
src/libsyntax/codemap.rs
+21
-0
未找到文件。
src/librustc/session/mod.rs
浏览文件 @
a4a249fc
...
...
@@ -30,7 +30,7 @@
use
std
::
path
::{
Path
,
PathBuf
};
use
std
::
cell
::{
Cell
,
RefCell
};
use
std
::
collections
::
HashSet
;
use
std
::
collections
::
{
HashMap
,
HashSet
}
;
use
std
::
env
;
use
std
::
rc
::
Rc
;
...
...
@@ -77,6 +77,11 @@ pub struct Session {
/// available in this crate
pub
available_macros
:
RefCell
<
HashSet
<
Name
>>
,
/// Map from imported macro spans (which consist of
/// the localized span for the macro body) to the
/// macro name and defintion span in the source crate.
pub
imported_macro_spans
:
RefCell
<
HashMap
<
Span
,
(
String
,
Span
)
>>
,
next_node_id
:
Cell
<
ast
::
NodeId
>
,
}
...
...
@@ -479,6 +484,7 @@ pub fn build_session_(sopts: config::Options,
next_node_id
:
Cell
::
new
(
1
),
injected_allocator
:
Cell
::
new
(
None
),
available_macros
:
RefCell
::
new
(
HashSet
::
new
()),
imported_macro_spans
:
RefCell
::
new
(
HashMap
::
new
()),
};
sess
...
...
src/librustc_metadata/common.rs
浏览文件 @
a4a249fc
...
...
@@ -223,6 +223,8 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
pub
const
tag_macro_defs
:
usize
=
0x10e
;
// top-level only
pub
const
tag_macro_def
:
usize
=
0x9e
;
pub
const
tag_macro_def_body
:
usize
=
0x9f
;
pub
const
tag_macro_def_span_lo
:
usize
=
0xa8
;
pub
const
tag_macro_def_span_hi
:
usize
=
0xa9
;
pub
const
tag_paren_sugar
:
usize
=
0xa0
;
...
...
src/librustc_metadata/creader.rs
浏览文件 @
a4a249fc
...
...
@@ -494,7 +494,7 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
let
mut
macros
=
vec!
[];
decoder
::
each_exported_macro
(
ekrate
.metadata
.as_slice
(),
&*
self
.cstore.intr
,
|
name
,
attrs
,
body
|
{
|
name
,
attrs
,
span
,
body
|
{
// NB: Don't use parse::parse_tts_from_source_str because it parses with
// quote_depth > 0.
let
mut
p
=
parse
::
new_parser_from_source_str
(
&
self
.sess.parse_sess
,
...
...
@@ -509,7 +509,7 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
panic!
(
FatalError
);
}
};
let
span
=
mk_sp
(
lo
,
p
.last_span.hi
);
let
local_
span
=
mk_sp
(
lo
,
p
.last_span.hi
);
// Mark the attrs as used
for
attr
in
&
attrs
{
...
...
@@ -520,7 +520,7 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
ident
:
ast
::
Ident
::
with_empty_ctxt
(
name
),
attrs
:
attrs
,
id
:
ast
::
DUMMY_NODE_ID
,
span
:
span
,
span
:
local_
span
,
imported_from
:
Some
(
item
.ident
),
// overridden in plugin/load.rs
export
:
false
,
...
...
@@ -529,6 +529,8 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
body
:
body
,
});
self
.sess.imported_macro_spans
.borrow_mut
()
.insert
(
local_span
,
(
name
.as_str
()
.to_string
(),
span
));
true
}
);
...
...
src/librustc_metadata/decoder.rs
浏览文件 @
a4a249fc
...
...
@@ -52,7 +52,7 @@
use
syntax
::
parse
::
token
;
use
syntax
::
ast
;
use
syntax
::
abi
;
use
syntax
::
codemap
::{
self
,
Span
};
use
syntax
::
codemap
::{
self
,
Span
,
BytePos
,
NO_EXPANSION
};
use
syntax
::
print
::
pprust
;
use
syntax
::
ptr
::
P
;
...
...
@@ -1471,19 +1471,28 @@ pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
}
pub
fn
each_exported_macro
<
F
>
(
data
:
&
[
u8
],
intr
:
&
IdentInterner
,
mut
f
:
F
)
where
F
:
FnMut
(
ast
::
Name
,
Vec
<
ast
::
Attribute
>
,
String
)
->
bool
,
F
:
FnMut
(
ast
::
Name
,
Vec
<
ast
::
Attribute
>
,
S
pan
,
S
tring
)
->
bool
,
{
let
macros
=
reader
::
get_doc
(
rbml
::
Doc
::
new
(
data
),
tag_macro_defs
);
for
macro_doc
in
reader
::
tagged_docs
(
macros
,
tag_macro_def
)
{
let
name
=
item_name
(
intr
,
macro_doc
);
let
attrs
=
get_attributes
(
macro_doc
);
let
span
=
get_macro_span
(
macro_doc
);
let
body
=
reader
::
get_doc
(
macro_doc
,
tag_macro_def_body
);
if
!
f
(
name
,
attrs
,
body
.as_str
()
.to_string
())
{
if
!
f
(
name
,
attrs
,
span
,
body
.as_str
()
.to_string
())
{
break
;
}
}
}
pub
fn
get_macro_span
(
doc
:
rbml
::
Doc
)
->
Span
{
let
lo_doc
=
reader
::
get_doc
(
doc
,
tag_macro_def_span_lo
);
let
lo
=
BytePos
(
reader
::
doc_as_u32
(
lo_doc
));
let
hi_doc
=
reader
::
get_doc
(
doc
,
tag_macro_def_span_hi
);
let
hi
=
BytePos
(
reader
::
doc_as_u32
(
hi_doc
));
return
Span
{
lo
:
lo
,
hi
:
hi
,
expn_id
:
NO_EXPANSION
};
}
pub
fn
get_dylib_dependency_formats
(
cdata
:
Cmd
)
->
Vec
<
(
ast
::
CrateNum
,
LinkagePreference
)
>
{
...
...
src/librustc_metadata/encoder.rs
浏览文件 @
a4a249fc
...
...
@@ -42,6 +42,7 @@
use
std
::
u32
;
use
syntax
::
abi
;
use
syntax
::
ast
::{
self
,
NodeId
,
Name
,
CRATE_NODE_ID
,
CrateNum
};
use
syntax
::
codemap
::
BytePos
;
use
syntax
::
attr
;
use
syntax
::
attr
::
AttrMetaMethods
;
use
syntax
::
errors
::
Handler
;
...
...
@@ -1727,6 +1728,10 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
encode_name
(
rbml_w
,
def
.name
);
encode_attributes
(
rbml_w
,
&
def
.attrs
);
let
&
BytePos
(
lo
)
=
&
def
.span.lo
;
let
&
BytePos
(
hi
)
=
&
def
.span.hi
;
rbml_w
.wr_tagged_u32
(
tag_macro_def_span_lo
,
lo
);
rbml_w
.wr_tagged_u32
(
tag_macro_def_span_hi
,
hi
);
rbml_w
.wr_tagged_str
(
tag_macro_def_body
,
&
::
syntax
::
print
::
pprust
::
tts_to_string
(
&
def
.body
));
...
...
src/librustc_trans/save/dump_csv.rs
浏览文件 @
a4a249fc
...
...
@@ -37,6 +37,8 @@
use
middle
::
ty
;
use
std
::
fs
::
File
;
use
std
::
hash
::
*
;
use
std
::
collections
::
HashSet
;
use
syntax
::
ast
::{
self
,
NodeId
};
use
syntax
::
codemap
::
*
;
...
...
@@ -70,6 +72,14 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
fmt
:
FmtStrs
<
'l
,
'tcx
>
,
cur_scope
:
NodeId
,
// Set of macro definition (callee) spans, and the set
// of macro use (callsite) spans. We store these to ensure
// we only write one macro def per unique macro definition, and
// one macro use per unique callsite span.
mac_defs
:
HashSet
<
Span
>
,
mac_uses
:
HashSet
<
Span
>
,
}
impl
<
'l
,
'tcx
>
DumpCsvVisitor
<
'l
,
'tcx
>
{
...
...
@@ -92,6 +102,8 @@ pub fn new(tcx: &'l ty::ctxt<'tcx>,
span_utils
,
tcx
),
cur_scope
:
0
,
mac_defs
:
HashSet
::
new
(),
mac_uses
:
HashSet
::
new
(),
}
}
...
...
@@ -814,10 +826,41 @@ fn process_var_decl(&mut self, p: &ast::Pat, value: String) {
&
typ
);
}
}
/// Extract macro use and definition information from the AST node defined
/// by the given NodeId, using the expansion information from the node's
/// span.
///
/// If the span is not macro-generated, do nothing, else use callee and
/// callsite spans to record macro definition and use data, using the
/// mac_uses and mac_defs sets to prevent multiples.
fn
process_macro_use
(
&
mut
self
,
span
:
Span
,
id
:
NodeId
)
{
let
data
=
match
self
.save_ctxt
.get_macro_use_data
(
span
,
id
)
{
None
=>
return
,
Some
(
data
)
=>
data
,
};
let
mut
hasher
=
SipHasher
::
new
();
data
.callee_span
.hash
(
&
mut
hasher
);
let
hash
=
hasher
.finish
();
let
qualname
=
format!
(
"{}::{}"
,
data
.name
,
hash
);
// Don't write macro definition for imported macros
if
!
self
.mac_defs
.contains
(
&
data
.callee_span
)
&&
!
data
.imported
{
self
.mac_defs
.insert
(
data
.callee_span
);
self
.fmt
.macro_str
(
data
.callee_span
,
data
.callee_span
,
data
.name
.clone
(),
qualname
.clone
());
}
if
!
self
.mac_uses
.contains
(
&
data
.span
)
{
self
.mac_uses
.insert
(
data
.span
);
self
.fmt
.macro_use_str
(
data
.span
,
data
.span
,
data
.name
,
qualname
,
data
.scope
);
}
}
}
impl
<
'l
,
'tcx
,
'v
>
Visitor
<
'v
>
for
DumpCsvVisitor
<
'l
,
'tcx
>
{
fn
visit_item
(
&
mut
self
,
item
:
&
ast
::
Item
)
{
self
.process_macro_use
(
item
.span
,
item
.id
);
match
item
.node
{
ast
::
ItemUse
(
ref
use_item
)
=>
{
match
use_item
.node
{
...
...
@@ -970,6 +1013,7 @@ fn visit_generics(&mut self, generics: &ast::Generics) {
}
fn
visit_trait_item
(
&
mut
self
,
trait_item
:
&
ast
::
TraitItem
)
{
self
.process_macro_use
(
trait_item
.span
,
trait_item
.id
);
match
trait_item
.node
{
ast
::
ConstTraitItem
(
ref
ty
,
Some
(
ref
expr
))
=>
{
self
.process_const
(
trait_item
.id
,
...
...
@@ -991,6 +1035,7 @@ fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
}
fn
visit_impl_item
(
&
mut
self
,
impl_item
:
&
ast
::
ImplItem
)
{
self
.process_macro_use
(
impl_item
.span
,
impl_item
.id
);
match
impl_item
.node
{
ast
::
ImplItemKind
::
Const
(
ref
ty
,
ref
expr
)
=>
{
self
.process_const
(
impl_item
.id
,
...
...
@@ -1012,6 +1057,7 @@ fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
}
fn
visit_ty
(
&
mut
self
,
t
:
&
ast
::
Ty
)
{
self
.process_macro_use
(
t
.span
,
t
.id
);
match
t
.node
{
ast
::
TyPath
(
_
,
ref
path
)
=>
{
match
self
.lookup_type_ref
(
t
.id
)
{
...
...
@@ -1031,6 +1077,7 @@ fn visit_ty(&mut self, t: &ast::Ty) {
}
fn
visit_expr
(
&
mut
self
,
ex
:
&
ast
::
Expr
)
{
self
.process_macro_use
(
ex
.span
,
ex
.id
);
match
ex
.node
{
ast
::
ExprCall
(
ref
_
f
,
ref
_
args
)
=>
{
// Don't need to do anything for function calls,
...
...
@@ -1117,11 +1164,13 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
}
}
fn
visit_mac
(
&
mut
self
,
_
:
&
ast
::
Mac
)
{
// Just stop, macros are poison to us.
fn
visit_mac
(
&
mut
self
,
mac
:
&
ast
::
Mac
)
{
// These shouldn't exist in the AST at this point, log a span bug.
self
.sess
.span_bug
(
mac
.span
,
"macro invocation should have been expanded out of AST"
);
}
fn
visit_pat
(
&
mut
self
,
p
:
&
ast
::
Pat
)
{
self
.process_macro_use
(
p
.span
,
p
.id
);
self
.process_pat
(
p
);
}
...
...
@@ -1177,10 +1226,13 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
}
fn
visit_stmt
(
&
mut
self
,
s
:
&
ast
::
Stmt
)
{
let
id
=
s
.node
.id
();
self
.process_macro_use
(
s
.span
,
id
.unwrap
());
visit
::
walk_stmt
(
self
,
s
)
}
fn
visit_local
(
&
mut
self
,
l
:
&
ast
::
Local
)
{
self
.process_macro_use
(
l
.span
,
l
.id
);
let
value
=
self
.span
.snippet
(
l
.span
);
self
.process_var_decl
(
&
l
.pat
,
value
);
...
...
src/librustc_trans/save/mod.rs
浏览文件 @
a4a249fc
...
...
@@ -73,6 +73,8 @@ pub enum Data {
FunctionCallData
(
FunctionCallData
),
/// Data about a method call.
MethodCallData
(
MethodCallData
),
/// Data about a macro use.
MacroUseData
(
MacroUseData
),
}
/// Data for all kinds of functions and methods.
...
...
@@ -174,6 +176,22 @@ pub struct MethodCallData {
pub
decl_id
:
Option
<
DefId
>
,
}
/// Data about a macro use.
#[derive(Debug)]
pub
struct
MacroUseData
{
pub
span
:
Span
,
pub
name
:
String
,
// Because macro expansion happens before ref-ids are determined,
// we use the callee span to reference the associated macro definition.
pub
callee_span
:
Span
,
pub
scope
:
NodeId
,
pub
imported
:
bool
,
}
macro_rules!
option_try
(
(
$e:expr
)
=>
(
match
$e
{
Some
(
e
)
=>
e
,
None
=>
return
None
})
);
impl
<
'l
,
'tcx
:
'l
>
SaveContext
<
'l
,
'tcx
>
{
...
...
@@ -655,6 +673,51 @@ pub fn get_field_ref_data(&self,
})
}
/// Attempt to return MacroUseData for any AST node.
///
/// For a given piece of AST defined by the supplied Span and NodeId,
/// returns None if the node is not macro-generated or the span is malformed,
/// else uses the expansion callsite and callee to return some MacroUseData.
pub
fn
get_macro_use_data
(
&
self
,
span
:
Span
,
id
:
NodeId
)
->
Option
<
MacroUseData
>
{
if
!
generated_code
(
span
)
{
return
None
;
}
// Note we take care to use the source callsite/callee, to handle
// nested expansions and ensure we only generate data for source-visible
// macro uses.
let
callsite
=
self
.tcx.sess
.codemap
()
.source_callsite
(
span
);
let
callee
=
self
.tcx.sess
.codemap
()
.source_callee
(
span
);
let
callee
=
option_try!
(
callee
);
let
callee_span
=
option_try!
(
callee
.span
);
// Ignore attribute macros, their spans are usually mangled
if
let
MacroAttribute
(
_
)
=
callee
.format
{
return
None
;
}
// If the callee is an imported macro from an external crate, need to get
// the source span and name from the session, as their spans are localized
// when read in, and no longer correspond to the source.
if
let
Some
(
mac
)
=
self
.tcx.sess.imported_macro_spans
.borrow
()
.get
(
&
callee_span
)
{
let
&
(
ref
mac_name
,
mac_span
)
=
mac
;
return
Some
(
MacroUseData
{
span
:
callsite
,
name
:
mac_name
.clone
(),
callee_span
:
mac_span
,
scope
:
self
.enclosing_scope
(
id
),
imported
:
true
,
});
}
Some
(
MacroUseData
{
span
:
callsite
,
name
:
callee
.name
()
.to_string
(),
callee_span
:
callee_span
,
scope
:
self
.enclosing_scope
(
id
),
imported
:
false
,
})
}
pub
fn
get_data_for_id
(
&
self
,
_
id
:
&
NodeId
)
->
Data
{
// FIXME
unimplemented!
();
...
...
src/librustc_trans/save/recorder.rs
浏览文件 @
a4a249fc
...
...
@@ -96,6 +96,8 @@ pub enum Row {
VarRef
,
TypeRef
,
FnRef
,
Macro
,
MacroUse
,
}
impl
<
'a
,
'tcx
:
'a
>
FmtStrs
<
'a
,
'tcx
>
{
...
...
@@ -219,6 +221,14 @@ fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
vec!
(
"refid"
,
"refidcrate"
,
"qualname"
,
"scopeid"
),
true
,
true
),
Macro
=>
(
"macro"
,
vec!
(
"name"
,
"qualname"
),
true
,
true
),
MacroUse
=>
(
"macro_use"
,
vec!
(
"callee_name"
,
"qualname"
,
"scopeid"
),
true
,
true
),
}
}
...
...
@@ -686,4 +696,19 @@ pub fn ref_str(&mut self,
sub_span
,
svec!
(
id
.index
.as_usize
(),
id
.krate
,
""
,
scope_id
));
}
pub
fn
macro_str
(
&
mut
self
,
span
:
Span
,
sub_span
:
Span
,
name
:
String
,
qualname
:
String
)
{
self
.record_with_span
(
Macro
,
span
,
sub_span
,
svec!
(
name
,
qualname
));
}
pub
fn
macro_use_str
(
&
mut
self
,
span
:
Span
,
sub_span
:
Span
,
name
:
String
,
qualname
:
String
,
scope_id
:
NodeId
)
{
let
scope_id
=
self
.normalize_node_id
(
scope_id
);
self
.record_with_span
(
MacroUse
,
span
,
sub_span
,
svec!
(
name
,
qualname
,
scope_id
));
}
}
src/librustc_trans/save/span_utils.rs
浏览文件 @
a4a249fc
...
...
@@ -378,6 +378,25 @@ pub fn report_span_err(&self, kind: &str, span: Span) {
}
}
// Given a macro_rules definition span, return the span of the macro's name.
pub
fn
span_for_macro_name
(
&
self
,
span
:
Span
)
->
Option
<
Span
>
{
let
mut
toks
=
self
.retokenise_span
(
span
);
loop
{
let
ts
=
toks
.real_token
();
if
ts
.tok
==
token
::
Eof
{
return
None
;
}
if
ts
.tok
==
token
::
Not
{
let
ts
=
toks
.real_token
();
if
ts
.tok
.is_ident
()
{
return
self
.make_sub_span
(
span
,
Some
(
ts
.sp
));
}
else
{
return
None
;
}
}
}
}
/// Return true if the span is generated code, and
/// it is not a subspan of the root callsite.
///
...
...
@@ -395,10 +414,16 @@ pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
if
sub_span
.is_none
()
{
return
true
;
}
// A generated span is deemed invalid if it is not a sub-span of the root
//If the span comes from a fake filemap, filter it.
if
!
self
.sess
.codemap
()
.lookup_char_pos
(
parent
.lo
)
.file
.is_real_file
()
{
return
true
;
}
// Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
// callsite. This filters out macro internal variables and most malformed spans.
let
span
=
self
.sess
.codemap
()
.source_callsite
(
parent
);
!
(
parent
.lo
>=
span
.lo
&&
parent
.hi
<=
span
.hi
)
!
(
span
.contains
(
parent
)
)
}
}
...
...
src/libsyntax/codemap.rs
浏览文件 @
a4a249fc
...
...
@@ -1064,6 +1064,27 @@ pub fn source_callsite(&self, sp: Span) -> Span {
span
}
/// Return the source callee.
///
/// Returns None if the supplied span has no expansion trace,
/// else returns the NameAndSpan for the macro definition
/// corresponding to the source callsite.
pub
fn
source_callee
(
&
self
,
sp
:
Span
)
->
Option
<
NameAndSpan
>
{
let
mut
span
=
sp
;
while
let
Some
(
callsite
)
=
self
.with_expn_info
(
span
.expn_id
,
|
ei
|
ei
.map
(|
ei
|
ei
.call_site
.clone
()))
{
if
let
Some
(
_
)
=
self
.with_expn_info
(
callsite
.expn_id
,
|
ei
|
ei
.map
(|
ei
|
ei
.call_site
.clone
()))
{
span
=
callsite
;
}
else
{
return
self
.with_expn_info
(
span
.expn_id
,
|
ei
|
ei
.map
(|
ei
|
ei
.callee
.clone
()));
}
}
None
}
pub
fn
span_to_filename
(
&
self
,
sp
:
Span
)
->
FileName
{
self
.lookup_char_pos
(
sp
.lo
)
.file.name
.to_string
()
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录