From 7f09b1f6a64339370440025d50d0ad4a7f239734 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 26 Apr 2016 15:23:46 -0700 Subject: [PATCH 01/12] std: Allow creating ExitStatus from raw values Sometimes a process may be waited on externally from the standard library, in which case it can be useful to create a raw `ExitStatus` structure to return. This commit extends the existing Unix `ExitStatusExt` extension trait and adds a new Windows-specific `ExitStatusExt` extension trait to do this. The methods are currently called `ExitStatus::from_raw`. cc #32713 --- src/libstd/process.rs | 6 ++++++ src/libstd/sys/unix/ext/process.rs | 9 +++++++++ src/libstd/sys/unix/process.rs | 6 ++++++ src/libstd/sys/windows/ext/process.rs | 15 +++++++++++++++ src/libstd/sys/windows/process.rs | 6 ++++++ 5 files changed, 42 insertions(+) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 1d2516a4c4099..3ff76a7bee302 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -459,6 +459,12 @@ impl AsInner for ExitStatus { fn as_inner(&self) -> &imp::ExitStatus { &self.0 } } +impl FromInner for ExitStatus { + fn from_inner(s: imp::ExitStatus) -> ExitStatus { + ExitStatus(s) + } +} + #[stable(feature = "process", since = "1.0.0")] impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 7f31cf9f3bf80..b0fed2f4694bf 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -132,6 +132,11 @@ impl CommandExt for process::Command { /// Unix-specific extensions to `std::process::ExitStatus` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { + /// Creates a new `ExitStatus` from the raw underlying `i32` return value of + /// a process. + #[unstable(feature = "exit_status_from", issue = "32713")] + fn from_raw(raw: i32) -> Self; + /// If the process was terminated by a signal, returns that signal. #[stable(feature = "rust1", since = "1.0.0")] fn signal(&self) -> Option; @@ -139,6 +144,10 @@ pub trait ExitStatusExt { #[stable(feature = "rust1", since = "1.0.0")] impl ExitStatusExt for process::ExitStatus { + fn from_raw(raw: i32) -> Self { + process::ExitStatus::from_inner(From::from(raw)) + } + fn signal(&self) -> Option { self.as_inner().signal() } diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 270c2096b2c3b..72e02a487e36c 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -550,6 +550,12 @@ impl ExitStatus { } } +impl From for ExitStatus { + fn from(a: c_int) -> ExitStatus { + ExitStatus(a) + } +} + impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(code) = self.code() { diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index f6ee59eec327a..56c6a73d4f82b 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -81,3 +81,18 @@ impl IntoRawHandle for process::ChildStderr { self.into_inner().into_handle().into_raw() as *mut _ } } + +/// Windows-specific extensions to `std::process::ExitStatus` +#[unstable(feature = "exit_status_from", issue = "32713")] +pub trait ExitStatusExt { + /// Creates a new `ExitStatus` from the raw underlying `u32` return value of + /// a process. + fn from_raw(raw: u32) -> Self; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExitStatusExt for process::ExitStatus { + fn from_raw(raw: u32) -> Self { + process::ExitStatus::from_inner(From::from(raw)) + } +} diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f4957297581bb..a0ad866c69d41 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -337,6 +337,12 @@ impl ExitStatus { } } +impl From for ExitStatus { + fn from(u: c::DWORD) -> ExitStatus { + ExitStatus(u) + } +} + impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "exit code: {}", self.0) From dca29d7b0832a5d75db18be96833a8885ef2c2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Tue, 3 May 2016 12:54:29 +0200 Subject: [PATCH 02/12] save-analysis: use a decoupled representation for dumped data Closes #33348 --- src/librustc_save_analysis/csv_dumper.rs | 119 ++-- src/librustc_save_analysis/data.rs | 88 +-- src/librustc_save_analysis/dump.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 111 ++-- src/librustc_save_analysis/external_data.rs | 640 ++++++++++++++++++++ src/librustc_save_analysis/json_dumper.rs | 585 +----------------- src/librustc_save_analysis/lib.rs | 22 +- src/librustc_save_analysis/span_utils.rs | 23 +- 8 files changed, 752 insertions(+), 838 deletions(-) create mode 100644 src/librustc_save_analysis/external_data.rs diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs index 4d6512db861e5..626537a4ae9a0 100644 --- a/src/librustc_save_analysis/csv_dumper.rs +++ b/src/librustc_save_analysis/csv_dumper.rs @@ -10,25 +10,20 @@ use std::io::Write; -use rustc::hir::def_id::{DefId, DefIndex}; -use syntax::codemap::Span; - -use super::data::*; +use super::external_data::*; use super::dump::Dump; -use super::span_utils::SpanUtils; -pub struct CsvDumper<'tcx, 'b, W: 'b> { - output: &'b mut W, - span: SpanUtils<'tcx> +pub struct CsvDumper<'b, W: 'b> { + output: &'b mut W } -impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> { - pub fn new(writer: &'b mut W, span: SpanUtils<'a>) -> CsvDumper<'a, 'b, W> { - CsvDumper { output: writer, span: span } +impl<'b, W: Write> CsvDumper<'b, W> { + pub fn new(writer: &'b mut W) -> CsvDumper<'b, W> { + CsvDumper { output: writer } } - fn record(&mut self, kind: &str, span: Span, values: String) { - let span_str = self.span.extent_str(span); + fn record(&mut self, kind: &str, span: SpanData, values: String) { + let span_str = span_extent_str(span); if let Err(_) = write!(self.output, "{},{}{}\n", kind, span_str, values) { error!("Error writing output"); } @@ -41,7 +36,7 @@ impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> { } } -impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { +impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { fn crate_prelude(&mut self, data: CratePreludeData) { let values = make_values_str(&[ ("name", &data.crate_name), @@ -93,21 +88,14 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn impl_data(&mut self, data: ImplData) { - let self_ref = data.self_ref.unwrap_or(null_def_id()); - let trait_ref = data.trait_ref.unwrap_or(null_def_id()); - let id = data.id.to_string(); - let ref_id = self_ref.index.as_usize().to_string(); - let ref_id_crate = self_ref.krate.to_string(); - let trait_id = trait_ref.index.as_usize().to_string(); - let trait_id_crate = trait_ref.krate.to_string(); + let ref_id = data.self_ref.unwrap_or(Id::null()).to_string(); + let trait_id = data.trait_ref.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("id", &id), ("refid", &ref_id), - ("refidcrate", &ref_id_crate), ("traitid", &trait_id), - ("traitidcrate", &trait_id_crate), ("scopeid", &scope) ]); @@ -115,33 +103,24 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn inheritance(&mut self, data: InheritanceData) { - let base_id = data.base_id.index.as_usize().to_string(); - let base_crate = data.base_id.krate.to_string(); - let deriv_id = data.deriv_id.to_string(); - let deriv_crate = 0.to_string(); - let values = make_values_str(&[ - ("base", &base_id), - ("basecrate", &base_crate), - ("derived", &deriv_id), - ("derivedcrate", &deriv_crate) - ]); + let base_id = data.base_id.to_string(); + let deriv_id = data.deriv_id.to_string(); + let values = make_values_str(&[ + ("base", &base_id), + ("derived", &deriv_id), + ]); self.record("inheritance", data.span, values); } fn function(&mut self, data: FunctionData) { - let (decl_id, decl_crate) = match data.declaration { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (String::new(), String::new()) - }; - let id = data.id.to_string(); + let decl_id = data.declaration.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), ("declid", &decl_id), - ("declidcrate", &decl_crate), ("scopeid", &scope) ]); @@ -149,12 +128,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn function_ref(&mut self, data: FunctionRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); + let ref_id = data.ref_id.to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("refid", &ref_id), - ("refidcrate", &ref_crate), ("qualname", ""), ("scopeid", &scope) ]); @@ -163,13 +140,11 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn function_call(&mut self, data: FunctionCallData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); + let ref_id = data.ref_id.to_string(); let qualname = String::new(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("refid", &ref_id), - ("refidcrate", &ref_crate), ("qualname", &qualname), ("scopeid", &scope) ]); @@ -190,21 +165,12 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn method_call(&mut self, data: MethodCallData) { - let (dcn, dck) = match data.decl_id { - Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()), - None => (String::new(), String::new()), - }; - - let ref_id = data.ref_id.unwrap_or(null_def_id()); - - let def_id = ref_id.index.as_usize().to_string(); - let def_crate = ref_id.krate.to_string(); + let decl_id = data.decl_id.unwrap_or(Id::null()).to_string(); + let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ - ("refid", &def_id), - ("refidcrate", &def_crate), - ("declid", &dcn), - ("declidcrate", &dck), + ("refid", &ref_id), + ("declid", &decl_id), ("scopeid", &scope) ]); @@ -245,15 +211,11 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn mod_ref(&mut self, data: ModRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; + let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("refid", &ref_id), - ("refidcrate", &ref_crate), ("qualname", &data.qualname), ("scopeid", &scope) ]); @@ -320,15 +282,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn type_ref(&mut self, data: TypeRefData) { - let (ref_id, ref_crate) = match data.ref_id { - Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), - None => (0.to_string(), 0.to_string()) - }; - + let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("refid", &ref_id), - ("refidcrate", &ref_crate), ("qualname", &data.qualname), ("scopeid", &scope) ]); @@ -348,16 +305,12 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn use_data(&mut self, data: UseData) { - let mod_id = data.mod_id.unwrap_or(null_def_id()); - let id = data.id.to_string(); - let ref_id = mod_id.index.as_usize().to_string(); - let ref_crate = mod_id.krate.to_string(); + let mod_id = data.mod_id.unwrap_or(Id::null()).to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ ("id", &id), - ("refid", &ref_id), - ("refidcrate", &ref_crate), + ("mod_id", &mod_id), ("name", &data.name), ("scopeid", &scope) ]); @@ -395,12 +348,10 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { } fn variable_ref(&mut self, data: VariableRefData) { - let ref_id = data.ref_id.index.as_usize().to_string(); - let ref_crate = data.ref_id.krate.to_string(); + let id = data.ref_id.to_string(); let scope = data.scope.to_string(); let values = make_values_str(&[ - ("refid", &ref_id), - ("refidcrate", &ref_crate), + ("id", &id), ("qualname", ""), ("scopeid", &scope) ]); @@ -431,9 +382,9 @@ fn make_values_str(pairs: &[(&'static str, &str)]) -> String { }) } -fn null_def_id() -> DefId { - DefId { - krate: 0, - index: DefIndex::new(0), - } +fn span_extent_str(span: SpanData) -> String { + format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{}\ + file_line_end,{},file_col_end,{},byte_end,{}", + span.file_name, span.line_start, span.column_start, span.byte_start, + span.line_end, span.column_end, span.byte_end) } diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs index b79c459920a3e..d13e01cffd4cf 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -16,39 +16,8 @@ use std::hash::Hasher; use rustc::hir::def_id::DefId; -use rustc::ty; use syntax::ast::{CrateNum, NodeId}; -use syntax::codemap::{Span, CodeMap}; - -#[derive(Debug, Clone, RustcEncodable)] -pub struct SpanData { - file_name: String, - byte_start: u32, - byte_end: u32, - /// 1-based. - line_start: usize, - line_end: usize, - /// 1-based, character offset. - column_start: usize, - column_end: usize, -} - -impl SpanData { - pub fn from_span(span: Span, cm: &CodeMap) -> SpanData { - let start = cm.lookup_char_pos(span.lo); - let end = cm.lookup_char_pos(span.hi); - - SpanData { - file_name: start.file.name.clone(), - byte_start: span.lo.0, - byte_end: span.hi.0, - line_start: start.line, - line_end: end.line, - column_start: start.col.0 + 1, - column_end: end.col.0 + 1, - } - } -} +use syntax::codemap::Span; pub struct CrateData { pub name: String, @@ -359,58 +328,3 @@ pub struct VariableRefData { pub scope: NodeId, pub ref_id: DefId, } - -// Emitted ids are used to cross-reference items across crates. DefIds and -// NodeIds do not usually correspond in any way. The strategy is to use the -// index from the DefId as a crate-local id. However, within a crate, DefId -// indices and NodeIds can overlap. So, we must adjust the NodeIds. If an -// item can be identified by a DefId as well as a NodeId, then we use the -// DefId index as the id. If it can't, then we have to use the NodeId, but -// need to adjust it so it will not clash with any possible DefId index. -pub fn normalize_node_id<'a>(tcx: &ty::TyCtxt<'a>, id: NodeId) -> usize { - match tcx.map.opt_local_def_id(id) { - Some(id) => id.index.as_usize(), - None => id as usize + tcx.map.num_local_def_ids() - } -} - -// Macro to implement a normalize() function (see below for usage) -macro_rules! impl_normalize { - ($($t:ty => $($field:ident),*);*) => { - $( - impl $t { - pub fn normalize<'a>(mut self, tcx: &ty::TyCtxt<'a>) -> $t { - $( - self.$field = normalize_node_id(tcx, self.$field) as u32; - )* - self - } - } - )* - } -} - -impl_normalize! { - EnumData => id, scope; - ExternCrateData => id, scope; - FunctionCallData => scope; - FunctionData => id, scope; - FunctionRefData => scope; - ImplData => id, scope; - InheritanceData => deriv_id; - MacroUseData => scope; - MethodCallData => scope; - MethodData => id, scope; - ModData => id, scope; - ModRefData => scope; - StructData => ctor_id, id, scope; - StructVariantData => id, scope; - TupleVariantData => id, scope; - TraitData => id, scope; - TypedefData => id; - TypeRefData => scope; - UseData => id, scope; - UseGlobData => id, scope; - VariableData => id; - VariableRefData => scope -} diff --git a/src/librustc_save_analysis/dump.rs b/src/librustc_save_analysis/dump.rs index 6d15acff1f1cc..adbf1e0a35ec1 100644 --- a/src/librustc_save_analysis/dump.rs +++ b/src/librustc_save_analysis/dump.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::data::*; +use super::external_data::*; pub trait Dump { fn crate_prelude(&mut self, CratePreludeData) {} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d12d1c8aae057..7a411969363e9 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -45,6 +45,7 @@ use syntax::ptr::P; use super::{escape, generated_code, SaveContext, PathCollector}; use super::data::*; use super::dump::Dump; +use super::external_data::Lower; use super::span_utils::SpanUtils; use super::recorder; @@ -133,7 +134,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: krate.span, }; - self.dumper.crate_prelude(data); + self.dumper.crate_prelude(data.lower(self.tcx)); } // Return all non-empty prefixes of a path. @@ -203,7 +204,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, scope: self.cur_scope, ref_id: None - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } @@ -228,7 +229,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, scope: self.cur_scope, ref_id: None - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } @@ -249,7 +250,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: *span, qualname: qualname.to_owned(), scope: 0 - }); + }.lower(self.tcx)); // write the other sub-paths if len <= 2 { @@ -262,7 +263,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname.to_owned(), scope: self.cur_scope, ref_id: None - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } @@ -304,7 +305,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: Some(def_id), scope: scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Def::Struct(..) | Def::Enum(..) | @@ -316,7 +317,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: Some(def_id), scope: scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Def::Static(_, _) | Def::Const(_) | @@ -329,14 +330,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: def_id, scope: scope, name: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Def::Fn(..) => { self.dumper.function_ref(FunctionRefData { span: sub_span.expect("No span found for fn ref"), ref_id: def_id, scope: scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Def::SelfTy(..) | Def::Label(_) | @@ -371,7 +372,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { type_value: typ, value: String::new(), scope: 0 - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } } @@ -389,7 +390,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if body.is_some() { if !self.span.filter_generated(Some(method_data.span), span) { - self.dumper.function(method_data.clone().normalize(&self.tcx)); + self.dumper.function(method_data.clone().lower(self.tcx)); } self.process_formals(&sig.decl.inputs, &method_data.qualname); } else { @@ -399,7 +400,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: method_data.span, scope: method_data.scope, qualname: method_data.qualname.clone(), - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } self.process_generic_params(&sig.generics, span, &method_data.qualname, id); @@ -424,7 +425,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref, self.cur_scope); if let Some(trait_ref_data) = trait_ref_data { if !self.span.filter_generated(Some(trait_ref_data.span), trait_ref.path.span) { - self.dumper.type_ref(trait_ref_data.normalize(&self.tcx)); + self.dumper.type_ref(trait_ref_data.lower(self.tcx)); } visit::walk_path(self, &trait_ref.path); @@ -435,9 +436,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let field_data = self.save_ctxt.get_field_data(field, parent_id); if let Some(mut field_data) = field_data { if !self.span.filter_generated(Some(field_data.span), field.span) { - field_data.scope = normalize_node_id(&self.tcx, field_data.scope) as u32; field_data.value = String::new(); - self.dumper.variable(field_data.normalize(&self.tcx)); + self.dumper.variable(field_data.lower(self.tcx)); } } } @@ -466,7 +466,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { id: param.id, qualname: name, value: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } self.visit_generics(generics); @@ -480,7 +480,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(fn_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, FunctionData, item.span); if !self.span.filter_generated(Some(fn_data.span), item.span) { - self.dumper.function(fn_data.clone().normalize(&self.tcx)); + self.dumper.function(fn_data.clone().lower(self.tcx)); } self.process_formals(&decl.inputs, &fn_data.qualname); @@ -502,9 +502,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(var_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(var_data, VariableData, item.span); if !self.span.filter_generated(Some(var_data.span), item.span) { - let mut var_data = var_data; - var_data.scope = normalize_node_id(&self.tcx, var_data.scope) as u32; - self.dumper.variable(var_data.normalize(&self.tcx)); + self.dumper.variable(var_data.lower(self.tcx)); } } self.visit_ty(&typ); @@ -529,8 +527,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname, value: self.span.snippet(expr.span), type_value: ty_to_string(&typ), - scope: normalize_node_id(&self.tcx, self.cur_scope) as u32 - }.normalize(&self.tcx)); + scope: self.cur_scope + }.lower(self.tcx)); } // walk type and init value @@ -554,7 +552,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname.clone(), scope: self.cur_scope, value: val - }.normalize(&self.tcx)); + }.lower(self.tcx)); } @@ -577,9 +575,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { Some(data) => data, }; down_cast_data!(enum_data, EnumData, item.span); - let normalized = enum_data.clone().normalize(&self.tcx); - if !self.span.filter_generated(Some(normalized.span), item.span) { - self.dumper.enum_data(normalized); + if !self.span.filter_generated(Some(enum_data.span), item.span) { + self.dumper.enum_data(enum_data.clone().lower(self.tcx)); } for variant in &enum_definition.variants { @@ -600,7 +597,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { type_value: enum_data.qualname.clone(), value: val, scope: enum_data.scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } _ => { @@ -614,7 +611,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { type_value: enum_data.qualname.clone(), value: val, scope: enum_data.scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } } @@ -640,12 +637,12 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(ref self_ref) = impl_data.self_ref { has_self_ref = true; if !self.span.filter_generated(Some(self_ref.span), item.span) { - self.dumper.type_ref(self_ref.clone().normalize(&self.tcx)); + self.dumper.type_ref(self_ref.clone().lower(self.tcx)); } } if let Some(ref trait_ref_data) = impl_data.trait_ref { if !self.span.filter_generated(Some(trait_ref_data.span), item.span) { - self.dumper.type_ref(trait_ref_data.clone().normalize(&self.tcx)); + self.dumper.type_ref(trait_ref_data.clone().lower(self.tcx)); } visit::walk_path(self, &trait_ref.as_ref().unwrap().path); @@ -658,7 +655,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: impl_data.scope, trait_ref: impl_data.trait_ref.map(|d| d.ref_id.unwrap()), self_ref: impl_data.self_ref.map(|d| d.ref_id.unwrap()) - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } if !has_self_ref { @@ -685,7 +682,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { qualname: qualname.clone(), scope: self.cur_scope, value: val - }.normalize(&self.tcx)); + }.lower(self.tcx)); } // super-traits @@ -708,7 +705,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: Some(id), scope: self.cur_scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } if !self.span.filter_generated(sub_span, trait_ref.path.span) { @@ -717,7 +714,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: sub_span, base_id: id, deriv_id: item.id - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } } @@ -734,7 +731,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(mod_data, ModData, item.span); if !self.span.filter_generated(Some(mod_data.span), item.span) { - self.dumper.mod_data(mod_data.normalize(&self.tcx)); + self.dumper.mod_data(mod_data.lower(self.tcx)); } } } @@ -765,14 +762,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: Some(vrd.ref_id), scope: vrd.scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Some(recorder::FnRef) => { self.dumper.function_ref(FunctionRefData { span: vrd.span, ref_id: vrd.ref_id, scope: vrd.scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Some(recorder::ModRef) => { self.dumper.mod_ref( ModRefData { @@ -780,27 +777,27 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: Some(vrd.ref_id), scope: vrd.scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } Some(recorder::VarRef) | None - => self.dumper.variable_ref(vrd.normalize(&self.tcx)) + => self.dumper.variable_ref(vrd.lower(self.tcx)) } } } Data::TypeRefData(trd) => { if !self.span.filter_generated(Some(trd.span), path.span) { - self.dumper.type_ref(trd.normalize(&self.tcx)); + self.dumper.type_ref(trd.lower(self.tcx)); } } Data::MethodCallData(mcd) => { if !self.span.filter_generated(Some(mcd.span), path.span) { - self.dumper.method_call(mcd.normalize(&self.tcx)); + self.dumper.method_call(mcd.lower(self.tcx)); } } Data::FunctionCallData(fcd) => { if !self.span.filter_generated(Some(fcd.span), path.span) { - self.dumper.function_call(fcd.normalize(&self.tcx)); + self.dumper.function_call(fcd.lower(self.tcx)); } } _ => { @@ -842,7 +839,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { down_cast_data!(struct_lit_data, TypeRefData, ex.span); if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) { - self.dumper.type_ref(struct_lit_data.normalize(&self.tcx)); + self.dumper.type_ref(struct_lit_data.lower(self.tcx)); } let scope = self.save_ctxt.enclosing_scope(ex.id); @@ -852,7 +849,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { .get_field_ref_data(field, variant, scope) { if !self.span.filter_generated(Some(field_data.span), field.ident.span) { - self.dumper.variable_ref(field_data.normalize(&self.tcx)); + self.dumper.variable_ref(field_data.lower(self.tcx)); } } @@ -867,7 +864,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { if let Some(mcd) = self.save_ctxt.get_expr_data(ex) { down_cast_data!(mcd, MethodCallData, ex.span); if !self.span.filter_generated(Some(mcd.span), ex.span) { - self.dumper.method_call(mcd.normalize(&self.tcx)); + self.dumper.method_call(mcd.lower(self.tcx)); } } @@ -892,7 +889,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ref_id: f.did, scope: self.cur_scope, name: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } self.visit_pat(&field.pat); @@ -931,7 +928,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { value: value, type_value: typ, scope: 0 - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } } @@ -961,7 +958,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { span: sub_span, name: data.name.clone(), qualname: qualname.clone() - }); + }.lower(self.tcx)); } } if !self.mac_uses.contains(&data.span) { @@ -974,7 +971,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { scope: data.scope, callee_span: data.callee_span, imported: data.imported - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } } @@ -1014,7 +1011,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, mod_id: mod_id, name: ident.to_string(), scope: self.cur_scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } self.write_sub_paths_truncated(path, true); } @@ -1037,7 +1034,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, id: item.id, names: names, scope: self.cur_scope - }.normalize(&self.tcx)); + }.lower(self.tcx)); } self.write_sub_paths(path, true); } @@ -1081,7 +1078,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, location: location, span: alias_span.expect("No span found for extern crate"), scope: self.cur_scope, - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } Fn(ref decl, _, _, _, ref ty_params, ref body) => @@ -1115,7 +1112,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, id: item.id, qualname: qualname.clone(), value: value - }.normalize(&self.tcx)); + }.lower(self.tcx)); } self.visit_ty(&ty); @@ -1195,7 +1192,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, ref_id: Some(id), scope: self.cur_scope, qualname: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } @@ -1232,7 +1229,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, if let Some(field_data) = self.save_ctxt.get_expr_data(ex) { down_cast_data!(field_data, VariableRefData, ex.span); if !self.span.filter_generated(Some(field_data.span), ex.span) { - self.dumper.variable_ref(field_data.normalize(&self.tcx)); + self.dumper.variable_ref(field_data.lower(self.tcx)); } } } @@ -1250,7 +1247,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, ref_id: def.struct_variant().fields[idx.node].did, scope: self.cur_scope, name: String::new() - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } ty::TyTuple(_) => {} @@ -1343,7 +1340,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, value: value, type_value: String::new(), scope: 0 - }.normalize(&self.tcx)); + }.lower(self.tcx)); } } Def::Variant(..) | Def::Enum(..) | diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs new file mode 100644 index 0000000000000..13923d4646426 --- /dev/null +++ b/src/librustc_save_analysis/external_data.rs @@ -0,0 +1,640 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt::{self, Display, Formatter}; + +use rustc::hir::def_id::DefId; +use rustc::hir::map::Map; +use rustc::ty::TyCtxt; +use syntax::ast::{CrateNum, NodeId}; +use syntax::codemap::{Span, CodeMap}; + +use super::data; + +// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet +pub trait Lower { + type Target; + fn lower(self, tcx: &TyCtxt) -> Self::Target; +} + +// We use a newtype to enforce conversion of all NodeIds (which are u32s as well) +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable)] +pub struct Id(u32); + +impl Id { + pub fn from_def_id(id: DefId) -> Id { + Id(id.index.as_u32()) + } + + // FIXME: this function is called with non-local NodeIds. This means that they + // cannot be mapped to a DefId. We should remove those calls. In the meantime, + // we return a "null Id" when the NodeId is invalid. + pub fn from_node_id(id: NodeId, map: &Map) -> Id { + map.opt_local_def_id(id).map(|id| Id(id.index.as_u32())) + .unwrap_or(Id::null()) + } + + pub fn null() -> Id { + Id(u32::max_value()) + } +} + +impl Display for Id { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +#[derive(Clone, Debug, RustcEncodable)] +pub struct SpanData { + pub file_name: String, + pub byte_start: u32, + pub byte_end: u32, + /// 1-based. + pub line_start: usize, + pub line_end: usize, + /// 1-based, character offset. + pub column_start: usize, + pub column_end: usize, +} + +impl SpanData { + pub fn from_span(span: Span, cm: &CodeMap) -> SpanData { + let start = cm.lookup_char_pos(span.lo); + let end = cm.lookup_char_pos(span.hi); + + SpanData { + file_name: start.file.name.clone(), + byte_start: span.lo.0, + byte_end: span.hi.0, + line_start: start.line, + line_end: end.line, + column_start: start.col.0 + 1, + column_end: end.col.0 + 1, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct CratePreludeData { + pub crate_name: String, + pub crate_root: String, + pub external_crates: Vec, + pub span: SpanData, +} + +impl Lower for data::CratePreludeData { + type Target = CratePreludeData; + + fn lower(self, tcx: &TyCtxt) -> CratePreludeData { + CratePreludeData { + crate_name: self.crate_name, + crate_root: self.crate_root, + external_crates: self.external_crates, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + } + } +} + +/// Data for enum declarations. +#[derive(Clone, Debug, RustcEncodable)] +pub struct EnumData { + pub id: Id, + pub value: String, + pub qualname: String, + pub span: SpanData, + pub scope: Id, +} + +impl Lower for data::EnumData { + type Target = EnumData; + + fn lower(self, tcx: &TyCtxt) -> EnumData { + EnumData { + id: Id::from_node_id(self.id, &tcx.map), + value: self.value, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +/// Data for extern crates. +#[derive(Debug, RustcEncodable)] +pub struct ExternCrateData { + pub id: Id, + pub name: String, + pub crate_num: CrateNum, + pub location: String, + pub span: SpanData, + pub scope: Id, +} + +impl Lower for data::ExternCrateData { + type Target = ExternCrateData; + + fn lower(self, tcx: &TyCtxt) -> ExternCrateData { + ExternCrateData { + id: Id::from_node_id(self.id, &tcx.map), + name: self.name, + crate_num: self.crate_num, + location: self.location, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionCallData { + pub span: SpanData, + pub scope: Id, + pub ref_id: Id, +} + +impl Lower for data::FunctionCallData { + type Target = FunctionCallData; + + fn lower(self, tcx: &TyCtxt) -> FunctionCallData { + FunctionCallData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: Id::from_def_id(self.ref_id), + } + } +} + +/// Data for all kinds of functions and methods. +#[derive(Clone, Debug, RustcEncodable)] +pub struct FunctionData { + pub id: Id, + pub name: String, + pub qualname: String, + pub declaration: Option, + pub span: SpanData, + pub scope: Id, +} + +impl Lower for data::FunctionData { + type Target = FunctionData; + + fn lower(self, tcx: &TyCtxt) -> FunctionData { + FunctionData { + id: Id::from_node_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + declaration: self.declaration.map(Id::from_def_id), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionRefData { + pub span: SpanData, + pub scope: Id, + pub ref_id: Id, +} + +impl Lower for data::FunctionRefData { + type Target = FunctionRefData; + + fn lower(self, tcx: &TyCtxt) -> FunctionRefData { + FunctionRefData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: Id::from_def_id(self.ref_id), + } + } +} +#[derive(Debug, RustcEncodable)] +pub struct ImplData { + pub id: Id, + pub span: SpanData, + pub scope: Id, + pub trait_ref: Option, + pub self_ref: Option, +} + +impl Lower for data::ImplData { + type Target = ImplData; + + fn lower(self, tcx: &TyCtxt) -> ImplData { + ImplData { + id: Id::from_node_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + trait_ref: self.trait_ref.map(Id::from_def_id), + self_ref: self.self_ref.map(Id::from_def_id), + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct InheritanceData { + pub span: SpanData, + pub base_id: Id, + pub deriv_id: Id +} + +impl Lower for data::InheritanceData { + type Target = InheritanceData; + + fn lower(self, tcx: &TyCtxt) -> InheritanceData { + InheritanceData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + base_id: Id::from_def_id(self.base_id), + deriv_id: Id::from_node_id(self.deriv_id, &tcx.map) + } + } +} + +/// Data about a macro declaration. +#[derive(Debug, RustcEncodable)] +pub struct MacroData { + pub span: SpanData, + pub name: String, + pub qualname: String, +} + +impl Lower for data::MacroData { + type Target = MacroData; + + fn lower(self, tcx: &TyCtxt) -> MacroData { + MacroData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, + qualname: self.qualname, + } + } +} + +/// Data about a macro use. +#[derive(Debug, RustcEncodable)] +pub struct MacroUseData { + pub span: SpanData, + pub name: String, + pub qualname: String, + // Because macro expansion happens before ref-ids are determined, + // we use the callee span to reference the associated macro definition. + pub callee_span: SpanData, + pub scope: Id, + pub imported: bool, +} + +impl Lower for data::MacroUseData { + type Target = MacroUseData; + + fn lower(self, tcx: &TyCtxt) -> MacroUseData { + MacroUseData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, + qualname: self.qualname, + callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + imported: self.imported, + } + } +} + +/// Data about a method call. +#[derive(Debug, RustcEncodable)] +pub struct MethodCallData { + pub span: SpanData, + pub scope: Id, + pub ref_id: Option, + pub decl_id: Option, +} + +impl Lower for data::MethodCallData { + type Target = MethodCallData; + + fn lower(self, tcx: &TyCtxt) -> MethodCallData { + MethodCallData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: self.ref_id.map(Id::from_def_id), + decl_id: self.decl_id.map(Id::from_def_id), + } + } +} + +/// Data for method declarations (methods with a body are treated as functions). +#[derive(Clone, Debug, RustcEncodable)] +pub struct MethodData { + pub id: Id, + pub qualname: String, + pub span: SpanData, + pub scope: Id, +} + +impl Lower for data::MethodData { + type Target = MethodData; + + fn lower(self, tcx: &TyCtxt) -> MethodData { + MethodData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + id: Id::from_node_id(self.id, &tcx.map), + qualname: self.qualname, + } + } +} + +/// Data for modules. +#[derive(Debug, RustcEncodable)] +pub struct ModData { + pub id: Id, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: Id, + pub filename: String, +} + +impl Lower for data::ModData { + type Target = ModData; + + fn lower(self, tcx: &TyCtxt) -> ModData { + ModData { + id: Id::from_node_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + filename: self.filename, + } + } +} + +/// Data for a reference to a module. +#[derive(Debug, RustcEncodable)] +pub struct ModRefData { + pub span: SpanData, + pub scope: Id, + pub ref_id: Option, + pub qualname: String +} + +impl Lower for data::ModRefData { + type Target = ModRefData; + + fn lower(self, tcx: &TyCtxt) -> ModRefData { + ModRefData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: self.ref_id.map(Id::from_def_id), + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructData { + pub span: SpanData, + pub id: Id, + pub ctor_id: Id, + pub qualname: String, + pub scope: Id, + pub value: String +} + +impl Lower for data::StructData { + type Target = StructData; + + fn lower(self, tcx: &TyCtxt) -> StructData { + StructData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + id: Id::from_node_id(self.id, &tcx.map), + ctor_id: Id::from_node_id(self.ctor_id, &tcx.map), + qualname: self.qualname, + scope: Id::from_node_id(self.scope, &tcx.map), + value: self.value + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructVariantData { + pub span: SpanData, + pub id: Id, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: Id +} + +impl Lower for data::StructVariantData { + type Target = StructVariantData; + + fn lower(self, tcx: &TyCtxt) -> StructVariantData { + StructVariantData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + id: Id::from_node_id(self.id, &tcx.map), + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TraitData { + pub span: SpanData, + pub id: Id, + pub qualname: String, + pub scope: Id, + pub value: String +} + +impl Lower for data::TraitData { + type Target = TraitData; + + fn lower(self, tcx: &TyCtxt) -> TraitData { + TraitData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + id: Id::from_node_id(self.id, &tcx.map), + qualname: self.qualname, + scope: Id::from_node_id(self.scope, &tcx.map), + value: self.value, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TupleVariantData { + pub span: SpanData, + pub id: Id, + pub name: String, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: Id, +} + +impl Lower for data::TupleVariantData { + type Target = TupleVariantData; + + fn lower(self, tcx: &TyCtxt) -> TupleVariantData { + TupleVariantData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + id: Id::from_node_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +/// Data for a typedef. +#[derive(Debug, RustcEncodable)] +pub struct TypedefData { + pub id: Id, + pub span: SpanData, + pub qualname: String, + pub value: String, +} + +impl Lower for data::TypedefData { + type Target = TypedefData; + + fn lower(self, tcx: &TyCtxt) -> TypedefData { + TypedefData { + id: Id::from_node_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + qualname: self.qualname, + value: self.value, + } + } +} + +/// Data for a reference to a type or trait. +#[derive(Clone, Debug, RustcEncodable)] +pub struct TypeRefData { + pub span: SpanData, + pub scope: Id, + pub ref_id: Option, + pub qualname: String, +} + +impl Lower for data::TypeRefData { + type Target = TypeRefData; + + fn lower(self, tcx: &TyCtxt) -> TypeRefData { + TypeRefData { + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: self.ref_id.map(Id::from_def_id), + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseData { + pub id: Id, + pub span: SpanData, + pub name: String, + pub mod_id: Option, + pub scope: Id +} + +impl Lower for data::UseData { + type Target = UseData; + + fn lower(self, tcx: &TyCtxt) -> UseData { + UseData { + id: Id::from_node_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + name: self.name, + mod_id: self.mod_id.map(Id::from_def_id), + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseGlobData { + pub id: Id, + pub span: SpanData, + pub names: Vec, + pub scope: Id +} + +impl Lower for data::UseGlobData { + type Target = UseGlobData; + + fn lower(self, tcx: &TyCtxt) -> UseGlobData { + UseGlobData { + id: Id::from_node_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + names: self.names, + scope: Id::from_node_id(self.scope, &tcx.map), + } + } +} + +/// Data for local and global variables (consts and statics). +#[derive(Debug, RustcEncodable)] +pub struct VariableData { + pub id: Id, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: Id, + pub value: String, + pub type_value: String, +} + +impl Lower for data::VariableData { + type Target = VariableData; + + fn lower(self, tcx: &TyCtxt) -> VariableData { + VariableData { + id: Id::from_node_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + value: self.value, + type_value: self.type_value, + } + } +} + +/// Data for the use of some item (e.g., the use of a local variable, which +/// will refer to that variables declaration (by ref_id)). +#[derive(Debug, RustcEncodable)] +pub struct VariableRefData { + pub name: String, + pub span: SpanData, + pub scope: Id, + pub ref_id: Id, +} + +impl Lower for data::VariableRefData { + type Target = VariableRefData; + + fn lower(self, tcx: &TyCtxt) -> VariableRefData { + VariableRefData { + name: self.name, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: Id::from_node_id(self.scope, &tcx.map), + ref_id: Id::from_def_id(self.ref_id), + } + } +} diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index 7c379774f2b2a..9ad2bcef4ed46 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -11,29 +11,25 @@ use std::io::Write; use rustc_serialize::json::as_json; -use syntax::codemap::CodeMap; -use syntax::ast::CrateNum; - -use super::data::{self, SpanData}; +use super::external_data::*; use super::dump::Dump; -pub struct JsonDumper<'a, 'b, W: Write + 'b> { +pub struct JsonDumper<'b, W: Write + 'b> { output: &'b mut W, - codemap: &'a CodeMap, first: bool, } -impl<'a, 'b, W: Write> JsonDumper<'a, 'b, W> { - pub fn new(writer: &'b mut W, codemap: &'a CodeMap) -> JsonDumper<'a, 'b, W> { +impl<'b, W: Write> JsonDumper<'b, W> { + pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> { if let Err(_) = write!(writer, "[") { error!("Error writing output"); } - JsonDumper { output: writer, codemap:codemap, first: true } + JsonDumper { output: writer, first: true } } } -impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> { +impl<'b, W: Write> Drop for JsonDumper<'b, W> { fn drop(&mut self) { if let Err(_) = write!(self.output, "]") { error!("Error writing output"); @@ -43,7 +39,7 @@ impl<'a, 'b, W: Write> Drop for JsonDumper<'a, 'b, W> { macro_rules! impl_fn { ($fn_name: ident, $data_type: ident) => { - fn $fn_name(&mut self, data: data::$data_type) { + fn $fn_name(&mut self, data: $data_type) { if self.first { self.first = false; } else { @@ -51,7 +47,6 @@ macro_rules! impl_fn { error!("Error writing output"); } } - let data = data.lower(self.codemap); if let Err(_) = write!(self.output, "{}", as_json(&data)) { error!("Error writing output '{}'", as_json(&data)); } @@ -59,7 +54,7 @@ macro_rules! impl_fn { } } -impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> { +impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> { impl_fn!(crate_prelude, CratePreludeData); impl_fn!(enum_data, EnumData); impl_fn!(extern_crate, ExternCrateData); @@ -85,567 +80,3 @@ impl<'a, 'b, W: Write + 'b> Dump for JsonDumper<'a, 'b, W> { impl_fn!(variable, VariableData); impl_fn!(variable_ref, VariableRefData); } - -trait Lower { - type Target; - fn lower(self, cm: &CodeMap) -> Self::Target; -} - -pub type Id = u32; - -#[derive(Debug, RustcEncodable)] -pub struct CratePreludeData { - pub crate_name: String, - pub crate_root: String, - pub external_crates: Vec, - pub span: SpanData, -} - -impl Lower for data::CratePreludeData { - type Target = CratePreludeData; - - fn lower(self, cm: &CodeMap) -> CratePreludeData { - CratePreludeData { - crate_name: self.crate_name, - crate_root: self.crate_root, - external_crates: self.external_crates, - span: SpanData::from_span(self.span, cm), - } - } -} - -/// Data for enum declarations. -#[derive(Clone, Debug, RustcEncodable)] -pub struct EnumData { - pub id: Id, - pub value: String, - pub qualname: String, - pub span: SpanData, - pub scope: Id, -} - -impl Lower for data::EnumData { - type Target = EnumData; - - fn lower(self, cm: &CodeMap) -> EnumData { - EnumData { - id: self.id, - value: self.value, - qualname: self.qualname, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - } - } -} - -/// Data for extern crates. -#[derive(Debug, RustcEncodable)] -pub struct ExternCrateData { - pub id: Id, - pub name: String, - pub crate_num: CrateNum, - pub location: String, - pub span: SpanData, - pub scope: Id, -} - -impl Lower for data::ExternCrateData { - type Target = ExternCrateData; - - fn lower(self, cm: &CodeMap) -> ExternCrateData { - ExternCrateData { - id: self.id, - name: self.name, - crate_num: self.crate_num, - location: self.location, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - } - } -} - -/// Data about a function call. -#[derive(Debug, RustcEncodable)] -pub struct FunctionCallData { - pub span: SpanData, - pub scope: Id, - pub ref_id: Id, -} - -impl Lower for data::FunctionCallData { - type Target = FunctionCallData; - - fn lower(self, cm: &CodeMap) -> FunctionCallData { - FunctionCallData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.index.as_u32(), - } - } -} - -/// Data for all kinds of functions and methods. -#[derive(Clone, Debug, RustcEncodable)] -pub struct FunctionData { - pub id: Id, - pub name: String, - pub qualname: String, - pub declaration: Option, - pub span: SpanData, - pub scope: Id, -} - -impl Lower for data::FunctionData { - type Target = FunctionData; - - fn lower(self, cm: &CodeMap) -> FunctionData { - FunctionData { - id: self.id, - name: self.name, - qualname: self.qualname, - declaration: self.declaration.map(|id| id.index.as_u32()), - span: SpanData::from_span(self.span, cm), - scope: self.scope, - } - } -} - -/// Data about a function call. -#[derive(Debug, RustcEncodable)] -pub struct FunctionRefData { - pub span: SpanData, - pub scope: Id, - pub ref_id: Id, -} - -impl Lower for data::FunctionRefData { - type Target = FunctionRefData; - - fn lower(self, cm: &CodeMap) -> FunctionRefData { - FunctionRefData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.index.as_u32(), - } - } -} -#[derive(Debug, RustcEncodable)] -pub struct ImplData { - pub id: Id, - pub span: SpanData, - pub scope: Id, - pub trait_ref: Option, - pub self_ref: Option, -} - -impl Lower for data::ImplData { - type Target = ImplData; - - fn lower(self, cm: &CodeMap) -> ImplData { - ImplData { - id: self.id, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - trait_ref: self.trait_ref.map(|id| id.index.as_u32()), - self_ref: self.self_ref.map(|id| id.index.as_u32()), - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct InheritanceData { - pub span: SpanData, - pub base_id: Id, - pub deriv_id: Id -} - -impl Lower for data::InheritanceData { - type Target = InheritanceData; - - fn lower(self, cm: &CodeMap) -> InheritanceData { - InheritanceData { - span: SpanData::from_span(self.span, cm), - base_id: self.base_id.index.as_u32(), - deriv_id: self.deriv_id - } - } -} - -/// Data about a macro declaration. -#[derive(Debug, RustcEncodable)] -pub struct MacroData { - pub span: SpanData, - pub name: String, - pub qualname: String, -} - -impl Lower for data::MacroData { - type Target = MacroData; - - fn lower(self, cm: &CodeMap) -> MacroData { - MacroData { - span: SpanData::from_span(self.span, cm), - name: self.name, - qualname: self.qualname, - } - } -} - -/// Data about a macro use. -#[derive(Debug, RustcEncodable)] -pub struct MacroUseData { - pub span: SpanData, - pub name: String, - pub qualname: String, - // Because macro expansion happens before ref-ids are determined, - // we use the callee span to reference the associated macro definition. - pub callee_span: SpanData, - pub scope: Id, - pub imported: bool, -} - -impl Lower for data::MacroUseData { - type Target = MacroUseData; - - fn lower(self, cm: &CodeMap) -> MacroUseData { - MacroUseData { - span: SpanData::from_span(self.span, cm), - name: self.name, - qualname: self.qualname, - callee_span: SpanData::from_span(self.callee_span, cm), - scope: self.scope, - imported: self.imported, - } - } -} - -/// Data about a method call. -#[derive(Debug, RustcEncodable)] -pub struct MethodCallData { - pub span: SpanData, - pub scope: Id, - pub ref_id: Option, - pub decl_id: Option, -} - -impl Lower for data::MethodCallData { - type Target = MethodCallData; - - fn lower(self, cm: &CodeMap) -> MethodCallData { - MethodCallData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.map(|id| id.index.as_u32()), - decl_id: self.decl_id.map(|id| id.index.as_u32()), - } - } -} - -/// Data for method declarations (methods with a body are treated as functions). -#[derive(Clone, Debug, RustcEncodable)] -pub struct MethodData { - pub id: Id, - pub qualname: String, - pub span: SpanData, - pub scope: Id, -} - -impl Lower for data::MethodData { - type Target = MethodData; - - fn lower(self, cm: &CodeMap) -> MethodData { - MethodData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - id: self.id, - qualname: self.qualname, - } - } -} - -/// Data for modules. -#[derive(Debug, RustcEncodable)] -pub struct ModData { - pub id: Id, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: Id, - pub filename: String, -} - -impl Lower for data::ModData { - type Target = ModData; - - fn lower(self, cm: &CodeMap) -> ModData { - ModData { - id: self.id, - name: self.name, - qualname: self.qualname, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - filename: self.filename, - } - } -} - -/// Data for a reference to a module. -#[derive(Debug, RustcEncodable)] -pub struct ModRefData { - pub span: SpanData, - pub scope: Id, - pub ref_id: Option, - pub qualname: String -} - -impl Lower for data::ModRefData { - type Target = ModRefData; - - fn lower(self, cm: &CodeMap) -> ModRefData { - ModRefData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.map(|id| id.index.as_u32()), - qualname: self.qualname, - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct StructData { - pub span: SpanData, - pub id: Id, - pub ctor_id: Id, - pub qualname: String, - pub scope: Id, - pub value: String -} - -impl Lower for data::StructData { - type Target = StructData; - - fn lower(self, cm: &CodeMap) -> StructData { - StructData { - span: SpanData::from_span(self.span, cm), - id: self.id, - ctor_id: self.ctor_id, - qualname: self.qualname, - scope: self.scope, - value: self.value - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct StructVariantData { - pub span: SpanData, - pub id: Id, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: Id -} - -impl Lower for data::StructVariantData { - type Target = StructVariantData; - - fn lower(self, cm: &CodeMap) -> StructVariantData { - StructVariantData { - span: SpanData::from_span(self.span, cm), - id: self.id, - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: self.scope, - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct TraitData { - pub span: SpanData, - pub id: Id, - pub qualname: String, - pub scope: Id, - pub value: String -} - -impl Lower for data::TraitData { - type Target = TraitData; - - fn lower(self, cm: &CodeMap) -> TraitData { - TraitData { - span: SpanData::from_span(self.span, cm), - id: self.id, - qualname: self.qualname, - scope: self.scope, - value: self.value, - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct TupleVariantData { - pub span: SpanData, - pub id: Id, - pub name: String, - pub qualname: String, - pub type_value: String, - pub value: String, - pub scope: Id, -} - -impl Lower for data::TupleVariantData { - type Target = TupleVariantData; - - fn lower(self, cm: &CodeMap) -> TupleVariantData { - TupleVariantData { - span: SpanData::from_span(self.span, cm), - id: self.id, - name: self.name, - qualname: self.qualname, - type_value: self.type_value, - value: self.value, - scope: self.scope, - } - } -} - -/// Data for a typedef. -#[derive(Debug, RustcEncodable)] -pub struct TypedefData { - pub id: Id, - pub span: SpanData, - pub qualname: String, - pub value: String, -} - -impl Lower for data::TypedefData { - type Target = TypedefData; - - fn lower(self, cm: &CodeMap) -> TypedefData { - TypedefData { - id: self.id, - span: SpanData::from_span(self.span, cm), - qualname: self.qualname, - value: self.value, - } - } -} - -/// Data for a reference to a type or trait. -#[derive(Clone, Debug, RustcEncodable)] -pub struct TypeRefData { - pub span: SpanData, - pub scope: Id, - pub ref_id: Option, - pub qualname: String, -} - -impl Lower for data::TypeRefData { - type Target = TypeRefData; - - fn lower(self, cm: &CodeMap) -> TypeRefData { - TypeRefData { - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.map(|id| id.index.as_u32()), - qualname: self.qualname, - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct UseData { - pub id: Id, - pub span: SpanData, - pub name: String, - pub mod_id: Option, - pub scope: Id -} - -impl Lower for data::UseData { - type Target = UseData; - - fn lower(self, cm: &CodeMap) -> UseData { - UseData { - id: self.id, - span: SpanData::from_span(self.span, cm), - name: self.name, - mod_id: self.mod_id.map(|id| id.index.as_u32()), - scope: self.scope, - } - } -} - -#[derive(Debug, RustcEncodable)] -pub struct UseGlobData { - pub id: Id, - pub span: SpanData, - pub names: Vec, - pub scope: Id -} - -impl Lower for data::UseGlobData { - type Target = UseGlobData; - - fn lower(self, cm: &CodeMap) -> UseGlobData { - UseGlobData { - id: self.id, - span: SpanData::from_span(self.span, cm), - names: self.names, - scope: self.scope, - } - } -} - -/// Data for local and global variables (consts and statics). -#[derive(Debug, RustcEncodable)] -pub struct VariableData { - pub id: Id, - pub name: String, - pub qualname: String, - pub span: SpanData, - pub scope: Id, - pub value: String, - pub type_value: String, -} - -impl Lower for data::VariableData { - type Target = VariableData; - - fn lower(self, cm: &CodeMap) -> VariableData { - VariableData { - id: self.id, - name: self.name, - qualname: self.qualname, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - value: self.value, - type_value: self.type_value, - } - } -} - -/// Data for the use of some item (e.g., the use of a local variable, which -/// will refer to that variables declaration (by ref_id)). -#[derive(Debug, RustcEncodable)] -pub struct VariableRefData { - pub name: String, - pub span: SpanData, - pub scope: Id, - pub ref_id: Id, -} - -impl Lower for data::VariableRefData { - type Target = VariableRefData; - - fn lower(self, cm: &CodeMap) -> VariableRefData { - VariableRefData { - name: self.name, - span: SpanData::from_span(self.span, cm), - scope: self.scope, - ref_id: self.ref_id.index.as_u32(), - } - } -} diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 85c8f1f8ec98c..906923e5cad95 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -28,6 +28,15 @@ #[macro_use] extern crate syntax; extern crate serialize as rustc_serialize; +mod csv_dumper; +mod json_dumper; +mod data; +mod dump; +mod dump_visitor; +pub mod external_data; +#[macro_use] +pub mod span_utils; + use rustc::hir; use rustc::hir::map::NodeItem; use rustc::hir::def::Def; @@ -45,14 +54,6 @@ use syntax::parse::token::{self, keywords}; use syntax::visit::{self, Visitor}; use syntax::print::pprust::ty_to_string; -mod csv_dumper; -mod json_dumper; -mod data; -mod dump; -mod dump_visitor; -#[macro_use] -pub mod span_utils; - pub use self::csv_dumper::CsvDumper; pub use self::json_dumper::JsonDumper; pub use self::data::*; @@ -748,7 +749,6 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>, root_path.pop(); let output = &mut output_file; - let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess); let save_ctxt = SaveContext::new(tcx); macro_rules! dump { @@ -762,8 +762,8 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>, } match format { - Format::Csv => dump!(CsvDumper::new(output, utils)), - Format::Json => dump!(JsonDumper::new(output, utils.sess.codemap())), + Format::Csv => dump!(CsvDumper::new(output)), + Format::Json => dump!(JsonDumper::new(output)), } } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index c64eeb92737e0..3028fb1bfa423 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -18,10 +18,8 @@ use std::path::Path; use syntax::ast; use syntax::codemap::*; -use syntax::parse::lexer; -use syntax::parse::lexer::{Reader, StringReader}; -use syntax::parse::token; -use syntax::parse::token::{keywords, Token}; +use syntax::parse::lexer::{self, Reader, StringReader}; +use syntax::parse::token::{self, keywords, Token}; #[derive(Clone)] pub struct SpanUtils<'a> { @@ -48,23 +46,6 @@ impl<'a> SpanUtils<'a> { } } - // Standard string for extents/location. - #[rustfmt_skip] - pub fn extent_str(&self, span: Span) -> String { - let lo_loc = self.sess.codemap().lookup_char_pos(span.lo); - let hi_loc = self.sess.codemap().lookup_char_pos(span.hi); - let lo_pos = self.sess.codemap().bytepos_to_file_charpos(span.lo); - let hi_pos = self.sess.codemap().bytepos_to_file_charpos(span.hi); - let lo_pos_byte = self.sess.codemap().lookup_byte_offset(span.lo).pos; - let hi_pos_byte = self.sess.codemap().lookup_byte_offset(span.hi).pos; - - format!("file_name,\"{}\",file_line,{},file_col,{},extent_start,{},extent_start_bytes,{},\ - file_line_end,{},file_col_end,{},extent_end,{},extent_end_bytes,{}", - SpanUtils::make_path_string(&lo_loc.file.name), - lo_loc.line, lo_loc.col.to_usize(), lo_pos.to_usize(), lo_pos_byte.to_usize(), - hi_loc.line, hi_loc.col.to_usize(), hi_pos.to_usize(), hi_pos_byte.to_usize()) - } - // sub_span starts at span.lo, so we need to adjust the positions etc. // If sub_span is None, we don't need to adjust. pub fn make_sub_span(&self, span: Span, sub_span: Option) -> Option { From 083c3952e0d5473cd5c41a9eb7b4ffca18cc8e5f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 May 2016 04:46:45 +0200 Subject: [PATCH 03/12] Update CSS for future rustdoc merge --- src/librustdoc/html/static/rustdoc.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index c07871a4029ca..94b59fe2addfd 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -270,6 +270,11 @@ nav.sub { padding: 0px; text-align: right; display: inline-block; + font-weight: normal; +} + +h3.impl > .out-of-band { + font-size: 21px; } .content .in-band { From cdca0843779eed0b9046e9fee48c91458ad51605 Mon Sep 17 00:00:00 2001 From: ggomez Date: Fri, 6 May 2016 18:47:12 +0200 Subject: [PATCH 04/12] Improve rustdoc css of "source" and "since" elements --- src/librustdoc/html/render.rs | 9 +++-- src/librustdoc/html/static/rustdoc.css | 38 +++++++++++++++++++--- src/librustdoc/html/static/styles/main.css | 3 ++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 96a9315599f9a..4c652f54009da 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2144,7 +2144,7 @@ fn render_stability_since_raw<'a>(w: &mut fmt::Formatter, containing_ver: Option<&'a str>) -> fmt::Result { if let Some(v) = ver { if containing_ver != ver && v.len() > 0 { - write!(w, "{}", + write!(w, "
{}
", v)? } } @@ -2545,13 +2545,16 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi render_header: bool, outer_version: Option<&str>) -> fmt::Result { if render_header { write!(w, "

