Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/librustc_hir_pretty/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,18 @@ pub fn path_to_string(segment: &hir::Path<'_>) -> String {
to_string(NO_ANN, |s| s.print_path(segment, false))
}

pub fn fn_to_string(
decl: &hir::FnDecl<'_>,
header: hir::FnHeader,
name: Option<Symbol>,
generics: &hir::Generics<'_>,
vis: &hir::Visibility<'_>,
arg_names: &[Ident],
body_id: Option<hir::BodyId>,
) -> String {
to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, vis, arg_names, body_id))
}

impl<'a> State<'a> {
pub fn cbox(&mut self, u: usize) {
self.s.cbox(u);
Expand Down
79 changes: 54 additions & 25 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ 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_hir_pretty::{bounds_to_string, fn_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};
Expand Down Expand Up @@ -199,23 +199,23 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
self.dumper.compilation_opts(data);
}

fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
for seg in path.segments {
fn write_segments(&mut self, segments: impl IntoIterator<Item = &'tcx hir::PathSegment<'tcx>>) {
for seg in segments {
if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
self.dumper.dump_ref(data);
}
}
}

fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
self.write_segments(path.segments)
}

// 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: &'tcx hir::Path<'tcx>) {
if let [segments @ .., _] = path.segments {
for seg in segments {
if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
self.dumper.dump_ref(data);
}
}
self.write_segments(segments)
}
}

Expand Down Expand Up @@ -276,7 +276,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
v.process_generic_params(&generics, &method_data.qualname, hir_id);

method_data.value = crate::make_signature(&sig.decl, &generics);
method_data.value =
fn_to_string(sig.decl, sig.header, Some(ident.name), generics, vis, &[], None);
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);
Expand Down Expand Up @@ -643,7 +644,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
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.hir_ref_id, &trait_ref.path);
v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
}
v.process_generic_params(generics, "", item.hir_id);
for impl_item in impl_items {
Expand Down Expand Up @@ -746,7 +747,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
}

fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::Path<'tcx>) {
fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::QPath<'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);
Expand All @@ -760,14 +761,30 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
}

fn process_path(&mut self, id: hir::HirId, path: &'tcx hir::Path<'tcx>) {
if self.span.filter_generated(path.span) {
fn process_path(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
let span = match path {
hir::QPath::Resolved(_, path) => path.span,
hir::QPath::TypeRelative(_, segment) => segment.ident.span,
};
if self.span.filter_generated(span) {
return;
}
self.dump_path_ref(id, path);

// Type arguments
for seg in path.segments {
let segments = match path {
hir::QPath::Resolved(ty, path) => {
if let Some(ty) = ty {
self.visit_ty(ty);
}
path.segments
}
hir::QPath::TypeRelative(ty, segment) => {
self.visit_ty(ty);
std::slice::from_ref(*segment)
}
};
for seg in segments {
if let Some(ref generic_args) = seg.args {
for arg in generic_args.args {
if let hir::GenericArg::Type(ref ty) = arg {
Expand All @@ -777,7 +794,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}
}

self.write_sub_paths_truncated(path);
if let hir::QPath::Resolved(_, path) = path {
self.write_sub_paths_truncated(path);
}
}

fn process_struct_lit(
Expand Down Expand Up @@ -931,9 +950,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
}

for (id, ref path) in collector.collected_paths {
if let hir::QPath::Resolved(_, path) = path {
self.process_path(id, path);
}
self.process_path(id, path);
}
}

Expand Down Expand Up @@ -1135,7 +1152,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
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)
self.process_path(
trait_ref.trait_ref.hir_ref_id,
&hir::QPath::Resolved(None, &trait_ref.trait_ref.path),
)
}
}
}
Expand Down Expand Up @@ -1330,13 +1350,16 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
self.process_macro_use(t.span);
match t.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
hir::TyKind::Path(ref path) => {
if generated_code(t.span) {
return;
}

if let Some(id) = self.lookup_def_id(t.hir_id) {
let sub_span = path.segments.last().unwrap().ident.span;
let sub_span = match path {
hir::QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
hir::QPath::TypeRelative(_, segment) => segment.ident.span,
};
let span = self.span_from_span(sub_span);
self.dumper.dump_ref(Ref {
kind: RefKind::Type,
Expand All @@ -1345,8 +1368,10 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
});
}

self.write_sub_paths_truncated(path);
intravisit::walk_path(self, path);
if let hir::QPath::Resolved(_, path) = path {
self.write_sub_paths_truncated(path);
}
intravisit::walk_qpath(self, path, t.hir_id, t.span);
}
hir::TyKind::Array(ref ty, ref anon_const) => {
self.visit_ty(ty);
Expand All @@ -1355,6 +1380,10 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
v.visit_expr(&map.body(anon_const.body).value)
});
}
hir::TyKind::Def(item_id, _) => {
let item = self.tcx.hir().item(item_id.id);
self.nest_tables(self.tcx.hir().local_def_id(item_id.id), |v| v.visit_item(item));
}
_ => intravisit::walk_ty(self, t),
}
}
Expand Down Expand Up @@ -1432,8 +1461,8 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
self.visit_expr(&arm.body);
}

