Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8ec68761
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,发现更多精彩内容 >>
提交
8ec68761
编写于
5月 30, 2020
作者:
M
marmeladema
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
save_analysis: work on HIR tree instead of AST
上级
f3fadf6a
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
902 addition
and
998 deletion
+902
-998
src/librustc_driver/lib.rs
src/librustc_driver/lib.rs
+4
-12
src/librustc_hir_pretty/lib.rs
src/librustc_hir_pretty/lib.rs
+24
-0
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/dump_visitor.rs
+411
-505
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/lib.rs
+220
-253
src/librustc_save_analysis/sig.rs
src/librustc_save_analysis/sig.rs
+243
-228
未找到文件。
src/librustc_driver/lib.rs
浏览文件 @
8ec68761
...
...
@@ -346,12 +346,15 @@ pub fn run_compiler(
queries
.global_ctxt
()
?
;
// Drop AST after creating GlobalCtxt to free memory
let
_
timer
=
sess
.prof
.generic_activity
(
"drop_ast"
);
mem
::
drop
(
queries
.expansion
()
?
.take
());
if
sess
.opts.debugging_opts.no_analysis
||
sess
.opts.debugging_opts.ast_json
{
return
early_exit
();
}
if
sess
.opts.debugging_opts.save_analysis
{
let
expanded_crate
=
&
queries
.expansion
()
?
.peek
()
.0
;
let
crate_name
=
queries
.crate_name
()
?
.peek
()
.clone
();
queries
.global_ctxt
()
?
.peek_mut
()
.enter
(|
tcx
|
{
let
result
=
tcx
.analysis
(
LOCAL_CRATE
);
...
...
@@ -359,7 +362,6 @@ pub fn run_compiler(
sess
.time
(
"save_analysis"
,
||
{
save
::
process_crate
(
tcx
,
&
expanded_crate
,
&
crate_name
,
&
compiler
.input
(),
None
,
...
...
@@ -371,13 +373,7 @@ pub fn run_compiler(
});
result
// AST will be dropped *after* the `after_analysis` callback
// (needed by the RLS)
})
?
;
}
else
{
// Drop AST after creating GlobalCtxt to free memory
let
_
timer
=
sess
.prof
.generic_activity
(
"drop_ast"
);
mem
::
drop
(
queries
.expansion
()
?
.take
());
}
queries
.global_ctxt
()
?
.peek_mut
()
.enter
(|
tcx
|
tcx
.analysis
(
LOCAL_CRATE
))
?
;
...
...
@@ -386,10 +382,6 @@ pub fn run_compiler(
return
early_exit
();
}
if
sess
.opts.debugging_opts.save_analysis
{
mem
::
drop
(
queries
.expansion
()
?
.take
());
}
queries
.ongoing_codegen
()
?
;
if
sess
.opts.debugging_opts.print_type_sizes
{
...
...
src/librustc_hir_pretty/lib.rs
浏览文件 @
8ec68761
...
...
@@ -203,6 +203,30 @@ pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility<'_
})
}
pub
fn
generic_params_to_string
(
generic_params
:
&
[
GenericParam
<
'_
>
])
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_generic_params
(
generic_params
))
}
pub
fn
bounds_to_string
<
'b
>
(
bounds
:
impl
IntoIterator
<
Item
=
&
'b
hir
::
GenericBound
<
'b
>>
)
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_bounds
(
""
,
bounds
))
}
pub
fn
param_to_string
(
arg
:
&
hir
::
Param
<
'_
>
)
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_param
(
arg
))
}
pub
fn
ty_to_string
(
ty
:
&
hir
::
Ty
<
'_
>
)
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_type
(
ty
))
}
pub
fn
path_segment_to_string
(
segment
:
&
hir
::
PathSegment
<
'_
>
)
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_path_segment
(
segment
))
}
pub
fn
path_to_string
(
segment
:
&
hir
::
Path
<
'_
>
)
->
String
{
to_string
(
NO_ANN
,
|
s
|
s
.print_path
(
segment
,
false
))
}
impl
<
'a
>
State
<
'a
>
{
pub
fn
cbox
(
&
mut
self
,
u
:
usize
)
{
self
.s
.cbox
(
u
);
...
...
src/librustc_save_analysis/dump_visitor.rs
浏览文件 @
8ec68761
...
...
@@ -13,19 +13,19 @@
//! DumpVisitor walks the AST and processes it, and Dumper is used for
//! recording the output.
use
rustc_ast
::
ast
::{
self
,
Attribute
,
NodeId
,
PatKind
};
use
rustc_ast
::
ptr
::
P
;
use
rustc_ast
::
token
;
use
rustc_ast
::
visit
::{
self
,
Visitor
};
use
rustc_ast
::
walk_list
;
use
rustc_ast_pretty
::
pprust
::{
bounds_to_string
,
generic_params_to_string
,
ty_to_string
};
use
rustc_ast
::
ast
::{
self
};
use
rustc_ast
::{
token
,
walk_list
};
use
rustc_data_structures
::
fx
::
FxHashSet
;
use
rustc_hir
as
hir
;
use
rustc_hir
::
def
::{
DefKind
as
HirDefKind
,
Res
};
use
rustc_hir
::
def_id
::{
DefId
,
LocalDefId
};
use
rustc_hir
::
intravisit
::{
self
,
Visitor
};
use
rustc_hir_pretty
::{
bounds_to_string
,
generic_params_to_string
,
ty_to_string
};
use
rustc_middle
::
hir
::
map
::
Map
;
use
rustc_middle
::
span_bug
;
use
rustc_middle
::
ty
::{
self
,
DefIdTree
,
TyCtxt
};
use
rustc_session
::
config
::
Input
;
use
rustc_span
::
source_map
::
{
respan
,
DUMMY_SP
}
;
use
rustc_span
::
source_map
::
respan
;
use
rustc_span
::
symbol
::
Ident
;
use
rustc_span
::
*
;
...
...
@@ -36,7 +36,7 @@
use
crate
::
sig
;
use
crate
::
span_utils
::
SpanUtils
;
use
crate
::{
escape
,
generated_code
,
id_from_def_id
,
id_from_
node
_id
,
lower_attributes
,
PathCollector
,
escape
,
generated_code
,
id_from_def_id
,
id_from_
hir
_id
,
lower_attributes
,
PathCollector
,
SaveContext
,
};
...
...
@@ -124,11 +124,11 @@ fn span_from_span(&self, span: Span) -> SpanData {
self
.save_ctxt
.span_from_span
(
span
)
}
fn
lookup_def_id
(
&
self
,
ref_id
:
Node
Id
)
->
Option
<
DefId
>
{
fn
lookup_def_id
(
&
self
,
ref_id
:
hir
::
Hir
Id
)
->
Option
<
DefId
>
{
self
.save_ctxt
.lookup_def_id
(
ref_id
)
}
pub
fn
dump_crate_info
(
&
mut
self
,
name
:
&
str
,
krate
:
&
ast
::
Crate
)
{
pub
fn
dump_crate_info
(
&
mut
self
,
name
:
&
str
,
krate
:
&
hir
::
Crate
<
'_
>
)
{
let
source_file
=
self
.tcx.sess.local_crate_source_file
.as_ref
();
let
crate_root
=
source_file
.map
(|
source_file
|
{
let
source_file
=
Path
::
new
(
source_file
);
...
...
@@ -151,7 +151,7 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
},
crate_root
:
crate_root
.unwrap_or_else
(||
"<no source>"
.to_owned
()),
external_crates
:
self
.save_ctxt
.get_external_crates
(),
span
:
self
.span_from_span
(
krate
.span
),
span
:
self
.span_from_span
(
krate
.
item.
span
),
};
self
.dumper
.crate_prelude
(
data
);
...
...
@@ -199,8 +199,8 @@ pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
self
.dumper
.compilation_opts
(
data
);
}
fn
write_sub_paths
(
&
mut
self
,
path
:
&
ast
::
Path
)
{
for
seg
in
&
path
.segments
{
fn
write_sub_paths
(
&
mut
self
,
path
:
&
'tcx
hir
::
Path
<
'tcx
>
)
{
for
seg
in
path
.segments
{
if
let
Some
(
data
)
=
self
.save_ctxt
.get_path_segment_data
(
seg
)
{
self
.dumper
.dump_ref
(
data
);
}
...
...
@@ -209,7 +209,7 @@ fn write_sub_paths(&mut self, path: &ast::Path) {
// As write_sub_paths, but does not process the last ident in the path (assuming it
// will be processed elsewhere). See note on write_sub_paths about global.
fn
write_sub_paths_truncated
(
&
mut
self
,
path
:
&
ast
::
Path
)
{
fn
write_sub_paths_truncated
(
&
mut
self
,
path
:
&
'tcx
hir
::
Path
<
'tcx
>
)
{
for
seg
in
&
path
.segments
[
..
path
.segments
.len
()
-
1
]
{
if
let
Some
(
data
)
=
self
.save_ctxt
.get_path_segment_data
(
seg
)
{
self
.dumper
.dump_ref
(
data
);
...
...
@@ -217,23 +217,19 @@ fn write_sub_paths_truncated(&mut self, path: &ast::Path) {
}
}
fn
process_formals
(
&
mut
self
,
formals
:
&
'
l
[
ast
::
Param
],
qualname
:
&
str
)
{
fn
process_formals
(
&
mut
self
,
formals
:
&
'
tcx
[
hir
::
Param
<
'tcx
>
],
qualname
:
&
str
)
{
for
arg
in
formals
{
self
.visit_pat
(
&
arg
.pat
);
let
mut
collector
=
PathCollector
::
new
();
let
mut
collector
=
PathCollector
::
new
(
self
.tcx
);
collector
.visit_pat
(
&
arg
.pat
);
for
(
id
,
ident
,
..
)
in
collector
.collected_idents
{
// FIXME(#71104) Should really be using just `node_id_to_hir_id` but
// some `NodeId` do not seem to have a corresponding HirId.
let
hir_id
=
self
.tcx
.hir
()
.opt_node_id_to_hir_id
(
id
);
let
typ
=
match
hir_id
.and_then
(|
hir_id
|
self
.save_ctxt.tables
.node_type_opt
(
hir_id
))
{
Some
(
s
)
=>
s
.to_string
(),
None
=>
continue
,
};
for
(
hir_id
,
ident
,
..
)
in
collector
.collected_idents
{
let
typ
=
match
self
.save_ctxt.tables
.node_type_opt
(
hir_id
)
{
Some
(
s
)
=>
s
.to_string
(),
None
=>
continue
,
};
if
!
self
.span
.filter_generated
(
ident
.span
)
{
let
id
=
id_from_
node_id
(
id
,
&
self
.save_ctxt
);
let
id
=
id_from_
hir_id
(
hir_
id
,
&
self
.save_ctxt
);
let
span
=
self
.span_from_span
(
ident
.span
);
self
.dumper
.dump_def
(
...
...
@@ -260,75 +256,74 @@ fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) {
fn
process_method
(
&
mut
self
,
sig
:
&
'
l
ast
::
FnSig
,
body
:
Option
<
&
'l
ast
::
Block
>
,
id
:
ast
::
Node
Id
,
sig
:
&
'
tcx
hir
::
FnSig
<
'tcx
>
,
body
:
Option
<
hir
::
BodyId
>
,
hir_id
:
hir
::
Hir
Id
,
ident
:
Ident
,
generics
:
&
'
l
ast
::
Generics
,
vis
:
ast
::
Visibility
,
generics
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
vis
:
&
hir
::
Visibility
<
'tcx
>
,
span
:
Span
,
)
{
debug!
(
"process_method: {}:{}"
,
id
,
ident
);
debug!
(
"process_method: {}:{}"
,
hir_
id
,
ident
);
let
map
=
&
self
.tcx
.hir
();
let
hir_id
=
map
.node_id_to_hir_id
(
id
);
self
.nest_tables
(
map
.local_def_id
(
hir_id
),
|
v
|
{
if
let
Some
(
mut
method_data
)
=
v
.save_ctxt
.get_method_data
(
id
,
ident
,
span
)
{
v
.process_formals
(
&
sig
.decl.inputs
,
&
method_data
.qualname
);
v
.process_generic_params
(
&
generics
,
&
method_data
.qualname
,
id
);
if
let
Some
(
mut
method_data
)
=
v
.save_ctxt
.get_method_data
(
hir_id
,
ident
,
span
)
{
if
let
Some
(
body
)
=
body
{
v
.process_formals
(
map
.body
(
body
)
.params
,
&
method_data
.qualname
);
}
v
.process_generic_params
(
&
generics
,
&
method_data
.qualname
,
hir_id
);
method_data
.value
=
crate
::
make_signature
(
&
sig
.decl
,
&
generics
);
method_data
.sig
=
sig
::
method_signature
(
id
,
ident
,
generics
,
sig
,
&
v
.save_ctxt
);
method_data
.sig
=
sig
::
method_signature
(
hir_
id
,
ident
,
generics
,
sig
,
&
v
.save_ctxt
);
v
.dumper
.dump_def
(
&
access_from_vis!
(
v
.save_ctxt
,
vis
,
hir_id
),
method_data
);
}
// walk arg and return types
for
arg
in
&
sig
.decl.inputs
{
v
.visit_ty
(
&
arg
.ty
);
for
arg
in
sig
.decl.inputs
{
v
.visit_ty
(
arg
);
}
if
let
ast
::
FnRetTy
::
Ty
(
ref
ret_ty
)
=
sig
.decl.output
{
// In async functions, return types are desugared and redefined
// as an `impl Trait` existential type. Because of this, to match
// the definition paths when resolving nested types we need to
// start walking from the newly-created definition.
match
sig
.header.asyncness
{
ast
::
Async
::
Yes
{
return_impl_trait_id
,
..
}
=>
{
let
hir_id
=
map
.node_id_to_hir_id
(
return_impl_trait_id
);
v
.nest_tables
(
map
.local_def_id
(
hir_id
),
|
v
|
v
.visit_ty
(
ret_ty
))
}
_
=>
v
.visit_ty
(
ret_ty
),
}
if
let
hir
::
FnRetTy
::
Return
(
ref
ret_ty
)
=
sig
.decl.output
{
v
.visit_ty
(
ret_ty
)
}
// walk the fn body
if
let
Some
(
body
)
=
body
{
v
.visit_
block
(
body
);
v
.visit_
expr
(
&
map
.body
(
body
)
.value
);
}
});
}
fn
process_struct_field_def
(
&
mut
self
,
field
:
&
ast
::
StructField
,
parent_id
:
NodeId
)
{
fn
process_struct_field_def
(
&
mut
self
,
field
:
&
'tcx
hir
::
StructField
<
'tcx
>
,
parent_id
:
hir
::
HirId
,
)
{
let
field_data
=
self
.save_ctxt
.get_field_data
(
field
,
parent_id
);
if
let
Some
(
field_data
)
=
field_data
{
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
field
.id
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
field
,
hir_id
),
field_data
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
field
,
field
.hir_id
),
field_data
);
}
}
// Dump generic params bindings, then visit_generics
fn
process_generic_params
(
&
mut
self
,
generics
:
&
'l
ast
::
Generics
,
prefix
:
&
str
,
id
:
NodeId
)
{
for
param
in
&
generics
.params
{
fn
process_generic_params
(
&
mut
self
,
generics
:
&
'tcx
hir
::
Generics
<
'tcx
>
,
prefix
:
&
str
,
id
:
hir
::
HirId
,
)
{
for
param
in
generics
.params
{
match
param
.kind
{
ast
::
GenericParamKind
::
Lifetime
{
..
}
=>
{}
ast
::
GenericParamKind
::
Type
{
..
}
=>
{
let
param_ss
=
param
.
ident
.span
;
hir
::
GenericParamKind
::
Lifetime
{
..
}
=>
{}
hir
::
GenericParamKind
::
Type
{
..
}
=>
{
let
param_ss
=
param
.
name
.ident
()
.span
;
let
name
=
escape
(
self
.span
.snippet
(
param_ss
));
// Append $id to name to make sure each one is unique.
let
qualname
=
format!
(
"{}::{}${}"
,
prefix
,
name
,
id
);
if
!
self
.span
.filter_generated
(
param_ss
)
{
let
id
=
id_from_
node_id
(
param
.
id
,
&
self
.save_ctxt
);
let
id
=
id_from_
hir_id
(
param
.hir_
id
,
&
self
.save_ctxt
);
let
span
=
self
.span_from_span
(
param_ss
);
self
.dumper
.dump_def
(
...
...
@@ -350,7 +345,7 @@ fn process_generic_params(&mut self, generics: &'l ast::Generics, prefix: &str,
);
}
}
ast
::
GenericParamKind
::
Const
{
..
}
=>
{}
hir
::
GenericParamKind
::
Const
{
..
}
=>
{}
}
}
self
.visit_generics
(
generics
);
...
...
@@ -358,90 +353,73 @@ fn process_generic_params(&mut self, generics: &'l ast::Generics, prefix: &str,
fn
process_fn
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
decl
:
&
'
l
ast
::
FnDecl
,
header
:
&
'l
ast
::
FnHeader
,
ty_params
:
&
'
l
ast
::
Generics
,
body
:
Option
<&
'l
ast
::
Block
>
,
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
decl
:
&
'
tcx
hir
::
FnDecl
<
'tcx
>
,
_
header
:
&
'tcx
hir
::
FnHeader
,
ty_params
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
body
:
hir
::
BodyId
,
)
{
let
map
=
&
self
.tcx
.hir
();
let
hir_id
=
map
.node_id_to_hir_id
(
item
.id
);
self
.nest_tables
(
map
.local_def_id
(
hir_id
),
|
v
|
{
self
.nest_tables
(
map
.local_def_id
(
item
.hir_id
),
|
v
|
{
let
body
=
map
.body
(
body
);
if
let
Some
(
fn_data
)
=
v
.save_ctxt
.get_item_data
(
item
)
{
down_cast_data!
(
fn_data
,
DefData
,
item
.span
);
v
.process_formals
(
&
decl
.input
s
,
&
fn_data
.qualname
);
v
.process_generic_params
(
ty_params
,
&
fn_data
.qualname
,
item
.id
);
v
.process_formals
(
body
.param
s
,
&
fn_data
.qualname
);
v
.process_generic_params
(
ty_params
,
&
fn_data
.qualname
,
item
.
hir_
id
);
v
.dumper
.dump_def
(
&
access_from!
(
v
.save_ctxt
,
item
,
hir_id
),
fn_data
);
v
.dumper
.dump_def
(
&
access_from!
(
v
.save_ctxt
,
item
,
item
.
hir_id
),
fn_data
);
}
for
arg
in
&
decl
.inputs
{
v
.visit_ty
(
&
arg
.ty
)
for
arg
in
decl
.inputs
{
v
.visit_ty
(
arg
)
}
if
let
ast
::
FnRetTy
::
Ty
(
ref
ret_ty
)
=
decl
.output
{
if
let
ast
::
TyKind
::
ImplTrait
(
..
)
=
ret_ty
.kind
{
// FIXME: Opaque type desugaring prevents us from easily
// processing trait bounds. See `visit_ty` for more details.
}
else
{
// In async functions, return types are desugared and redefined
// as an `impl Trait` existential type. Because of this, to match
// the definition paths when resolving nested types we need to
// start walking from the newly-created definition.
match
header
.asyncness
{
ast
::
Async
::
Yes
{
return_impl_trait_id
,
..
}
=>
{
let
hir_id
=
map
.node_id_to_hir_id
(
return_impl_trait_id
);
v
.nest_tables
(
map
.local_def_id
(
hir_id
),
|
v
|
v
.visit_ty
(
ret_ty
))
}
_
=>
v
.visit_ty
(
ret_ty
),
}
}
if
let
hir
::
FnRetTy
::
Return
(
ref
ret_ty
)
=
decl
.output
{
v
.visit_ty
(
ret_ty
)
}
walk_list!
(
v
,
visit_block
,
body
);
v
.visit_expr
(
&
body
.value
);
});
}
fn
process_static_or_const_item
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
typ
:
&
'
l
ast
::
Ty
,
expr
:
Option
<&
'l
ast
::
Expr
>
,
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
typ
:
&
'
tcx
hir
::
Ty
<
'tcx
>
,
expr
:
&
'tcx
hir
::
Expr
<
'tcx
>
,
)
{
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
item
.hir_id
),
|
v
|
{
if
let
Some
(
var_data
)
=
v
.save_ctxt
.get_item_data
(
item
)
{
down_cast_data!
(
var_data
,
DefData
,
item
.span
);
v
.dumper
.dump_def
(
&
access_from!
(
v
.save_ctxt
,
item
,
hir_id
),
var_data
);
v
.dumper
.dump_def
(
&
access_from!
(
v
.save_ctxt
,
item
,
item
.
hir_id
),
var_data
);
}
v
.visit_ty
(
&
typ
);
walk_list!
(
v
,
visit_expr
,
expr
);
v
.visit_expr
(
expr
);
});
}
fn
process_assoc_const
(
&
mut
self
,
id
:
ast
::
Node
Id
,
hir_id
:
hir
::
Hir
Id
,
ident
:
Ident
,
typ
:
&
'
l
ast
::
Ty
,
expr
:
Option
<&
'
l
ast
::
Expr
>
,
typ
:
&
'
tcx
hir
::
Ty
<
'tcx
>
,
expr
:
Option
<&
'
tcx
hir
::
Expr
<
'tcx
>
>
,
parent_id
:
DefId
,
vis
:
ast
::
Visibility
,
attrs
:
&
'
l
[
Attribute
],
vis
:
&
hir
::
Visibility
<
'tcx
>
,
attrs
:
&
'
tcx
[
ast
::
Attribute
],
)
{
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
id
);
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
)
.to_def_id
()));
if
!
self
.span
.filter_generated
(
ident
.span
)
{
let
sig
=
sig
::
assoc_const_signature
(
id
,
ident
.name
,
typ
,
expr
,
&
self
.save_ctxt
);
let
sig
=
sig
::
assoc_const_signature
(
hir_
id
,
ident
.name
,
typ
,
expr
,
&
self
.save_ctxt
);
let
span
=
self
.span_from_span
(
ident
.span
);
self
.dumper
.dump_def
(
&
access_from_vis!
(
self
.save_ctxt
,
vis
,
hir_id
),
Def
{
kind
:
DefKind
::
Const
,
id
:
id_from_
node_id
(
id
,
&
self
.save_ctxt
),
id
:
id_from_
hir_id
(
hir_
id
,
&
self
.save_ctxt
),
span
,
name
:
ident
.name
.to_string
(),
qualname
,
...
...
@@ -468,32 +446,32 @@ fn process_assoc_const(
// FIXME tuple structs should generate tuple-specific data.
fn
process_struct
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
def
:
&
'
l
ast
::
VariantData
,
ty_params
:
&
'
l
ast
::
Generics
,
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
def
:
&
'
tcx
hir
::
VariantData
<
'tcx
>
,
ty_params
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
)
{
debug!
(
"process_struct {:?} {:?}"
,
item
,
item
.span
);
let
name
=
item
.ident
.to_string
();
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
)
.to_def_id
()));
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
item
.hir_id
)
.to_def_id
())
);
let
kind
=
match
item
.kind
{
ast
::
ItemKind
::
Struct
(
_
,
_
)
=>
DefKind
::
Struct
,
ast
::
ItemKind
::
Union
(
_
,
_
)
=>
DefKind
::
Union
,
hir
::
ItemKind
::
Struct
(
_
,
_
)
=>
DefKind
::
Struct
,
hir
::
ItemKind
::
Union
(
_
,
_
)
=>
DefKind
::
Union
,
_
=>
unreachable!
(),
};
let
(
value
,
fields
)
=
match
item
.kind
{
ast
::
ItemKind
::
Struct
(
ast
::
VariantData
::
Struct
(
ref
fields
,
..
),
..
)
|
ast
::
ItemKind
::
Union
(
ast
::
VariantData
::
Struct
(
ref
fields
,
..
),
..
)
=>
{
hir
::
ItemKind
::
Struct
(
hir
::
VariantData
::
Struct
(
ref
fields
,
..
),
..
)
|
hir
::
ItemKind
::
Union
(
hir
::
VariantData
::
Struct
(
ref
fields
,
..
),
..
)
=>
{
let
include_priv_fields
=
!
self
.save_ctxt.config.pub_only
;
let
fields_str
=
fields
.iter
()
.enumerate
()
.filter_map
(|(
i
,
f
)|
{
.filter_map
(|
f
|
{
if
include_priv_fields
||
f
.vis.node
.is_pub
()
{
f
.ident
.map
(|
i
|
i
.to_string
())
.or_else
(||
Some
(
i
.to_string
()
))
Some
(
f
.ident
.to_string
(
))
}
else
{
None
}
...
...
@@ -501,7 +479,7 @@ fn process_struct(
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
);
let
value
=
format!
(
"{} {{ {} }}"
,
name
,
fields_str
);
(
value
,
fields
.iter
()
.map
(|
f
|
id_from_
node_id
(
f
.
id
,
&
self
.save_ctxt
))
.collect
())
(
value
,
fields
.iter
()
.map
(|
f
|
id_from_
hir_id
(
f
.hir_
id
,
&
self
.save_ctxt
))
.collect
())
}
_
=>
(
String
::
new
(),
vec!
[]),
};
...
...
@@ -509,10 +487,10 @@ fn process_struct(
if
!
self
.span
.filter_generated
(
item
.ident.span
)
{
let
span
=
self
.span_from_span
(
item
.ident.span
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
item
,
hir_id
),
&
access_from!
(
self
.save_ctxt
,
item
,
item
.
hir_id
),
Def
{
kind
,
id
:
id_from_
node_id
(
item
.
id
,
&
self
.save_ctxt
),
id
:
id_from_
hir_id
(
item
.hir_
id
,
&
self
.save_ctxt
),
span
,
name
,
qualname
:
qualname
.clone
(),
...
...
@@ -522,26 +500,26 @@ fn process_struct(
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
&
self
.save_ctxt
),
},
);
}
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
item
.
hir_id
),
|
v
|
{
for
field
in
def
.fields
()
{
v
.process_struct_field_def
(
field
,
item
.id
);
v
.process_struct_field_def
(
field
,
item
.
hir_
id
);
v
.visit_ty
(
&
field
.ty
);
}
v
.process_generic_params
(
ty_params
,
&
qualname
,
item
.id
);
v
.process_generic_params
(
ty_params
,
&
qualname
,
item
.
hir_
id
);
});
}
fn
process_enum
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
enum_definition
:
&
'
l
ast
::
EnumDef
,
ty_params
:
&
'
l
ast
::
Generics
,
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
enum_definition
:
&
'
tcx
hir
::
EnumDef
<
'tcx
>
,
ty_params
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
)
{
let
enum_data
=
self
.save_ctxt
.get_item_data
(
item
);
let
enum_data
=
match
enum_data
{
...
...
@@ -550,29 +528,22 @@ fn process_enum(
};
down_cast_data!
(
enum_data
,
DefData
,
item
.span
);
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
hir_id
);
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
item
.hir_id
);
for
variant
in
&
enum_definition
.variants
{
for
variant
in
enum_definition
.variants
{
let
name
=
variant
.ident.name
.to_string
();
let
qualname
=
format!
(
"{}::{}"
,
enum_data
.qualname
,
name
);
let
name_span
=
variant
.ident.span
;
match
variant
.data
{
ast
::
VariantData
::
Struct
(
ref
fields
,
..
)
=>
{
let
fields_str
=
fields
.iter
()
.enumerate
()
.map
(|(
i
,
f
)|
{
f
.ident
.map
(|
i
|
i
.to_string
())
.unwrap_or_else
(||
i
.to_string
())
})
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
);
hir
::
VariantData
::
Struct
(
ref
fields
,
..
)
=>
{
let
fields_str
=
fields
.iter
()
.map
(|
f
|
f
.ident
.to_string
())
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
);
let
value
=
format!
(
"{}::{} {{ {} }}"
,
enum_data
.name
,
name
,
fields_str
);
if
!
self
.span
.filter_generated
(
name_span
)
{
let
span
=
self
.span_from_span
(
name_span
);
let
id
=
id_from_
node
_id
(
variant
.id
,
&
self
.save_ctxt
);
let
parent
=
Some
(
id_from_
node_id
(
item
.
id
,
&
self
.save_ctxt
));
let
id
=
id_from_
hir
_id
(
variant
.id
,
&
self
.save_ctxt
);
let
parent
=
Some
(
id_from_
hir_id
(
item
.hir_
id
,
&
self
.save_ctxt
));
self
.dumper
.dump_def
(
&
access
,
...
...
@@ -589,7 +560,7 @@ fn process_enum(
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
variant
.attrs
),
sig
:
sig
::
variant_signature
(
variant
,
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
variant
.attrs
.
clone
(),
variant
.attrs
.
to_vec
(),
&
self
.save_ctxt
,
),
},
...
...
@@ -598,7 +569,7 @@ fn process_enum(
}
ref
v
=>
{
let
mut
value
=
format!
(
"{}::{}"
,
enum_data
.name
,
name
);
if
let
&
ast
::
VariantData
::
Tuple
(
ref
fields
,
_
)
=
v
{
if
let
&
hir
::
VariantData
::
Tuple
(
ref
fields
,
_
)
=
v
{
value
.push
(
'('
);
value
.push_str
(
&
fields
...
...
@@ -611,8 +582,8 @@ fn process_enum(
}
if
!
self
.span
.filter_generated
(
name_span
)
{
let
span
=
self
.span_from_span
(
name_span
);
let
id
=
id_from_
node
_id
(
variant
.id
,
&
self
.save_ctxt
);
let
parent
=
Some
(
id_from_
node_id
(
item
.
id
,
&
self
.save_ctxt
));
let
id
=
id_from_
hir
_id
(
variant
.id
,
&
self
.save_ctxt
);
let
parent
=
Some
(
id_from_
hir_id
(
item
.hir_
id
,
&
self
.save_ctxt
));
self
.dumper
.dump_def
(
&
access
,
...
...
@@ -629,7 +600,7 @@ fn process_enum(
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
variant
.attrs
),
sig
:
sig
::
variant_signature
(
variant
,
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
variant
.attrs
.
clone
(),
variant
.attrs
.
to_vec
(),
&
self
.save_ctxt
,
),
},
...
...
@@ -640,20 +611,20 @@ fn process_enum(
for
field
in
variant
.data
.fields
()
{
self
.process_struct_field_def
(
field
,
variant
.id
);
self
.visit_ty
(
&
field
.ty
);
self
.visit_ty
(
field
.ty
);
}
}
self
.process_generic_params
(
ty_params
,
&
enum_data
.qualname
,
item
.id
);
self
.process_generic_params
(
ty_params
,
&
enum_data
.qualname
,
item
.
hir_
id
);
self
.dumper
.dump_def
(
&
access
,
enum_data
);
}
fn
process_impl
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
generics
:
&
'
l
ast
::
Generics
,
trait_ref
:
&
'
l
Option
<
ast
::
TraitRef
>
,
typ
:
&
'
l
ast
::
Ty
,
impl_items
:
&
'
l
[
P
<
ast
::
AssocItem
>
],
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
generics
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
trait_ref
:
&
'
tcx
Option
<
hir
::
TraitRef
<
'tcx
>
>
,
typ
:
&
'
tcx
hir
::
Ty
<
'tcx
>
,
impl_items
:
&
'
tcx
[
hir
::
ImplItemRef
<
'tcx
>
],
)
{
if
let
Some
(
impl_data
)
=
self
.save_ctxt
.get_item_data
(
item
)
{
if
!
self
.span
.filter_generated
(
item
.span
)
{
...
...
@@ -667,46 +638,48 @@ fn process_impl(
}
let
map
=
&
self
.tcx
.hir
();
let
hir_id
=
map
.node_id_to_hir_id
(
item
.id
);
self
.nest_tables
(
map
.local_def_id
(
hir_id
),
|
v
|
{
self
.nest_tables
(
map
.local_def_id
(
item
.hir_id
),
|
v
|
{
v
.visit_ty
(
&
typ
);
if
let
&
Some
(
ref
trait_ref
)
=
trait_ref
{
v
.process_path
(
trait_ref
.ref_id
,
&
trait_ref
.path
);
v
.process_path
(
trait_ref
.
hir_
ref_id
,
&
trait_ref
.path
);
}
v
.process_generic_params
(
generics
,
""
,
item
.id
);
v
.process_generic_params
(
generics
,
""
,
item
.
hir_
id
);
for
impl_item
in
impl_items
{
v
.process_impl_item
(
impl_item
,
map
.local_def_id
(
hir_id
)
.to_def_id
());
v
.process_impl_item
(
map
.impl_item
(
impl_item
.id
),
map
.local_def_id
(
item
.hir_id
)
.to_def_id
(),
);
}
});
}
fn
process_trait
(
&
mut
self
,
item
:
&
'
l
ast
::
Item
,
generics
:
&
'
l
ast
::
Generics
,
trait_refs
:
&
'l
ast
::
GenericBounds
,
methods
:
&
'
l
[
P
<
ast
::
AssocItem
>
],
item
:
&
'
tcx
hir
::
Item
<
'tcx
>
,
generics
:
&
'
tcx
hir
::
Generics
<
'tcx
>
,
trait_refs
:
hir
::
GenericBounds
<
'tcx
>
,
methods
:
&
'
tcx
[
hir
::
TraitItemRef
],
)
{
let
name
=
item
.ident
.to_string
();
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
_from_node_id
(
item
.
id
)
.to_def_id
())
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
item
.hir_
id
)
.to_def_id
())
);
let
mut
val
=
name
.clone
();
if
!
generics
.params
.is_empty
()
{
val
.push_str
(
&
generic_params_to_string
(
&
generics
.params
));
val
.push_str
(
&
generic_params_to_string
(
generics
.params
));
}
if
!
trait_refs
.is_empty
()
{
val
.push_str
(
": "
);
val
.push_str
(
&
bounds_to_string
(
trait_refs
));
}
if
!
self
.span
.filter_generated
(
item
.ident.span
)
{
let
id
=
id_from_
node_id
(
item
.
id
,
&
self
.save_ctxt
);
let
id
=
id_from_
hir_id
(
item
.hir_
id
,
&
self
.save_ctxt
);
let
span
=
self
.span_from_span
(
item
.ident.span
);
let
children
=
methods
.iter
()
.map
(|
i
|
id_from_node_id
(
i
.id
,
&
self
.save_ctxt
))
.collect
();
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
let
children
=
methods
.iter
()
.map
(|
i
|
id_from_hir_id
(
i
.id.hir_id
,
&
self
.save_ctxt
))
.collect
(
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
item
,
hir_id
),
&
access_from!
(
self
.save_ctxt
,
item
,
item
.
hir_id
),
Def
{
kind
:
DefKind
::
Trait
,
id
,
...
...
@@ -719,7 +692,7 @@ fn process_trait(
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
&
self
.save_ctxt
),
},
);
}
...
...
@@ -727,12 +700,12 @@ fn process_trait(
// super-traits
for
super_bound
in
trait_refs
.iter
()
{
let
trait_ref
=
match
*
super_bound
{
ast
::
GenericBound
::
Trait
(
ref
trait_ref
,
_
)
=>
trait_ref
,
ast
::
GenericBound
::
Outlives
(
..
)
=>
continue
,
hir
::
GenericBound
::
Trait
(
ref
trait_ref
,
_
)
=>
trait_ref
,
hir
::
GenericBound
::
Outlives
(
..
)
=>
continue
,
};
let
trait_ref
=
&
trait_ref
.trait_ref
;
if
let
Some
(
id
)
=
self
.lookup_def_id
(
trait_ref
.ref_id
)
{
if
let
Some
(
id
)
=
self
.lookup_def_id
(
trait_ref
.
hir_
ref_id
)
{
let
sub_span
=
trait_ref
.path.segments
.last
()
.unwrap
()
.ident.span
;
if
!
self
.span
.filter_generated
(
sub_span
)
{
let
span
=
self
.span_from_span
(
sub_span
);
...
...
@@ -746,60 +719,57 @@ fn process_trait(
kind
:
RelationKind
::
SuperTrait
,
span
,
from
:
id_from_def_id
(
id
),
to
:
id_from_
node_id
(
item
.
id
,
&
self
.save_ctxt
),
to
:
id_from_
hir_id
(
item
.hir_
id
,
&
self
.save_ctxt
),
});
}
}
}
// walk generics and methods
self
.process_generic_params
(
generics
,
&
qualname
,
item
.id
);
self
.process_generic_params
(
generics
,
&
qualname
,
item
.
hir_
id
);
for
method
in
methods
{
let
map
=
&
self
.tcx
.hir
();
self
.process_trait_item
(
method
,
map
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
())
self
.process_trait_item
(
map
.trait_item
(
method
.id
),
map
.local_def_id
(
item
.hir_id
)
.to_def_id
(),
)
}
}
// `item` is the module in question, represented as an item.
fn
process_mod
(
&
mut
self
,
item
:
&
ast
::
Item
)
{
// `item` is the module in question, represented as an
(
item.
fn
process_mod
(
&
mut
self
,
item
:
&
'tcx
hir
::
Item
<
'tcx
>
)
{
if
let
Some
(
mod_data
)
=
self
.save_ctxt
.get_item_data
(
item
)
{
down_cast_data!
(
mod_data
,
DefData
,
item
.span
);
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
item
,
hir_id
),
mod_data
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
item
,
item
.hir_id
),
mod_data
);
}
}
fn
dump_path_ref
(
&
mut
self
,
id
:
NodeId
,
path
:
&
ast
::
Path
)
{
fn
dump_path_ref
(
&
mut
self
,
id
:
hir
::
HirId
,
path
:
&
hir
::
Path
<
'tcx
>
)
{
let
path_data
=
self
.save_ctxt
.get_path_data
(
id
,
path
);
if
let
Some
(
path_data
)
=
path_data
{
self
.dumper
.dump_ref
(
path_data
);
}
}
fn
process_path
(
&
mut
self
,
id
:
NodeId
,
path
:
&
'l
ast
::
Path
)
{
fn
dump_path_segment_ref
(
&
mut
self
,
id
:
hir
::
HirId
,
segment
:
&
hir
::
PathSegment
<
'tcx
>
)
{
let
segment_data
=
self
.save_ctxt
.get_path_segment_data_with_id
(
segment
,
id
);
if
let
Some
(
segment_data
)
=
segment_data
{
self
.dumper
.dump_ref
(
segment_data
);
}
}
fn
process_path
(
&
mut
self
,
id
:
hir
::
HirId
,
path
:
&
'tcx
hir
::
Path
<
'tcx
>
)
{
if
self
.span
.filter_generated
(
path
.span
)
{
return
;
}
self
.dump_path_ref
(
id
,
path
);
// Type arguments
for
seg
in
&
path
.segments
{
for
seg
in
path
.segments
{
if
let
Some
(
ref
generic_args
)
=
seg
.args
{
match
**
generic_args
{
ast
::
GenericArgs
::
AngleBracketed
(
ref
data
)
=>
{
for
arg
in
&
data
.args
{
if
let
ast
::
AngleBracketedArg
::
Arg
(
ast
::
GenericArg
::
Type
(
ty
))
=
arg
{
self
.visit_ty
(
ty
);
}
}
}
ast
::
GenericArgs
::
Parenthesized
(
ref
data
)
=>
{
for
t
in
&
data
.inputs
{
self
.visit_ty
(
t
);
}
if
let
ast
::
FnRetTy
::
Ty
(
ty
)
=
&
data
.output
{
self
.visit_ty
(
ty
);
}
for
arg
in
generic_args
.args
{
if
let
hir
::
GenericArg
::
Type
(
ref
ty
)
=
arg
{
self
.visit_ty
(
ty
);
}
}
}
...
...
@@ -810,14 +780,16 @@ fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
fn
process_struct_lit
(
&
mut
self
,
ex
:
&
'
l
ast
::
Expr
,
path
:
&
'
l
ast
::
Path
,
fields
:
&
'
l
[
ast
::
Field
],
variant
:
&
'
l
ty
::
VariantDef
,
base
:
&
'l
Option
<
P
<
ast
::
Expr
>>
,
ex
:
&
'
tcx
hir
::
Expr
<
'tcx
>
,
path
:
&
'
tcx
hir
::
QPath
<
'tcx
>
,
fields
:
&
'
tcx
[
hir
::
Field
<
'tcx
>
],
variant
:
&
'
tcx
ty
::
VariantDef
,
base
:
Option
<&
'tcx
hir
::
Expr
<
'tcx
>>
,
)
{
if
let
Some
(
struct_lit_data
)
=
self
.save_ctxt
.get_expr_data
(
ex
)
{
self
.write_sub_paths_truncated
(
path
);
if
let
hir
::
QPath
::
Resolved
(
_
,
path
)
=
path
{
self
.write_sub_paths_truncated
(
path
);
}
down_cast_data!
(
struct_lit_data
,
RefData
,
ex
.span
);
if
!
generated_code
(
ex
.span
)
{
self
.dumper
.dump_ref
(
struct_lit_data
);
...
...
@@ -837,9 +809,9 @@ fn process_struct_lit(
fn
process_method_call
(
&
mut
self
,
ex
:
&
'
l
ast
::
Expr
,
seg
:
&
'
l
ast
::
PathSegment
,
args
:
&
'
l
[
P
<
ast
::
Expr
>
],
ex
:
&
'
tcx
hir
::
Expr
<
'tcx
>
,
seg
:
&
'
tcx
hir
::
PathSegment
<
'tcx
>
,
args
:
&
'
tcx
[
hir
::
Expr
<
'tcx
>
],
)
{
debug!
(
"process_method_call {:?} {:?}"
,
ex
,
ex
.span
);
if
let
Some
(
mcd
)
=
self
.save_ctxt
.get_expr_data
(
ex
)
{
...
...
@@ -850,13 +822,11 @@ fn process_method_call(
}
// Explicit types in the turbo-fish.
if
let
Some
(
ref
generic_args
)
=
seg
.args
{
if
let
ast
::
GenericArgs
::
AngleBracketed
(
ref
data
)
=
**
generic_args
{
for
arg
in
&
data
.args
{
if
let
ast
::
AngleBracketedArg
::
Arg
(
ast
::
GenericArg
::
Type
(
ty
))
=
arg
{
self
.visit_ty
(
ty
)
};
}
if
let
Some
(
generic_args
)
=
seg
.args
{
for
arg
in
generic_args
.args
{
if
let
hir
::
GenericArg
::
Type
(
ty
)
=
arg
{
self
.visit_ty
(
&
ty
)
};
}
}
...
...
@@ -864,19 +834,18 @@ fn process_method_call(
walk_list!
(
self
,
visit_expr
,
args
);
}
fn
process_pat
(
&
mut
self
,
p
:
&
'
l
ast
::
Pat
)
{
fn
process_pat
(
&
mut
self
,
p
:
&
'
tcx
hir
::
Pat
<
'tcx
>
)
{
match
p
.kind
{
PatKind
::
Struct
(
ref
_
path
,
ref
fields
,
_
)
=>
{
hir
::
PatKind
::
Struct
(
ref
_
path
,
fields
,
_
)
=>
{
// FIXME do something with _path?
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
p
.id
);
let
adt
=
match
self
.save_ctxt.tables
.node_type_opt
(
hir_id
)
{
let
adt
=
match
self
.save_ctxt.tables
.node_type_opt
(
p
.hir_id
)
{
Some
(
ty
)
if
ty
.ty_adt_def
()
.is_some
()
=>
ty
.ty_adt_def
()
.unwrap
(),
_
=>
{
visit
::
walk_pat
(
self
,
p
);
intra
visit
::
walk_pat
(
self
,
p
);
return
;
}
};
let
variant
=
adt
.variant_of_res
(
self
.save_ctxt
.get_path_res
(
p
.id
));
let
variant
=
adt
.variant_of_res
(
self
.save_ctxt
.get_path_res
(
p
.
hir_
id
));
for
field
in
fields
{
if
let
Some
(
index
)
=
self
.tcx
.find_field_index
(
field
.ident
,
variant
)
{
...
...
@@ -892,22 +861,22 @@ fn process_pat(&mut self, p: &'l ast::Pat) {
self
.visit_pat
(
&
field
.pat
);
}
}
_
=>
visit
::
walk_pat
(
self
,
p
),
_
=>
intra
visit
::
walk_pat
(
self
,
p
),
}
}
fn
process_var_decl
(
&
mut
self
,
pat
:
&
'
l
ast
::
Pat
)
{
fn
process_var_decl
(
&
mut
self
,
pat
:
&
'
tcx
hir
::
Pat
<
'tcx
>
)
{
// The pattern could declare multiple new vars,
// we must walk the pattern and collect them all.
let
mut
collector
=
PathCollector
::
new
();
let
mut
collector
=
PathCollector
::
new
(
self
.tcx
);
collector
.visit_pat
(
&
pat
);
self
.visit_pat
(
&
pat
);
// Process collected paths.
for
(
id
,
ident
,
_
)
in
collector
.collected_idents
{
match
self
.save_ctxt
.get_path_res
(
id
)
{
let
res
=
self
.save_ctxt
.get_path_res
(
id
);
match
res
{
Res
::
Local
(
hir_id
)
=>
{
let
id
=
self
.tcx
.hir
()
.hir_id_to_node_id
(
hir_id
);
let
typ
=
self
.save_ctxt
.tables
...
...
@@ -917,8 +886,8 @@ fn process_var_decl(&mut self, pat: &'l ast::Pat) {
// Rust uses the id of the pattern for var lookups, so we'll use it too.
if
!
self
.span
.filter_generated
(
ident
.span
)
{
let
qualname
=
format!
(
"{}${}"
,
ident
.to_string
(),
id
);
let
id
=
id_from_
node_id
(
id
,
&
self
.save_ctxt
);
let
qualname
=
format!
(
"{}${}"
,
ident
.to_string
(),
hir_
id
);
let
id
=
id_from_
hir_id
(
hir_
id
,
&
self
.save_ctxt
);
let
span
=
self
.span_from_span
(
ident
.span
);
self
.dumper
.dump_def
(
...
...
@@ -951,7 +920,7 @@ fn process_var_decl(&mut self, pat: &'l ast::Pat) {
_
,
)
|
Res
::
SelfTy
(
..
)
=>
{
self
.dump_path_
ref
(
id
,
&
ast
::
Path
::
from_ident
(
ident
));
self
.dump_path_
segment_ref
(
id
,
&
hir
::
PathSegment
::
from_ident
(
ident
));
}
def
=>
{
error!
(
"unexpected definition kind when processing collected idents: {:?}"
,
def
)
...
...
@@ -960,7 +929,9 @@ fn process_var_decl(&mut self, pat: &'l ast::Pat) {
}
for
(
id
,
ref
path
)
in
collector
.collected_paths
{
self
.process_path
(
id
,
path
);
if
let
hir
::
QPath
::
Resolved
(
_
,
path
)
=
path
{
self
.process_path
(
id
,
path
);
}
}
}
...
...
@@ -1007,45 +978,49 @@ fn process_macro_use(&mut self, _span: Span) {
// }
}
fn
process_trait_item
(
&
mut
self
,
trait_item
:
&
'
l
ast
::
AssocItem
,
trait_id
:
DefId
)
{
fn
process_trait_item
(
&
mut
self
,
trait_item
:
&
'
tcx
hir
::
TraitItem
<
'tcx
>
,
trait_id
:
DefId
)
{
self
.process_macro_use
(
trait_item
.span
);
let
vis_span
=
trait_item
.span
.shrink_to_lo
();
match
trait_item
.kind
{
ast
::
AssocItemKind
::
Const
(
_
,
ref
ty
,
ref
expr
)
=>
{
hir
::
TraitItemKind
::
Const
(
ref
ty
,
body
)
=>
{
let
body
=
body
.map
(|
b
|
&
self
.tcx
.hir
()
.body
(
b
)
.value
);
let
respan
=
respan
(
vis_span
,
hir
::
VisibilityKind
::
Public
);
self
.process_assoc_const
(
trait_item
.id
,
trait_item
.
hir_
id
,
trait_item
.ident
,
&
ty
,
expr
.as_ref
()
.map
(|
e
|
&**
e
)
,
body
,
trait_id
,
respan
(
vis_span
,
ast
::
VisibilityKind
::
Public
)
,
&
respan
,
&
trait_item
.attrs
,
);
}
ast
::
AssocItemKind
::
Fn
(
_
,
ref
sig
,
ref
generics
,
ref
body
)
=>
{
hir
::
TraitItemKind
::
Fn
(
ref
sig
,
ref
trait_fn
)
=>
{
let
body
=
if
let
hir
::
TraitFn
::
Provided
(
body
)
=
trait_fn
{
Some
(
*
body
)
}
else
{
None
};
let
respan
=
respan
(
vis_span
,
hir
::
VisibilityKind
::
Public
);
self
.process_method
(
sig
,
body
.as_ref
()
.map
(|
x
|
&**
x
)
,
trait_item
.id
,
body
,
trait_item
.
hir_
id
,
trait_item
.ident
,
generics
,
respan
(
vis_span
,
ast
::
VisibilityKind
::
Public
)
,
&
trait_item
.
generics
,
&
respan
,
trait_item
.span
,
);
}
ast
::
AssocItemKind
::
TyAlias
(
_
,
_
,
ref
bounds
,
ref
default_ty
)
=>
{
hir
::
TraitItemKind
::
Type
(
ref
bounds
,
ref
default_ty
)
=>
{
// FIXME do something with _bounds (for type refs)
let
name
=
trait_item
.ident.name
.to_string
();
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
trait_item
.id
)
.to_def_id
()
)
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
trait_item
.hir_id
)
.to_def_id
())
);
if
!
self
.span
.filter_generated
(
trait_item
.ident.span
)
{
let
span
=
self
.span_from_span
(
trait_item
.ident.span
);
let
id
=
id_from_
node_id
(
trait_item
.
id
,
&
self
.save_ctxt
);
let
id
=
id_from_
hir_id
(
trait_item
.hir_
id
,
&
self
.save_ctxt
);
self
.dumper
.dump_def
(
&
Access
{
public
:
true
,
reachable
:
true
},
...
...
@@ -1061,13 +1036,16 @@ fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
trait_item
.attrs
),
sig
:
sig
::
assoc_type_signature
(
trait_item
.id
,
trait_item
.
hir_
id
,
trait_item
.ident
,
Some
(
bounds
),
default_ty
.as_ref
()
.map
(|
ty
|
&**
ty
),
&
self
.save_ctxt
,
),
attributes
:
lower_attributes
(
trait_item
.attrs
.clone
(),
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
trait_item
.attrs
.to_vec
(),
&
self
.save_ctxt
,
),
},
);
}
...
...
@@ -1076,98 +1054,122 @@ fn process_trait_item(&mut self, trait_item: &'l ast::AssocItem, trait_id: DefId
self
.visit_ty
(
default_ty
)
}
}
ast
::
AssocItemKind
::
MacCall
(
_
)
=>
{}
}
}
fn
process_impl_item
(
&
mut
self
,
impl_item
:
&
'
l
ast
::
AssocItem
,
impl_id
:
DefId
)
{
fn
process_impl_item
(
&
mut
self
,
impl_item
:
&
'
tcx
hir
::
ImplItem
<
'tcx
>
,
impl_id
:
DefId
)
{
self
.process_macro_use
(
impl_item
.span
);
match
impl_item
.kind
{
ast
::
AssocItemKind
::
Const
(
_
,
ref
ty
,
ref
expr
)
=>
{
hir
::
ImplItemKind
::
Const
(
ref
ty
,
body
)
=>
{
let
body
=
self
.tcx
.hir
()
.body
(
body
);
self
.process_assoc_const
(
impl_item
.id
,
impl_item
.
hir_
id
,
impl_item
.ident
,
&
ty
,
expr
.as_deref
(
),
Some
(
&
body
.value
),
impl_id
,
impl_item
.vis
.clone
()
,
&
impl_item
.vis
,
&
impl_item
.attrs
,
);
}
ast
::
AssocItemKind
::
Fn
(
_
,
ref
sig
,
ref
generics
,
ref
body
)
=>
{
hir
::
ImplItemKind
::
Fn
(
ref
sig
,
body
)
=>
{
self
.process_method
(
sig
,
body
.as_deref
(
),
impl_item
.id
,
Some
(
body
),
impl_item
.
hir_
id
,
impl_item
.ident
,
generics
,
impl_item
.vis
.clone
()
,
&
impl_item
.
generics
,
&
impl_item
.vis
,
impl_item
.span
,
);
}
ast
::
AssocItemKind
::
TyAlias
(
_
,
_
,
_
,
None
)
=>
{}
ast
::
AssocItemKind
::
TyAlias
(
_
,
_
,
_
,
Some
(
ref
ty
)
)
=>
{
hir
::
ImplItemKind
::
OpaqueTy
(
..
)
=>
{}
hir
::
ImplItemKind
::
TyAlias
(
ref
ty
)
=>
{
// FIXME: uses of the assoc type should ideally point to this
// 'def' and the name here should be a ref to the def in the
// trait.
self
.visit_ty
(
ty
)
}
ast
::
AssocItemKind
::
MacCall
(
_
)
=>
{}
}
}
/// Dumps imports in a use tree recursively.
///
/// A use tree is an import that may contain nested braces (RFC 2128). The `use_tree` parameter
/// is the current use tree under scrutiny, while `id` and `prefix` are its corresponding node
/// ID and path. `root_item` is the topmost use tree in the hierarchy.
///
/// If `use_tree` is a simple or glob import, it is dumped into the analysis data. Otherwise,
/// each child use tree is dumped recursively.
fn
process_use_tree
(
&
mut
self
,
use_tree
:
&
'l
ast
::
UseTree
,
id
:
NodeId
,
root_item
:
&
'l
ast
::
Item
,
prefix
:
&
ast
::
Path
,
)
{
let
path
=
&
use_tree
.prefix
;
// The access is calculated using the current tree ID, but with the root tree's visibility
// (since nested trees don't have their own visibility).
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
id
);
let
access
=
access_from!
(
self
.save_ctxt
,
root_item
,
hir_id
);
// The parent `DefId` of a given use tree is always the enclosing item.
let
parent
=
self
.save_ctxt
.tcx
.hir
()
.opt_local_def_id_from_node_id
(
id
)
.and_then
(|
id
|
self
.save_ctxt.tcx
.parent
(
id
.to_def_id
()))
.map
(
id_from_def_id
);
match
use_tree
.kind
{
ast
::
UseTreeKind
::
Simple
(
alias
,
..
)
=>
{
let
ident
=
use_tree
.ident
();
let
path
=
ast
::
Path
{
segments
:
prefix
.segments
.iter
()
.chain
(
path
.segments
.iter
())
.cloned
()
.collect
(),
span
:
path
.span
,
};
pub
(
crate
)
fn
process_crate
(
&
mut
self
,
krate
:
&
'tcx
hir
::
Crate
<
'tcx
>
)
{
let
id
=
hir
::
CRATE_HIR_ID
;
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
id
)
.to_def_id
()));
let
sm
=
self
.tcx.sess
.source_map
();
let
filename
=
sm
.span_to_filename
(
krate
.item.span
);
let
data_id
=
id_from_hir_id
(
id
,
&
self
.save_ctxt
);
let
children
=
krate
.item
.module
.item_ids
.iter
()
.map
(|
i
|
id_from_hir_id
(
i
.id
,
&
self
.save_ctxt
))
.collect
();
let
span
=
self
.span_from_span
(
krate
.item.span
);
self
.dumper
.dump_def
(
&
Access
{
public
:
true
,
reachable
:
true
},
Def
{
kind
:
DefKind
::
Mod
,
id
:
data_id
,
name
:
String
::
new
(),
qualname
,
span
,
value
:
filename
.to_string
(),
children
,
parent
:
None
,
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
krate
.item.attrs
),
sig
:
None
,
attributes
:
lower_attributes
(
krate
.item.attrs
.to_owned
(),
&
self
.save_ctxt
),
},
);
intravisit
::
walk_crate
(
self
,
krate
);
}
fn
process_bounds
(
&
mut
self
,
bounds
:
hir
::
GenericBounds
<
'tcx
>
)
{
for
bound
in
bounds
{
if
let
hir
::
GenericBound
::
Trait
(
ref
trait_ref
,
_
)
=
*
bound
{
self
.process_path
(
trait_ref
.trait_ref.hir_ref_id
,
&
trait_ref
.trait_ref.path
)
}
}
}
}
impl
<
'l
,
'tcx
>
Visitor
<
'tcx
>
for
DumpVisitor
<
'l
,
'tcx
>
{
type
Map
=
Map
<
'tcx
>
;
fn
nested_visit_map
(
&
mut
self
)
->
intravisit
::
NestedVisitorMap
<
Self
::
Map
>
{
intravisit
::
NestedVisitorMap
::
All
(
self
.tcx
.hir
())
}
fn
visit_item
(
&
mut
self
,
item
:
&
'tcx
hir
::
Item
<
'tcx
>
)
{
self
.process_macro_use
(
item
.span
);
match
item
.kind
{
hir
::
ItemKind
::
Use
(
path
,
hir
::
UseKind
::
Single
)
=>
{
let
sub_span
=
path
.segments
.last
()
.unwrap
()
.ident.span
;
if
!
self
.span
.filter_generated
(
sub_span
)
{
let
ref_id
=
self
.lookup_def_id
(
id
)
.map
(
id_from_def
_id
);
let
alias_span
=
alias
.map
(|
i
|
self
.span_from_span
(
i
.span
)
);
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
item
.hir
_id
);
let
ref_id
=
self
.lookup_def_id
(
item
.hir_id
)
.map
(
id_from_def_id
);
let
span
=
self
.span_from_span
(
sub_span
);
let
parent
=
self
.save_ctxt
.tcx
.hir
()
.opt_local_def_id
(
item
.hir_id
)
.and_then
(|
id
|
self
.save_ctxt.tcx
.parent
(
id
.to_def_id
()))
.map
(
id_from_def_id
);
self
.dumper
.import
(
&
access
,
Import
{
kind
:
ImportKind
::
Use
,
ref_id
,
span
,
alias_span
,
name
:
ident
.to_string
(),
alias_span
:
None
,
name
:
i
tem
.i
dent
.to_string
(),
value
:
String
::
new
(),
parent
,
},
...
...
@@ -1175,25 +1177,27 @@ fn process_use_tree(
self
.write_sub_paths_truncated
(
&
path
);
}
}
ast
::
UseTreeKind
::
Glob
=>
{
let
path
=
ast
::
Path
{
segments
:
prefix
.segments
.iter
()
.chain
(
path
.segments
.iter
())
.cloned
()
.collect
(),
span
:
path
.span
,
};
hir
::
ItemKind
::
Use
(
path
,
hir
::
UseKind
::
Glob
)
=>
{
// Make a comma-separated list of names of imported modules.
let
def_id
=
self
.tcx
.hir
()
.local_def_id
_from_node_id
(
id
);
let
def_id
=
self
.tcx
.hir
()
.local_def_id
(
item
.hir_
id
);
let
names
=
self
.tcx
.names_imported_by_glob_use
(
def_id
);
let
names
:
Vec
<
_
>
=
names
.iter
()
.map
(|
n
|
n
.to_string
())
.collect
();
// Otherwise it's a span with wrong macro expansion info, which
// we don't want to track anyway, since it's probably macro-internal `use`
if
let
Some
(
sub_span
)
=
self
.span
.sub_span_of_token
(
use_tree
.span
,
token
::
BinOp
(
token
::
Star
))
self
.span
.sub_span_of_token
(
item
.span
,
token
::
BinOp
(
token
::
Star
))
{
if
!
self
.span
.filter_generated
(
use_tree
.span
)
{
if
!
self
.span
.filter_generated
(
item
.span
)
{
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
item
.hir_id
);
let
span
=
self
.span_from_span
(
sub_span
);
let
parent
=
self
.save_ctxt
.tcx
.hir
()
.opt_local_def_id
(
item
.hir_id
)
.and_then
(|
id
|
self
.save_ctxt.tcx
.parent
(
id
.to_def_id
()))
.map
(
id_from_def_id
);
self
.dumper
.import
(
&
access
,
Import
{
...
...
@@ -1210,73 +1214,7 @@ fn process_use_tree(
}
}
}
ast
::
UseTreeKind
::
Nested
(
ref
nested_items
)
=>
{
let
prefix
=
ast
::
Path
{
segments
:
prefix
.segments
.iter
()
.chain
(
path
.segments
.iter
())
.cloned
()
.collect
(),
span
:
path
.span
,
};
for
&
(
ref
tree
,
id
)
in
nested_items
{
self
.process_use_tree
(
tree
,
id
,
root_item
,
&
prefix
);
}
}
}
}
fn
process_bounds
(
&
mut
self
,
bounds
:
&
'l
ast
::
GenericBounds
)
{
for
bound
in
bounds
{
if
let
ast
::
GenericBound
::
Trait
(
ref
trait_ref
,
_
)
=
*
bound
{
self
.process_path
(
trait_ref
.trait_ref.ref_id
,
&
trait_ref
.trait_ref.path
)
}
}
}
}
impl
<
'l
,
'tcx
>
Visitor
<
'l
>
for
DumpVisitor
<
'l
,
'tcx
>
{
fn
visit_mod
(
&
mut
self
,
m
:
&
'l
ast
::
Mod
,
span
:
Span
,
attrs
:
&
[
ast
::
Attribute
],
id
:
NodeId
)
{
// Since we handle explicit modules ourselves in visit_item, this should
// only get called for the root module of a crate.
assert_eq!
(
id
,
ast
::
CRATE_NODE_ID
);
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
id
)
.to_def_id
())
);
let
sm
=
self
.tcx.sess
.source_map
();
let
filename
=
sm
.span_to_filename
(
span
);
let
data_id
=
id_from_node_id
(
id
,
&
self
.save_ctxt
);
let
children
=
m
.items
.iter
()
.map
(|
i
|
id_from_node_id
(
i
.id
,
&
self
.save_ctxt
))
.collect
();
let
span
=
self
.span_from_span
(
span
);
self
.dumper
.dump_def
(
&
Access
{
public
:
true
,
reachable
:
true
},
Def
{
kind
:
DefKind
::
Mod
,
id
:
data_id
,
name
:
String
::
new
(),
qualname
,
span
,
value
:
filename
.to_string
(),
children
,
parent
:
None
,
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
attrs
),
sig
:
None
,
attributes
:
lower_attributes
(
attrs
.to_owned
(),
&
self
.save_ctxt
),
},
);
visit
::
walk_mod
(
self
,
m
);
}
fn
visit_item
(
&
mut
self
,
item
:
&
'l
ast
::
Item
)
{
use
rustc_ast
::
ast
::
ItemKind
::
*
;
self
.process_macro_use
(
item
.span
);
match
item
.kind
{
Use
(
ref
use_tree
)
=>
{
let
prefix
=
ast
::
Path
{
segments
:
vec!
[],
span
:
DUMMY_SP
};
self
.process_use_tree
(
use_tree
,
item
.id
,
item
,
&
prefix
);
}
ExternCrate
(
_
)
=>
{
hir
::
ItemKind
::
ExternCrate
(
_
)
=>
{
let
name_span
=
item
.ident.span
;
if
!
self
.span
.filter_generated
(
name_span
)
{
let
span
=
self
.span_from_span
(
name_span
);
...
...
@@ -1284,7 +1222,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
.save_ctxt
.tcx
.hir
()
.opt_local_def_id
_from_node_id
(
item
.
id
)
.opt_local_def_id
(
item
.hir_
id
)
.and_then
(|
id
|
self
.save_ctxt.tcx
.parent
(
id
.to_def_id
()))
.map
(
id_from_def_id
);
self
.dumper
.import
(
...
...
@@ -1301,43 +1239,44 @@ fn visit_item(&mut self, item: &'l ast::Item) {
);
}
}
Fn
(
_
,
ref
sig
,
ref
ty_params
,
ref
body
)
=>
{
self
.process_fn
(
item
,
&
sig
.decl
,
&
sig
.header
,
ty_params
,
body
.as_deref
())
hir
::
ItemKind
::
Fn
(
ref
sig
,
ref
ty_params
,
body
)
=>
{
self
.process_fn
(
item
,
sig
.decl
,
&
sig
.header
,
ty_params
,
body
)
}
hir
::
ItemKind
::
Static
(
ref
typ
,
_
,
body
)
=>
{
let
body
=
self
.tcx
.hir
()
.body
(
body
);
self
.process_static_or_const_item
(
item
,
typ
,
&
body
.value
)
}
hir
::
ItemKind
::
Const
(
ref
typ
,
body
)
=>
{
let
body
=
self
.tcx
.hir
()
.body
(
body
);
self
.process_static_or_const_item
(
item
,
typ
,
&
body
.value
)
}
Static
(
ref
typ
,
_
,
ref
e
)
=>
self
.process_static_or_const_item
(
item
,
typ
,
e
.as_deref
()),
Const
(
_
,
ref
typ
,
ref
e
)
=>
self
.process_static_or_const_item
(
item
,
typ
,
e
.as_deref
()),
Struct
(
ref
def
,
ref
ty_params
)
|
Union
(
ref
def
,
ref
ty_params
)
=>
{
hir
::
ItemKind
::
Struct
(
ref
def
,
ref
ty_params
)
|
hir
::
ItemKind
::
Union
(
ref
def
,
ref
ty_params
)
=>
{
self
.process_struct
(
item
,
def
,
ty_params
)
}
Enum
(
ref
def
,
ref
ty_params
)
=>
self
.process_enum
(
item
,
def
,
ty_params
),
Impl
{
ref
generics
,
ref
of_trait
,
ref
self_ty
,
ref
items
,
..
}
=>
{
hir
::
ItemKind
::
Enum
(
ref
def
,
ref
ty_params
)
=>
self
.process_enum
(
item
,
def
,
ty_params
),
hir
::
ItemKind
::
Impl
{
ref
generics
,
ref
of_trait
,
ref
self_ty
,
ref
items
,
..
}
=>
{
self
.process_impl
(
item
,
generics
,
of_trait
,
&
self_ty
,
items
)
}
Trait
(
_
,
_
,
ref
generics
,
ref
trait_refs
,
ref
methods
)
=>
{
hir
::
ItemKind
::
Trait
(
_
,
_
,
ref
generics
,
ref
trait_refs
,
methods
)
=>
{
self
.process_trait
(
item
,
generics
,
trait_refs
,
methods
)
}
Mod
(
ref
m
)
=>
{
hir
::
ItemKind
::
Mod
(
ref
m
)
=>
{
self
.process_mod
(
item
);
visit
::
walk_mod
(
self
,
m
);
intravisit
::
walk_mod
(
self
,
m
,
item
.hir_id
);
}
TyAlias
(
_
,
ref
ty_params
,
_
,
ref
ty
)
=>
{
hir
::
ItemKind
::
TyAlias
(
ty
,
ref
generics
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id
(
item
.hir_id
)
.to_def_id
())
);
let
value
=
match
ty
{
Some
(
ty
)
=>
ty_to_string
(
&
ty
),
None
=>
"_"
.to_string
(),
};
let
value
=
ty_to_string
(
&
ty
);
if
!
self
.span
.filter_generated
(
item
.ident.span
)
{
let
span
=
self
.span_from_span
(
item
.ident.span
);
let
id
=
id_from_node_id
(
item
.id
,
&
self
.save_ctxt
);
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
let
id
=
id_from_hir_id
(
item
.hir_id
,
&
self
.save_ctxt
);
self
.dumper
.dump_def
(
&
access_from!
(
self
.save_ctxt
,
item
,
hir_id
),
&
access_from!
(
self
.save_ctxt
,
item
,
item
.
hir_id
),
Def
{
kind
:
DefKind
::
Type
,
id
,
...
...
@@ -1350,52 +1289,51 @@ fn visit_item(&mut self, item: &'l ast::Item) {
decl_id
:
None
,
docs
:
self
.save_ctxt
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
&
self
.save_ctxt
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
&
self
.save_ctxt
),
},
);
}
walk_list!
(
self
,
visit_ty
,
ty
);
self
.process_generic_params
(
ty_params
,
&
qualname
,
item
.
id
);
self
.visit_ty
(
ty
);
self
.process_generic_params
(
generics
,
&
qualname
,
item
.hir_
id
);
}
MacCall
(
_
)
=>
(),
_
=>
visit
::
walk_item
(
self
,
item
),
_
=>
intravisit
::
walk_item
(
self
,
item
),
}
}
fn
visit_generics
(
&
mut
self
,
generics
:
&
'
l
ast
::
Generics
)
{
for
param
in
&
generics
.params
{
fn
visit_generics
(
&
mut
self
,
generics
:
&
'
tcx
hir
::
Generics
<
'tcx
>
)
{
for
param
in
generics
.params
{
match
param
.kind
{
ast
::
GenericParamKind
::
Lifetime
{
..
}
=>
{}
ast
::
GenericParamKind
::
Type
{
ref
default
,
..
}
=>
{
self
.process_bounds
(
&
param
.bounds
);
hir
::
GenericParamKind
::
Lifetime
{
..
}
=>
{}
hir
::
GenericParamKind
::
Type
{
ref
default
,
..
}
=>
{
self
.process_bounds
(
param
.bounds
);
if
let
Some
(
ref
ty
)
=
default
{
self
.visit_ty
(
&
ty
);
self
.visit_ty
(
ty
);
}
}
ast
::
GenericParamKind
::
Const
{
ref
ty
}
=>
{
self
.process_bounds
(
&
param
.bounds
);
self
.visit_ty
(
&
ty
);
hir
::
GenericParamKind
::
Const
{
ref
ty
}
=>
{
self
.process_bounds
(
param
.bounds
);
self
.visit_ty
(
ty
);
}
}
}
for
pred
in
&
generics
.where_clause.predicates
{
if
let
ast
::
WherePredicate
::
BoundPredicate
(
ref
wbp
)
=
*
pred
{
self
.process_bounds
(
&
wbp
.bounds
);
self
.visit_ty
(
&
wbp
.bounded_ty
);
for
pred
in
generics
.where_clause.predicates
{
if
let
hir
::
WherePredicate
::
BoundPredicate
(
ref
wbp
)
=
*
pred
{
self
.process_bounds
(
wbp
.bounds
);
self
.visit_ty
(
wbp
.bounded_ty
);
}
}
}
fn
visit_ty
(
&
mut
self
,
t
:
&
'
l
ast
::
Ty
)
{
fn
visit_ty
(
&
mut
self
,
t
:
&
'
tcx
hir
::
Ty
<
'tcx
>
)
{
self
.process_macro_use
(
t
.span
);
match
t
.kind
{
ast
::
TyKind
::
Path
(
_
,
ref
path
)
=>
{
hir
::
TyKind
::
Path
(
hir
::
QPath
::
Resolved
(
_
,
path
)
)
=>
{
if
generated_code
(
t
.span
)
{
return
;
}
if
let
Some
(
id
)
=
self
.lookup_def_id
(
t
.id
)
{
if
let
Some
(
id
)
=
self
.lookup_def_id
(
t
.
hir_
id
)
{
let
sub_span
=
path
.segments
.last
()
.unwrap
()
.ident.span
;
let
span
=
self
.span_from_span
(
sub_span
);
self
.dumper
.dump_ref
(
Ref
{
...
...
@@ -1406,57 +1344,37 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
}
self
.write_sub_paths_truncated
(
path
);
visit
::
walk_path
(
self
,
path
);
intra
visit
::
walk_path
(
self
,
path
);
}
ast
::
TyKind
::
Array
(
ref
element
,
ref
length
)
=>
{
self
.visit_ty
(
element
);
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
length
.id
);
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
v
.visit_expr
(
&
length
.value
)
hir
::
TyKind
::
Array
(
ref
ty
,
ref
anon_const
)
=>
{
self
.visit_ty
(
ty
);
let
map
=
self
.tcx
.hir
(
);
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
anon_const
.
hir_id
),
|
v
|
{
v
.visit_expr
(
&
map
.body
(
anon_const
.body
)
.value
)
});
}
ast
::
TyKind
::
ImplTrait
(
id
,
ref
bounds
)
=>
{
// FIXME: As of writing, the opaque type lowering introduces
// another DefPath scope/segment (used to declare the resulting
// opaque type item).
// However, the synthetic scope does *not* have associated
// typeck tables, which means we can't nest it and we fire an
// assertion when resolving the qualified type paths in trait
// bounds...
// This will panic if called on return type `impl Trait`, which
// we guard against in `process_fn`.
// FIXME(#71104) Should really be using just `node_id_to_hir_id` but
// some `NodeId` do not seem to have a corresponding HirId.
if
let
Some
(
hir_id
)
=
self
.tcx
.hir
()
.opt_node_id_to_hir_id
(
id
)
{
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
v
.process_bounds
(
bounds
)
});
}
}
_
=>
visit
::
walk_ty
(
self
,
t
),
_
=>
intravisit
::
walk_ty
(
self
,
t
),
}
}
fn
visit_expr
(
&
mut
self
,
ex
:
&
'
l
ast
::
Expr
)
{
fn
visit_expr
(
&
mut
self
,
ex
:
&
'
tcx
hir
::
Expr
<
'tcx
>
)
{
debug!
(
"visit_expr {:?}"
,
ex
.kind
);
self
.process_macro_use
(
ex
.span
);
match
ex
.kind
{
ast
::
ExprKind
::
Struct
(
ref
path
,
ref
fields
,
ref
base
)
=>
{
let
expr_hir_id
=
self
.save_ctxt.tcx
.hir
()
.node_id_to_hir_id
(
ex
.id
);
let
hir_expr
=
self
.save_ctxt.tcx
.hir
()
.expect_expr
(
expr_hir_id
);
hir
::
ExprKind
::
Struct
(
ref
path
,
ref
fields
,
ref
base
)
=>
{
let
hir_expr
=
self
.save_ctxt.tcx
.hir
()
.expect_expr
(
ex
.hir_id
);
let
adt
=
match
self
.save_ctxt.tables
.expr_ty_opt
(
&
hir_expr
)
{
Some
(
ty
)
if
ty
.ty_adt_def
()
.is_some
()
=>
ty
.ty_adt_def
()
.unwrap
(),
_
=>
{
visit
::
walk_expr
(
self
,
ex
);
intra
visit
::
walk_expr
(
self
,
ex
);
return
;
}
};
let
node_id
=
self
.save_ctxt.tcx
.hir
()
.hir_id_to_node_id
(
hir_expr
.hir_id
);
let
res
=
self
.save_ctxt
.get_path_res
(
node_id
);
self
.process_struct_lit
(
ex
,
path
,
fields
,
adt
.variant_of_res
(
res
),
base
)
let
res
=
self
.save_ctxt
.get_path_res
(
hir_expr
.hir_id
);
self
.process_struct_lit
(
ex
,
path
,
fields
,
adt
.variant_of_res
(
res
),
*
base
)
}
ast
::
ExprKind
::
MethodCall
(
ref
seg
,
ref
args
)
=>
self
.process_method_call
(
ex
,
seg
,
args
),
ast
::
ExprKind
::
Field
(
ref
sub_ex
,
_
)
=>
{
hir
::
ExprKind
::
MethodCall
(
ref
seg
,
_
,
args
)
=>
self
.process_method_call
(
ex
,
seg
,
args
),
hir
::
ExprKind
::
Field
(
ref
sub_ex
,
_
)
=>
{
self
.visit_expr
(
&
sub_ex
);
if
let
Some
(
field_data
)
=
self
.save_ctxt
.get_expr_data
(
ex
)
{
...
...
@@ -1466,71 +1384,62 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
}
}
}
ast
::
ExprKind
::
Closure
(
_
,
_
,
_
,
ref
decl
,
ref
body
,
_
fn_decl_span
)
=>
{
let
id
=
format!
(
"${}"
,
ex
.id
);
hir
::
ExprKind
::
Closure
(
_
,
ref
decl
,
body
,
_
fn_decl_span
,
_
)
=>
{
let
id
=
format!
(
"${}"
,
ex
.
hir_
id
);
// walk arg and return types
for
arg
in
&
decl
.inputs
{
self
.visit_ty
(
&
arg
.
ty
);
for
ty
in
decl
.inputs
{
self
.visit_ty
(
ty
);
}
if
let
ast
::
FnRetTy
::
Ty
(
ref
ret_ty
)
=
decl
.output
{
self
.visit_ty
(
&
ret_ty
);
if
let
hir
::
FnRetTy
::
Return
(
ref
ret_ty
)
=
decl
.output
{
self
.visit_ty
(
ret_ty
);
}
// walk the body
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
ex
.id
);
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
v
.process_formals
(
&
decl
.inputs
,
&
id
);
v
.visit_expr
(
body
)
let
map
=
self
.tcx
.hir
();
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
ex
.hir_id
),
|
v
|
{
let
body
=
map
.body
(
body
);
v
.process_formals
(
body
.params
,
&
id
);
v
.visit_expr
(
&
body
.value
)
});
}
ast
::
ExprKind
::
ForLoop
(
ref
pattern
,
ref
subexpression
,
ref
block
,
_
)
=>
{
self
.process_var_decl
(
pattern
);
debug!
(
"for loop, walk sub-expr: {:?}"
,
subexpression
.kind
);
self
.visit_expr
(
subexpression
);
visit
::
walk_block
(
self
,
block
);
}
ast
::
ExprKind
::
Let
(
ref
pat
,
ref
scrutinee
)
=>
{
self
.process_var_decl
(
pat
);
self
.visit_expr
(
scrutinee
);
}
ast
::
ExprKind
::
Repeat
(
ref
element
,
ref
count
)
=>
{
self
.visit_expr
(
element
);
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
count
.id
);
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
hir_id
),
|
v
|
{
v
.visit_expr
(
&
count
.value
)
hir
::
ExprKind
::
Repeat
(
ref
expr
,
ref
anon_const
)
=>
{
self
.visit_expr
(
expr
);
let
map
=
self
.tcx
.hir
();
self
.nest_tables
(
self
.tcx
.hir
()
.local_def_id
(
anon_const
.hir_id
),
|
v
|
{
v
.visit_expr
(
&
map
.body
(
anon_const
.body
)
.value
)
});
}
// In particular, we take this branch for call and path expressions,
// where we'll index the idents involved just by continuing to walk.
_
=>
visit
::
walk_expr
(
self
,
ex
),
_
=>
intra
visit
::
walk_expr
(
self
,
ex
),
}
}
fn
visit_pat
(
&
mut
self
,
p
:
&
'
l
ast
::
Pat
)
{
fn
visit_pat
(
&
mut
self
,
p
:
&
'
tcx
hir
::
Pat
<
'tcx
>
)
{
self
.process_macro_use
(
p
.span
);
self
.process_pat
(
p
);
}
fn
visit_arm
(
&
mut
self
,
arm
:
&
'
l
ast
::
Arm
)
{
fn
visit_arm
(
&
mut
self
,
arm
:
&
'
tcx
hir
::
Arm
<
'tcx
>
)
{
self
.process_var_decl
(
&
arm
.pat
);
if
let
Some
(
expr
)
=
&
arm
.guard
{
if
let
Some
(
hir
::
Guard
::
If
(
expr
)
)
=
&
arm
.guard
{
self
.visit_expr
(
expr
);
}
self
.visit_expr
(
&
arm
.body
);
}
fn
visit_path
(
&
mut
self
,
p
:
&
'
l
ast
::
Path
,
id
:
Node
Id
)
{
fn
visit_path
(
&
mut
self
,
p
:
&
'
tcx
hir
::
Path
<
'tcx
>
,
id
:
hir
::
Hir
Id
)
{
self
.process_path
(
id
,
p
);
}
fn
visit_stmt
(
&
mut
self
,
s
:
&
'
l
ast
::
Stmt
)
{
fn
visit_stmt
(
&
mut
self
,
s
:
&
'
tcx
hir
::
Stmt
<
'tcx
>
)
{
self
.process_macro_use
(
s
.span
);
visit
::
walk_stmt
(
self
,
s
)
intra
visit
::
walk_stmt
(
self
,
s
)
}
fn
visit_local
(
&
mut
self
,
l
:
&
'
l
ast
::
Local
)
{
fn
visit_local
(
&
mut
self
,
l
:
&
'
tcx
hir
::
Local
<
'tcx
>
)
{
self
.process_macro_use
(
l
.span
);
self
.process_var_decl
(
&
l
.pat
);
...
...
@@ -1539,29 +1448,27 @@ fn visit_local(&mut self, l: &'l ast::Local) {
walk_list!
(
self
,
visit_expr
,
&
l
.init
);
}
fn
visit_foreign_item
(
&
mut
self
,
item
:
&
'l
ast
::
ForeignItem
)
{
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
item
.id
);
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
hir_id
);
fn
visit_foreign_item
(
&
mut
self
,
item
:
&
'tcx
hir
::
ForeignItem
<
'tcx
>
)
{
let
access
=
access_from!
(
self
.save_ctxt
,
item
,
item
.hir_id
);
match
item
.kind
{
ast
::
ForeignItemKind
::
Fn
(
_
,
ref
sig
,
ref
generics
,
_
)
=>
{
let
decl
=
&
sig
.decl
;
hir
::
ForeignItemKind
::
Fn
(
decl
,
_
,
ref
generics
)
=>
{
if
let
Some
(
fn_data
)
=
self
.save_ctxt
.get_extern_item_data
(
item
)
{
down_cast_data!
(
fn_data
,
DefData
,
item
.span
);
self
.process_generic_params
(
generics
,
&
fn_data
.qualname
,
item
.id
);
self
.process_generic_params
(
generics
,
&
fn_data
.qualname
,
item
.
hir_
id
);
self
.dumper
.dump_def
(
&
access
,
fn_data
);
}
for
arg
in
&
decl
.inputs
{
self
.visit_ty
(
&
arg
.
ty
);
for
ty
in
decl
.inputs
{
self
.visit_ty
(
ty
);
}
if
let
ast
::
FnRetTy
::
Ty
(
ref
ret_ty
)
=
decl
.output
{
self
.visit_ty
(
&
ret_ty
);
if
let
hir
::
FnRetTy
::
Return
(
ref
ret_ty
)
=
decl
.output
{
self
.visit_ty
(
ret_ty
);
}
}
ast
::
ForeignItemKind
::
Static
(
ref
ty
,
_
,
_
)
=>
{
hir
::
ForeignItemKind
::
Static
(
ref
ty
,
_
)
=>
{
if
let
Some
(
var_data
)
=
self
.save_ctxt
.get_extern_item_data
(
item
)
{
down_cast_data!
(
var_data
,
DefData
,
item
.span
);
self
.dumper
.dump_def
(
&
access
,
var_data
);
...
...
@@ -1569,13 +1476,12 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
self
.visit_ty
(
ty
);
}
ast
::
ForeignItemKind
::
TyAlias
(
..
)
=>
{
hir
::
ForeignItemKind
::
Type
=>
{
if
let
Some
(
var_data
)
=
self
.save_ctxt
.get_extern_item_data
(
item
)
{
down_cast_data!
(
var_data
,
DefData
,
item
.span
);
self
.dumper
.dump_def
(
&
access
,
var_data
);
}
}
ast
::
ForeignItemKind
::
MacCall
(
..
)
=>
{}
}
}
}
src/librustc_save_analysis/lib.rs
浏览文件 @
8ec68761
...
...
@@ -9,14 +9,16 @@
mod
span_utils
;
mod
sig
;
use
rustc_ast
::
ast
::{
self
,
Attribute
,
NodeId
,
PatKind
,
DUMMY_NODE_ID
};
use
rustc_ast
::
ast
::{
self
};
use
rustc_ast
::
util
::
comments
::
strip_doc_comment_decoration
;
use
rustc_ast
::
visit
::{
self
,
Visitor
};
use
rustc_ast_pretty
::
pprust
::{
self
,
param_to_string
,
ty_to_string
};
use
rustc_ast_pretty
::
pprust
::
attribute_to_string
;
use
rustc_hir
as
hir
;
use
rustc_hir
::
def
::{
CtorOf
,
DefKind
as
HirDefKind
,
Res
};
use
rustc_hir
::
def_id
::{
DefId
,
LOCAL_CRATE
};
use
rustc_hir
::
intravisit
::{
self
,
Visitor
};
use
rustc_hir
::
Node
;
use
rustc_hir_pretty
::
ty_to_string
;
use
rustc_middle
::
hir
::
map
::
Map
;
use
rustc_middle
::
middle
::
cstore
::
ExternCrate
;
use
rustc_middle
::
middle
::
privacy
::
AccessLevels
;
use
rustc_middle
::
ty
::{
self
,
DefIdTree
,
TyCtxt
};
...
...
@@ -129,34 +131,32 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
result
}
pub
fn
get_extern_item_data
(
&
self
,
item
:
&
ast
::
ForeignItem
)
->
Option
<
Data
>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
())
);
pub
fn
get_extern_item_data
(
&
self
,
item
:
&
hir
::
ForeignItem
<
'_
>
)
->
Option
<
Data
>
{
let
def_id
=
self
.tcx
.hir
()
.local_def_id
(
item
.hir_id
)
.to_def_id
();
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
match
item
.kind
{
ast
::
ForeignItemKind
::
Fn
(
_
,
ref
sig
,
ref
generics
,
_
)
=>
{
hir
::
ForeignItemKind
::
Fn
(
ref
decl
,
_
,
ref
generics
)
=>
{
filter!
(
self
.span_utils
,
item
.ident.span
);
Some
(
Data
::
DefData
(
Def
{
kind
:
DefKind
::
ForeignFunction
,
id
:
id_from_
node_id
(
item
.id
,
self
),
id
:
id_from_
def_id
(
def_id
),
span
:
self
.span_from_span
(
item
.ident.span
),
name
:
item
.ident
.to_string
(),
qualname
,
value
:
make_signature
(
&
sig
.
decl
,
generics
),
value
:
make_signature
(
decl
,
generics
),
parent
:
None
,
children
:
vec!
[],
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
foreign_item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ForeignItemKind
::
Static
(
ref
ty
,
_
,
_
)
=>
{
hir
::
ForeignItemKind
::
Static
(
ref
ty
,
_
)
=>
{
filter!
(
self
.span_utils
,
item
.ident.span
);
let
id
=
id_from_
node_id
(
item
.id
,
self
);
let
id
=
id_from_
def_id
(
def_id
);
let
span
=
self
.span_from_span
(
item
.ident.span
);
Some
(
Data
::
DefData
(
Def
{
...
...
@@ -171,28 +171,23 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
foreign_item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
// FIXME(plietar): needs a new DefKind in rls-data
ast
::
ForeignItemKind
::
TyAlias
(
..
)
=>
None
,
ast
::
ForeignItemKind
::
MacCall
(
..
)
=>
None
,
hir
::
ForeignItemKind
::
Type
=>
None
,
}
}
pub
fn
get_item_data
(
&
self
,
item
:
&
ast
::
Item
)
->
Option
<
Data
>
{
pub
fn
get_item_data
(
&
self
,
item
:
&
hir
::
Item
<
'_
>
)
->
Option
<
Data
>
{
let
def_id
=
self
.tcx
.hir
()
.local_def_id
(
item
.hir_id
)
.to_def_id
();
match
item
.kind
{
ast
::
ItemKind
::
Fn
(
_
,
ref
sig
,
..
,
ref
generics
,
_
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
);
hir
::
ItemKind
::
Fn
(
ref
sig
,
ref
generics
,
_
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
filter!
(
self
.span_utils
,
item
.ident.span
);
Some
(
Data
::
DefData
(
Def
{
kind
:
DefKind
::
Function
,
id
:
id_from_
node_id
(
item
.id
,
self
),
id
:
id_from_
def_id
(
def_id
),
span
:
self
.span_from_span
(
item
.ident.span
),
name
:
item
.ident
.to_string
(),
qualname
,
...
...
@@ -202,20 +197,15 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ItemKind
::
Static
(
ref
typ
,
..
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
);
hir
::
ItemKind
::
Static
(
ref
typ
,
..
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
filter!
(
self
.span_utils
,
item
.ident.span
);
let
id
=
id_from_
node_id
(
item
.id
,
self
);
let
id
=
id_from_
def_id
(
def_id
);
let
span
=
self
.span_from_span
(
item
.ident.span
);
Some
(
Data
::
DefData
(
Def
{
...
...
@@ -230,19 +220,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ItemKind
::
Const
(
_
,
ref
typ
,
_
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
);
hir
::
ItemKind
::
Const
(
ref
typ
,
_
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
filter!
(
self
.span_utils
,
item
.ident.span
);
let
id
=
id_from_
node_id
(
item
.id
,
self
);
let
id
=
id_from_
def_id
(
def_id
);
let
span
=
self
.span_from_span
(
item
.ident.span
);
Some
(
Data
::
DefData
(
Def
{
...
...
@@ -257,16 +242,11 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ItemKind
::
Mod
(
ref
m
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
);
hir
::
ItemKind
::
Mod
(
ref
m
)
=>
{
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
let
sm
=
self
.tcx.sess
.source_map
();
let
filename
=
sm
.span_to_filename
(
m
.inner
);
...
...
@@ -275,48 +255,43 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
Some
(
Data
::
DefData
(
Def
{
kind
:
DefKind
::
Mod
,
id
:
id_from_
node_id
(
item
.id
,
self
),
id
:
id_from_
def_id
(
def_id
),
name
:
item
.ident
.to_string
(),
qualname
,
span
:
self
.span_from_span
(
item
.ident.span
),
value
:
filename
.to_string
(),
parent
:
None
,
children
:
m
.item
s
.iter
()
.map
(|
i
|
id_from_node
_id
(
i
.id
,
self
))
.collect
(),
children
:
m
.item
_ids
.iter
()
.map
(|
i
|
id_from_hir
_id
(
i
.id
,
self
))
.collect
(),
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ItemKind
::
Enum
(
ref
def
,
_
)
=>
{
hir
::
ItemKind
::
Enum
(
ref
def
,
_
)
=>
{
let
name
=
item
.ident
.to_string
();
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
item
.id
)
.to_def_id
()
)
);
let
qualname
=
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
));
filter!
(
self
.span_utils
,
item
.ident.span
);
let
variants_str
=
def
.variants
.iter
()
.map
(|
v
|
v
.ident
.to_string
())
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
);
let
value
=
format!
(
"{}::{{{}}}"
,
name
,
variants_str
);
Some
(
Data
::
DefData
(
Def
{
kind
:
DefKind
::
Enum
,
id
:
id_from_
node_id
(
item
.id
,
self
),
id
:
id_from_
def_id
(
def_id
),
span
:
self
.span_from_span
(
item
.ident.span
),
name
,
qualname
,
value
,
parent
:
None
,
children
:
def
.variants
.iter
()
.map
(|
v
|
id_from_
node
_id
(
v
.id
,
self
))
.collect
(),
children
:
def
.variants
.iter
()
.map
(|
v
|
id_from_
hir
_id
(
v
.id
,
self
))
.collect
(),
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
item
.attrs
),
sig
:
sig
::
item_signature
(
item
,
self
),
attributes
:
lower_attributes
(
item
.attrs
.
clone
(),
self
),
attributes
:
lower_attributes
(
item
.attrs
.
to_vec
(),
self
),
}))
}
ast
::
ItemKind
::
Impl
{
ref
of_trait
,
ref
self_ty
,
ref
items
,
..
}
=>
{
if
let
ast
::
TyKind
::
Path
(
None
,
ref
path
)
=
self_ty
.kind
{
hir
::
ItemKind
::
Impl
{
ref
of_trait
,
ref
self_ty
,
ref
items
,
..
}
=>
{
if
let
hir
::
TyKind
::
Path
(
hir
::
QPath
::
Resolved
(
_
,
ref
path
)
)
=
self_ty
.kind
{
// Common case impl for a struct or something basic.
if
generated_code
(
path
.span
)
{
return
None
;
...
...
@@ -327,7 +302,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
let
impl_id
=
self
.next_impl_id
();
let
span
=
self
.span_from_span
(
sub_span
);
let
type_data
=
self
.lookup_def_id
(
self_ty
.id
);
let
type_data
=
self
.lookup_def_id
(
self_ty
.
hir_
id
);
type_data
.map
(|
type_data
|
{
Data
::
RelationData
(
Relation
{
...
...
@@ -336,7 +311,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
from
:
id_from_def_id
(
type_data
),
to
:
of_trait
.as_ref
()
.and_then
(|
t
|
self
.lookup_def_id
(
t
.ref_id
))
.and_then
(|
t
|
self
.lookup_def_id
(
t
.
hir_
ref_id
))
.map
(
id_from_def_id
)
.unwrap_or_else
(
null_id
),
},
...
...
@@ -351,7 +326,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
parent
:
None
,
children
:
items
.iter
()
.map
(|
i
|
id_from_
node_id
(
i
.
id
,
self
))
.map
(|
i
|
id_from_
hir_id
(
i
.id.hir_
id
,
self
))
.collect
(),
docs
:
String
::
new
(),
sig
:
None
,
...
...
@@ -370,126 +345,120 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
}
}
pub
fn
get_field_data
(
&
self
,
field
:
&
ast
::
StructField
,
scope
:
NodeId
)
->
Option
<
Def
>
{
if
let
Some
(
ident
)
=
field
.ident
{
let
name
=
ident
.to_string
();
let
qualname
=
format!
(
"::{}::{}"
,
self
.tcx
.def_path_str
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
scope
)
.to_def_id
()),
ident
);
filter!
(
self
.span_utils
,
ident
.span
);
let
def_id
=
self
.tcx
.hir
()
.local_def_id_from_node_id
(
field
.id
)
.to_def_id
();
let
typ
=
self
.tcx
.type_of
(
def_id
)
.to_string
();
let
id
=
id_from_node_id
(
field
.id
,
self
);
let
span
=
self
.span_from_span
(
ident
.span
);
Some
(
Def
{
kind
:
DefKind
::
Field
,
id
,
span
,
name
,
qualname
,
value
:
typ
,
parent
:
Some
(
id_from_node_id
(
scope
,
self
)),
children
:
vec!
[],
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
field
.attrs
),
sig
:
sig
::
field_signature
(
field
,
self
),
attributes
:
lower_attributes
(
field
.attrs
.clone
(),
self
),
})
}
else
{
None
}
pub
fn
get_field_data
(
&
self
,
field
:
&
hir
::
StructField
<
'_
>
,
scope
:
hir
::
HirId
)
->
Option
<
Def
>
{
let
name
=
field
.ident
.to_string
();
let
scope_def_id
=
self
.tcx
.hir
()
.local_def_id
(
scope
)
.to_def_id
();
let
qualname
=
format!
(
"::{}::{}"
,
self
.tcx
.def_path_str
(
scope_def_id
),
field
.ident
);
filter!
(
self
.span_utils
,
field
.ident.span
);
let
field_def_id
=
self
.tcx
.hir
()
.local_def_id
(
field
.hir_id
)
.to_def_id
();
let
typ
=
self
.tcx
.type_of
(
field_def_id
)
.to_string
();
let
id
=
id_from_def_id
(
field_def_id
);
let
span
=
self
.span_from_span
(
field
.ident.span
);
Some
(
Def
{
kind
:
DefKind
::
Field
,
id
,
span
,
name
,
qualname
,
value
:
typ
,
parent
:
Some
(
id_from_def_id
(
scope_def_id
)),
children
:
vec!
[],
decl_id
:
None
,
docs
:
self
.docs_for_attrs
(
&
field
.attrs
),
sig
:
sig
::
field_signature
(
field
,
self
),
attributes
:
lower_attributes
(
field
.attrs
.to_vec
(),
self
),
})
}
// FIXME would be nice to take a MethodItem here, but the ast provides both
// trait and impl flavours, so the caller must do the disassembly.
pub
fn
get_method_data
(
&
self
,
id
:
ast
::
Node
Id
,
ident
:
Ident
,
span
:
Span
)
->
Option
<
Def
>
{
pub
fn
get_method_data
(
&
self
,
hir_id
:
hir
::
Hir
Id
,
ident
:
Ident
,
span
:
Span
)
->
Option
<
Def
>
{
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let
(
qualname
,
parent_scope
,
decl_id
,
docs
,
attributes
)
=
match
self
.tcx
.impl_of_method
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
id
)
.to_def_id
())
{
Some
(
impl_id
)
=>
match
self
.tcx
.hir
()
.get_if_local
(
impl_id
)
{
Some
(
Node
::
Item
(
item
))
=>
match
item
.kind
{
hir
::
ItemKind
::
Impl
{
ref
self_ty
,
..
}
=>
{
let
hir
=
self
.tcx
.hir
();
let
mut
qualname
=
String
::
from
(
"<"
);
qualname
.push_str
(
&
rustc_hir_pretty
::
id_to_string
(
&
hir
,
self_ty
.hir_id
));
let
trait_id
=
self
.tcx
.trait_id_of_impl
(
impl_id
);
let
def_id
=
self
.tcx
.hir
()
.local_def_id
(
hir_id
)
.to_def_id
();
let
(
qualname
,
parent_scope
,
decl_id
,
docs
,
attributes
)
=
match
self
.tcx
.impl_of_method
(
def_id
)
{
Some
(
impl_id
)
=>
match
self
.tcx
.hir
()
.get_if_local
(
impl_id
)
{
Some
(
Node
::
Item
(
item
))
=>
match
item
.kind
{
hir
::
ItemKind
::
Impl
{
ref
self_ty
,
..
}
=>
{
let
hir
=
self
.tcx
.hir
();
let
mut
qualname
=
String
::
from
(
"<"
);
qualname
.push_str
(
&
rustc_hir_pretty
::
id_to_string
(
&
hir
,
self_ty
.hir_id
));
let
trait_id
=
self
.tcx
.trait_id_of_impl
(
impl_id
);
let
mut
docs
=
String
::
new
();
let
mut
attrs
=
vec!
[];
if
let
Some
(
Node
::
ImplItem
(
item
))
=
hir
.find
(
hir_id
)
{
docs
=
self
.docs_for_attrs
(
&
item
.attrs
);
attrs
=
item
.attrs
.to_vec
();
}
let
mut
decl_id
=
None
;
if
let
Some
(
def_id
)
=
trait_id
{
// A method in a trait impl.
qualname
.push_str
(
" as "
);
qualname
.push_str
(
&
self
.tcx
.def_path_str
(
def_id
));
decl_id
=
self
.tcx
.associated_items
(
def_id
)
.filter_by_name_unhygienic
(
ident
.name
)
.next
()
.map
(|
item
|
item
.def_id
);
}
qualname
.push_str
(
">"
);
(
qualname
,
trait_id
,
decl_id
,
docs
,
attrs
)
}
_
=>
{
span_bug!
(
span
,
"Container {:?} for method {} not an impl?"
,
impl_id
,
hir_id
);
}
},
r
=>
{
span_bug!
(
span
,
"Container {:?} for method {} is not a node item {:?}"
,
impl_id
,
hir_id
,
r
);
}
},
None
=>
match
self
.tcx
.trait_of_item
(
def_id
)
{
Some
(
def_id
)
=>
{
let
mut
docs
=
String
::
new
();
let
mut
attrs
=
vec!
[];
if
let
Some
(
Node
::
ImplItem
(
item
))
=
hir
.find
(
hir
.node_id_to_hir_id
(
id
))
{
if
let
Some
(
Node
::
TraitItem
(
item
))
=
self
.tcx
.hir
()
.find
(
hir_id
)
{
docs
=
self
.docs_for_attrs
(
&
item
.attrs
);
attrs
=
item
.attrs
.to_vec
();
}
let
mut
decl_id
=
None
;
if
let
Some
(
def_id
)
=
trait_id
{
// A method in a trait impl.
qualname
.push_str
(
" as "
);
qualname
.push_str
(
&
self
.tcx
.def_path_str
(
def_id
));
decl_id
=
self
.tcx
.associated_items
(
def_id
)
.filter_by_name_unhygienic
(
ident
.name
)
.next
()
.map
(|
item
|
item
.def_id
);
}
qualname
.push_str
(
">"
);
(
qualname
,
trait_id
,
decl_id
,
docs
,
attrs
)
(
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
)),
Some
(
def_id
),
None
,
docs
,
attrs
,
)
}
_
=>
{
span_bug!
(
span
,
"Container {:?} for method {} not an impl?"
,
impl_id
,
id
);
None
=>
{
debug!
(
"could not find container for method {} at {:?}"
,
hir_id
,
span
);
// This is not necessarily a bug, if there was a compilation error,
// the tables we need might not exist.
return
None
;
}
},
r
=>
{
span_bug!
(
span
,
"Container {:?} for method {} is not a node item {:?}"
,
impl_id
,
id
,
r
);
}
},
None
=>
match
self
.tcx
.trait_of_item
(
self
.tcx
.hir
()
.local_def_id_from_node_id
(
id
)
.to_def_id
())
{
Some
(
def_id
)
=>
{
let
mut
docs
=
String
::
new
();
let
mut
attrs
=
vec!
[];
let
hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
id
);
if
let
Some
(
Node
::
TraitItem
(
item
))
=
self
.tcx
.hir
()
.find
(
hir_id
)
{
docs
=
self
.docs_for_attrs
(
&
item
.attrs
);
attrs
=
item
.attrs
.to_vec
();
}
(
format!
(
"::{}"
,
self
.tcx
.def_path_str
(
def_id
)),
Some
(
def_id
),
None
,
docs
,
attrs
,
)
}
None
=>
{
debug!
(
"could not find container for method {} at {:?}"
,
id
,
span
);
// This is not necessarily a bug, if there was a compilation error,
// the tables we need might not exist.
return
None
;
}
},
};
};
let
qualname
=
format!
(
"{}::{}"
,
qualname
,
ident
.name
);
...
...
@@ -497,7 +466,7 @@ pub fn get_method_data(&self, id: ast::NodeId, ident: Ident, span: Span) -> Opti
Some
(
Def
{
kind
:
DefKind
::
Method
,
id
:
id_from_
node_id
(
id
,
self
),
id
:
id_from_
def_id
(
def_id
),
span
:
self
.span_from_span
(
ident
.span
),
name
:
ident
.name
.to_string
(),
qualname
,
...
...
@@ -512,8 +481,8 @@ pub fn get_method_data(&self, id: ast::NodeId, ident: Ident, span: Span) -> Opti
})
}
pub
fn
get_trait_ref_data
(
&
self
,
trait_ref
:
&
ast
::
TraitRef
)
->
Option
<
Ref
>
{
self
.lookup_def_id
(
trait_ref
.ref_id
)
.and_then
(|
def_id
|
{
pub
fn
get_trait_ref_data
(
&
self
,
trait_ref
:
&
hir
::
TraitRef
<
'_
>
)
->
Option
<
Ref
>
{
self
.lookup_def_id
(
trait_ref
.
hir_
ref_id
)
.and_then
(|
def_id
|
{
let
span
=
trait_ref
.path.span
;
if
generated_code
(
span
)
{
return
None
;
...
...
@@ -525,22 +494,20 @@ pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
})
}
pub
fn
get_expr_data
(
&
self
,
expr
:
&
ast
::
Expr
)
->
Option
<
Data
>
{
let
expr_hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
expr
.id
);
let
hir_node
=
self
.tcx
.hir
()
.expect_expr
(
expr_hir_id
);
pub
fn
get_expr_data
(
&
self
,
expr
:
&
hir
::
Expr
<
'_
>
)
->
Option
<
Data
>
{
let
hir_node
=
self
.tcx
.hir
()
.expect_expr
(
expr
.hir_id
);
let
ty
=
self
.tables
.expr_ty_adjusted_opt
(
&
hir_node
);
if
ty
.is_none
()
||
ty
.unwrap
()
.kind
==
ty
::
Error
{
return
None
;
}
match
expr
.kind
{
ast
::
ExprKind
::
Field
(
ref
sub_ex
,
ident
)
=>
{
let
sub_ex_hir_id
=
self
.tcx
.hir
()
.node_id_to_hir_id
(
sub_ex
.id
);
let
hir_node
=
match
self
.tcx
.hir
()
.find
(
sub_ex_hir_id
)
{
hir
::
ExprKind
::
Field
(
ref
sub_ex
,
ident
)
=>
{
let
hir_node
=
match
self
.tcx
.hir
()
.find
(
sub_ex
.hir_id
)
{
Some
(
Node
::
Expr
(
expr
))
=>
expr
,
_
=>
{
debug!
(
"Missing or weird node for sub-expression {} in {:?}"
,
sub_ex
.id
,
expr
sub_ex
.
hir_
id
,
expr
);
return
None
;
}
...
...
@@ -567,7 +534,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
}
}
ast
::
ExprKind
::
Struct
(
ref
path
,
..
)
=>
{
hir
::
ExprKind
::
Struct
(
hir
::
QPath
::
Resolved
(
_
,
path
)
,
..
)
=>
{
match
self
.tables
.expr_ty_adjusted
(
&
hir_node
)
.kind
{
ty
::
Adt
(
def
,
_
)
if
!
def
.is_enum
()
=>
{
let
sub_span
=
path
.segments
.last
()
.unwrap
()
.ident.span
;
...
...
@@ -587,9 +554,8 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
}
}
ast
::
ExprKind
::
MethodCall
(
ref
seg
,
..
)
=>
{
let
expr_hir_id
=
self
.tcx
.hir
()
.definitions
()
.node_id_to_hir_id
(
expr
.id
);
let
method_id
=
match
self
.tables
.type_dependent_def_id
(
expr_hir_id
)
{
hir
::
ExprKind
::
MethodCall
(
ref
seg
,
..
)
=>
{
let
method_id
=
match
self
.tables
.type_dependent_def_id
(
expr
.hir_id
)
{
Some
(
id
)
=>
id
,
None
=>
{
debug!
(
"could not resolve method id for {:?}"
,
expr
);
...
...
@@ -609,8 +575,8 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
ref_id
:
def_id
.or
(
decl_id
)
.map
(
id_from_def_id
)
.unwrap_or_else
(
null_id
),
}))
}
ast
::
ExprKind
::
Path
(
_
,
ref
path
)
=>
{
self
.get_path_data
(
expr
.id
,
path
)
.map
(
Data
::
RefData
)
hir
::
ExprKind
::
Path
(
hir
::
QPath
::
Resolved
(
_
,
path
)
)
=>
{
self
.get_path_data
(
expr
.
hir_
id
,
path
)
.map
(
Data
::
RefData
)
}
_
=>
{
// FIXME
...
...
@@ -619,12 +585,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
}
pub
fn
get_path_res
(
&
self
,
id
:
NodeId
)
->
Res
{
// FIXME(#71104)
let
hir_id
=
match
self
.tcx
.hir
()
.opt_node_id_to_hir_id
(
id
)
{
Some
(
id
)
=>
id
,
None
=>
return
Res
::
Err
,
};
pub
fn
get_path_res
(
&
self
,
hir_id
:
hir
::
HirId
)
->
Res
{
match
self
.tcx
.hir
()
.get
(
hir_id
)
{
Node
::
TraitRef
(
tr
)
=>
tr
.path.res
,
...
...
@@ -638,7 +599,7 @@ pub fn get_path_res(&self, id: NodeId) -> Res {
Some
(
res
)
if
res
!=
Res
::
Err
=>
res
,
_
=>
{
let
parent_node
=
self
.tcx
.hir
()
.get_parent_node
(
hir_id
);
self
.get_path_res
(
self
.tcx
.hir
()
.hir_id_to_node_id
(
parent_node
)
)
self
.get_path_res
(
parent_node
)
}
},
...
...
@@ -666,33 +627,24 @@ pub fn get_path_res(&self, id: NodeId) -> Res {
}
}
pub
fn
get_path_data
(
&
self
,
id
:
NodeId
,
path
:
&
ast
::
Path
)
->
Option
<
Ref
>
{
pub
fn
get_path_data
(
&
self
,
id
:
hir
::
HirId
,
path
:
&
hir
::
Path
<
'_
>
)
->
Option
<
Ref
>
{
path
.segments
.last
()
.and_then
(|
seg
|
{
self
.get_path_segment_data
(
seg
)
.or_else
(||
self
.get_path_segment_data_with_id
(
seg
,
id
))
})
}
pub
fn
get_path_segment_data
(
&
self
,
path_seg
:
&
ast
::
PathSegment
)
->
Option
<
Ref
>
{
self
.get_path_segment_data_with_id
(
path_seg
,
path_seg
.
id
)
pub
fn
get_path_segment_data
(
&
self
,
path_seg
:
&
hir
::
PathSegment
<
'_
>
)
->
Option
<
Ref
>
{
self
.get_path_segment_data_with_id
(
path_seg
,
path_seg
.
hir_id
?
)
}
fn
get_path_segment_data_with_id
(
pub
fn
get_path_segment_data_with_id
(
&
self
,
path_seg
:
&
ast
::
PathSegment
,
id
:
Node
Id
,
path_seg
:
&
hir
::
PathSegment
<
'_
>
,
id
:
hir
::
Hir
Id
,
)
->
Option
<
Ref
>
{
// Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
fn
fn_type
(
seg
:
&
ast
::
PathSegment
)
->
bool
{
if
let
Some
(
ref
generic_args
)
=
seg
.args
{
if
let
ast
::
GenericArgs
::
Parenthesized
(
_
)
=
**
generic_args
{
return
true
;
}
}
false
}
if
id
==
DUMMY_NODE_ID
{
return
None
;
fn
fn_type
(
seg
:
&
hir
::
PathSegment
<
'_
>
)
->
bool
{
seg
.args
.map
(|
args
|
args
.parenthesized
)
.unwrap_or
(
false
)
}
let
res
=
self
.get_path_res
(
id
);
...
...
@@ -701,11 +653,9 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
let
span
=
self
.span_from_span
(
span
);
match
res
{
Res
::
Local
(
id
)
=>
Some
(
Ref
{
kind
:
RefKind
::
Variable
,
span
,
ref_id
:
id_from_node_id
(
self
.tcx
.hir
()
.hir_id_to_node_id
(
id
),
self
),
}),
Res
::
Local
(
id
)
=>
{
Some
(
Ref
{
kind
:
RefKind
::
Variable
,
span
,
ref_id
:
id_from_hir_id
(
id
,
self
)
})
}
Res
::
Def
(
HirDefKind
::
Trait
,
def_id
)
if
fn_type
(
path_seg
)
=>
{
Some
(
Ref
{
kind
:
RefKind
::
Type
,
span
,
ref_id
:
id_from_def_id
(
def_id
)
})
}
...
...
@@ -791,7 +741,7 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
pub
fn
get_field_ref_data
(
&
self
,
field_ref
:
&
ast
::
Field
,
field_ref
:
&
hir
::
Field
<
'_
>
,
variant
:
&
ty
::
VariantDef
,
)
->
Option
<
Ref
>
{
filter!
(
self
.span_utils
,
field_ref
.ident.span
);
...
...
@@ -839,14 +789,14 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
})
}
fn
lookup_def_id
(
&
self
,
ref_id
:
Node
Id
)
->
Option
<
DefId
>
{
fn
lookup_def_id
(
&
self
,
ref_id
:
hir
::
Hir
Id
)
->
Option
<
DefId
>
{
match
self
.get_path_res
(
ref_id
)
{
Res
::
PrimTy
(
_
)
|
Res
::
SelfTy
(
..
)
|
Res
::
Err
=>
None
,
def
=>
def
.opt_def_id
(),
}
}
fn
docs_for_attrs
(
&
self
,
attrs
:
&
[
Attribute
])
->
String
{
fn
docs_for_attrs
(
&
self
,
attrs
:
&
[
ast
::
Attribute
])
->
String
{
let
mut
result
=
String
::
new
();
for
attr
in
attrs
{
...
...
@@ -890,7 +840,7 @@ fn next_impl_id(&self) -> u32 {
}
}
fn
make_signature
(
decl
:
&
ast
::
FnDecl
,
generics
:
&
ast
::
Generics
)
->
String
{
fn
make_signature
(
decl
:
&
hir
::
FnDecl
<
'_
>
,
generics
:
&
hir
::
Generics
<
'_
>
)
->
String
{
let
mut
sig
=
"fn "
.to_owned
();
if
!
generics
.params
.is_empty
()
{
sig
.push
(
'<'
);
...
...
@@ -898,18 +848,18 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
&
generics
.params
.iter
()
.map
(|
param
|
param
.
ident
.to_string
())
.map
(|
param
|
param
.
name
.ident
()
.to_string
())
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
),
);
sig
.push_str
(
"> "
);
}
sig
.push
(
'('
);
sig
.push_str
(
&
decl
.inputs
.iter
()
.map
(
param
_to_string
)
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
));
sig
.push_str
(
&
decl
.inputs
.iter
()
.map
(
ty
_to_string
)
.collect
::
<
Vec
<
_
>>
()
.join
(
", "
));
sig
.push
(
')'
);
match
decl
.output
{
ast
::
FnRetTy
::
Default
(
_
)
=>
sig
.push_str
(
" -> ()"
),
ast
::
FnRetTy
::
Ty
(
ref
t
)
=>
sig
.push_str
(
&
format!
(
" -> {}"
,
ty_to_string
(
t
))),
hir
::
FnRetTy
::
DefaultReturn
(
_
)
=>
sig
.push_str
(
" -> ()"
),
hir
::
FnRetTy
::
Return
(
ref
t
)
=>
sig
.push_str
(
&
format!
(
" -> {}"
,
ty_to_string
(
t
))),
}
sig
...
...
@@ -918,26 +868,33 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
// An AST visitor for collecting paths (e.g., the names of structs) and formal
// variables (idents) from patterns.
struct
PathCollector
<
'l
>
{
collected_paths
:
Vec
<
(
NodeId
,
&
'l
ast
::
Path
)
>
,
collected_idents
:
Vec
<
(
NodeId
,
Ident
,
ast
::
Mutability
)
>
,
tcx
:
TyCtxt
<
'l
>
,
collected_paths
:
Vec
<
(
hir
::
HirId
,
&
'l
hir
::
QPath
<
'l
>
)
>
,
collected_idents
:
Vec
<
(
hir
::
HirId
,
Ident
,
hir
::
Mutability
)
>
,
}
impl
<
'l
>
PathCollector
<
'l
>
{
fn
new
()
->
PathCollector
<
'l
>
{
PathCollector
{
collected_paths
:
vec!
[],
collected_idents
:
vec!
[]
}
fn
new
(
tcx
:
TyCtxt
<
'l
>
)
->
PathCollector
<
'l
>
{
PathCollector
{
tcx
,
collected_paths
:
vec!
[],
collected_idents
:
vec!
[]
}
}
}
impl
<
'l
>
Visitor
<
'l
>
for
PathCollector
<
'l
>
{
fn
visit_pat
(
&
mut
self
,
p
:
&
'l
ast
::
Pat
)
{
type
Map
=
Map
<
'l
>
;
fn
nested_visit_map
(
&
mut
self
)
->
intravisit
::
NestedVisitorMap
<
Self
::
Map
>
{
intravisit
::
NestedVisitorMap
::
All
(
self
.tcx
.hir
())
}
fn
visit_pat
(
&
mut
self
,
p
:
&
'l
hir
::
Pat
<
'l
>
)
{
match
p
.kind
{
PatKind
::
Struct
(
ref
path
,
..
)
=>
{
self
.collected_paths
.push
((
p
.id
,
path
));
hir
::
PatKind
::
Struct
(
ref
path
,
..
)
=>
{
self
.collected_paths
.push
((
p
.
hir_
id
,
path
));
}
PatKind
::
TupleStruct
(
ref
path
,
..
)
|
PatKind
::
Path
(
_
,
ref
path
)
=>
{
self
.collected_paths
.push
((
p
.id
,
path
));
hir
::
PatKind
::
TupleStruct
(
ref
path
,
..
)
|
hir
::
PatKind
::
Path
(
ref
path
)
=>
{
self
.collected_paths
.push
((
p
.
hir_
id
,
path
));
}
PatKind
::
Ident
(
bm
,
ident
,
_
)
=>
{
hir
::
PatKind
::
Binding
(
bm
,
_
,
ident
,
_
)
=>
{
debug!
(
"PathCollector, visit ident in pat {}: {:?} {:?}"
,
ident
,
p
.span
,
ident
.span
...
...
@@ -946,14 +903,18 @@ fn visit_pat(&mut self, p: &'l ast::Pat) {
// Even if the ref is mut, you can't change the ref, only
// the data pointed at, so showing the initialising expression
// is still worthwhile.
ast
::
BindingMode
::
ByRef
(
_
)
=>
ast
::
Mutability
::
Not
,
ast
::
BindingMode
::
ByValue
(
mt
)
=>
mt
,
hir
::
BindingAnnotation
::
Unannotated
|
hir
::
BindingAnnotation
::
Ref
=>
{
hir
::
Mutability
::
Not
}
hir
::
BindingAnnotation
::
Mutable
|
hir
::
BindingAnnotation
::
RefMut
=>
{
hir
::
Mutability
::
Mut
}
};
self
.collected_idents
.push
((
p
.id
,
ident
,
immut
));
self
.collected_idents
.push
((
p
.
hir_
id
,
ident
,
immut
));
}
_
=>
{}
}
visit
::
walk_pat
(
self
,
p
);
intra
visit
::
walk_pat
(
self
,
p
);
}
}
...
...
@@ -1035,7 +996,6 @@ fn save(&mut self, _: &SaveContext<'_, '_>, analysis: &Analysis) {
pub
fn
process_crate
<
'l
,
'tcx
,
H
:
SaveHandler
>
(
tcx
:
TyCtxt
<
'tcx
>
,
krate
:
&
ast
::
Crate
,
cratename
:
&
str
,
input
:
&
'l
Input
,
config
:
Option
<
Config
>
,
...
...
@@ -1063,9 +1023,9 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
let
mut
visitor
=
DumpVisitor
::
new
(
save_ctxt
);
visitor
.dump_crate_info
(
cratename
,
krate
);
visitor
.dump_crate_info
(
cratename
,
tcx
.hir
()
.krate
()
);
visitor
.dump_compilation_options
(
input
,
cratename
);
visit
::
walk_crate
(
&
mut
visitor
,
krate
);
visit
or
.process_crate
(
tcx
.hir
()
.krate
()
);
handler
.save
(
&
visitor
.save_ctxt
,
&
visitor
.analysis
())
})
...
...
@@ -1109,13 +1069,17 @@ fn id_from_def_id(id: DefId) -> rls_data::Id {
rls_data
::
Id
{
krate
:
id
.krate
.as_u32
(),
index
:
id
.index
.as_u32
()
}
}
fn
id_from_
node_id
(
id
:
Node
Id
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
rls_data
::
Id
{
let
def_id
=
scx
.tcx
.hir
()
.opt_local_def_id
_from_node_id
(
id
);
fn
id_from_
hir_id
(
id
:
hir
::
Hir
Id
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
rls_data
::
Id
{
let
def_id
=
scx
.tcx
.hir
()
.opt_local_def_id
(
id
);
def_id
.map
(|
id
|
id_from_def_id
(
id
.to_def_id
()))
.unwrap_or_else
(||
{
// Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId`
// out of the maximum u32 value. This will work unless you have *billions*
// of definitions in a single crate (very unlikely to actually happen).
rls_data
::
Id
{
krate
:
LOCAL_CRATE
.as_u32
(),
index
:
!
id
.as_u32
()
}
// Create a *fake* `DefId` out of a `HirId` by combining the owner
// `local_def_index` and the `local_id`.
// This will work unless you have *billions* of definitions in a single
// crate (very unlikely to actually happen).
rls_data
::
Id
{
krate
:
LOCAL_CRATE
.as_u32
(),
index
:
id
.owner.local_def_index
.as_u32
()
|
id
.local_id
.as_u32
()
.reverse_bits
(),
}
})
}
...
...
@@ -1123,7 +1087,10 @@ fn null_id() -> rls_data::Id {
rls_data
::
Id
{
krate
:
u32
::
max_value
(),
index
:
u32
::
max_value
()
}
}
fn
lower_attributes
(
attrs
:
Vec
<
Attribute
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Vec
<
rls_data
::
Attribute
>
{
fn
lower_attributes
(
attrs
:
Vec
<
ast
::
Attribute
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Vec
<
rls_data
::
Attribute
>
{
attrs
.into_iter
()
// Only retain real attributes. Doc comments are lowered separately.
...
...
@@ -1133,7 +1100,7 @@ fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext<'_, '_>) -> Vec<rls
// attribute. First normalize all inner attribute (#![..]) to outer
// ones (#[..]), then remove the two leading and the one trailing character.
attr
.style
=
ast
::
AttrStyle
::
Outer
;
let
value
=
pprust
::
attribute_to_string
(
&
attr
);
let
value
=
attribute_to_string
(
&
attr
);
// This str slicing works correctly, because the leading and trailing characters
// are in the ASCII range and thus exactly one byte each.
let
value
=
value
[
2
..
value
.len
()
-
1
]
.to_string
();
...
...
src/librustc_save_analysis/sig.rs
浏览文件 @
8ec68761
...
...
@@ -25,16 +25,18 @@
//
// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
use
crate
::{
id_from_def_id
,
id_from_
node
_id
,
SaveContext
};
use
crate
::{
id_from_def_id
,
id_from_
hir
_id
,
SaveContext
};
use
rls_data
::{
SigElement
,
Signature
};
use
rustc_ast
::
ast
::
{
self
,
Extern
,
NodeId
}
;
use
rustc_
ast_pretty
::
pprust
;
use
rustc_ast
::
ast
::
Mutability
;
use
rustc_
hir
as
hir
;
use
rustc_hir
::
def
::{
DefKind
,
Res
};
use
rustc_hir_pretty
::
id_to_string
;
use
rustc_hir_pretty
::{
bounds_to_string
,
path_segment_to_string
,
path_to_string
,
ty_to_string
};
use
rustc_span
::
symbol
::{
Ident
,
Symbol
};
pub
fn
item_signature
(
item
:
&
ast
::
Item
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Option
<
Signature
>
{
pub
fn
item_signature
(
item
:
&
hir
::
Item
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
return
None
;
}
...
...
@@ -42,7 +44,7 @@ pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Sig
}
pub
fn
foreign_item_signature
(
item
:
&
ast
::
ForeignItem
,
item
:
&
hir
::
ForeignItem
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
...
...
@@ -53,7 +55,10 @@ pub fn foreign_item_signature(
/// Signature for a struct or tuple field declaration.
/// Does not include a trailing comma.
pub
fn
field_signature
(
field
:
&
ast
::
StructField
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Option
<
Signature
>
{
pub
fn
field_signature
(
field
:
&
hir
::
StructField
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
return
None
;
}
...
...
@@ -61,7 +66,10 @@ pub fn field_signature(field: &ast::StructField, scx: &SaveContext<'_, '_>) -> O
}
/// Does not include a trailing comma.
pub
fn
variant_signature
(
variant
:
&
ast
::
Variant
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Option
<
Signature
>
{
pub
fn
variant_signature
(
variant
:
&
hir
::
Variant
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
return
None
;
}
...
...
@@ -69,10 +77,10 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> O
}
pub
fn
method_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Ident
,
generics
:
&
ast
::
Generics
,
m
:
&
ast
::
FnSig
,
generics
:
&
hir
::
Generics
<
'_
>
,
m
:
&
hir
::
FnSig
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
...
...
@@ -82,10 +90,10 @@ pub fn method_signature(
}
pub
fn
assoc_const_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Symbol
,
ty
:
&
ast
::
Ty
,
default
:
Option
<&
ast
::
Expr
>
,
ty
:
&
hir
::
Ty
<
'_
>
,
default
:
Option
<&
hir
::
Expr
<
'_
>
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
...
...
@@ -95,10 +103,10 @@ pub fn assoc_const_signature(
}
pub
fn
assoc_type_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Ident
,
bounds
:
Option
<
&
ast
::
GenericBounds
>
,
default
:
Option
<&
ast
::
Ty
>
,
bounds
:
Option
<
hir
::
GenericBounds
<
'_
>
>
,
default
:
Option
<&
hir
::
Ty
<
'_
>
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Option
<
Signature
>
{
if
!
scx
.config.signatures
{
...
...
@@ -110,7 +118,7 @@ pub fn assoc_type_signature(
type
Result
=
std
::
result
::
Result
<
Signature
,
&
'static
str
>
;
trait
Sig
{
fn
make
(
&
self
,
offset
:
usize
,
id
:
Option
<
Node
Id
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
;
fn
make
(
&
self
,
offset
:
usize
,
id
:
Option
<
hir
::
Hir
Id
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
;
}
fn
extend_sig
(
...
...
@@ -145,39 +153,34 @@ fn text_sig(text: String) -> Signature {
Signature
{
text
,
defs
:
vec!
[],
refs
:
vec!
[]
}
}
fn
push_extern
(
text
:
&
mut
String
,
ext
:
Extern
)
{
match
ext
{
Extern
::
None
=>
{}
Extern
::
Implicit
=>
text
.push_str
(
"extern "
),
Extern
::
Explicit
(
abi
)
=>
text
.push_str
(
&
format!
(
"extern
\"
{}
\"
"
,
abi
.symbol
)),
}
}
impl
Sig
for
ast
::
Ty
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
let
id
=
Some
(
self
.id
);
impl
<
'hir
>
Sig
for
hir
::
Ty
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
id
=
Some
(
self
.hir_id
);
match
self
.kind
{
ast
::
TyKind
::
Slice
(
ref
ty
)
=>
{
hir
::
TyKind
::
Slice
(
ref
ty
)
=>
{
let
nested
=
ty
.make
(
offset
+
1
,
id
,
scx
)
?
;
let
text
=
format!
(
"[{}]"
,
nested
.text
);
Ok
(
replace_text
(
nested
,
text
))
}
ast
::
TyKind
::
Ptr
(
ref
mt
)
=>
{
hir
::
TyKind
::
Ptr
(
ref
mt
)
=>
{
let
prefix
=
match
mt
.mutbl
{
ast
::
Mutability
::
Mut
=>
"*mut "
,
ast
::
Mutability
::
Not
=>
"*const "
,
hir
::
Mutability
::
Mut
=>
"*mut "
,
hir
::
Mutability
::
Not
=>
"*const "
,
};
let
nested
=
mt
.ty
.make
(
offset
+
prefix
.len
(),
id
,
scx
)
?
;
let
text
=
format!
(
"{}{}"
,
prefix
,
nested
.text
);
Ok
(
replace_text
(
nested
,
text
))
}
ast
::
TyKind
::
Rptr
(
ref
lifetime
,
ref
mt
)
=>
{
hir
::
TyKind
::
Rptr
(
ref
lifetime
,
ref
mt
)
=>
{
let
mut
prefix
=
"&"
.to_owned
();
if
let
&
Some
(
ref
l
)
=
lifetime
{
prefix
.push_str
(
&
l
.ident
.to_string
());
prefix
.push
(
' '
);
}
if
let
ast
::
Mutability
::
Mut
=
mt
.mutbl
{
prefix
.push_str
(
&
lifetime
.name
.ident
()
.to_string
());
prefix
.push
(
' '
);
if
let
hir
::
Mutability
::
Mut
=
mt
.mutbl
{
prefix
.push_str
(
"mut "
);
};
...
...
@@ -185,9 +188,8 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
let
text
=
format!
(
"{}{}"
,
prefix
,
nested
.text
);
Ok
(
replace_text
(
nested
,
text
))
}
ast
::
TyKind
::
Never
=>
Ok
(
text_sig
(
"!"
.to_owned
())),
ast
::
TyKind
::
CVarArgs
=>
Ok
(
text_sig
(
"..."
.to_owned
())),
ast
::
TyKind
::
Tup
(
ref
ts
)
=>
{
hir
::
TyKind
::
Never
=>
Ok
(
text_sig
(
"!"
.to_owned
())),
hir
::
TyKind
::
Tup
(
ts
)
=>
{
let
mut
text
=
"("
.to_owned
();
let
mut
defs
=
vec!
[];
let
mut
refs
=
vec!
[];
...
...
@@ -201,12 +203,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
text
.push
(
')'
);
Ok
(
Signature
{
text
,
defs
,
refs
})
}
ast
::
TyKind
::
Paren
(
ref
ty
)
=>
{
let
nested
=
ty
.make
(
offset
+
1
,
id
,
scx
)
?
;
let
text
=
format!
(
"({})"
,
nested
.text
);
Ok
(
replace_text
(
nested
,
text
))
}
ast
::
TyKind
::
BareFn
(
ref
f
)
=>
{
hir
::
TyKind
::
BareFn
(
ref
f
)
=>
{
let
mut
text
=
String
::
new
();
if
!
f
.generic_params
.is_empty
()
{
// FIXME defs, bounds on lifetimes
...
...
@@ -215,8 +212,8 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
&
f
.generic_params
.iter
()
.filter_map
(|
param
|
match
param
.kind
{
ast
::
GenericParamKind
::
Lifetime
{
..
}
=>
{
Some
(
param
.
ident
.to_string
())
hir
::
GenericParamKind
::
Lifetime
{
..
}
=>
{
Some
(
param
.
name
.ident
()
.to_string
())
}
_
=>
None
,
})
...
...
@@ -226,23 +223,22 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
text
.push
(
'>'
);
}
if
let
ast
::
Unsafe
::
Yes
(
_
)
=
f
.unsafety
{
if
let
hir
::
Unsafety
::
Unsafe
=
f
.unsafety
{
text
.push_str
(
"unsafe "
);
}
push_extern
(
&
mut
text
,
f
.ext
);
text
.push_str
(
"fn("
);
let
mut
defs
=
vec!
[];
let
mut
refs
=
vec!
[];
for
i
in
&
f
.decl.inputs
{
let
nested
=
i
.
ty
.make
(
offset
+
text
.len
(),
Some
(
i
.
id
),
scx
)
?
;
for
i
in
f
.decl.inputs
{
let
nested
=
i
.
make
(
offset
+
text
.len
(),
Some
(
i
.hir_
id
),
scx
)
?
;
text
.push_str
(
&
nested
.text
);
text
.push
(
','
);
defs
.extend
(
nested
.defs
.into_iter
());
refs
.extend
(
nested
.refs
.into_iter
());
}
text
.push
(
')'
);
if
let
ast
::
FnRetTy
::
Ty
(
ref
t
)
=
f
.decl.output
{
if
let
hir
::
FnRetTy
::
Return
(
ref
t
)
=
f
.decl.output
{
text
.push_str
(
" -> "
);
let
nested
=
t
.make
(
offset
+
text
.len
(),
None
,
scx
)
?
;
text
.push_str
(
&
nested
.text
);
...
...
@@ -253,23 +249,19 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
Signature
{
text
,
defs
,
refs
})
}
ast
::
TyKind
::
Path
(
None
,
ref
path
)
=>
path
.make
(
offset
,
id
,
scx
),
ast
::
TyKind
::
Path
(
Some
(
ref
qself
),
ref
path
)
=>
{
let
nested_ty
=
qself
.ty
.make
(
offset
+
1
,
id
,
scx
)
?
;
let
prefix
=
if
qself
.position
==
0
{
format!
(
"<{}>::"
,
nested_ty
.text
)
}
else
if
qself
.position
==
1
{
let
first
=
pprust
::
path_segment_to_string
(
&
path
.segments
[
0
]);
format!
(
"<{} as {}>::"
,
nested_ty
.text
,
first
)
}
else
{
// FIXME handle path instead of elipses.
format!
(
"<{} as ...>::"
,
nested_ty
.text
)
};
hir
::
TyKind
::
Path
(
hir
::
QPath
::
Resolved
(
None
,
ref
path
))
=>
path
.make
(
offset
,
id
,
scx
),
hir
::
TyKind
::
Path
(
hir
::
QPath
::
Resolved
(
Some
(
ref
qself
),
ref
path
))
=>
{
let
nested_ty
=
qself
.make
(
offset
+
1
,
id
,
scx
)
?
;
let
prefix
=
format!
(
"<{} as {}>::"
,
nested_ty
.text
,
path_segment_to_string
(
&
path
.segments
[
0
])
);
let
name
=
p
prust
::
p
ath_segment_to_string
(
path
.segments
.last
()
.ok_or
(
"Bad path"
)
?
);
let
name
=
path_segment_to_string
(
path
.segments
.last
()
.ok_or
(
"Bad path"
)
?
);
let
res
=
scx
.get_path_res
(
id
.ok_or
(
"Missing id for Path"
)
?
);
let
id
=
id_from_def_id
(
res
.def_id
());
if
path
.segments
.len
()
-
qself
.position
==
1
{
if
path
.segments
.len
()
==
2
{
let
start
=
offset
+
prefix
.len
();
let
end
=
start
+
name
.len
();
...
...
@@ -289,44 +281,60 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
})
}
}
ast
::
TyKind
::
TraitObject
(
ref
bounds
,
..
)
=>
{
hir
::
TyKind
::
TraitObject
(
bounds
,
..
)
=>
{
// FIXME recurse into bounds
let
nested
=
pprust
::
bounds_to_string
(
bounds
);
let
bounds
:
Vec
<
hir
::
GenericBound
<
'_
>>
=
bounds
.iter
()
.map
(|
hir
::
PolyTraitRef
{
bound_generic_params
,
trait_ref
,
span
}|
{
hir
::
GenericBound
::
Trait
(
hir
::
PolyTraitRef
{
bound_generic_params
,
trait_ref
:
hir
::
TraitRef
{
path
:
trait_ref
.path
,
hir_ref_id
:
trait_ref
.hir_ref_id
,
},
span
:
*
span
,
},
hir
::
TraitBoundModifier
::
None
,
)
})
.collect
();
let
nested
=
bounds_to_string
(
&
bounds
);
Ok
(
text_sig
(
nested
))
}
ast
::
TyKind
::
ImplTrait
(
_
,
ref
bounds
)
=>
{
// FIXME recurse into bounds
let
nested
=
pprust
::
bounds_to_string
(
bounds
);
Ok
(
text_sig
(
format!
(
"impl {}"
,
nested
)))
}
ast
::
TyKind
::
Array
(
ref
ty
,
ref
v
)
=>
{
hir
::
TyKind
::
Array
(
ref
ty
,
ref
anon_const
)
=>
{
let
nested_ty
=
ty
.make
(
offset
+
1
,
id
,
scx
)
?
;
let
expr
=
pprust
::
expr_to_string
(
&
v
.value
)
.replace
(
'\n'
,
" "
);
let
expr
=
id_to_string
(
&
scx
.tcx
.hir
(),
anon_const
.body.hir_id
)
.replace
(
'\n'
,
" "
);
let
text
=
format!
(
"[{}; {}]"
,
nested_ty
.text
,
expr
);
Ok
(
replace_text
(
nested_ty
,
text
))
}
ast
::
TyKind
::
Typeof
(
_
)
|
ast
::
TyKind
::
Infer
|
ast
::
TyKind
::
Err
|
ast
::
TyKind
::
ImplicitSelf
|
ast
::
TyKind
::
MacCall
(
_
)
=>
Err
(
"Ty"
),
hir
::
TyKind
::
Typeof
(
_
)
|
hir
::
TyKind
::
Infer
|
hir
::
TyKind
::
Def
(
..
)
|
hir
::
TyKind
::
Path
(
..
)
|
hir
::
TyKind
::
Err
=>
Err
(
"Ty"
),
}
}
}
impl
Sig
for
ast
::
Item
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
let
id
=
Some
(
self
.id
);
impl
<
'hir
>
Sig
for
hir
::
Item
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
id
=
Some
(
self
.hir_id
);
match
self
.kind
{
ast
::
ItemKind
::
Static
(
ref
ty
,
m
,
ref
expr
)
=>
{
hir
::
ItemKind
::
Static
(
ref
ty
,
m
,
ref
body
)
=>
{
let
mut
text
=
"static "
.to_owned
();
if
m
==
ast
::
Mutability
::
Mut
{
if
m
==
hir
::
Mutability
::
Mut
{
text
.push_str
(
"mut "
);
}
let
name
=
self
.ident
.to_string
();
let
defs
=
vec!
[
SigElement
{
id
:
id_from_
node_id
(
self
.
id
,
scx
),
id
:
id_from_
hir_id
(
self
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
}];
...
...
@@ -336,21 +344,19 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
let
ty
=
ty
.make
(
offset
+
text
.len
(),
id
,
scx
)
?
;
text
.push_str
(
&
ty
.text
);
if
let
Some
(
expr
)
=
expr
{
text
.push_str
(
" = "
);
let
expr
=
pprust
::
expr_to_string
(
expr
)
.replace
(
'\n'
,
" "
);
text
.push_str
(
&
expr
);
}
text
.push_str
(
" = "
);
let
expr
=
id_to_string
(
&
scx
.tcx
.hir
(),
body
.hir_id
)
.replace
(
'\n'
,
" "
);
text
.push_str
(
&
expr
);
text
.push
(
';'
);
Ok
(
extend_sig
(
ty
,
text
,
defs
,
vec!
[]))
}
ast
::
ItemKind
::
Const
(
_
,
ref
ty
,
ref
expr
)
=>
{
hir
::
ItemKind
::
Const
(
ref
ty
,
ref
body
)
=>
{
let
mut
text
=
"const "
.to_owned
();
let
name
=
self
.ident
.to_string
();
let
defs
=
vec!
[
SigElement
{
id
:
id_from_
node_id
(
self
.
id
,
scx
),
id
:
id_from_
hir_id
(
self
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
}];
...
...
@@ -360,38 +366,35 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
let
ty
=
ty
.make
(
offset
+
text
.len
(),
id
,
scx
)
?
;
text
.push_str
(
&
ty
.text
);
if
let
Some
(
expr
)
=
expr
{
text
.push_str
(
" = "
);
let
expr
=
pprust
::
expr_to_string
(
expr
)
.replace
(
'\n'
,
" "
);
text
.push_str
(
&
expr
);
}
text
.push_str
(
" = "
);
let
expr
=
id_to_string
(
&
scx
.tcx
.hir
(),
body
.hir_id
)
.replace
(
'\n'
,
" "
);
text
.push_str
(
&
expr
);
text
.push
(
';'
);
Ok
(
extend_sig
(
ty
,
text
,
defs
,
vec!
[]))
}
ast
::
ItemKind
::
Fn
(
_
,
ast
::
FnSig
{
ref
decl
,
header
},
ref
generics
,
_
)
=>
{
hir
::
ItemKind
::
Fn
(
hir
::
FnSig
{
ref
decl
,
header
},
ref
generics
,
_
)
=>
{
let
mut
text
=
String
::
new
();
if
let
ast
::
Const
::
Yes
(
_
)
=
header
.constness
{
if
let
hir
::
Constness
::
Const
=
header
.constness
{
text
.push_str
(
"const "
);
}
if
h
eader
.asyncness
.is_async
()
{
if
h
ir
::
IsAsync
::
Async
==
header
.asyncness
{
text
.push_str
(
"async "
);
}
if
let
ast
::
Unsafe
::
Yes
(
_
)
=
header
.unsafety
{
if
let
hir
::
Unsafety
::
Unsafe
=
header
.unsafety
{
text
.push_str
(
"unsafe "
);
}
push_extern
(
&
mut
text
,
header
.ext
);
text
.push_str
(
"fn "
);
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push
(
'('
);
for
i
in
&
decl
.inputs
{
for
i
in
decl
.inputs
{
// FIXME should descend into patterns to add defs.
sig
.text
.push_str
(
&
pprust
::
pat_to_string
(
&
i
.pat
));
sig
.text
.push_str
(
": "
);
let
nested
=
i
.
ty
.make
(
offset
+
sig
.text
.len
(),
Some
(
i
.
id
),
scx
)
?
;
let
nested
=
i
.
make
(
offset
+
sig
.text
.len
(),
Some
(
i
.hir_
id
),
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
sig
.text
.push
(
','
);
sig
.defs
.extend
(
nested
.defs
.into_iter
());
...
...
@@ -399,7 +402,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
}
sig
.text
.push
(
')'
);
if
let
ast
::
FnRetTy
::
Ty
(
ref
t
)
=
decl
.output
{
if
let
hir
::
FnRetTy
::
Return
(
ref
t
)
=
decl
.output
{
sig
.text
.push_str
(
" -> "
);
let
nested
=
t
.make
(
offset
+
sig
.text
.len
(),
None
,
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
...
...
@@ -410,11 +413,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
sig
)
}
ast
::
ItemKind
::
Mod
(
ref
_
mod
)
=>
{
hir
::
ItemKind
::
Mod
(
ref
_
mod
)
=>
{
let
mut
text
=
"mod "
.to_owned
();
let
name
=
self
.ident
.to_string
();
let
defs
=
vec!
[
SigElement
{
id
:
id_from_
node_id
(
self
.
id
,
scx
),
id
:
id_from_
hir_id
(
self
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
}];
...
...
@@ -424,78 +427,82 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
Signature
{
text
,
defs
,
refs
:
vec!
[]
})
}
ast
::
ItemKind
::
TyAlias
(
_
,
ref
generics
,
_
,
ref
ty
)
=>
{
hir
::
ItemKind
::
TyAlias
(
ref
ty
,
ref
generics
)
=>
{
let
text
=
"type "
.to_owned
();
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push_str
(
" = "
);
let
ty
=
match
ty
{
Some
(
ty
)
=>
ty
.make
(
offset
+
sig
.text
.len
(),
id
,
scx
)
?
,
None
=>
return
Err
(
"Ty"
),
};
let
ty
=
ty
.make
(
offset
+
sig
.text
.len
(),
id
,
scx
)
?
;
sig
.text
.push_str
(
&
ty
.text
);
sig
.text
.push
(
';'
);
Ok
(
merge_sigs
(
sig
.text
.clone
(),
vec!
[
sig
,
ty
]))
}
ast
::
ItemKind
::
Enum
(
_
,
ref
generics
)
=>
{
hir
::
ItemKind
::
Enum
(
_
,
ref
generics
)
=>
{
let
text
=
"enum "
.to_owned
();
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push_str
(
" {}"
);
Ok
(
sig
)
}
ast
::
ItemKind
::
Struct
(
_
,
ref
generics
)
=>
{
hir
::
ItemKind
::
Struct
(
_
,
ref
generics
)
=>
{
let
text
=
"struct "
.to_owned
();
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push_str
(
" {}"
);
Ok
(
sig
)
}
ast
::
ItemKind
::
Union
(
_
,
ref
generics
)
=>
{
hir
::
ItemKind
::
Union
(
_
,
ref
generics
)
=>
{
let
text
=
"union "
.to_owned
();
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push_str
(
" {}"
);
Ok
(
sig
)
}
ast
::
ItemKind
::
Trait
(
is_auto
,
unsafety
,
ref
generics
,
ref
bounds
,
_
)
=>
{
hir
::
ItemKind
::
Trait
(
is_auto
,
unsafety
,
ref
generics
,
bounds
,
_
)
=>
{
let
mut
text
=
String
::
new
();
if
is_auto
==
ast
::
IsAuto
::
Yes
{
if
is_auto
==
hir
::
IsAuto
::
Yes
{
text
.push_str
(
"auto "
);
}
if
let
ast
::
Unsafe
::
Yes
(
_
)
=
unsafety
{
if
let
hir
::
Unsafety
::
Unsafe
=
unsafety
{
text
.push_str
(
"unsafe "
);
}
text
.push_str
(
"trait "
);
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
if
!
bounds
.is_empty
()
{
sig
.text
.push_str
(
": "
);
sig
.text
.push_str
(
&
pprust
::
bounds_to_string
(
bounds
));
sig
.text
.push_str
(
&
bounds_to_string
(
bounds
));
}
// FIXME where clause
sig
.text
.push_str
(
" {}"
);
Ok
(
sig
)
}
ast
::
ItemKind
::
TraitAlias
(
ref
generics
,
ref
bounds
)
=>
{
hir
::
ItemKind
::
TraitAlias
(
ref
generics
,
bounds
)
=>
{
let
mut
text
=
String
::
new
();
text
.push_str
(
"trait "
);
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
if
!
bounds
.is_empty
()
{
sig
.text
.push_str
(
" = "
);
sig
.text
.push_str
(
&
pprust
::
bounds_to_string
(
bounds
));
sig
.text
.push_str
(
&
bounds_to_string
(
bounds
));
}
// FIXME where clause
sig
.text
.push_str
(
";"
);
Ok
(
sig
)
}
ast
::
ItemKind
::
Impl
{
hir
::
ItemKind
::
Impl
{
unsafety
,
polarity
,
defaultness
,
defaultness_span
:
_
,
constness
,
ref
generics
,
ref
of_trait
,
...
...
@@ -503,14 +510,14 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
items
:
_
,
}
=>
{
let
mut
text
=
String
::
new
();
if
let
ast
::
Defaultness
::
Default
(
_
)
=
defaultness
{
if
let
hir
::
Defaultness
::
Default
{
..
}
=
defaultness
{
text
.push_str
(
"default "
);
}
if
let
ast
::
Unsafe
::
Yes
(
_
)
=
unsafety
{
if
let
hir
::
Unsafety
::
Unsafe
=
unsafety
{
text
.push_str
(
"unsafe "
);
}
text
.push_str
(
"impl"
);
if
let
ast
::
Const
::
Yes
(
_
)
=
constness
{
if
let
hir
::
Constness
::
Const
=
constness
{
text
.push_str
(
" const"
);
}
...
...
@@ -520,7 +527,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
text
.push
(
' '
);
let
trait_sig
=
if
let
Some
(
ref
t
)
=
*
of_trait
{
if
let
ast
::
ImplPolarity
::
Negative
(
_
)
=
polarity
{
if
let
hir
::
ImplPolarity
::
Negative
(
_
)
=
polarity
{
text
.push
(
'!'
);
}
let
trait_sig
=
t
.path
.make
(
offset
+
text
.len
(),
id
,
scx
)
?
;
...
...
@@ -540,27 +547,23 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
// FIXME where clause
}
ast
::
ItemKind
::
ForeignMod
(
_
)
=>
Err
(
"extern mod"
),
ast
::
ItemKind
::
GlobalAsm
(
_
)
=>
Err
(
"glboal asm"
),
ast
::
ItemKind
::
ExternCrate
(
_
)
=>
Err
(
"extern crate"
),
hir
::
ItemKind
::
ForeignMod
(
_
)
=>
Err
(
"extern mod"
),
hir
::
ItemKind
::
GlobalAsm
(
_
)
=>
Err
(
"glboal asm"
),
hir
::
ItemKind
::
ExternCrate
(
_
)
=>
Err
(
"extern crate"
),
hir
::
ItemKind
::
OpaqueTy
(
..
)
=>
Err
(
"opaque type"
),
// FIXME should implement this (e.g., pub use).
ast
::
ItemKind
::
Use
(
_
)
=>
Err
(
"import"
),
ast
::
ItemKind
::
MacCall
(
..
)
|
ast
::
ItemKind
::
MacroDef
(
_
)
=>
Err
(
"Macro"
),
hir
::
ItemKind
::
Use
(
..
)
=>
Err
(
"import"
),
}
}
}
impl
Sig
for
ast
::
Path
{
fn
make
(
&
self
,
offset
:
usize
,
id
:
Option
<
Node
Id
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
impl
<
'hir
>
Sig
for
hir
::
Path
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
id
:
Option
<
hir
::
Hir
Id
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
let
res
=
scx
.get_path_res
(
id
.ok_or
(
"Missing id for Path"
)
?
);
let
(
name
,
start
,
end
)
=
match
res
{
Res
::
PrimTy
(
..
)
|
Res
::
SelfTy
(
..
)
|
Res
::
Err
=>
{
return
Ok
(
Signature
{
text
:
pprust
::
path_to_string
(
self
),
defs
:
vec!
[],
refs
:
vec!
[],
});
return
Ok
(
Signature
{
text
:
path_to_string
(
self
),
defs
:
vec!
[],
refs
:
vec!
[]
});
}
Res
::
Def
(
DefKind
::
AssocConst
|
DefKind
::
Variant
|
DefKind
::
Ctor
(
..
),
_
)
=>
{
let
len
=
self
.segments
.len
();
...
...
@@ -570,13 +573,13 @@ fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) ->
// FIXME: really we should descend into the generics here and add SigElements for
// them.
// FIXME: would be nice to have a def for the first path segment.
let
seg1
=
p
prust
::
p
ath_segment_to_string
(
&
self
.segments
[
len
-
2
]);
let
seg2
=
p
prust
::
p
ath_segment_to_string
(
&
self
.segments
[
len
-
1
]);
let
seg1
=
path_segment_to_string
(
&
self
.segments
[
len
-
2
]);
let
seg2
=
path_segment_to_string
(
&
self
.segments
[
len
-
1
]);
let
start
=
offset
+
seg1
.len
()
+
2
;
(
format!
(
"{}::{}"
,
seg1
,
seg2
),
start
,
start
+
seg2
.len
())
}
_
=>
{
let
name
=
p
prust
::
p
ath_segment_to_string
(
self
.segments
.last
()
.ok_or
(
"Bad path"
)
?
);
let
name
=
path_segment_to_string
(
self
.segments
.last
()
.ok_or
(
"Bad path"
)
?
);
let
end
=
offset
+
name
.len
();
(
name
,
offset
,
end
)
}
...
...
@@ -588,8 +591,13 @@ fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) ->
}
// This does not cover the where clause, which must be processed separately.
impl
Sig
for
ast
::
Generics
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
impl
<
'hir
>
Sig
for
hir
::
Generics
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
if
self
.params
.is_empty
()
{
return
Ok
(
text_sig
(
String
::
new
()));
}
...
...
@@ -597,30 +605,30 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
let
mut
text
=
"<"
.to_owned
();
let
mut
defs
=
Vec
::
with_capacity
(
self
.params
.len
());
for
param
in
&
self
.params
{
for
param
in
self
.params
{
let
mut
param_text
=
String
::
new
();
if
let
ast
::
GenericParamKind
::
Const
{
..
}
=
param
.kind
{
if
let
hir
::
GenericParamKind
::
Const
{
..
}
=
param
.kind
{
param_text
.push_str
(
"const "
);
}
param_text
.push_str
(
&
param
.
ident
.as_str
());
param_text
.push_str
(
&
param
.
name
.ident
()
.as_str
());
defs
.push
(
SigElement
{
id
:
id_from_
node_id
(
param
.
id
,
scx
),
id
:
id_from_
hir_id
(
param
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
param_text
.as_str
()
.len
(),
});
if
let
ast
::
GenericParamKind
::
Const
{
ref
ty
}
=
param
.kind
{
if
let
hir
::
GenericParamKind
::
Const
{
ref
ty
}
=
param
.kind
{
param_text
.push_str
(
": "
);
param_text
.push_str
(
&
pprust
::
ty_to_string
(
&
ty
));
param_text
.push_str
(
&
ty_to_string
(
&
ty
));
}
if
!
param
.bounds
.is_empty
()
{
param_text
.push_str
(
": "
);
match
param
.kind
{
ast
::
GenericParamKind
::
Lifetime
{
..
}
=>
{
hir
::
GenericParamKind
::
Lifetime
{
..
}
=>
{
let
bounds
=
param
.bounds
.iter
()
.map
(|
bound
|
match
bound
{
ast
::
GenericBound
::
Outlives
(
lt
)
=>
lt
.ident
.to_string
(),
hir
::
GenericBound
::
Outlives
(
lt
)
=>
lt
.name
.ident
()
.to_string
(),
_
=>
panic!
(),
})
.collect
::
<
Vec
<
_
>>
()
...
...
@@ -628,11 +636,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
param_text
.push_str
(
&
bounds
);
// FIXME add lifetime bounds refs.
}
ast
::
GenericParamKind
::
Type
{
..
}
=>
{
param_text
.push_str
(
&
pprust
::
bounds_to_string
(
&
param
.bounds
));
hir
::
GenericParamKind
::
Type
{
..
}
=>
{
param_text
.push_str
(
&
bounds_to_string
(
param
.bounds
));
// FIXME descend properly into bounds.
}
ast
::
GenericParamKind
::
Const
{
..
}
=>
{
hir
::
GenericParamKind
::
Const
{
..
}
=>
{
// Const generics cannot contain bounds.
}
}
...
...
@@ -646,21 +654,24 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
}
}
impl
Sig
for
ast
::
StructField
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
impl
<
'hir
>
Sig
for
hir
::
StructField
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
mut
text
=
String
::
new
();
let
mut
defs
=
None
;
if
let
Some
(
ident
)
=
self
.ident
{
text
.push_str
(
&
ident
.to_string
());
defs
=
Some
(
SigElement
{
id
:
id_from_node_id
(
self
.id
,
scx
),
start
:
offset
,
end
:
offset
+
text
.len
(),
});
text
.push_str
(
": "
);
}
let
mut
ty_sig
=
self
.ty
.make
(
offset
+
text
.len
(),
Some
(
self
.id
),
scx
)
?
;
text
.push_str
(
&
self
.ident
.to_string
());
let
defs
=
Some
(
SigElement
{
id
:
id_from_hir_id
(
self
.hir_id
,
scx
),
start
:
offset
,
end
:
offset
+
text
.len
(),
});
text
.push_str
(
": "
);
let
mut
ty_sig
=
self
.ty
.make
(
offset
+
text
.len
(),
Some
(
self
.hir_id
),
scx
)
?
;
text
.push_str
(
&
ty_sig
.text
);
ty_sig
.text
=
text
;
ty_sig
.defs
.extend
(
defs
.into_iter
());
...
...
@@ -668,14 +679,19 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
}
}
impl
Sig
for
ast
::
Variant
{
fn
make
(
&
self
,
offset
:
usize
,
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
impl
<
'hir
>
Sig
for
hir
::
Variant
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
mut
text
=
self
.ident
.to_string
();
match
self
.data
{
ast
::
VariantData
::
Struct
(
ref
fields
,
r
)
=>
{
hir
::
VariantData
::
Struct
(
fields
,
r
)
=>
{
let
id
=
parent_id
.unwrap
();
let
name_def
=
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
offset
,
end
:
offset
+
text
.len
(),
};
...
...
@@ -696,9 +712,9 @@ fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '
text
.push
(
'}'
);
Ok
(
Signature
{
text
,
defs
,
refs
})
}
ast
::
VariantData
::
Tuple
(
ref
fields
,
id
)
=>
{
hir
::
VariantData
::
Tuple
(
fields
,
id
)
=>
{
let
name_def
=
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
offset
,
end
:
offset
+
text
.len
(),
};
...
...
@@ -715,9 +731,9 @@ fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '
text
.push
(
')'
);
Ok
(
Signature
{
text
,
defs
,
refs
})
}
ast
::
VariantData
::
Unit
(
id
)
=>
{
hir
::
VariantData
::
Unit
(
id
)
=>
{
let
name_def
=
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
offset
,
end
:
offset
+
text
.len
(),
};
...
...
@@ -727,23 +743,26 @@ fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '
}
}
impl
Sig
for
ast
::
ForeignItem
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
NodeId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
)
->
Result
{
let
id
=
Some
(
self
.id
);
impl
<
'hir
>
Sig
for
hir
::
ForeignItem
<
'hir
>
{
fn
make
(
&
self
,
offset
:
usize
,
_
parent_id
:
Option
<
hir
::
HirId
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
id
=
Some
(
self
.hir_id
);
match
self
.kind
{
ast
::
ForeignItemKind
::
Fn
(
_
,
ref
sig
,
ref
generics
,
_
)
=>
{
let
decl
=
&
sig
.decl
;
hir
::
ForeignItemKind
::
Fn
(
decl
,
_
,
ref
generics
)
=>
{
let
mut
text
=
String
::
new
();
text
.push_str
(
"fn "
);
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.id
,
self
.ident
,
scx
)
?
;
let
mut
sig
=
name_and_generics
(
text
,
offset
,
generics
,
self
.hir_id
,
self
.ident
,
scx
)
?
;
sig
.text
.push
(
'('
);
for
i
in
&
decl
.inputs
{
// FIXME should descend into patterns to add defs.
sig
.text
.push_str
(
&
pprust
::
pat_to_string
(
&
i
.pat
));
for
i
in
decl
.inputs
{
sig
.text
.push_str
(
": "
);
let
nested
=
i
.
ty
.make
(
offset
+
sig
.text
.len
(),
Some
(
i
.
id
),
scx
)
?
;
let
nested
=
i
.
make
(
offset
+
sig
.text
.len
(),
Some
(
i
.hir_
id
),
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
sig
.text
.push
(
','
);
sig
.defs
.extend
(
nested
.defs
.into_iter
());
...
...
@@ -751,7 +770,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
}
sig
.text
.push
(
')'
);
if
let
ast
::
FnRetTy
::
Ty
(
ref
t
)
=
decl
.output
{
if
let
hir
::
FnRetTy
::
Return
(
ref
t
)
=
decl
.output
{
sig
.text
.push_str
(
" -> "
);
let
nested
=
t
.make
(
offset
+
sig
.text
.len
(),
None
,
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
...
...
@@ -762,14 +781,14 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
sig
)
}
ast
::
ForeignItemKind
::
Static
(
ref
ty
,
m
,
_
)
=>
{
hir
::
ForeignItemKind
::
Static
(
ref
ty
,
m
)
=>
{
let
mut
text
=
"static "
.to_owned
();
if
m
==
ast
::
Mutability
::
Mut
{
if
m
==
Mutability
::
Mut
{
text
.push_str
(
"mut "
);
}
let
name
=
self
.ident
.to_string
();
let
defs
=
vec!
[
SigElement
{
id
:
id_from_
node_id
(
self
.
id
,
scx
),
id
:
id_from_
hir_id
(
self
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
}];
...
...
@@ -781,11 +800,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
extend_sig
(
ty_sig
,
text
,
defs
,
vec!
[]))
}
ast
::
ForeignItemKind
::
TyAlias
(
..
)
=>
{
hir
::
ForeignItemKind
::
Type
=>
{
let
mut
text
=
"type "
.to_owned
();
let
name
=
self
.ident
.to_string
();
let
defs
=
vec!
[
SigElement
{
id
:
id_from_
node_id
(
self
.
id
,
scx
),
id
:
id_from_
hir_id
(
self
.hir_
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
}];
...
...
@@ -794,7 +813,6 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
Ok
(
Signature
{
text
,
defs
,
refs
:
vec!
[]
})
}
ast
::
ForeignItemKind
::
MacCall
(
..
)
=>
Err
(
"macro"
),
}
}
}
...
...
@@ -802,14 +820,14 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
fn
name_and_generics
(
mut
text
:
String
,
offset
:
usize
,
generics
:
&
ast
::
Generics
,
id
:
Node
Id
,
generics
:
&
hir
::
Generics
<
'_
>
,
id
:
hir
::
Hir
Id
,
name
:
Ident
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
name
=
name
.to_string
();
let
def
=
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
offset
+
text
.len
(),
end
:
offset
+
text
.len
()
+
name
.len
(),
};
...
...
@@ -821,16 +839,16 @@ fn name_and_generics(
}
fn
make_assoc_type_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Ident
,
bounds
:
Option
<
&
ast
::
GenericBounds
>
,
default
:
Option
<&
ast
::
Ty
>
,
bounds
:
Option
<
hir
::
GenericBounds
<
'_
>
>
,
default
:
Option
<&
hir
::
Ty
<
'_
>
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
mut
text
=
"type "
.to_owned
();
let
name
=
ident
.to_string
();
let
mut
defs
=
vec!
[
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
text
.len
(),
end
:
text
.len
()
+
name
.len
(),
}];
...
...
@@ -839,7 +857,7 @@ fn make_assoc_type_signature(
if
let
Some
(
bounds
)
=
bounds
{
text
.push_str
(
": "
);
// FIXME should descend into bounds
text
.push_str
(
&
pprust
::
bounds_to_string
(
bounds
));
text
.push_str
(
&
bounds_to_string
(
bounds
));
}
if
let
Some
(
default
)
=
default
{
text
.push_str
(
" = "
);
...
...
@@ -853,16 +871,16 @@ fn make_assoc_type_signature(
}
fn
make_assoc_const_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Symbol
,
ty
:
&
ast
::
Ty
,
default
:
Option
<&
ast
::
Expr
>
,
ty
:
&
hir
::
Ty
<
'_
>
,
default
:
Option
<&
hir
::
Expr
<
'_
>
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
let
mut
text
=
"const "
.to_owned
();
let
name
=
ident
.to_string
();
let
mut
defs
=
vec!
[
SigElement
{
id
:
id_from_
node
_id
(
id
,
scx
),
id
:
id_from_
hir
_id
(
id
,
scx
),
start
:
text
.len
(),
end
:
text
.len
()
+
name
.len
(),
}];
...
...
@@ -877,41 +895,38 @@ fn make_assoc_const_signature(
if
let
Some
(
default
)
=
default
{
text
.push_str
(
" = "
);
text
.push_str
(
&
pprust
::
expr_to_string
(
default
));
text
.push_str
(
&
id_to_string
(
&
scx
.tcx
.hir
(),
default
.hir_id
));
}
text
.push
(
';'
);
Ok
(
Signature
{
text
,
defs
,
refs
})
}
fn
make_method_signature
(
id
:
Node
Id
,
id
:
hir
::
Hir
Id
,
ident
:
Ident
,
generics
:
&
ast
::
Generics
,
m
:
&
ast
::
FnSig
,
generics
:
&
hir
::
Generics
<
'_
>
,
m
:
&
hir
::
FnSig
<
'_
>
,
scx
:
&
SaveContext
<
'_
,
'_
>
,
)
->
Result
{
// FIXME code dup with function signature
let
mut
text
=
String
::
new
();
if
let
ast
::
Const
::
Yes
(
_
)
=
m
.header.constness
{
if
let
hir
::
Constness
::
Const
=
m
.header.constness
{
text
.push_str
(
"const "
);
}
if
m
.header.asyncness
.is_async
()
{
if
hir
::
IsAsync
::
Async
==
m
.header.asyncness
{
text
.push_str
(
"async "
);
}
if
let
ast
::
Unsafe
::
Yes
(
_
)
=
m
.header.unsafety
{
if
let
hir
::
Unsafety
::
Unsafe
=
m
.header.unsafety
{
text
.push_str
(
"unsafe "
);
}
push_extern
(
&
mut
text
,
m
.header.ext
);
text
.push_str
(
"fn "
);
let
mut
sig
=
name_and_generics
(
text
,
0
,
generics
,
id
,
ident
,
scx
)
?
;
sig
.text
.push
(
'('
);
for
i
in
&
m
.decl.inputs
{
// FIXME should descend into patterns to add defs.
sig
.text
.push_str
(
&
pprust
::
pat_to_string
(
&
i
.pat
));
for
i
in
m
.decl.inputs
{
sig
.text
.push_str
(
": "
);
let
nested
=
i
.
ty
.make
(
sig
.text
.len
(),
Some
(
i
.
id
),
scx
)
?
;
let
nested
=
i
.
make
(
sig
.text
.len
(),
Some
(
i
.hir_
id
),
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
sig
.text
.push
(
','
);
sig
.defs
.extend
(
nested
.defs
.into_iter
());
...
...
@@ -919,7 +934,7 @@ fn make_method_signature(
}
sig
.text
.push
(
')'
);
if
let
ast
::
FnRetTy
::
Ty
(
ref
t
)
=
m
.decl.output
{
if
let
hir
::
FnRetTy
::
Return
(
ref
t
)
=
m
.decl.output
{
sig
.text
.push_str
(
" -> "
);
let
nested
=
t
.make
(
sig
.text
.len
(),
None
,
scx
)
?
;
sig
.text
.push_str
(
&
nested
.text
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录