{}", i.inner_impl())?; - let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); - render_stability_since_raw(w, since, outer_version)?; write!(w, "")?; + let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); if let Some(l) = (Item { item: &i.impl_item, cx: cx }).href() { + write!(w, "
")?; + render_stability_since_raw(w, since, outer_version)?; write!(w, "[src]", i.impl_item.def_id.index.as_usize(), l, "goto source code")?; + } else { + render_stability_since_raw(w, since, outer_version)?; } write!(w, "
")?; write!(w, "

\n")?; diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 94b59fe2addfd..4d65b91ed421c 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -97,6 +97,7 @@ h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):no h1.fqn { border-bottom: 1px dashed; margin-top: 0; + position: relative; } h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { border-bottom: 1px solid; @@ -105,6 +106,7 @@ h3.impl, h3.method, h4.method, h3.type, h4.type { font-weight: 600; margin-top: 10px; margin-bottom: 10px; + position: relative; } h3.impl, h3.method, h3.type { margin-top: 15px; @@ -265,25 +267,39 @@ nav.sub { .content .out-of-band { font-size: 23px; - width: 40%; margin: 0px; padding: 0px; text-align: right; display: inline-block; font-weight: normal; + position: absolute; + right: 0; } h3.impl > .out-of-band { font-size: 21px; } +h4 > code, h3 > code { + position: inherit; +} + +.in-band, code { + z-index: 5; +} + .content .in-band { - width: 60%; margin: 0px; padding: 0px; display: inline-block; } +#main { position: relative; } +#main > .since { + top: inherit; + font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +} + .content table { border-spacing: 0 5px; border-collapse: separate; @@ -503,11 +519,13 @@ em.stab p { opacity: 0.65; } -span.since { - float: right; +.since { font-weight: normal; font-size: initial; color: grey; + position: absolute; + right: 0; + top: 0; } .variants_table { @@ -602,7 +620,19 @@ a.test-arrow { color: #999; } +.ghost { + display: none; +} + +.ghost + .since { + position: initial; + display: table-cell; +} +.since + .srclink { + display: table-cell; + padding-left: 10px; +} /* Media Queries */ diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 5c073860f08ca..59b2ff7e3d649 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -26,6 +26,9 @@ h1.fqn { h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { border-bottom-color: #DDDDDD; } +.in-band, code { + background-color: white; +} .docblock code { background-color: #F5F5F5; From 01be25b1f98e75de46a6a4ee1ae6901d736de070 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 May 2016 16:15:48 +1200 Subject: [PATCH 05/12] Use crate/index pair for def ids --- src/librustc_save_analysis/csv_dumper.rs | 156 +++++++++----- src/librustc_save_analysis/external_data.rs | 224 +++++++++----------- 2 files changed, 201 insertions(+), 179 deletions(-) diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs index 626537a4ae9a0..ac658af4006b1 100644 --- a/src/librustc_save_analysis/csv_dumper.rs +++ b/src/librustc_save_analysis/csv_dumper.rs @@ -60,8 +60,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn enum_data(&mut self, data: EnumData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), @@ -73,9 +73,9 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn extern_crate(&mut self, data: ExternCrateData) { - let id = data.id.to_string(); + let id = data.id.index.as_u32().to_string(); let crate_num = data.crate_num.to_string(); - let scope = data.scope.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("name", &data.name), @@ -88,14 +88,21 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn impl_data(&mut self, data: ImplData) { - let id = data.id.to_string(); - let ref_id = data.self_ref.unwrap_or(Id::null()).to_string(); - let trait_id = data.trait_ref.unwrap_or(Id::null()).to_string(); - let scope = data.scope.to_string(); + let self_ref = data.self_ref.unwrap_or(null_def_id()); + let trait_ref = data.trait_ref.unwrap_or(null_def_id()); + + let id = data.id.index.as_u32().to_string(); + let ref_id = self_ref.index.as_usize().to_string(); + let ref_id_crate = self_ref.krate.to_string(); + let trait_id = trait_ref.index.as_usize().to_string(); + let trait_id_crate = trait_ref.krate.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("refid", &ref_id), + ("refidcrate", &ref_id_crate), ("traitid", &trait_id), + ("traitidcrate", &trait_id_crate), ("scopeid", &scope) ]); @@ -103,24 +110,33 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn inheritance(&mut self, data: InheritanceData) { - let base_id = data.base_id.to_string(); - let deriv_id = data.deriv_id.to_string(); - let values = make_values_str(&[ - ("base", &base_id), - ("derived", &deriv_id), - ]); + let base_id = data.base_id.index.as_usize().to_string(); + let base_crate = data.base_id.krate.to_string(); + let deriv_id = data.deriv_id.index.as_u32().to_string(); + let deriv_crate = data.deriv_id.krate.to_string(); + let values = make_values_str(&[ + ("base", &base_id), + ("basecrate", &base_crate), + ("derived", &deriv_id), + ("derivedcrate", &deriv_crate) + ]); self.record("inheritance", data.span, values); } fn function(&mut self, data: FunctionData) { - let id = data.id.to_string(); - let decl_id = data.declaration.unwrap_or(Id::null()).to_string(); - let scope = data.scope.to_string(); + let (decl_id, decl_crate) = match data.declaration { + Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), + None => (String::new(), String::new()) + }; + + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), ("declid", &decl_id), + ("declidcrate", &decl_crate), ("scopeid", &scope) ]); @@ -128,10 +144,12 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn function_ref(&mut self, data: FunctionRefData) { - let ref_id = data.ref_id.to_string(); - let scope = data.scope.to_string(); + let ref_id = data.ref_id.index.as_usize().to_string(); + let ref_crate = data.ref_id.krate.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("refid", &ref_id), + ("refidcrate", &ref_crate), ("qualname", ""), ("scopeid", &scope) ]); @@ -140,11 +158,13 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn function_call(&mut self, data: FunctionCallData) { - let ref_id = data.ref_id.to_string(); + let ref_id = data.ref_id.index.as_usize().to_string(); + let ref_crate = data.ref_id.krate.to_string(); let qualname = String::new(); - let scope = data.scope.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("refid", &ref_id), + ("refidcrate", &ref_crate), ("qualname", &qualname), ("scopeid", &scope) ]); @@ -153,8 +173,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn method(&mut self, data: MethodData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), @@ -165,12 +185,21 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn method_call(&mut self, data: MethodCallData) { - let decl_id = data.decl_id.unwrap_or(Id::null()).to_string(); - let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); - let scope = data.scope.to_string(); + let (dcn, dck) = match data.decl_id { + Some(declid) => (declid.index.as_usize().to_string(), declid.krate.to_string()), + None => (String::new(), String::new()), + }; + + let ref_id = data.ref_id.unwrap_or(null_def_id()); + + let def_id = ref_id.index.as_usize().to_string(); + let def_crate = ref_id.krate.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ - ("refid", &ref_id), - ("declid", &decl_id), + ("refid", &def_id), + ("refidcrate", &def_crate), + ("declid", &dcn), + ("declidcrate", &dck), ("scopeid", &scope) ]); @@ -187,7 +216,7 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn macro_use(&mut self, data: MacroUseData) { - let scope = data.scope.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("callee_name", &data.name), ("qualname", &data.qualname), @@ -198,8 +227,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn mod_data(&mut self, data: ModData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), @@ -211,11 +240,15 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn mod_ref(&mut self, data: ModRefData) { - let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); + let (ref_id, ref_crate) = match data.ref_id { + Some(rid) => (rid.index.as_usize().to_string(), rid.krate.to_string()), + None => (0.to_string(), 0.to_string()) + }; - let scope = data.scope.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("refid", &ref_id), + ("refidcrate", &ref_crate), ("qualname", &data.qualname), ("scopeid", &scope) ]); @@ -224,9 +257,9 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn struct_data(&mut self, data: StructData) { - let id = data.id.to_string(); - let ctor_id = data.ctor_id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let ctor_id = data.ctor_id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("ctor_id", &ctor_id), @@ -239,8 +272,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn struct_variant(&mut self, data: StructVariantData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("ctor_id", &id), @@ -254,8 +287,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn trait_data(&mut self, data: TraitData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), @@ -267,8 +300,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn tuple_variant(&mut self, data: TupleVariantData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("name", &data.name), @@ -282,10 +315,15 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn type_ref(&mut self, data: TypeRefData) { - let ref_id = data.ref_id.unwrap_or(Id::null()).to_string(); - let scope = data.scope.to_string(); + let (ref_id, ref_crate) = match data.ref_id { + Some(id) => (id.index.as_usize().to_string(), id.krate.to_string()), + None => (0.to_string(), 0.to_string()) + }; + + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("refid", &ref_id), + ("refidcrate", &ref_crate), ("qualname", &data.qualname), ("scopeid", &scope) ]); @@ -294,7 +332,7 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn typedef(&mut self, data: TypedefData) { - let id = data.id.to_string(); + let id = data.id.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("qualname", &data.qualname), @@ -305,12 +343,16 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn use_data(&mut self, data: UseData) { - let id = data.id.to_string(); - let mod_id = data.mod_id.unwrap_or(Id::null()).to_string(); - let scope = data.scope.to_string(); + let mod_id = data.mod_id.unwrap_or(null_def_id()); + + let id = data.id.index.as_u32().to_string(); + let ref_id = mod_id.index.as_usize().to_string(); + let ref_crate = mod_id.krate.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), - ("mod_id", &mod_id), + ("refid", &ref_id), + ("refidcrate", &ref_crate), ("name", &data.name), ("scopeid", &scope) ]); @@ -321,8 +363,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { fn use_glob(&mut self, data: UseGlobData) { let names = data.names.join(", "); - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("value", &names), @@ -333,8 +375,8 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn variable(&mut self, data: VariableData) { - let id = data.id.to_string(); - let scope = data.scope.to_string(); + let id = data.id.index.as_u32().to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("name", &data.name), @@ -348,10 +390,12 @@ impl<'b, W: Write + 'b> Dump for CsvDumper<'b, W> { } fn variable_ref(&mut self, data: VariableRefData) { - let id = data.ref_id.to_string(); - let scope = data.scope.to_string(); + let ref_id = data.ref_id.index.as_usize().to_string(); + let ref_crate = data.ref_id.krate.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ - ("id", &id), + ("refid", &ref_id), + ("refidcrate", &ref_crate), ("qualname", ""), ("scopeid", &scope) ]); diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 13923d4646426..db4bd1d6d7308 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::{self, Display, Formatter}; - -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::map::Map; use rustc::ty::TyCtxt; use syntax::ast::{CrateNum, NodeId}; @@ -24,32 +22,12 @@ pub trait Lower { fn lower(self, tcx: &TyCtxt) -> Self::Target; } -// We use a newtype to enforce conversion of all NodeIds (which are u32s as well) -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable)] -pub struct Id(u32); - -impl Id { - pub fn from_def_id(id: DefId) -> Id { - Id(id.index.as_u32()) - } - - // FIXME: this function is called with non-local NodeIds. This means that they - // cannot be mapped to a DefId. We should remove those calls. In the meantime, - // we return a "null Id" when the NodeId is invalid. - pub fn from_node_id(id: NodeId, map: &Map) -> Id { - map.opt_local_def_id(id).map(|id| Id(id.index.as_u32())) - .unwrap_or(Id::null()) - } - - pub fn null() -> Id { - Id(u32::max_value()) - } +fn make_def_id(id: NodeId, map: &Map) -> DefId { + map.opt_local_def_id(id).unwrap_or(null_def_id()) } -impl Display for Id { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.0.fmt(f) - } +pub fn null_def_id() -> DefId { + DefId { krate: u32::max_value(), index: DefIndex::from_u32(u32::max_value()) } } #[derive(Clone, Debug, RustcEncodable)] @@ -106,11 +84,11 @@ impl Lower for data::CratePreludeData { /// Data for enum declarations. #[derive(Clone, Debug, RustcEncodable)] pub struct EnumData { - pub id: Id, + pub id: DefId, pub value: String, pub qualname: String, pub span: SpanData, - pub scope: Id, + pub scope: DefId, } impl Lower for data::EnumData { @@ -118,11 +96,11 @@ impl Lower for data::EnumData { fn lower(self, tcx: &TyCtxt) -> EnumData { EnumData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), value: self.value, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -130,12 +108,12 @@ impl Lower for data::EnumData { /// Data for extern crates. #[derive(Debug, RustcEncodable)] pub struct ExternCrateData { - pub id: Id, + pub id: DefId, pub name: String, pub crate_num: CrateNum, pub location: String, pub span: SpanData, - pub scope: Id, + pub scope: DefId, } impl Lower for data::ExternCrateData { @@ -143,12 +121,12 @@ impl Lower for data::ExternCrateData { fn lower(self, tcx: &TyCtxt) -> ExternCrateData { ExternCrateData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), name: self.name, crate_num: self.crate_num, location: self.location, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -157,8 +135,8 @@ impl Lower for data::ExternCrateData { #[derive(Debug, RustcEncodable)] pub struct FunctionCallData { pub span: SpanData, - pub scope: Id, - pub ref_id: Id, + pub scope: DefId, + pub ref_id: DefId, } impl Lower for data::FunctionCallData { @@ -167,8 +145,8 @@ impl Lower for data::FunctionCallData { fn lower(self, tcx: &TyCtxt) -> FunctionCallData { FunctionCallData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: Id::from_def_id(self.ref_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, } } } @@ -176,12 +154,12 @@ impl Lower for data::FunctionCallData { /// Data for all kinds of functions and methods. #[derive(Clone, Debug, RustcEncodable)] pub struct FunctionData { - pub id: Id, + pub id: DefId, pub name: String, pub qualname: String, - pub declaration: Option, + pub declaration: Option, pub span: SpanData, - pub scope: Id, + pub scope: DefId, } impl Lower for data::FunctionData { @@ -189,12 +167,12 @@ impl Lower for data::FunctionData { fn lower(self, tcx: &TyCtxt) -> FunctionData { FunctionData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, - declaration: self.declaration.map(Id::from_def_id), + declaration: self.declaration, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -203,8 +181,8 @@ impl Lower for data::FunctionData { #[derive(Debug, RustcEncodable)] pub struct FunctionRefData { pub span: SpanData, - pub scope: Id, - pub ref_id: Id, + pub scope: DefId, + pub ref_id: DefId, } impl Lower for data::FunctionRefData { @@ -213,18 +191,18 @@ impl Lower for data::FunctionRefData { fn lower(self, tcx: &TyCtxt) -> FunctionRefData { FunctionRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: Id::from_def_id(self.ref_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, } } } #[derive(Debug, RustcEncodable)] pub struct ImplData { - pub id: Id, + pub id: DefId, pub span: SpanData, - pub scope: Id, - pub trait_ref: Option, - pub self_ref: Option, + pub scope: DefId, + pub trait_ref: Option, + pub self_ref: Option, } impl Lower for data::ImplData { @@ -232,11 +210,11 @@ impl Lower for data::ImplData { fn lower(self, tcx: &TyCtxt) -> ImplData { ImplData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - trait_ref: self.trait_ref.map(Id::from_def_id), - self_ref: self.self_ref.map(Id::from_def_id), + scope: make_def_id(self.scope, &tcx.map), + trait_ref: self.trait_ref, + self_ref: self.self_ref, } } } @@ -244,8 +222,8 @@ impl Lower for data::ImplData { #[derive(Debug, RustcEncodable)] pub struct InheritanceData { pub span: SpanData, - pub base_id: Id, - pub deriv_id: Id + pub base_id: DefId, + pub deriv_id: DefId } impl Lower for data::InheritanceData { @@ -254,8 +232,8 @@ impl Lower for data::InheritanceData { fn lower(self, tcx: &TyCtxt) -> InheritanceData { InheritanceData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - base_id: Id::from_def_id(self.base_id), - deriv_id: Id::from_node_id(self.deriv_id, &tcx.map) + base_id: self.base_id, + deriv_id: make_def_id(self.deriv_id, &tcx.map) } } } @@ -289,7 +267,7 @@ pub struct MacroUseData { // Because macro expansion happens before ref-ids are determined, // we use the callee span to reference the associated macro definition. pub callee_span: SpanData, - pub scope: Id, + pub scope: DefId, pub imported: bool, } @@ -302,7 +280,7 @@ impl Lower for data::MacroUseData { name: self.name, qualname: self.qualname, callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), imported: self.imported, } } @@ -312,9 +290,9 @@ impl Lower for data::MacroUseData { #[derive(Debug, RustcEncodable)] pub struct MethodCallData { pub span: SpanData, - pub scope: Id, - pub ref_id: Option, - pub decl_id: Option, + pub scope: DefId, + pub ref_id: Option, + pub decl_id: Option, } impl Lower for data::MethodCallData { @@ -323,9 +301,9 @@ impl Lower for data::MethodCallData { fn lower(self, tcx: &TyCtxt) -> MethodCallData { MethodCallData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: self.ref_id.map(Id::from_def_id), - decl_id: self.decl_id.map(Id::from_def_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + decl_id: self.decl_id, } } } @@ -333,10 +311,10 @@ impl Lower for data::MethodCallData { /// Data for method declarations (methods with a body are treated as functions). #[derive(Clone, Debug, RustcEncodable)] pub struct MethodData { - pub id: Id, + pub id: DefId, pub qualname: String, pub span: SpanData, - pub scope: Id, + pub scope: DefId, } impl Lower for data::MethodData { @@ -345,8 +323,8 @@ impl Lower for data::MethodData { fn lower(self, tcx: &TyCtxt) -> MethodData { MethodData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - id: Id::from_node_id(self.id, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), + id: make_def_id(self.id, &tcx.map), qualname: self.qualname, } } @@ -355,11 +333,11 @@ impl Lower for data::MethodData { /// Data for modules. #[derive(Debug, RustcEncodable)] pub struct ModData { - pub id: Id, + pub id: DefId, pub name: String, pub qualname: String, pub span: SpanData, - pub scope: Id, + pub scope: DefId, pub filename: String, } @@ -368,11 +346,11 @@ impl Lower for data::ModData { fn lower(self, tcx: &TyCtxt) -> ModData { ModData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), filename: self.filename, } } @@ -382,8 +360,8 @@ impl Lower for data::ModData { #[derive(Debug, RustcEncodable)] pub struct ModRefData { pub span: SpanData, - pub scope: Id, - pub ref_id: Option, + pub scope: DefId, + pub ref_id: Option, pub qualname: String } @@ -393,8 +371,8 @@ impl Lower for data::ModRefData { fn lower(self, tcx: &TyCtxt) -> ModRefData { ModRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: self.ref_id.map(Id::from_def_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, qualname: self.qualname, } } @@ -403,10 +381,10 @@ impl Lower for data::ModRefData { #[derive(Debug, RustcEncodable)] pub struct StructData { pub span: SpanData, - pub id: Id, - pub ctor_id: Id, + pub id: DefId, + pub ctor_id: DefId, pub qualname: String, - pub scope: Id, + pub scope: DefId, pub value: String } @@ -416,10 +394,10 @@ impl Lower for data::StructData { fn lower(self, tcx: &TyCtxt) -> StructData { StructData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - id: Id::from_node_id(self.id, &tcx.map), - ctor_id: Id::from_node_id(self.ctor_id, &tcx.map), + id: make_def_id(self.id, &tcx.map), + ctor_id: make_def_id(self.ctor_id, &tcx.map), qualname: self.qualname, - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), value: self.value } } @@ -428,11 +406,11 @@ impl Lower for data::StructData { #[derive(Debug, RustcEncodable)] pub struct StructVariantData { pub span: SpanData, - pub id: Id, + pub id: DefId, pub qualname: String, pub type_value: String, pub value: String, - pub scope: Id + pub scope: DefId } impl Lower for data::StructVariantData { @@ -441,11 +419,11 @@ impl Lower for data::StructVariantData { fn lower(self, tcx: &TyCtxt) -> StructVariantData { StructVariantData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), qualname: self.qualname, type_value: self.type_value, value: self.value, - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -453,9 +431,9 @@ impl Lower for data::StructVariantData { #[derive(Debug, RustcEncodable)] pub struct TraitData { pub span: SpanData, - pub id: Id, + pub id: DefId, pub qualname: String, - pub scope: Id, + pub scope: DefId, pub value: String } @@ -465,9 +443,9 @@ impl Lower for data::TraitData { fn lower(self, tcx: &TyCtxt) -> TraitData { TraitData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), qualname: self.qualname, - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), value: self.value, } } @@ -476,12 +454,12 @@ impl Lower for data::TraitData { #[derive(Debug, RustcEncodable)] pub struct TupleVariantData { pub span: SpanData, - pub id: Id, + pub id: DefId, pub name: String, pub qualname: String, pub type_value: String, pub value: String, - pub scope: Id, + pub scope: DefId, } impl Lower for data::TupleVariantData { @@ -490,12 +468,12 @@ impl Lower for data::TupleVariantData { fn lower(self, tcx: &TyCtxt) -> TupleVariantData { TupleVariantData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, type_value: self.type_value, value: self.value, - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -503,7 +481,7 @@ impl Lower for data::TupleVariantData { /// Data for a typedef. #[derive(Debug, RustcEncodable)] pub struct TypedefData { - pub id: Id, + pub id: DefId, pub span: SpanData, pub qualname: String, pub value: String, @@ -514,7 +492,7 @@ impl Lower for data::TypedefData { fn lower(self, tcx: &TyCtxt) -> TypedefData { TypedefData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), qualname: self.qualname, value: self.value, @@ -526,8 +504,8 @@ impl Lower for data::TypedefData { #[derive(Clone, Debug, RustcEncodable)] pub struct TypeRefData { pub span: SpanData, - pub scope: Id, - pub ref_id: Option, + pub scope: DefId, + pub ref_id: Option, pub qualname: String, } @@ -537,8 +515,8 @@ impl Lower for data::TypeRefData { fn lower(self, tcx: &TyCtxt) -> TypeRefData { TypeRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: self.ref_id.map(Id::from_def_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, qualname: self.qualname, } } @@ -546,11 +524,11 @@ impl Lower for data::TypeRefData { #[derive(Debug, RustcEncodable)] pub struct UseData { - pub id: Id, + pub id: DefId, pub span: SpanData, pub name: String, - pub mod_id: Option, - pub scope: Id + pub mod_id: Option, + pub scope: DefId } impl Lower for data::UseData { @@ -558,21 +536,21 @@ impl Lower for data::UseData { fn lower(self, tcx: &TyCtxt) -> UseData { UseData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, - mod_id: self.mod_id.map(Id::from_def_id), - scope: Id::from_node_id(self.scope, &tcx.map), + mod_id: self.mod_id, + scope: make_def_id(self.scope, &tcx.map), } } } #[derive(Debug, RustcEncodable)] pub struct UseGlobData { - pub id: Id, + pub id: DefId, pub span: SpanData, pub names: Vec, - pub scope: Id + pub scope: DefId } impl Lower for data::UseGlobData { @@ -580,10 +558,10 @@ impl Lower for data::UseGlobData { fn lower(self, tcx: &TyCtxt) -> UseGlobData { UseGlobData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), names: self.names, - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), } } } @@ -591,11 +569,11 @@ impl Lower for data::UseGlobData { /// Data for local and global variables (consts and statics). #[derive(Debug, RustcEncodable)] pub struct VariableData { - pub id: Id, + pub id: DefId, pub name: String, pub qualname: String, pub span: SpanData, - pub scope: Id, + pub scope: DefId, pub value: String, pub type_value: String, } @@ -605,11 +583,11 @@ impl Lower for data::VariableData { fn lower(self, tcx: &TyCtxt) -> VariableData { VariableData { - id: Id::from_node_id(self.id, &tcx.map), + id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), + scope: make_def_id(self.scope, &tcx.map), value: self.value, type_value: self.type_value, } @@ -622,8 +600,8 @@ impl Lower for data::VariableData { pub struct VariableRefData { pub name: String, pub span: SpanData, - pub scope: Id, - pub ref_id: Id, + pub scope: DefId, + pub ref_id: DefId, } impl Lower for data::VariableRefData { @@ -633,8 +611,8 @@ impl Lower for data::VariableRefData { VariableRefData { name: self.name, span: SpanData::from_span(self.span, tcx.sess.codemap()), - scope: Id::from_node_id(self.scope, &tcx.map), - ref_id: Id::from_def_id(self.ref_id), + scope: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, } } } From 50717281af218ccc3316d9a208e8fb7ddf85b763 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 3 May 2016 10:21:22 -0700 Subject: [PATCH 06/12] Add detailed error explanation for E0509 Edited the error explanation for E0509 to clarify dropping of moved fields Edited the error explanation for E0509 to clarify move out of Drop value language Fixed typeo in last commit to E0509 Switched to erroneous code wording --- src/librustc_borrowck/diagnostics.rs | 96 +++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index c7ad0b6a6c606..20120e77011fd 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -429,6 +429,101 @@ You can find more information about borrowing in the rust-book: http://doc.rust-lang.org/stable/book/references-and-borrowing.html "##, +E0509: r##" +This error occurs when an attempt is made to move out of a value whose type +implements the `Drop` trait. + +Example of erroneous code: + +```compile_fail +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let fancy_field = drop_struct.fancy; // Error E0509 + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Here, we tried to move a field out of a struct of type `DropStruct` which +implements the `Drop` trait. However, a struct cannot be dropped if one or +more of its fields have been moved. + +Structs implementing the `Drop` trait have an implicit destructor that gets +called when they go out of scope. This destructor may use the fields of the +struct, so moving out of the struct could make it impossible to run the +destructor. Therefore, we must think of all values whose type implements the +`Drop` trait as single units whose fields cannot be moved. + +This error can be fixed by creating a reference to the fields of a struct, +enum, or tuple using the `ref` keyword: + +``` +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + // Destruct DropStruct, possibly using FancyNum + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let ref fancy_field = drop_struct.fancy; // No more errors! + println!("Fancy: {}", fancy_field.num); + // implicit call to `drop_struct.drop()` as drop_struct goes out of scope +} +``` + +Note that this technique can also be used in the arms of a match expression: + +``` +struct FancyNum { + num: usize +} + +enum DropEnum { + Fancy(FancyNum) +} + +impl Drop for DropEnum { + fn drop(&mut self) { + // Destruct DropEnum, possibly using FancyNum + } +} + +fn main() { + // Creates and enum of type `DropEnum`, which implements `Drop` + let drop_enum = DropEnum::Fancy(FancyNum{num: 10}); + match drop_enum { + // Creates a reference to the inside of `DropEnum::Fancy` + DropEnum::Fancy(ref fancy_field) => // No error! + println!("It was fancy-- {}!", fancy_field.num), + } + // implicit call to `drop_enum.drop()` as drop_enum goes out of scope +} +``` +"##, + } register_diagnostics! { @@ -443,6 +538,5 @@ register_diagnostics! { E0505, // cannot move out of `..` because it is borrowed E0506, // cannot assign to `..` because it is borrowed E0508, // cannot move out of type `..`, a non-copy fixed-size array - E0509, // cannot move out of type `..`, which defines the `Drop` trait E0524, // two closures require unique access to `..` at the same time } From d75c079cdeb6bfd1938ab24d061025c2b54aebab Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 7 May 2016 11:22:28 +0200 Subject: [PATCH 07/12] book: fixup code in error handling tutorial A few oversights happened while porting the example from docopt to getopts. I retraced all the steps, fixing code and description as necessary. Fixes: #33422 --- src/doc/book/error-handling.md | 120 +++++++++++++++++---------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/src/doc/book/error-handling.md b/src/doc/book/error-handling.md index 12cb71973ab25..a10e98fac7adf 100644 --- a/src/doc/book/error-handling.md +++ b/src/doc/book/error-handling.md @@ -1573,8 +1573,9 @@ detail on Getopts, but there is [some good documentation][15] describing it. The short story is that Getopts generates an argument parser and a help message from a vector of options (The fact that it is a vector is hidden behind a struct and a set of methods). Once the -parsing is done, we can decode the program arguments into a Rust -struct. From there, we can get information about the flags, for +parsing is done, the parser returns a struct that records matches +for defined options, and remaining "free" arguments. +From there, we can get information about the flags, for instance, whether they were passed in, and what arguments they had. Here's our program with the appropriate `extern crate` statements, and the basic argument setup for Getopts: @@ -1605,8 +1606,8 @@ fn main() { print_usage(&program, opts); return; } - let data_path = &args[1]; - let city = &args[2]; + let data_path = &matches.free[0]; + let city: &str = &matches.free[1]; // Do stuff with information } @@ -1680,8 +1681,8 @@ fn main() { return; } - let data_path = &args[1]; - let city: &str = &args[2]; + let data_path = &matches.free[0]; + let city: &str = &matches.free[1]; let file = File::open(data_path).unwrap(); let mut rdr = csv::Reader::from_reader(file); @@ -1792,13 +1793,15 @@ fn main() { Ok(m) => { m } Err(e) => { panic!(e.to_string()) } }; + if matches.opt_present("h") { print_usage(&program, opts); return; } - let data_path = &args[1]; - let city = &args[2]; + let data_path = &matches.free[0]; + let city: &str = &matches.free[1]; + for pop in search(data_path, city) { println!("{}, {}: {:?}", pop.city, pop.country, pop.count); } @@ -1876,14 +1879,14 @@ when calling `search`: ```rust,ignore ... -match search(&data_file, &city) { - Ok(pops) => { - for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + match search(data_path, city) { + Ok(pops) => { + for pop in pops { + println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + } } + Err(err) => println!("{}", err) } - Err(err) => println!("{}", err) -} ... ``` @@ -1914,43 +1917,37 @@ fn print_usage(program: &str, opts: Options) { println!("{}", opts.usage(&format!("Usage: {} [options] ", program))); } ``` -The next part is going to be only a little harder: +Of course we need to adapt the argument handling code: ```rust,ignore ... -let mut opts = Options::new(); -opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); -opts.optflag("h", "help", "Show this usage message."); -... -let file = matches.opt_str("f"); -let data_file = &file.as_ref().map(Path::new); - -let city = if !matches.free.is_empty() { - &matches.free[0] -} else { - print_usage(&program, opts); - return; -}; - -match search(data_file, city) { - Ok(pops) => { - for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + let mut opts = Options::new(); + opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); + opts.optflag("h", "help", "Show this usage message."); + ... + let data_path = matches.opt_str("f"); + + let city = if !matches.free.is_empty() { + &matches.free[0] + } else { + print_usage(&program, opts); + return; + }; + + match search(&data_path, city) { + Ok(pops) => { + for pop in pops { + println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + } } + Err(err) => println!("{}", err) } - Err(err) => println!("{}", err) -} ... ``` -In this piece of code, we take `file` (which has the type -`Option`), and convert it to a type that `search` can use, in -this case, `&Option>`. To do this, we take a reference of -file, and map `Path::new` onto it. In this case, `as_ref()` converts -the `Option` into an `Option<&str>`, and from there, we can -execute `Path::new` to the content of the optional, and return the -optional of the new value. Once we have that, it is a simple matter of -getting the `city` argument and executing `search`. +We've made the user experience a bit nicer by showing the usage message, +instead of a panic from an out-of-bounds index, when `city`, the +remaining free argument, is not present. Modifying `search` is slightly trickier. The `csv` crate can build a parser out of @@ -2000,6 +1997,8 @@ enum CliError { And now for impls on `Display` and `Error`: ```rust,ignore +use std::fmt; + impl fmt::Display for CliError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -2020,13 +2019,13 @@ impl Error for CliError { } } - fn cause(&self) -> Option<&error::Error> { - match *self { + fn cause(&self) -> Option<&Error> { + match *self { CliError::Io(ref err) => Some(err), - CliError::Parse(ref err) => Some(err), - // Our custom error doesn't have an underlying cause, but we could - // modify it so that it does. - CliError::NotFound() => None, + CliError::Csv(ref err) => Some(err), + // Our custom error doesn't have an underlying cause, + // but we could modify it so that it does. + CliError::NotFound => None, } } } @@ -2122,10 +2121,10 @@ string and add a flag to the Option variable. Once we've done that, Getopts does ```rust,ignore ... -let mut opts = Options::new(); -opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); -opts.optflag("h", "help", "Show this usage message."); -opts.optflag("q", "quiet", "Silences errors and warnings."); + let mut opts = Options::new(); + opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); + opts.optflag("h", "help", "Show this usage message."); + opts.optflag("q", "quiet", "Silences errors and warnings."); ... ``` @@ -2133,13 +2132,16 @@ Now we only need to implement our “quiet” functionality. This requires us to tweak the case analysis in `main`: ```rust,ignore -match search(&args.arg_data_path, &args.arg_city) { - Err(CliError::NotFound) if args.flag_quiet => process::exit(1), - Err(err) => panic!("{}", err), - Ok(pops) => for pop in pops { - println!("{}, {}: {:?}", pop.city, pop.country, pop.count); +use std::process; +... + match search(&data_path, city) { + Err(CliError::NotFound) if matches.opt_present("q") => process::exit(1), + Err(err) => panic!("{}", err), + Ok(pops) => for pop in pops { + println!("{}, {}: {:?}", pop.city, pop.country, pop.count); + } } -} +... ``` Certainly, we don't want to be quiet if there was an IO error or if the data From 1bd4c9d7231cc3434e29f59ea16c01fff3db0f86 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 May 2016 14:04:13 +0200 Subject: [PATCH 08/12] Doc improvement on std::fmt module --- src/libcollections/fmt.rs | 12 ++++++++++++ src/libcore/fmt/mod.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index e30e0b213afa1..1f5d542c547ee 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -505,12 +505,24 @@ use string; /// /// # Examples /// +/// Basic usage: +/// /// ``` /// use std::fmt; /// /// let s = fmt::format(format_args!("Hello, {}!", "world")); /// assert_eq!(s, "Hello, world!".to_string()); /// ``` +/// +/// Please note that using [`format!`][format!] might be preferrable. +/// Example: +/// +/// ``` +/// let s = format!("Hello, {}!", "world"); +/// assert_eq!(s, "Hello, world!".to_string()); +/// ``` +/// +/// [format!]: ../macro.format!.html #[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments) -> string::String { let mut output = string::String::new(); diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0c824b5a8e69a..32c6d0e8dcb09 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -776,6 +776,32 @@ pub trait UpperExp { /// /// * output - the buffer to write output to /// * args - the precompiled arguments generated by `format_args!` +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::fmt; +/// +/// let mut output = String::new(); +/// fmt::write(&mut output, format_args!("Hello {}!", "world")) +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// Please note that using [`write!`][write_macro] might be preferrable. Example: +/// +/// ``` +/// use std::fmt::Write; +/// +/// let mut output = String::new(); +/// write!(&mut output, "Hello {}!", "world") +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// [write_macro]: ../macro.write!.html #[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut Write, args: Arguments) -> Result { let mut formatter = Formatter { From a7439ad75a180a5be77bd3f73bcc6c6896226036 Mon Sep 17 00:00:00 2001 From: silvo38 Date: Sun, 8 May 2016 22:33:03 +1000 Subject: [PATCH 09/12] Fix minor typo in E0312 --- src/librustc/infer/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 11d92f8585489..940d7e911ff3c 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -735,7 +735,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { } infer::Reborrow(span) => { let mut err = struct_span_err!(self.tcx.sess, span, E0312, - "lifetime of reference outlines \ + "lifetime of reference outlives \ lifetime of borrowed content..."); self.tcx.note_and_explain_region(&mut err, "...the reference is valid for ", From ba17bd0b42b3f8e13cac97781f7d81efad13b166 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 9 May 2016 10:18:06 +0200 Subject: [PATCH 10/12] rustdoc: fix emitting duplicate implementors in .js files The collect() fn checks for double quotes; use them here as well. Fixes: #30219 --- src/librustdoc/html/render.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a3200e69e3c42..b91b3c3a7174f 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -783,7 +783,7 @@ fn write_shared(cx: &Context, try_err!(write!(&mut f, "{}", *implementor), &mydst); } - try_err!(write!(&mut f, r"implementors['{}'] = [", krate.name), &mydst); + try_err!(write!(&mut f, r#"implementors["{}"] = ["#, krate.name), &mydst); for imp in imps { // If the trait and implementation are in the same crate, then // there's no need to emit information about it (there's inlining From 62b19c627ebde2bbfa6021de146c502124da7975 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 6 May 2016 19:32:18 -0400 Subject: [PATCH 11/12] Utilize `Result::unwrap_err` in more places. --- src/libcollectionstest/string.rs | 2 +- src/libserialize/json.rs | 2 +- src/libstd/fs.rs | 2 +- src/libstd/io/buffered.rs | 2 +- src/libstd/sync/mpsc/mod.rs | 2 +- src/libterm/terminfo/parm.rs | 16 ++++++++-------- src/test/run-make/static-unwinding/main.rs | 2 +- src/test/run-pass/command-before-exec.rs | 2 +- src/test/run-pass/no-landing-pads.rs | 2 +- src/test/run-pass/panic-recover-propagate.rs | 4 ++-- src/test/run-pass/sepcomp-unwind.rs | 2 +- src/test/run-pass/terminate-in-initializer.rs | 4 ++-- src/test/run-pass/unit-like-struct-drop-run.rs | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index d71529023f4f7..c2eafa1b90f12 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -52,7 +52,7 @@ fn test_from_utf8() { String::from("ศไทย中华Việt Nam")); let xs = b"hello\xFF".to_vec(); - let err = String::from_utf8(xs).err().unwrap(); + let err = String::from_utf8(xs).unwrap_err(); assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a7d723515664d..90b2c6116038c 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -3948,7 +3948,7 @@ mod tests { let mut mem_buf = string::String::new(); let mut encoder = Encoder::new(&mut mem_buf); let result = hm.encode(&mut encoder); - match result.err().unwrap() { + match result.unwrap_err() { EncoderError::BadHashmapKey => (), _ => panic!("expected bad hash map key") } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 03ebaa59ca562..c19fe1e1d2604 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1772,7 +1772,7 @@ mod tests { let tmpdir = tmpdir(); let dir = &tmpdir.join("mkdir_error_twice"); check!(fs::create_dir(dir)); - let e = fs::create_dir(dir).err().unwrap(); + let e = fs::create_dir(dir).unwrap_err(); assert_eq!(e.kind(), ErrorKind::AlreadyExists); } diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 632ef3db80451..a92ca95f4ee7e 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -1127,7 +1127,7 @@ mod tests { let mut writer = BufWriter::new(PanicWriter); let _ = writer.write(b"hello world"); let _ = writer.flush(); - }).join().err().unwrap(); + }).join().unwrap_err(); assert_eq!(WRITES.load(Ordering::SeqCst), 1); } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index dbcc2bc95bc21..63b659d8db3b7 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -535,7 +535,7 @@ impl Sender { /// /// // This send will fail because the receiver is gone /// drop(rx); - /// assert_eq!(tx.send(1).err().unwrap().0, 1); + /// assert_eq!(tx.send(1).unwrap_err().0, 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn send(&self, t: T) -> Result<(), SendError> { diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index 60b5dffac59ad..fbc6bfb6c8d9f 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -594,7 +594,7 @@ mod test { assert!(res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, - res.err().unwrap()); + res.unwrap_err()); } let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"]; for &cap in caps.iter() { @@ -610,7 +610,7 @@ mod test { assert!(res.is_ok(), "Binop {} failed with 2 stack entries: {}", cap, - res.err().unwrap()); + res.unwrap_err()); } } @@ -625,15 +625,15 @@ mod test { for &(op, bs) in v.iter() { let s = format!("%{{1}}%{{2}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), vec![b'0' + bs[0]]); let s = format!("%{{1}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), vec![b'0' + bs[1]]); let s = format!("%{{2}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), vec![b'0' + bs[2]]); } } @@ -643,13 +643,13 @@ mod test { let mut vars = Variables::new(); let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"; let res = expand(s, &[Number(1)], &mut vars); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::>()); let res = expand(s, &[Number(8)], &mut vars); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::>()); let res = expand(s, &[Number(42)], &mut vars); - assert!(res.is_ok(), res.err().unwrap()); + assert!(res.is_ok(), res.unwrap_err()); assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::>()); } diff --git a/src/test/run-make/static-unwinding/main.rs b/src/test/run-make/static-unwinding/main.rs index ba4860be91d66..1cd785334f63a 100644 --- a/src/test/run-make/static-unwinding/main.rs +++ b/src/test/run-make/static-unwinding/main.rs @@ -25,7 +25,7 @@ fn main() { thread::spawn(move|| { let _a = A; lib::callback(|| panic!()); - }).join().err().unwrap(); + }).join().unwrap_err(); unsafe { assert_eq!(lib::statik, 1); diff --git a/src/test/run-pass/command-before-exec.rs b/src/test/run-pass/command-before-exec.rs index 16560637b6926..72f952fb6c0df 100644 --- a/src/test/run-pass/command-before-exec.rs +++ b/src/test/run-pass/command-before-exec.rs @@ -62,7 +62,7 @@ fn main() { let output = Command::new(&me).arg("bad").before_exec(|| { Err(Error::from_raw_os_error(102)) - }).output().err().unwrap(); + }).output().unwrap_err(); assert_eq!(output.raw_os_error(), Some(102)); let pid = unsafe { libc::getpid() }; diff --git a/src/test/run-pass/no-landing-pads.rs b/src/test/run-pass/no-landing-pads.rs index 8445bccf13493..e718046ebbcd7 100644 --- a/src/test/run-pass/no-landing-pads.rs +++ b/src/test/run-pass/no-landing-pads.rs @@ -27,6 +27,6 @@ fn main() { thread::spawn(move|| -> () { let _a = A; panic!(); - }).join().err().unwrap(); + }).join().unwrap_err(); assert!(unsafe { !HIT }); } diff --git a/src/test/run-pass/panic-recover-propagate.rs b/src/test/run-pass/panic-recover-propagate.rs index d420ef99863c2..2c87c6b92686c 100644 --- a/src/test/run-pass/panic-recover-propagate.rs +++ b/src/test/run-pass/panic-recover-propagate.rs @@ -28,10 +28,10 @@ fn main() { panic!("hi there"); }); - panic::propagate(result.err().unwrap()); + panic::propagate(result.unwrap_err()); }).join(); - let msg = *result.err().unwrap().downcast::<&'static str>().unwrap(); + let msg = *result.unwrap_err().downcast::<&'static str>().unwrap(); assert_eq!("hi there", msg); assert_eq!(1, A.load(Ordering::SeqCst)); } diff --git a/src/test/run-pass/sepcomp-unwind.rs b/src/test/run-pass/sepcomp-unwind.rs index 96e9c1ed2ccf9..3a93845a0620a 100644 --- a/src/test/run-pass/sepcomp-unwind.rs +++ b/src/test/run-pass/sepcomp-unwind.rs @@ -39,5 +39,5 @@ mod b { } fn main() { - thread::spawn(move|| { ::b::g() }).join().err().unwrap(); + thread::spawn(move|| { ::b::g() }).join().unwrap_err(); } diff --git a/src/test/run-pass/terminate-in-initializer.rs b/src/test/run-pass/terminate-in-initializer.rs index 2875f73fc6cfa..c9133bae85408 100644 --- a/src/test/run-pass/terminate-in-initializer.rs +++ b/src/test/run-pass/terminate-in-initializer.rs @@ -24,13 +24,13 @@ fn test_ret() { let _x: Box = return; } fn test_panic() { fn f() { let _x: Box = panic!(); } - thread::spawn(move|| f() ).join().err().unwrap(); + thread::spawn(move|| f() ).join().unwrap_err(); } fn test_panic_indirect() { fn f() -> ! { panic!(); } fn g() { let _x: Box = f(); } - thread::spawn(move|| g() ).join().err().unwrap(); + thread::spawn(move|| g() ).join().unwrap_err(); } pub fn main() { diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index eaee3505a67ca..ec37be9420db7 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -30,6 +30,6 @@ pub fn main() { let _b = Foo; }).join(); - let s = x.err().unwrap().downcast::<&'static str>().unwrap(); + let s = x.unwrap_err().downcast::<&'static str>().unwrap(); assert_eq!(&**s, "This panic should happen."); } From 6100b70b98ee090c9b8e7b4788e4513e64fcc3ff Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 9 May 2016 16:48:02 +0200 Subject: [PATCH 12/12] rustdoc: do not strip blanket impls in crate of origin In `impl Trait for T`, the blanket type parameters `T` were recognized as "local" and "not exported", so these impls were thrown out. Now we check if they are generic, and keep them in that case. Fixes: #29503 --- src/librustdoc/clean/mod.rs | 7 +++++++ src/librustdoc/passes.rs | 8 +++++--- src/test/rustdoc/issue-29503.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-29503.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f5b8db1143ed6..a47b66bf2f72e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1540,6 +1540,13 @@ impl Type { _ => None, } } + + pub fn is_generic(&self) -> bool { + match *self { + ResolvedPath { is_generic, .. } => is_generic, + _ => false, + } + } } impl GetDefId for Type { diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 34c83e1819df6..1980d1f9cc45f 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -115,9 +115,9 @@ impl<'a> fold::DocFolder for Stripper<'a> { // trait impls for private items should be stripped clean::ImplItem(clean::Impl{ - for_: clean::ResolvedPath{ did, .. }, .. + for_: clean::ResolvedPath{ did, is_generic, .. }, .. }) => { - if did.is_local() && !self.access_levels.is_exported(did) { + if did.is_local() && !is_generic && !self.access_levels.is_exported(did) { return None; } } @@ -183,7 +183,9 @@ impl<'a> fold::DocFolder for ImplStripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = i.inner { if let Some(did) = imp.for_.def_id() { - if did.is_local() && !self.retained.contains(&did) { + if did.is_local() && !imp.for_.is_generic() && + !self.retained.contains(&did) + { return None; } } diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs new file mode 100644 index 0000000000000..d8b484f6b501b --- /dev/null +++ b/src/test/rustdoc/issue-29503.rs @@ -0,0 +1,26 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt; + +// @has issue_29503/trait.MyTrait.html +pub trait MyTrait { + fn my_string(&self) -> String; +} + +// @has - "//ul[@id='implementors-list']/li" "impl MyTrait for T where T: Debug" +impl MyTrait for T where T: fmt::Debug { + fn my_string(&self) -> String { + format!("{:?}", self) + } +} + +pub fn main() { +}