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 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/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 ", diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 03fb5260c3992..8d9b88e899be2 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -653,6 +653,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! { @@ -664,6 +759,5 @@ register_diagnostics! { E0504, // cannot move `..` into closure because it is borrowed E0505, // cannot move out of `..` 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 } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index fda7c7aeb3306..3514862205289 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -497,6 +497,91 @@ impl Bar { ``` "##, +E0408: r##" +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Example of erroneous code: + +```compile_fail +match x { + Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is + // not bound in pattern #2 + _ => () +} +``` + +Here, `y` is bound to the contents of the `Some` and can be used within the +block corresponding to the match arm. However, in case `x` is `None`, we have +not specified what `y` is, and the block will use a nonexistent variable. + +To fix this error, either split into multiple match arms: + +``` +let x = Some(1); +match x { + Some(y) => { /* use y */ } + None => { /* ... */ } +} +``` + +or, bind the variable to a field of the same type in all sub-patterns of the +or pattern: + +``` +let x = (0, 2); +match x { + (0, y) | (y, 0) => { /* use y */} + _ => {} +} +``` + +In this example, if `x` matches the pattern `(0, _)`, the second field is set +to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all +cases `y` is set to some value. +"##, + +E0409: r##" +An "or" pattern was used where the variable bindings are not consistently bound +across patterns. + +Example of erroneous code: + +```compile_fail +let x = (0, 2); +match x { + (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with + // different mode in pattern #2 + // than in pattern #1 + _ => () +} +``` + +Here, `y` is bound by-value in one case and by-reference in the other. + +To fix this error, just use the same mode in both cases. +Generally using `ref` or `ref mut` where not already used will fix this: + +```ignore +let x = (0, 2); +match x { + (0, ref y) | (ref y, 0) => { /* use y */} + _ => () +} +``` + +Alternatively, split the pattern: + +``` +let x = (0, 2); +match x { + (y, 0) => { /* use y */ } + (0, ref y) => { /* use y */} + _ => () +} +``` +"##, + E0411: r##" The `Self` keyword was used outside an impl or a trait. Erroneous code example: @@ -1145,10 +1230,7 @@ register_diagnostics! { // E0258, E0402, // cannot use an outer type parameter in this context E0406, // undeclared associated type - E0408, // variable from pattern #1 is not bound in pattern # - E0409, // variable is bound with different mode in pattern # than in - // pattern #1 - E0410, // variable from pattern is not bound in pattern 1 +// E0410, merged into 408 E0418, // is not an enum variant, struct or const E0420, // is not an associated const E0421, // unresolved associated const diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7c6c76f130efe..e3c2a9300baf8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -126,12 +126,10 @@ enum ResolutionError<'a> { TypeNotMemberOfTrait(Name, &'a str), /// error E0438: const is not a member of trait ConstNotMemberOfTrait(Name, &'a str), - /// error E0408: variable `{}` from pattern #1 is not bound in pattern - VariableNotBoundInPattern(Name, usize), + /// error E0408: variable `{}` from pattern #{} is not bound in pattern #{} + VariableNotBoundInPattern(Name, usize, usize), /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1 VariableBoundWithDifferentMode(Name, usize), - /// error E0410: variable from pattern is not bound in pattern #1 - VariableNotBoundInParentPattern(Name, usize), /// error E0411: use of `Self` outside of an impl or trait SelfUsedOutsideImplOrTrait, /// error E0412: use of undeclared @@ -272,13 +270,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, const_, trait_) } - ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => { + ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => { struct_span_err!(resolver.session, span, E0408, - "variable `{}` from pattern #1 is not bound in pattern #{}", + "variable `{}` from pattern #{} is not bound in pattern #{}", variable_name, - pattern_number) + from, + to) } ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => { struct_span_err!(resolver.session, @@ -289,14 +288,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, variable_name, pattern_number) } - ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => { - struct_span_err!(resolver.session, - span, - E0410, - "variable `{}` from pattern #{} is not bound in pattern #1", - variable_name, - pattern_number) - } ResolutionError::SelfUsedOutsideImplOrTrait => { struct_span_err!(resolver.session, span, @@ -2038,7 +2029,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { resolve_error(self, p.span, - ResolutionError::VariableNotBoundInPattern(key, i + 1)); + ResolutionError::VariableNotBoundInPattern(key, 1, i + 1)); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { @@ -2055,7 +2046,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !map_0.contains_key(&key) { resolve_error(self, binding.span, - ResolutionError::VariableNotBoundInParentPattern(key, i + 1)); + ResolutionError::VariableNotBoundInPattern(key, i + 1, 1)); } } } diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs index 4d6512db861e5..ac658af4006b1 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), @@ -65,8 +60,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -78,9 +73,9 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -96,12 +91,12 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { 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 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.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("refid", &ref_id), @@ -117,8 +112,8 @@ 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 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), @@ -135,8 +130,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { None => (String::new(), String::new()) }; - 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), @@ -151,7 +146,7 @@ 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 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), @@ -166,7 +161,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { 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), @@ -178,8 +173,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -199,7 +194,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { let def_id = ref_id.index.as_usize().to_string(); let def_crate = ref_id.krate.to_string(); - let scope = data.scope.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("refid", &def_id), ("refidcrate", &def_crate), @@ -221,7 +216,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -232,8 +227,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -250,7 +245,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { 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), @@ -262,9 +257,9 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -277,8 +272,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -292,8 +287,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -305,8 +300,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -325,7 +320,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, 'b, W> { 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), @@ -337,7 +332,7 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -350,10 +345,10 @@ 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 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.to_string(); + let scope = data.scope.index.as_u32().to_string(); let values = make_values_str(&[ ("id", &id), ("refid", &ref_id), @@ -368,8 +363,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -380,8 +375,8 @@ impl<'a, 'b, W: Write + 'b> Dump for CsvDumper<'a, '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), @@ -397,7 +392,7 @@ 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 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), @@ -431,9 +426,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 e654cef0c3056..19f9ba95b35d6 100644 --- a/src/librustc_save_analysis/data.rs +++ b/src/librustc_save_analysis/data.rs @@ -14,39 +14,8 @@ //! retrieve the data from a crate. 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, @@ -357,58 +326,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..db4bd1d6d7308 --- /dev/null +++ b/src/librustc_save_analysis/external_data.rs @@ -0,0 +1,618 @@ +// 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 rustc::hir::def_id::{DefId, DefIndex}; +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; +} + +fn make_def_id(id: NodeId, map: &Map) -> DefId { + map.opt_local_def_id(id).unwrap_or(null_def_id()) +} + +pub fn null_def_id() -> DefId { + DefId { krate: u32::max_value(), index: DefIndex::from_u32(u32::max_value()) } +} + +#[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: DefId, + pub value: String, + pub qualname: String, + pub span: SpanData, + pub scope: DefId, +} + +impl Lower for data::EnumData { + type Target = EnumData; + + fn lower(self, tcx: &TyCtxt) -> EnumData { + EnumData { + id: make_def_id(self.id, &tcx.map), + value: self.value, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +/// Data for extern crates. +#[derive(Debug, RustcEncodable)] +pub struct ExternCrateData { + pub id: DefId, + pub name: String, + pub crate_num: CrateNum, + pub location: String, + pub span: SpanData, + pub scope: DefId, +} + +impl Lower for data::ExternCrateData { + type Target = ExternCrateData; + + fn lower(self, tcx: &TyCtxt) -> ExternCrateData { + ExternCrateData { + 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: make_def_id(self.scope, &tcx.map), + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionCallData { + pub span: SpanData, + pub scope: DefId, + pub ref_id: DefId, +} + +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: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + } + } +} + +/// Data for all kinds of functions and methods. +#[derive(Clone, Debug, RustcEncodable)] +pub struct FunctionData { + pub id: DefId, + pub name: String, + pub qualname: String, + pub declaration: Option, + pub span: SpanData, + pub scope: DefId, +} + +impl Lower for data::FunctionData { + type Target = FunctionData; + + fn lower(self, tcx: &TyCtxt) -> FunctionData { + FunctionData { + id: make_def_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + declaration: self.declaration, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +/// Data about a function call. +#[derive(Debug, RustcEncodable)] +pub struct FunctionRefData { + pub span: SpanData, + pub scope: DefId, + pub ref_id: DefId, +} + +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: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + } + } +} +#[derive(Debug, RustcEncodable)] +pub struct ImplData { + pub id: DefId, + pub span: SpanData, + pub scope: DefId, + pub trait_ref: Option, + pub self_ref: Option, +} + +impl Lower for data::ImplData { + type Target = ImplData; + + fn lower(self, tcx: &TyCtxt) -> ImplData { + ImplData { + id: make_def_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: make_def_id(self.scope, &tcx.map), + trait_ref: self.trait_ref, + self_ref: self.self_ref, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct InheritanceData { + pub span: SpanData, + pub base_id: DefId, + pub deriv_id: DefId +} + +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: self.base_id, + deriv_id: make_def_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: DefId, + 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: make_def_id(self.scope, &tcx.map), + imported: self.imported, + } + } +} + +/// Data about a method call. +#[derive(Debug, RustcEncodable)] +pub struct MethodCallData { + pub span: SpanData, + pub scope: DefId, + 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: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + decl_id: self.decl_id, + } + } +} + +/// Data for method declarations (methods with a body are treated as functions). +#[derive(Clone, Debug, RustcEncodable)] +pub struct MethodData { + pub id: DefId, + pub qualname: String, + pub span: SpanData, + pub scope: DefId, +} + +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: make_def_id(self.scope, &tcx.map), + id: make_def_id(self.id, &tcx.map), + qualname: self.qualname, + } + } +} + +/// Data for modules. +#[derive(Debug, RustcEncodable)] +pub struct ModData { + pub id: DefId, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: DefId, + pub filename: String, +} + +impl Lower for data::ModData { + type Target = ModData; + + fn lower(self, tcx: &TyCtxt) -> ModData { + ModData { + id: make_def_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: make_def_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: DefId, + 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: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructData { + pub span: SpanData, + pub id: DefId, + pub ctor_id: DefId, + pub qualname: String, + pub scope: DefId, + 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: make_def_id(self.id, &tcx.map), + ctor_id: make_def_id(self.ctor_id, &tcx.map), + qualname: self.qualname, + scope: make_def_id(self.scope, &tcx.map), + value: self.value + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct StructVariantData { + pub span: SpanData, + pub id: DefId, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: DefId +} + +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: make_def_id(self.id, &tcx.map), + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TraitData { + pub span: SpanData, + pub id: DefId, + pub qualname: String, + pub scope: DefId, + 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: make_def_id(self.id, &tcx.map), + qualname: self.qualname, + scope: make_def_id(self.scope, &tcx.map), + value: self.value, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct TupleVariantData { + pub span: SpanData, + pub id: DefId, + pub name: String, + pub qualname: String, + pub type_value: String, + pub value: String, + pub scope: DefId, +} + +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: make_def_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + type_value: self.type_value, + value: self.value, + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +/// Data for a typedef. +#[derive(Debug, RustcEncodable)] +pub struct TypedefData { + pub id: DefId, + 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: make_def_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: DefId, + 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: make_def_id(self.scope, &tcx.map), + ref_id: self.ref_id, + qualname: self.qualname, + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseData { + pub id: DefId, + pub span: SpanData, + pub name: String, + pub mod_id: Option, + pub scope: DefId +} + +impl Lower for data::UseData { + type Target = UseData; + + fn lower(self, tcx: &TyCtxt) -> UseData { + UseData { + 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, + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +#[derive(Debug, RustcEncodable)] +pub struct UseGlobData { + pub id: DefId, + pub span: SpanData, + pub names: Vec, + pub scope: DefId +} + +impl Lower for data::UseGlobData { + type Target = UseGlobData; + + fn lower(self, tcx: &TyCtxt) -> UseGlobData { + UseGlobData { + id: make_def_id(self.id, &tcx.map), + span: SpanData::from_span(self.span, tcx.sess.codemap()), + names: self.names, + scope: make_def_id(self.scope, &tcx.map), + } + } +} + +/// Data for local and global variables (consts and statics). +#[derive(Debug, RustcEncodable)] +pub struct VariableData { + pub id: DefId, + pub name: String, + pub qualname: String, + pub span: SpanData, + pub scope: DefId, + pub value: String, + pub type_value: String, +} + +impl Lower for data::VariableData { + type Target = VariableData; + + fn lower(self, tcx: &TyCtxt) -> VariableData { + VariableData { + id: make_def_id(self.id, &tcx.map), + name: self.name, + qualname: self.qualname, + span: SpanData::from_span(self.span, tcx.sess.codemap()), + scope: make_def_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: DefId, + pub ref_id: DefId, +} + +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: make_def_id(self.scope, &tcx.map), + ref_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 { 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/html/render.rs b/src/librustdoc/html/render.rs index a3200e69e3c42..6a2a0a37c1c05 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 @@ -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 c07871a4029ca..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,20 +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; @@ -498,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 { @@ -597,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; 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/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."); } 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() { +}