1
Fork 0

Auto merge of #33523 - Manishearth:rollup, r=Manishearth

Rollup of 10 pull requests

- Successful merges: #33129, #33224, #33370, #33383, #33431, #33474, #33480, #33496, #33509, #33514
- Failed merges:
This commit is contained in:
bors 2016-05-09 16:11:51 -07:00
commit e0fd34bba0
32 changed files with 1104 additions and 923 deletions

View file

@ -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] <city>", 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 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;
};
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);
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<String>`), and convert it to a type that `search` can use, in
this case, `&Option<AsRef<Path>>`. To do this, we take a reference of
file, and map `Path::new` onto it. In this case, `as_ref()` converts
the `Option<String>` 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

View file

@ -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());
}

View file

@ -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 ",

View file

@ -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
}

View file

@ -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

View file

@ -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));
}
}
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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) {}

View file

@ -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(..) |

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<data::ExternalCrateData>,
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<DefId>,
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<DefId>,
pub self_ref: Option<DefId>,
}
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<DefId>,
pub decl_id: Option<DefId>,
}
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<DefId>,
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<DefId>,
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<DefId>,
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<String>,
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,
}
}
}

View file

@ -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<data::ExternalCrateData>,
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<Id>,
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<Id>,
pub self_ref: Option<Id>,
}
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<Id>,
pub decl_id: Option<Id>,
}
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<Id>,
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<Id>,
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<Id>,
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<String>,
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(),
}
}
}

View file

@ -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)),
}
}

View file

@ -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<Span>) -> Option<Span> {

View file

@ -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 {

View file

@ -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, "<span class=\"since\">{}</span>",
write!(w, "<div class=\"since\">{}</div>",
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, "<h3 class='impl'><span class='in-band'><code>{}</code>", 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, "</span><span class='out-of-band'>")?;
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, "<div class='ghost'></div>")?;
render_stability_since_raw(w, since, outer_version)?;
write!(w, "<a id='src-{}' class='srclink' \
href='{}' title='{}'>[src]</a>",
i.impl_item.def_id.index.as_usize(), l, "goto source code")?;
} else {
render_stability_since_raw(w, since, outer_version)?;
}
write!(w, "</span>")?;
write!(w, "</h3>\n")?;

View file

@ -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 */

View file

@ -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;

View file

@ -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<Item> {
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;
}
}

View file

@ -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")
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -535,7 +535,7 @@ impl<T> Sender<T> {
///
/// // 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<T>> {

View file

@ -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::<Vec<_>>());
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::<Vec<_>>());
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::<Vec<_>>());
}

View file

@ -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);

View file

@ -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() };

View file

@ -27,6 +27,6 @@ fn main() {
thread::spawn(move|| -> () {
let _a = A;
panic!();
}).join().err().unwrap();
}).join().unwrap_err();
assert!(unsafe { !HIT });
}

View file

@ -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));
}

View file

@ -39,5 +39,5 @@ mod b {
}
fn main() {
thread::spawn(move|| { ::b::g() }).join().err().unwrap();
thread::spawn(move|| { ::b::g() }).join().unwrap_err();
}

View file

@ -24,13 +24,13 @@ fn test_ret() { let _x: Box<isize> = return; }
fn test_panic() {
fn f() { let _x: Box<isize> = 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<isize> = f(); }
thread::spawn(move|| g() ).join().err().unwrap();
thread::spawn(move|| g() ).join().unwrap_err();
}
pub fn main() {

View file

@ -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.");
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> MyTrait for T where T: Debug"
impl<T> MyTrait for T where T: fmt::Debug {
fn my_string(&self) -> String {
format!("{:?}", self)
}
}
pub fn main() {
}