fn visit_path(&mut self, p: &'tcx hir::Path<'tcx>, id: hir::HirId) {
self.process_path(id, p);
fn visit_qpath(&mut self, path: &'tcx hir::QPath<'tcx>, id: hir::HirId, _: Span) {
self.process_path(id, path);
}

fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
Expand Down
67 changes: 35 additions & 32 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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_hir_pretty::{fn_to_string, ty_to_string};
use rustc_middle::hir::map::Map;
use rustc_middle::middle::cstore::ExternCrate;
use rustc_middle::middle::privacy::AccessLevels;
Expand Down Expand Up @@ -135,7 +135,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
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 {
hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
filter!(self.span_utils, item.ident.span);

Some(Data::DefData(Def {
Expand All @@ -144,7 +144,23 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
span: self.span_from_span(item.ident.span),
name: item.ident.to_string(),
qualname,
value: make_signature(decl, generics),
value: fn_to_string(
decl,
hir::FnHeader {
// functions in extern block are implicitly unsafe
unsafety: hir::Unsafety::Unsafe,
// functions in extern block cannot be const
constness: hir::Constness::NotConst,
abi: self.tcx.hir().get_foreign_abi(item.hir_id),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I managed to get the real abi of the extern block using get_foreign_abi. I don't think we should change the hir to store a FnHeader in ForeignItem::Fn. I tried it locally, it works, but its really invasive and somehow orthogonal to this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, let's stick with what we have. Thanks!

// functions in extern block cannot be async
asyncness: hir::IsAsync::NotAsync,
},
Some(item.ident.name),
generics,
&item.vis,
arg_names,
None,
),
parent: None,
children: vec![],
decl_id: None,
Expand Down Expand Up @@ -191,7 +207,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
span: self.span_from_span(item.ident.span),
name: item.ident.to_string(),
qualname,
value: make_signature(&sig.decl, generics),
value: fn_to_string(
sig.decl,
sig.header,
Some(item.ident.name),
generics,
&item.vis,
&[],
None,
),
parent: None,
children: vec![],
decl_id: None,
Expand Down Expand Up @@ -579,7 +603,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
}))
}
hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
hir::ExprKind::Path(ref path) => {
self.get_path_data(expr.hir_id, path).map(Data::RefData)
}
_ => {
Expand Down Expand Up @@ -631,8 +655,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
}
}

pub fn get_path_data(&self, id: hir::HirId, path: &hir::Path<'_>) -> Option<Ref> {
path.segments.last().and_then(|seg| {
pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option<Ref> {
let segment = match path {
hir::QPath::Resolved(_, path) => path.segments.last(),
hir::QPath::TypeRelative(_, segment) => Some(*segment),
};
segment.and_then(|seg| {
self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
})
}
Expand Down Expand Up @@ -844,31 +872,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
}
}

fn make_signature(decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>) -> String {
let mut sig = "fn ".to_owned();
if !generics.params.is_empty() {
sig.push('<');
sig.push_str(
&generics
.params
.iter()
.map(|param| param.name.ident().to_string())
.collect::<Vec<_>>()
.join(", "),
);
sig.push_str("> ");
}
sig.push('(');
sig.push_str(&decl.inputs.iter().map(ty_to_string).collect::<Vec<_>>().join(", "));
sig.push(')');
match decl.output {
hir::FnRetTy::DefaultReturn(_) => sig.push_str(" -> ()"),
hir::FnRetTy::Return(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
}

sig
}

// An AST visitor for collecting paths (e.g., the names of structs) and formal
// variables (idents) from patterns.
struct PathCollector<'l> {
Expand Down
26 changes: 21 additions & 5 deletions src/librustc_save_analysis/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ impl<'hir> Sig for hir::Ty<'hir> {
})
}
}
hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
let nested_ty = ty.make(offset + 1, id, scx)?;
let prefix = format!("<{}>::", nested_ty.text,);

let name = path_segment_to_string(segment);
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
let id = id_from_def_id(res.def_id());

let start = offset + prefix.len();
let end = start + name.len();
Ok(Signature {
text: prefix + &name,
defs: vec![],
refs: vec![SigElement { id, start, end }],
})
}
hir::TyKind::TraitObject(bounds, ..) => {
// FIXME recurse into bounds
let bounds: Vec<hir::GenericBound<'_>> = bounds
Expand Down Expand Up @@ -308,11 +324,11 @@ impl<'hir> Sig for hir::Ty<'hir> {
let text = format!("[{}; {}]", nested_ty.text, expr);
Ok(replace_text(nested_ty, text))
}
hir::TyKind::Typeof(_)
| hir::TyKind::Infer
| hir::TyKind::Def(..)
| hir::TyKind::Path(..)
| hir::TyKind::Err => Err("Ty"),
hir::TyKind::Def(item_id, _) => {
let item = scx.tcx.hir().item(item_id.id);
item.make(offset, Some(item_id.id), scx)
}
hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
}
}
}
Expand Down