diff --git a/Cargo.lock b/Cargo.lock index e33d09bc21179..77c9cfbc48626 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4257,6 +4257,7 @@ dependencies = [ "rustc_parse", "rustc_session", "rustc_span", + "rustc_target", "serde_json", ] diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs index e642915b86a5e..691c18cdc3254 100644 --- a/src/librustc_hir_pretty/lib.rs +++ b/src/librustc_hir_pretty/lib.rs @@ -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, + generics: &hir::Generics<'_>, + vis: &hir::Visibility<'_>, + arg_names: &[Ident], + body_id: Option, +) -> 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); @@ -385,7 +397,7 @@ impl<'a> State<'a> { &f.param_names[..], ); } - hir::TyKind::Def(..) => {} + hir::TyKind::Def(item, _) => self.ann.nested(self, Nested::Item(item)), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime) => { let mut first = true; diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 5948c88054ded..d648e1b5a14cc 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -20,5 +20,6 @@ rustc_parse = { path = "../librustc_parse" } serde_json = "1" rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } +rustc_target = { path = "../librustc_target" } rls-data = "0.19" rls-span = "0.5" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index a5e61ab9ab033..fbde6bfd9aae6 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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}; @@ -199,21 +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>) { + 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>) { - 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); - } + if let [segments @ .., _] = path.segments { + self.write_segments(segments) } } @@ -274,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); @@ -641,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 { @@ -744,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); @@ -758,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 { @@ -775,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( @@ -929,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); } } @@ -1133,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), + ) } } } @@ -1328,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, @@ -1343,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); @@ -1353,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), } } @@ -1430,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>) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8c7731c18e9c4..c246c2b30d1e2 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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; @@ -28,6 +28,7 @@ use rustc_session::output::{filename_for_metadata, out_filename}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::*; +use rustc_target::spec::abi::Abi; use std::cell::Cell; use std::default::Default; @@ -135,7 +136,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 { @@ -144,7 +145,20 @@ 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 { + unsafety: hir::Unsafety::Normal, + constness: hir::Constness::NotConst, + abi: Abi::Rust, + asyncness: hir::IsAsync::NotAsync, + }, + Some(item.ident.name), + generics, + &item.vis, + arg_names, + None, + ), parent: None, children: vec![], decl_id: None, @@ -191,7 +205,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, @@ -534,10 +556,14 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } } } - hir::ExprKind::Struct(hir::QPath::Resolved(_, path), ..) => { + hir::ExprKind::Struct(qpath, ..) => { + let segment = match qpath { + hir::QPath::Resolved(_, path) => path.segments.last().unwrap(), + hir::QPath::TypeRelative(_, segment) => segment, + }; 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; + let sub_span = segment.ident.span; filter!(self.span_utils, sub_span); let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { @@ -575,12 +601,12 @@ 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) } _ => { // FIXME - bug!(); + bug!("invalid expression: {:?}", expr); } } } @@ -627,8 +653,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } } - pub fn get_path_data(&self, id: hir::HirId, path: &hir::Path<'_>) -> Option { - path.segments.last().and_then(|seg| { + pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option { + 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)) }) } @@ -840,31 +870,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::>() - .join(", "), - ); - sig.push_str("> "); - } - sig.push('('); - sig.push_str(&decl.inputs.iter().map(ty_to_string).collect::>().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> { diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 6fec5cdba8b59..5f337f5f77033 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -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> = bounds @@ -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"), } } } diff --git a/src/test/ui/save-analysis/issue-73020.rs b/src/test/ui/save-analysis/issue-73020.rs new file mode 100644 index 0000000000000..87ce0933681c5 --- /dev/null +++ b/src/test/ui/save-analysis/issue-73020.rs @@ -0,0 +1,5 @@ +// compile-flags: -Zsave-analysis +use {self}; //~ ERROR E0431 + +fn main () { +} diff --git a/src/test/ui/save-analysis/issue-73020.stderr b/src/test/ui/save-analysis/issue-73020.stderr new file mode 100644 index 0000000000000..5bb3aae99975c --- /dev/null +++ b/src/test/ui/save-analysis/issue-73020.stderr @@ -0,0 +1,9 @@ +error[E0431]: `self` import can only appear in an import list with a non-empty prefix + --> $DIR/issue-73020.rs:2:6 + | +LL | use {self}; + | ^^^^ can only appear in an import list with a non-empty prefix + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0431`. diff --git a/src/test/ui/save-analysis/issue-73022.rs b/src/test/ui/save-analysis/issue-73022.rs new file mode 100644 index 0000000000000..9ad89a319ba3b --- /dev/null +++ b/src/test/ui/save-analysis/issue-73022.rs @@ -0,0 +1,13 @@ +// build-pass +// compile-flags: -Zsave-analysis +enum Enum2 { + Variant8 { _field: bool }, +} + +impl Enum2 { + fn new_variant8() -> Enum2 { + Self::Variant8 { _field: true } + } +} + +fn main() {}