Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e0fd34b

Browse files
committedMay 9, 2016
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:
2 parents 0e7cb8b + 52f48bd commit e0fd34b

32 files changed

+1106
-925
lines changed
 

‎src/doc/book/error-handling.md

+61-59
Original file line numberDiff line numberDiff line change
@@ -1573,8 +1573,9 @@ detail on Getopts, but there is [some good documentation][15]
15731573
describing it. The short story is that Getopts generates an argument
15741574
parser and a help message from a vector of options (The fact that it
15751575
is a vector is hidden behind a struct and a set of methods). Once the
1576-
parsing is done, we can decode the program arguments into a Rust
1577-
struct. From there, we can get information about the flags, for
1576+
parsing is done, the parser returns a struct that records matches
1577+
for defined options, and remaining "free" arguments.
1578+
From there, we can get information about the flags, for
15781579
instance, whether they were passed in, and what arguments they
15791580
had. Here's our program with the appropriate `extern crate`
15801581
statements, and the basic argument setup for Getopts:
@@ -1605,8 +1606,8 @@ fn main() {
16051606
print_usage(&program, opts);
16061607
return;
16071608
}
1608-
let data_path = &args[1];
1609-
let city = &args[2];
1609+
let data_path = &matches.free[0];
1610+
let city: &str = &matches.free[1];
16101611
16111612
// Do stuff with information
16121613
}
@@ -1680,8 +1681,8 @@ fn main() {
16801681
return;
16811682
}
16821683
1683-
let data_path = &args[1];
1684-
let city: &str = &args[2];
1684+
let data_path = &matches.free[0];
1685+
let city: &str = &matches.free[1];
16851686
16861687
let file = File::open(data_path).unwrap();
16871688
let mut rdr = csv::Reader::from_reader(file);
@@ -1792,13 +1793,15 @@ fn main() {
17921793
Ok(m) => { m }
17931794
Err(e) => { panic!(e.to_string()) }
17941795
};
1796+
17951797
if matches.opt_present("h") {
17961798
print_usage(&program, opts);
17971799
return;
17981800
}
17991801
1800-
let data_path = &args[1];
1801-
let city = &args[2];
1802+
let data_path = &matches.free[0];
1803+
let city: &str = &matches.free[1];
1804+
18021805
for pop in search(data_path, city) {
18031806
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
18041807
}
@@ -1876,14 +1879,14 @@ when calling `search`:
18761879

18771880
```rust,ignore
18781881
...
1879-
match search(&data_file, &city) {
1880-
Ok(pops) => {
1881-
for pop in pops {
1882-
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1882+
match search(data_path, city) {
1883+
Ok(pops) => {
1884+
for pop in pops {
1885+
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1886+
}
18831887
}
1888+
Err(err) => println!("{}", err)
18841889
}
1885-
Err(err) => println!("{}", err)
1886-
}
18871890
...
18881891
```
18891892

@@ -1914,43 +1917,37 @@ fn print_usage(program: &str, opts: Options) {
19141917
println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program)));
19151918
}
19161919
```
1917-
The next part is going to be only a little harder:
1920+
Of course we need to adapt the argument handling code:
19181921

19191922
```rust,ignore
19201923
...
1921-
let mut opts = Options::new();
1922-
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
1923-
opts.optflag("h", "help", "Show this usage message.");
1924-
...
1925-
let file = matches.opt_str("f");
1926-
let data_file = &file.as_ref().map(Path::new);
1927-
1928-
let city = if !matches.free.is_empty() {
1929-
&matches.free[0]
1930-
} else {
1931-
print_usage(&program, opts);
1932-
return;
1933-
};
1934-
1935-
match search(data_file, city) {
1936-
Ok(pops) => {
1937-
for pop in pops {
1938-
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1924+
let mut opts = Options::new();
1925+
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
1926+
opts.optflag("h", "help", "Show this usage message.");
1927+
...
1928+
let data_path = matches.opt_str("f");
1929+
1930+
let city = if !matches.free.is_empty() {
1931+
&matches.free[0]
1932+
} else {
1933+
print_usage(&program, opts);
1934+
return;
1935+
};
1936+
1937+
match search(&data_path, city) {
1938+
Ok(pops) => {
1939+
for pop in pops {
1940+
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1941+
}
19391942
}
1943+
Err(err) => println!("{}", err)
19401944
}
1941-
Err(err) => println!("{}", err)
1942-
}
19431945
...
19441946
```
19451947

1946-
In this piece of code, we take `file` (which has the type
1947-
`Option<String>`), and convert it to a type that `search` can use, in
1948-
this case, `&Option<AsRef<Path>>`. To do this, we take a reference of
1949-
file, and map `Path::new` onto it. In this case, `as_ref()` converts
1950-
the `Option<String>` into an `Option<&str>`, and from there, we can
1951-
execute `Path::new` to the content of the optional, and return the
1952-
optional of the new value. Once we have that, it is a simple matter of
1953-
getting the `city` argument and executing `search`.
1948+
We've made the user experience a bit nicer by showing the usage message,
1949+
instead of a panic from an out-of-bounds index, when `city`, the
1950+
remaining free argument, is not present.
19541951

19551952
Modifying `search` is slightly trickier. The `csv` crate can build a
19561953
parser out of
@@ -2000,6 +1997,8 @@ enum CliError {
20001997
And now for impls on `Display` and `Error`:
20011998

20021999
```rust,ignore
2000+
use std::fmt;
2001+
20032002
impl fmt::Display for CliError {
20042003
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20052004
match *self {
@@ -2020,13 +2019,13 @@ impl Error for CliError {
20202019
}
20212020
}
20222021
2023-
fn cause(&self) -> Option<&error::Error> {
2024-
match *self {
2022+
fn cause(&self) -> Option<&Error> {
2023+
match *self {
20252024
CliError::Io(ref err) => Some(err),
2026-
CliError::Parse(ref err) => Some(err),
2027-
// Our custom error doesn't have an underlying cause, but we could
2028-
// modify it so that it does.
2029-
CliError::NotFound() => None,
2025+
CliError::Csv(ref err) => Some(err),
2026+
// Our custom error doesn't have an underlying cause,
2027+
// but we could modify it so that it does.
2028+
CliError::NotFound => None,
20302029
}
20312030
}
20322031
}
@@ -2122,24 +2121,27 @@ string and add a flag to the Option variable. Once we've done that, Getopts does
21222121

21232122
```rust,ignore
21242123
...
2125-
let mut opts = Options::new();
2126-
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
2127-
opts.optflag("h", "help", "Show this usage message.");
2128-
opts.optflag("q", "quiet", "Silences errors and warnings.");
2124+
let mut opts = Options::new();
2125+
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
2126+
opts.optflag("h", "help", "Show this usage message.");
2127+
opts.optflag("q", "quiet", "Silences errors and warnings.");
21292128
...
21302129
```
21312130

21322131
Now we only need to implement our “quiet” functionality. This requires us to
21332132
tweak the case analysis in `main`:
21342133

21352134
```rust,ignore
2136-
match search(&args.arg_data_path, &args.arg_city) {
2137-
Err(CliError::NotFound) if args.flag_quiet => process::exit(1),
2138-
Err(err) => panic!("{}", err),
2139-
Ok(pops) => for pop in pops {
2140-
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
2135+
use std::process;
2136+
...
2137+
match search(&data_path, city) {
2138+
Err(CliError::NotFound) if matches.opt_present("q") => process::exit(1),
2139+
Err(err) => panic!("{}", err),
2140+
Ok(pops) => for pop in pops {
2141+
println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
2142+
}
21412143
}
2142-
}
2144+
...
21432145
```
21442146

21452147
Certainly, we don't want to be quiet if there was an IO error or if the data

‎src/libcollectionstest/string.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn test_from_utf8() {
5252
String::from("ศไทย中华Việt Nam"));
5353

5454
let xs = b"hello\xFF".to_vec();
55-
let err = String::from_utf8(xs).err().unwrap();
55+
let err = String::from_utf8(xs).unwrap_err();
5656
assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
5757
}
5858

‎src/librustc/infer/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
735735
}
736736
infer::Reborrow(span) => {
737737
let mut err = struct_span_err!(self.tcx.sess, span, E0312,
738-
"lifetime of reference outlines \
738+
"lifetime of reference outlives \
739739
lifetime of borrowed content...");
740740
self.tcx.note_and_explain_region(&mut err,
741741
"...the reference is valid for ",

‎src/librustc_borrowck/diagnostics.rs

+95-1
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,101 @@ You can find more information about borrowing in the rust-book:
653653
http://doc.rust-lang.org/stable/book/references-and-borrowing.html
654654
"##,
655655

656+
E0509: r##"
657+
This error occurs when an attempt is made to move out of a value whose type
658+
implements the `Drop` trait.
659+
660+
Example of erroneous code:
661+
662+
```compile_fail
663+
struct FancyNum {
664+
num: usize
665+
}
666+
667+
struct DropStruct {
668+
fancy: FancyNum
669+
}
670+
671+
impl Drop for DropStruct {
672+
fn drop(&mut self) {
673+
// Destruct DropStruct, possibly using FancyNum
674+
}
675+
}
676+
677+
fn main() {
678+
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
679+
let fancy_field = drop_struct.fancy; // Error E0509
680+
println!("Fancy: {}", fancy_field.num);
681+
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
682+
}
683+
```
684+
685+
Here, we tried to move a field out of a struct of type `DropStruct` which
686+
implements the `Drop` trait. However, a struct cannot be dropped if one or
687+
more of its fields have been moved.
688+
689+
Structs implementing the `Drop` trait have an implicit destructor that gets
690+
called when they go out of scope. This destructor may use the fields of the
691+
struct, so moving out of the struct could make it impossible to run the
692+
destructor. Therefore, we must think of all values whose type implements the
693+
`Drop` trait as single units whose fields cannot be moved.
694+
695+
This error can be fixed by creating a reference to the fields of a struct,
696+
enum, or tuple using the `ref` keyword:
697+
698+
```
699+
struct FancyNum {
700+
num: usize
701+
}
702+
703+
struct DropStruct {
704+
fancy: FancyNum
705+
}
706+
707+
impl Drop for DropStruct {
708+
fn drop(&mut self) {
709+
// Destruct DropStruct, possibly using FancyNum
710+
}
711+
}
712+
713+
fn main() {
714+
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
715+
let ref fancy_field = drop_struct.fancy; // No more errors!
716+
println!("Fancy: {}", fancy_field.num);
717+
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
718+
}
719+
```
720+
721+
Note that this technique can also be used in the arms of a match expression:
722+
723+
```
724+
struct FancyNum {
725+
num: usize
726+
}
727+
728+
enum DropEnum {
729+
Fancy(FancyNum)
730+
}
731+
732+
impl Drop for DropEnum {
733+
fn drop(&mut self) {
734+
// Destruct DropEnum, possibly using FancyNum
735+
}
736+
}
737+
738+
fn main() {
739+
// Creates and enum of type `DropEnum`, which implements `Drop`
740+
let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
741+
match drop_enum {
742+
// Creates a reference to the inside of `DropEnum::Fancy`
743+
DropEnum::Fancy(ref fancy_field) => // No error!
744+
println!("It was fancy-- {}!", fancy_field.num),
745+
}
746+
// implicit call to `drop_enum.drop()` as drop_enum goes out of scope
747+
}
748+
```
749+
"##,
750+
656751
}
657752

658753
register_diagnostics! {
@@ -664,6 +759,5 @@ register_diagnostics! {
664759
E0504, // cannot move `..` into closure because it is borrowed
665760
E0505, // cannot move out of `..` because it is borrowed
666761
E0508, // cannot move out of type `..`, a non-copy fixed-size array
667-
E0509, // cannot move out of type `..`, which defines the `Drop` trait
668762
E0524, // two closures require unique access to `..` at the same time
669763
}
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.