]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #30343 - Seeker14491:patch-1, r=bluss
authorbors <bors@rust-lang.org>
Sun, 13 Dec 2015 17:11:36 +0000 (17:11 +0000)
committerbors <bors@rust-lang.org>
Sun, 13 Dec 2015 17:11:36 +0000 (17:11 +0000)
The `MIN` link was broken. Reverts #29624.

30 files changed:
mk/cfg/i686-unknown-freebsd.mk
src/doc/book/getting-started.md
src/doc/book/testing.md
src/doc/book/vectors.md
src/doc/nomicon/subtyping.md
src/libcollections/str.rs
src/libcore/num/dec2flt/mod.rs
src/libcore/num/dec2flt/rawfp.rs
src/libcore/str/mod.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/infer/resolve.rs
src/librustc/middle/infer/unify_key.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/fragments.rs
src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/consts.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/mod.rs
src/libstd/io/error.rs
src/test/compile-fail/shadowed-use-visibility.rs
src/test/compile-fail/struct-fields-missing.rs
src/test/run-pass/dst-irrefutable-bind.rs [new file with mode: 0644]
src/test/run-pass/issue-27889.rs [new file with mode: 0644]
src/test/run-pass/issue-29844.rs [new file with mode: 0644]

index 0ac0ca98a2f1eece8fbdb20c65d154776bf74806..bbc0c2d6f396ecad629d20fbbf06d03c76eb5108 100644 (file)
@@ -7,7 +7,7 @@ CFG_LIB_NAME_i686-unknown-freebsd=lib$(1).so
 CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -arch i386 -I/usr/local/include $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
 CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
index 5b1040dd05ee19dbc0b9c267cfaa91e8b28a04b6..17fc5d9233d195cf9be1b94a9ed1ca7598e4eda2 100644 (file)
@@ -63,6 +63,13 @@ these platforms are required to have each of the following:
 |  Target                       | std |rustc|cargo| notes                      |
 |-------------------------------|-----|-----|-----|----------------------------|
 | `i686-pc-windows-msvc`        |  ✓  |  ✓  |  ✓  | 32-bit MSVC (Windows 7+)   |
+| `x86_64-unknown-linux-musl`   |  ✓  |     |     | 64-bit Linux with MUSL     |
+| `arm-linux-androideabi`       |  ✓  |     |     | ARM Android                |
+| `arm-unknown-linux-gnueabi`   |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
+| `arm-unknown-linux-gnueabihf` |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
+| `aarch64-unknown-linux-gnu`   |  ✓  |     |     | ARM64 Linux (2.6.18+)      |
+| `mips-unknown-linux-gnu`      |  ✓  |     |     | MIPS Linux (2.6.18+)       |
+| `mipsel-unknown-linux-gnu`    |  ✓  |     |     | MIPS (LE) Linux (2.6.18+)  |
 
 ### Tier 3
 
@@ -75,15 +82,8 @@ unofficial locations.
 
 |  Target                       | std |rustc|cargo| notes                      |
 |-------------------------------|-----|-----|-----|----------------------------|
-| `x86_64-unknown-linux-musl`   |  ✓  |     |     | 64-bit Linux with MUSL     |
-| `arm-linux-androideabi`       |  ✓  |     |     | ARM Android                |
 | `i686-linux-android`          |  ✓  |     |     | 32-bit x86 Android         |
 | `aarch64-linux-android`       |  ✓  |     |     | ARM64 Android              |
-| `arm-unknown-linux-gnueabi`   |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
-| `arm-unknown-linux-gnueabihf` |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
-| `aarch64-unknown-linux-gnu`   |  ✓  |     |     | ARM64 Linux (2.6.18+)      |
-| `mips-unknown-linux-gnu`      |  ✓  |     |     | MIPS Linux (2.6.18+)       |
-| `mipsel-unknown-linux-gnu`    |  ✓  |     |     | MIPS (LE) Linux (2.6.18+)  |
 | `powerpc-unknown-linux-gnu`   |  ✓  |     |     | PowerPC Linux (2.6.18+)    |
 | `i386-apple-ios`              |  ✓  |     |     | 32-bit x86 iOS             |
 | `x86_64-apple-ios`            |  ✓  |     |     | 64-bit x86 iOS             |
@@ -127,7 +127,7 @@ not want the script to run ‘sudo’ then pass it the --disable-sudo flag.
 You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh,
 or by running this script again with the --uninstall flag.
 
-Continue? (y/N) 
+Continue? (y/N)
 ```
 
 From here, press `y` for ‘yes’, and then follow the rest of the prompts.
@@ -188,7 +188,7 @@ was installed.
 Now that you have Rust installed, we'll help you write your first Rust program.
 It's traditional when learning a new language to write a little program to
 print the text “Hello, world!” to the screen, and in this section, we'll follow
-that tradition. 
+that tradition.
 
 The nice thing about starting with such a simple program is that you can
 quickly verify that your compiler is installed, and that it's working properly.
@@ -202,7 +202,7 @@ practicing it early on is good.
 > There are a number of extensions in development by the community, and the
 > Rust team ships plugins for [various editors]. Configuring your editor or
 > IDE is out of the scope of this tutorial, so check the documentation for your
-> specific setup. 
+> specific setup.
 
 [SolidOak]: https://github.com/oakes/SolidOak
 [various editors]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
@@ -244,14 +244,14 @@ following commands:
 
 ```bash
 $ rustc main.rs
-$ ./main 
+$ ./main
 Hello, world!
 ```
 
 In Windows, just replace `main` with `main.exe`. Regardless of your operating
 system, you should see the string `Hello, world!` print to the terminal. If you
 did, then congratulations! You've officially written a Rust program. That makes
-you a Rust programmer! Welcome. 
+you a Rust programmer! Welcome.
 
 ## Anatomy of a Rust Program
 
@@ -285,13 +285,13 @@ Inside the `main()` function:
 This line does all of the work in this little program: it prints text to the
 screen. There are a number of details that are important here. The first is
 that it’s indented with four spaces, not tabs.
+
 The second important part is the `println!()` line. This is calling a Rust
 *[macro]*, which is how metaprogramming is done in Rust. If it were calling a
 function instead, it would look like this: `println()` (without the !). We'll
 discuss Rust macros in more detail later, but for now you just need to
 know that when you see a `!` that means that you’re calling a macro instead of
-a normal function. 
+a normal function.
 
 
 [macro]: macros.html
@@ -313,7 +313,7 @@ begin. Most lines of Rust code end with a `;`.
 ## Compiling and Running Are Separate Steps
 
 In "Writing and Running a Rust Program", we showed you how to run a newly
-created program. We'll break that process down and examine each step now. 
+created program. We'll break that process down and examine each step now.
 
 Before running a Rust program, you have to compile it. You can use the Rust
 compiler by entering the `rustc` command and passing it the name of your source
@@ -395,7 +395,7 @@ in which you installed Rust, to determine if Cargo is separate.
 ## Converting to Cargo
 
 Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you need
-to do three things: 
+to do three things:
 
 1. Put your source file in the right directory.
 2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere else)
@@ -419,7 +419,7 @@ Cargo expects your source files to live inside a *src* directory, so do that
 first. This leaves the top-level project directory (in this case,
 *hello_world*) for READMEs, license information, and anything else not related
 to your code. In this way, using Cargo helps you keep your projects nice and
-tidy. There's a place for everything, and everything is in its place. 
+tidy. There's a place for everything, and everything is in its place.
 
 Now, copy *main.rs* to the *src* directory, and delete the compiled file you
 created with `rustc`. As usual, replace `main` with `main.exe` if you're on
@@ -428,7 +428,7 @@ Windows.
 This example retains `main.rs` as the source filename because it's creating an
 executable. If you wanted to make a library instead, you'd name the file
 `lib.rs`. This convention is used by Cargo to successfully compile your
-projects, but it can be overridden if you wish. 
+projects, but it can be overridden if you wish.
 
 ### Creating a Configuration File
 
@@ -436,7 +436,7 @@ Next, create a new file inside your *hello_world* directory, and call it
 `Cargo.toml`.
 
 Make sure to capitalize the `C` in `Cargo.toml`, or Cargo won't know what to do
-with the configuration file. 
+with the configuration file.
 
 This file is in the *[TOML]* (Tom's Obvious, Minimal Language) format. TOML is
 similar to INI, but has some extra goodies, and is used as Cargo’s
@@ -464,7 +464,7 @@ know to compile your program: its name, what version it is, and who wrote it.
 Once you've added this information to the *Cargo.toml* file, save it to finish
 creating the configuration file.
 
-## Building and Running a Cargo Project 
+## Building and Running a Cargo Project
 
 With your *Cargo.toml* file in place in your project's root directory, you
 should be ready to build and run your Hello World program! To do so, enter the
@@ -477,7 +477,7 @@ $ ./target/debug/hello_world
 Hello, world!
 ```
 
-Bam! If all goes well, `Hello, world!` should print to the terminal once more. 
+Bam! If all goes well, `Hello, world!` should print to the terminal once more.
 
 You just built a project with `cargo build` and ran it with
 `./target/debug/hello_world`, but you can actually do both in one step with
@@ -532,7 +532,7 @@ doesn't have dependencies, so the file is a bit sparse. Realistically, you
 won't ever need to touch this file yourself; just let Cargo handle it.
 
 That’s it! If you've been following along, you should have successfully built
-`hello_world` with Cargo. 
+`hello_world` with Cargo.
 
 Even though the project is simple, it now uses much of the real tooling you’ll
 use for the rest of your Rust career. In fact, you can expect to start
@@ -587,7 +587,7 @@ fn main() {
 }
 ```
 
-Cargo has generated a "Hello World!" for you, and you’re ready to start coding! 
+Cargo has generated a "Hello World!" for you, and you’re ready to start coding!
 
 > Note: If you want to look at Cargo in more detail, check out the official [Cargo
 guide], which covers all of its features.
@@ -598,7 +598,7 @@ guide], which covers all of its features.
 
 This chapter covered the basics that will serve you well through the rest of
 this book, and the rest of your time with Rust. Now that you’ve got the tools
-down, we'll cover more about the Rust language itself. 
+down, we'll cover more about the Rust language itself.
 
 You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
 start from the bottom and work your way up with ‘[Syntax and
index 32f0d689e30ecec843021e0323adf898f7cf5279..561cc3ab2d11323069894172832acc9f24b6c53b 100644 (file)
@@ -503,7 +503,7 @@ for the function test. These will auto increment with names like `add_two_1` as
 you add more examples.
 
 We haven’t covered all of the details with writing documentation tests. For more,
-please see the [Documentation chapter](documentation.html)
+please see the [Documentation chapter](documentation.html).
 
 One final note: documentation tests *cannot* be run on binary crates.
 To see more on file arrangement see the [Crates and
index 7b826f08ae6fbb34c9ee1ed47b482ef813b3270a..b09735c3feee6b9d12c7816fe06c8adafa6933d0 100644 (file)
@@ -61,6 +61,33 @@ error: aborting due to previous error
 There’s a lot of punctuation in that message, but the core of it makes sense:
 you cannot index with an `i32`.
 
+## Out-of-bounds Access
+
+If you try to access an index that doesn’t exist:
+
+```ignore
+let v = vec![1, 2, 3];
+println!("Item 7 is {}", v[7]);
+```
+
+then the current thread will [panic] with a message like this:
+
+```text
+thread '<main>' panicked at 'index out of bounds: the len is 3 but the index is 7'
+```
+
+If you want to handle out-of-bounds errors without panicking, you can use
+methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when
+given an invalid index:
+
+```rust
+let v = vec![1, 2, 3];
+match v.get(7) {
+    Some(x) => println!("Item 7 is {}", x),
+    None => println!("Sorry, this vector is too short.")
+}
+```
+
 ## Iterating
 
 Once you have a vector, you can iterate through its elements with `for`. There
@@ -87,3 +114,6 @@ API documentation][vec].
 
 [vec]: ../std/vec/index.html
 [generic]: generics.html
+[panic]: concurrency.html#panics
+[get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get
+[get_mut]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_mut
index 65dcb6a94e13ccbf9aec33415fc638525202f9b9..5def5c3903353ef85575993ccaa6c0173db1b316 100644 (file)
@@ -44,10 +44,11 @@ subtyping of its outputs. There are two kinds of variance in Rust:
 * F is *invariant* over `T` otherwise (no subtyping relation can be derived)
 
 (For those of you who are familiar with variance from other languages, what we
-refer to as "just" variance is in fact *covariance*. Rust does not have
-contravariance. Historically Rust did have some contravariance but it was
-scrapped due to poor interactions with other features. If you experience
-contravariance in Rust call your local compiler developer for medical advice.)
+refer to as "just" variance is in fact *covariance*. Rust has *contravariance*
+for functions. The future of contravariance is uncertain and it may be
+scrapped. For now, `fn(T)` is contravariant in `T`, which is used in matching
+methods in trait implementations to the trait definition. Traits don't have
+inferred variance, so `Fn(T)` is invariant in `T`).
 
 Some important variances:
 
@@ -200,7 +201,7 @@ use std::cell::Cell;
 
 struct Foo<'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H> {
     a: &'a A,     // variant over 'a and A
-    b: &'b mut B, // invariant over 'b and B
+    b: &'b mut B, // variant over 'b and invariant over B
     c: *const C,  // variant over C
     d: *mut D,    // invariant over D
     e: Vec<E>,    // variant over E
index be3f93992d9eff8eb3757eb73c306cc2904f9385..68669b68d294a3b731d3a11436d8ab1042f60c22 100644 (file)
@@ -305,7 +305,7 @@ pub fn as_ptr(&self) -> *const u8 {
     /// satisifed:
     ///
     /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be bye positions within the string slice.
+    /// * `begin` and `end` must be byte positions within the string slice.
     /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
     ///
     /// # Examples
@@ -348,7 +348,7 @@ pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
     /// satisifed:
     ///
     /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be bye positions within the string slice.
+    /// * `begin` and `end` must be byte positions within the string slice.
     /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
     #[stable(feature = "str_slice_mut", since = "1.5.0")]
     #[inline]
index 55be4cd31910baedc5b547c1b9a1a0f3b728efd5..9c0ec0f22c50fc387843cc2feb3097622e558cc0 100644 (file)
@@ -97,7 +97,7 @@
 use str::FromStr;
 
 use self::parse::{parse_decimal, Decimal, Sign};
-use self::parse::ParseResult::{self, Valid, ShortcutToInf, ShortcutToZero};
+use self::parse::ParseResult::{Valid, Invalid, ShortcutToInf, ShortcutToZero};
 use self::num::digits_to_big;
 use self::rawfp::RawFloat;
 
 pub mod parse;
 
 macro_rules! from_str_float_impl {
-    ($t:ty, $func:ident) => {
+    ($t:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl FromStr for $t {
             type Err = ParseFloatError;
@@ -146,8 +146,8 @@ fn from_str(src: &str) -> Result<Self, ParseFloatError> {
         }
     }
 }
-from_str_float_impl!(f32, to_f32);
-from_str_float_impl!(f64, to_f64);
+from_str_float_impl!(f32);
+from_str_float_impl!(f64);
 
 /// An error which can be returned when parsing a float.
 #[derive(Debug, Clone, PartialEq)]
@@ -183,11 +183,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-pub fn pfe_empty() -> ParseFloatError {
+fn pfe_empty() -> ParseFloatError {
     ParseFloatError { kind: FloatErrorKind::Empty }
 }
 
-pub fn pfe_invalid() -> ParseFloatError {
+fn pfe_invalid() -> ParseFloatError {
     ParseFloatError { kind: FloatErrorKind::Invalid }
 }
 
@@ -211,7 +211,7 @@ fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
         Valid(decimal) => try!(convert(decimal)),
         ShortcutToInf => T::infinity(),
         ShortcutToZero => T::zero(),
-        ParseResult::Invalid => match s {
+        Invalid => match s {
             "inf" => T::infinity(),
             "NaN" => T::nan(),
             _ => { return Err(pfe_invalid()); }
index be61653c37937f161e4cffad5fbf90b2abe96007..197589740032ad40e16ea2fb725f9ad871eb4206 100644 (file)
@@ -288,7 +288,7 @@ pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
 /// Construct the subnormal. A mantissa of 0 is allowed and constructs zero.
 pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
     assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal");
-    // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
+    // Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
     T::from_bits(significand)
 }
 
index 7aacdbeb768791eac256a50cfa07d3a6b64ac4c6..40bd108a91860f9b24b02d3dccd1db8307bebd04 100644 (file)
@@ -292,7 +292,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 /// Iterator for the char (representing *Unicode Scalar Values*) of a string
 ///
-/// Created with the method `.chars()`.
+/// Created with the method [`chars()`].
+///
+/// [`chars()`]: ../primitive.str.html#method.chars
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chars<'a> {
@@ -499,7 +501,9 @@ pub fn as_str(&self) -> &'a str {
 /// External iterator for a string's bytes.
 /// Use with the `std::iter` module.
 ///
-/// Created with the method `.bytes()`.
+/// Created with the method [`bytes()`].
+///
+/// [`bytes()`]: ../primitive.str.html#method.bytes
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Bytes<'a>(Cloned<slice::Iter<'a, u8>>);
@@ -782,10 +786,14 @@ fn next_back(&mut self) -> Option<&'a str>
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split()`.
+        /// Created with the method [`split()`].
+        ///
+        /// [`split()`]: ../primitive.str.html#method.split
         struct Split;
     reverse:
-        /// Created with the method `.rsplit()`.
+        /// Created with the method [`rsplit()`].
+        ///
+        /// [`rsplit()`]: ../primitive.str.html#method.rsplit
         struct RSplit;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -796,10 +804,14 @@ fn next_back(&mut self) -> Option<&'a str>
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.split_terminator()`.
+        /// Created with the method [`split_terminator()`].
+        ///
+        /// [`split_terminator()`]: ../primitive.str.html#method.split_terminator
         struct SplitTerminator;
     reverse:
-        /// Created with the method `.rsplit_terminator()`.
+        /// Created with the method [`rsplit_terminator()`].
+        ///
+        /// [`rsplit_terminator()`]: ../primitive.str.html#method.rsplit_terminator
         struct RSplitTerminator;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -842,10 +854,14 @@ fn next_back(&mut self) -> Option<&'a str>
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.splitn()`.
+        /// Created with the method [`splitn()`].
+        ///
+        /// [`splitn()`]: ../primitive.str.html#method.splitn
         struct SplitN;
     reverse:
-        /// Created with the method `.rsplitn()`.
+        /// Created with the method [`rsplitn()`].
+        ///
+        /// [`rsplitn()`]: ../primitive.str.html#method.rsplitn
         struct RSplitN;
     stability:
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -880,10 +896,14 @@ fn next_back(&mut self) -> Option<(usize, &'a str)>
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.match_indices()`.
+        /// Created with the method [`match_indices()`].
+        ///
+        /// [`match_indices()`]: ../primitive.str.html#method.match_indices
         struct MatchIndices;
     reverse:
-        /// Created with the method `.rmatch_indices()`.
+        /// Created with the method [`rmatch_indices()`].
+        ///
+        /// [`rmatch_indices()`]: ../primitive.str.html#method.rmatch_indices
         struct RMatchIndices;
     stability:
         #[stable(feature = "str_match_indices", since = "1.5.0")]
@@ -920,10 +940,14 @@ fn next_back(&mut self) -> Option<&'a str>
 
 generate_pattern_iterators! {
     forward:
-        /// Created with the method `.matches()`.
+        /// Created with the method [`matches()`].
+        ///
+        /// [`matches()`]: ../primitive.str.html#method.matches
         struct Matches;
     reverse:
-        /// Created with the method `.rmatches()`.
+        /// Created with the method [`rmatches()`].
+        ///
+        /// [`rmatches()`]: ../primitive.str.html#method.rmatches
         struct RMatches;
     stability:
         #[stable(feature = "str_matches", since = "1.2.0")]
@@ -932,7 +956,9 @@ fn next_back(&mut self) -> Option<&'a str>
     delegate double ended;
 }
 
-/// Created with the method `.lines()`.
+/// Created with the method [`lines()`].
+///
+/// [`lines()`]: ../primitive.str.html#method.lines
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Lines<'a>(Map<SplitTerminator<'a, char>, LinesAnyMap>);
@@ -960,7 +986,9 @@ fn next_back(&mut self) -> Option<&'a str> {
     }
 }
 
-/// Created with the method `.lines_any()`.
+/// Created with the method [`lines_any()`].
+///
+/// [`lines_any()`]: ../primitive.str.html#method.lines_any
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")]
 #[derive(Clone)]
index 5f2a3bec423f5bf7dcd41751d47ab53a5f74bd9e..6420fcd9e50b4386326b9025a66388ced1a98d2d 100644 (file)
@@ -521,7 +521,6 @@ fn check_and_note_conflicting_crates(&self, terr: &TypeError<'tcx>, sp: Span) {
                 }
             },
             TypeError::Traits(ref exp_found) => {
-                self.tcx.sess.note("errrr0");
                 report_path_match(exp_found.expected, exp_found.found);
             },
             _ => () // FIXME(#22750) handle traits and stuff
index b39ddfe95c83ab0c7c74629bbf6cad28d78b0038..d677328e415a8a0085bd58b8dcbb2f7794711e1f 100644 (file)
@@ -1225,6 +1225,13 @@ pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
         value.fold_with(&mut r)
     }
 
+    pub fn resolve_type_and_region_vars_if_possible<T>(&self, value: &T) -> T
+        where T: TypeFoldable<'tcx>
+    {
+        let mut r = resolve::OpportunisticTypeAndRegionResolver::new(self);
+        value.fold_with(&mut r)
+    }
+
     /// Resolves all type variables in `t` and then, if any were left
     /// unresolved, substitutes an error type. This is used after the
     /// main checking when doing a second pass before writeback. The
index f6068f1b6449852d94227bfb22af402330deb901..30cf6344e2332dd6a1fb65990232897eb18f5f2d 100644 (file)
@@ -20,6 +20,7 @@
 use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
 
 use rustc_data_structures::graph::{self, Direction, NodeIndex};
+use rustc_data_structures::unify::{self, UnificationTable};
 use middle::free_region::FreeRegionMap;
 use middle::ty::{self, Ty};
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
@@ -234,15 +235,16 @@ pub struct RegionVarBindings<'a, 'tcx: 'a> {
     // bound on a variable and so forth, which can never be rolled
     // back.
     undo_log: RefCell<Vec<UndoLogEntry>>,
+    unification_table: RefCell<UnificationTable<ty::RegionVid>>,
 
     // This contains the results of inference.  It begins as an empty
     // option and only acquires a value after inference is complete.
     values: RefCell<Option<Vec<VarValue>>>,
 }
 
-#[derive(Debug)]
 pub struct RegionSnapshot {
     length: usize,
+    region_snapshot: unify::Snapshot<ty::RegionVid>,
     skolemization_count: u32,
 }
 
@@ -260,6 +262,7 @@ pub fn new(tcx: &'a ty::ctxt<'tcx>) -> RegionVarBindings<'a, 'tcx> {
             skolemization_count: Cell::new(0),
             bound_count: Cell::new(0),
             undo_log: RefCell::new(Vec::new()),
+            unification_table: RefCell::new(UnificationTable::new()),
         }
     }
 
@@ -273,6 +276,7 @@ pub fn start_snapshot(&self) -> RegionSnapshot {
         self.undo_log.borrow_mut().push(OpenSnapshot);
         RegionSnapshot {
             length: length,
+            region_snapshot: self.unification_table.borrow_mut().snapshot(),
             skolemization_count: self.skolemization_count.get(),
         }
     }
@@ -289,6 +293,7 @@ pub fn commit(&self, snapshot: RegionSnapshot) {
             (*undo_log)[snapshot.length] = CommitedSnapshot;
         }
         self.skolemization_count.set(snapshot.skolemization_count);
+        self.unification_table.borrow_mut().commit(snapshot.region_snapshot);
     }
 
     pub fn rollback_to(&self, snapshot: RegionSnapshot) {
@@ -328,6 +333,8 @@ pub fn rollback_to(&self, snapshot: RegionSnapshot) {
         let c = undo_log.pop().unwrap();
         assert!(c == OpenSnapshot);
         self.skolemization_count.set(snapshot.skolemization_count);
+        self.unification_table.borrow_mut()
+            .rollback_to(snapshot.region_snapshot);
     }
 
     pub fn num_vars(&self) -> u32 {
@@ -340,7 +347,8 @@ pub fn num_vars(&self) -> u32 {
     pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
         let id = self.num_vars();
         self.var_origins.borrow_mut().push(origin.clone());
-        let vid = RegionVid { index: id };
+        let vid = self.unification_table.borrow_mut().new_key(());
+        assert_eq!(vid.index, id);
         if self.in_snapshot() {
             self.undo_log.borrow_mut().push(AddVar(vid));
         }
@@ -460,6 +468,10 @@ pub fn make_eqregion(&self, origin: SubregionOrigin<'tcx>, sub: Region, sup: Reg
             // equating regions.
             self.make_subregion(origin.clone(), sub, sup);
             self.make_subregion(origin, sup, sub);
+
+            if let (ty::ReVar(sub), ty::ReVar(sup)) = (sub, sup) {
+                self.unification_table.borrow_mut().union(sub, sup);
+            }
         }
     }
 
@@ -568,6 +580,10 @@ pub fn resolve_var(&self, rid: RegionVid) -> ty::Region {
         }
     }
 
+    pub fn opportunistic_resolve_var(&self, rid: RegionVid) -> ty::Region {
+        ty::ReVar(self.unification_table.borrow_mut().find(rid))
+    }
+
     fn combine_map(&self, t: CombineMapType) -> &RefCell<CombineMap> {
         match t {
             Glb => &self.glbs,
@@ -1312,6 +1328,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl fmt::Debug for RegionSnapshot {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "RegionSnapshot(length={},skolemization={})",
+               self.length, self.skolemization_count)
+    }
+}
+
 impl<'tcx> fmt::Debug for GenericKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
index 4bcceade775999c1d90d024890a7bfb4421e044f..5190c658194f723da547c83803acce5ecde8e221 100644 (file)
@@ -45,6 +45,41 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
     }
 }
 
+/// The opportunistic type and region resolver is similar to the
+/// opportunistic type resolver, but also opportunistly resolves
+/// regions. It is useful for canonicalization.
+pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx:'a> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+}
+
+impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+        OpportunisticTypeAndRegionResolver { infcx: infcx }
+    }
+}
+
+impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+    fn tcx(&self) -> &ty::ctxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        if !t.needs_infer() {
+            t // micro-optimize -- if there is nothing in this type that this fold affects...
+        } else {
+            let t0 = self.infcx.shallow_resolve(t);
+            ty::fold::super_fold_ty(self, t0)
+        }
+    }
+
+    fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+        match r {
+          ty::ReVar(rid) => self.infcx.region_vars.opportunistic_resolve_var(rid),
+          _ => r,
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // FULL TYPE RESOLUTION
 
index 41aa191ac24d210f23a3e36dd7cf84293ad6fe5c..85d7d67a0e3ca0bd480dc11599a07ac0a3ac87b4 100644 (file)
@@ -23,6 +23,13 @@ fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } }
     fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
 }
 
+impl UnifyKey for ty::RegionVid {
+    type Value = ();
+    fn index(&self) -> u32 { self.index }
+    fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid { index: i } }
+    fn tag(_: Option<ty::RegionVid>) -> &'static str { "RegionVid" }
+}
+
 impl<'tcx> ToType<'tcx> for IntVarValue {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
index 50169ca64307b3f91f727d60618168a5d9a483b1..3f48051029d9dfe49a71d9f3fe0ce100f392b78f 100644 (file)
@@ -744,7 +744,7 @@ fn check_if_assigned_path_is_moved(&self,
                 self.check_if_assigned_path_is_moved(id, span,
                                                      use_kind, lp_base);
             }
-            LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
+            LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
                 match lp_base.to_type().sty {
                     ty::TyStruct(def, _) | ty::TyEnum(def, _) if def.has_dtor() => {
                         // In the case where the owner implements drop, then
@@ -770,7 +770,7 @@ fn check_if_assigned_path_is_moved(&self,
                 self.check_if_assigned_path_is_moved(id, span,
                                                      use_kind, lp_base);
             }
-            LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) |
+            LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) |
             LpExtend(ref lp_base, _, LpDeref(_)) => {
                 // assigning to `P[i]` requires `P` is initialized
                 // assigning to `(*P)` requires `P` is initialized
index 1639fcf77a66122120d7abaac5747e8bc1f6419f..c5e2b69683b10cc3676f4141c3186d37bb12d490 100644 (file)
@@ -379,7 +379,7 @@ fn add_fragment_siblings<'tcx>(this: &MoveData<'tcx>,
         // bind.
         //
         // Anyway, for now: LV[j] is not tracked precisely
-        LpExtend(_, _, LpInterior(InteriorElement(..))) => {
+        LpExtend(_, _, LpInterior(_, InteriorElement(..))) => {
             let mp = this.move_path(tcx, lp.clone());
             gathered_fragments.push(AllButOneFrom(mp));
         }
@@ -387,7 +387,7 @@ fn add_fragment_siblings<'tcx>(this: &MoveData<'tcx>,
         // field access LV.x and tuple access LV#k are the cases
         // we are interested in
         LpExtend(ref loan_parent, mc,
-                 LpInterior(InteriorField(ref field_name))) => {
+                 LpInterior(_, InteriorField(ref field_name))) => {
             let enum_variant_info = match loan_parent.kind {
                 LpDowncast(ref loan_parent_2, variant_def_id) =>
                     Some((variant_def_id, loan_parent_2.clone())),
@@ -516,7 +516,7 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>,
         LpVar(..) | LpUpvar(..) | LpExtend(..) => enum_variant_did,
     };
 
-    let loan_path_elem = LpInterior(InteriorField(new_field_name));
+    let loan_path_elem = LpInterior(opt_variant_did, InteriorField(new_field_name));
     let new_lp_type = match new_field_name {
         mc::NamedField(ast_name) =>
             tcx.named_element_ty(parent.to_type(), ast_name, opt_variant_did),
index e7ce93972633be7216b6315b8b157860eb31b981..cb75180b474667850ea26b1432fcf669b6375791 100644 (file)
@@ -97,8 +97,12 @@ fn restrict(&self,
                 // Overwriting the base would not change the type of
                 // the memory, so no additional restrictions are
                 // needed.
+                let opt_variant_id = match cmt_base.cat {
+                    Categorization::Downcast(_, variant_id) => Some(variant_id),
+                    _ => None
+                };
                 let result = self.restrict(cmt_base);
-                self.extend(result, &cmt, LpInterior(i.cleaned()))
+                self.extend(result, &cmt, LpInterior(opt_variant_id, i.cleaned()))
             }
 
             Categorization::StaticItem => {
index b727f10d276ac0f0f400ffe6859ef60a20ff6b1c..64bbf49e3a8e0e50829bb93c7de1d425a6be9e36 100644 (file)
@@ -377,10 +377,18 @@ fn cleaned(self) -> InteriorKind {
     }
 }
 
+// This can be:
+// - a pointer dereference (`*LV` in README.md)
+// - a field reference, with an optional definition of the containing
+//   enum variant (`LV.f` in README.md)
+// `DefId` is present when the field is part of struct that is in
+// a variant of an enum. For instance in:
+// `enum E { X { foo: u32 }, Y { foo: u32 }}`
+// each `foo` is qualified by the definitition id of the variant (`X` or `Y`).
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum LoanPathElem {
-    LpDeref(mc::PointerKind),    // `*LV` in README.md
-    LpInterior(InteriorKind),    // `LV.f` in README.md
+    LpDeref(mc::PointerKind),
+    LpInterior(Option<DefId>, InteriorKind),
 }
 
 pub fn closure_to_block(closure_id: ast::NodeId,
@@ -413,8 +421,9 @@ pub fn kill_scope(&self, tcx: &ty::ctxt<'tcx>) -> region::CodeExtent {
 
     fn has_fork(&self, other: &LoanPath<'tcx>) -> bool {
         match (&self.kind, &other.kind) {
-            (&LpExtend(ref base, _, LpInterior(id)), &LpExtend(ref base2, _, LpInterior(id2))) =>
-                if id == id2 {
+            (&LpExtend(ref base, _, LpInterior(opt_variant_id, id)),
+             &LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) =>
+                if id == id2 && opt_variant_id == opt_variant_id2 {
                     base.has_fork(&**base2)
                 } else {
                     true
@@ -428,23 +437,23 @@ fn has_fork(&self, other: &LoanPath<'tcx>) -> bool {
     fn depth(&self) -> usize {
         match self.kind {
             LpExtend(ref base, _, LpDeref(_)) => base.depth(),
-            LpExtend(ref base, _, LpInterior(_)) => base.depth() + 1,
+            LpExtend(ref base, _, LpInterior(_, _)) => base.depth() + 1,
             _ => 0,
         }
     }
 
     fn common(&self, other: &LoanPath<'tcx>) -> Option<LoanPath<'tcx>> {
         match (&self.kind, &other.kind) {
-            (&LpExtend(ref base, a, LpInterior(id)),
-             &LpExtend(ref base2, _, LpInterior(id2))) => {
-                if id == id2 {
+            (&LpExtend(ref base, a, LpInterior(opt_variant_id, id)),
+             &LpExtend(ref base2, _, LpInterior(opt_variant_id2, id2))) => {
+                if id == id2 && opt_variant_id == opt_variant_id2 {
                     base.common(&**base2).map(|x| {
                         let xd = x.depth();
                         if base.depth() == xd && base2.depth() == xd {
                             assert_eq!(base.ty, base2.ty);
                             assert_eq!(self.ty, other.ty);
                             LoanPath {
-                                kind: LpExtend(Rc::new(x), a, LpInterior(id)),
+                                kind: LpExtend(Rc::new(x), a, LpInterior(opt_variant_id, id)),
                                 ty: self.ty,
                             }
                         } else {
@@ -509,7 +518,11 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
 
         Categorization::Interior(ref cmt_base, ik) => {
             opt_loan_path(cmt_base).map(|lp| {
-                new_lp(LpExtend(lp, cmt.mutbl, LpInterior(ik.cleaned())))
+                let opt_variant_id = match cmt_base.cat {
+                    Categorization::Downcast(_, did) =>  Some(did),
+                    _ => None
+                };
+                new_lp(LpExtend(lp, cmt.mutbl, LpInterior(opt_variant_id, ik.cleaned())))
             })
         }
 
@@ -1068,7 +1081,7 @@ pub fn append_loan_path_to_string(&self,
             }
 
 
-            LpExtend(ref lp_base, _, LpInterior(InteriorField(fname))) => {
+            LpExtend(ref lp_base, _, LpInterior(_, InteriorField(fname))) => {
                 self.append_autoderefd_loan_path_to_string(&**lp_base, out);
                 match fname {
                     mc::NamedField(fname) => {
@@ -1082,7 +1095,7 @@ pub fn append_loan_path_to_string(&self,
                 }
             }
 
-            LpExtend(ref lp_base, _, LpInterior(InteriorElement(..))) => {
+            LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) => {
                 self.append_autoderefd_loan_path_to_string(&**lp_base, out);
                 out.push_str("[..]");
             }
@@ -1210,7 +1223,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "{:?}.*", lp)
             }
 
-            LpExtend(ref lp, _, LpInterior(ref interior)) => {
+            LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
                 write!(f, "{:?}.{:?}", lp, interior)
             }
         }
@@ -1242,7 +1255,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "{}.*", lp)
             }
 
-            LpExtend(ref lp, _, LpInterior(ref interior)) => {
+            LpExtend(ref lp, _, LpInterior(_, ref interior)) => {
                 write!(f, "{}.{:?}", lp, interior)
             }
         }
index 3ac6e7c5d69eb9988229858461bc5378ed888d53..62404a73ad3be5184bc1a66ed6d0542edbdd7752 100644 (file)
@@ -195,7 +195,7 @@ fn loan_path_is_precise(loan_path: &LoanPath) -> bool {
         LpVar(_) | LpUpvar(_) => {
             true
         }
-        LpExtend(_, _, LpInterior(InteriorKind::InteriorElement(..))) => {
+        LpExtend(_, _, LpInterior(_, InteriorKind::InteriorElement(..))) => {
             // Paths involving element accesses a[i] do not refer to a unique
             // location, as there is no accurate tracking of the indices.
             //
index fd471893acd53c5517328ae67e73597b8457d293..94c3ea073d2f69d48e307d98582c81933606f853 100644 (file)
@@ -871,6 +871,9 @@ fn merge_import_resolution(&mut self,
                             is_public: is_public
                         };
                     }
+                } else {
+                    // FIXME #30159: This is required for backwards compatability.
+                    dest_import_resolution[namespace].is_public |= is_public;
                 }
             };
             merge_child_item(ValueNS);
index 0e09a15492a891ae3bafb659f4f4d9601196c441..0ad780fb0e4d33add43667cb0648c4b333736e4e 100644 (file)
@@ -1944,8 +1944,16 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::PatBox(ref inner) => {
             let pat_ty = node_id_type(bcx, inner.id);
-            // Don't load DSTs, instead pass along a fat ptr
-            let val = if type_is_sized(tcx, pat_ty) {
+            // Pass along DSTs as fat pointers.
+            let val = if type_is_fat_ptr(tcx, pat_ty) {
+                // We need to check for this, as the pattern could be binding
+                // a fat pointer by-value.
+                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                    val.val
+                } else {
+                    Load(bcx, val.val)
+                }
+            } else if type_is_sized(tcx, pat_ty) {
                 Load(bcx, val.val)
             } else {
                 val.val
@@ -1955,8 +1963,16 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::PatRegion(ref inner, _) => {
             let pat_ty = node_id_type(bcx, inner.id);
-            // Don't load DSTs, instead pass along a fat ptr
-            let val = if type_is_sized(tcx, pat_ty) {
+            // Pass along DSTs as fat pointers.
+            let val = if type_is_fat_ptr(tcx, pat_ty) {
+                // We need to check for this, as the pattern could be binding
+                // a fat pointer by-value.
+                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                    val.val
+                } else {
+                    Load(bcx, val.val)
+                }
+            } else if type_is_sized(tcx, pat_ty) {
                 Load(bcx, val.val)
             } else {
                 val.val
index 5284911340bd744084df505dc9ad268e946968f0..77664f19aac2ae0c0f1776a366e978616b92dba8 100644 (file)
@@ -321,27 +321,26 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           -> Result<ValueRef, ConstEvalFailure> {
     debug!("get_const_expr_as_global: {:?}", expr.id);
     // Special-case constants to cache a common global for all uses.
-    match expr.node {
-        hir::ExprPath(..) => {
-            let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
-            match def {
-                def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
-                    if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
-                        debug!("get_const_expr_as_global ({:?}): found const {:?}",
-                               expr.id, def_id);
-                        return get_const_val(ccx, def_id, expr);
-                    }
+    if let hir::ExprPath(..) = expr.node {
+        // `def` must be its own statement and cannot be in the `match`
+        // otherwise the `def_map` will be borrowed for the entire match instead
+        // of just to get the `def` value
+        let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
+        match def {
+            def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+                if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
+                    debug!("get_const_expr_as_global ({:?}): found const {:?}",
+                           expr.id, def_id);
+                    return get_const_val(ccx, def_id, expr);
                 }
-                _ => {}
-            }
+            },
+            _ => {},
         }
-        _ => {}
     }
 
     let key = (expr.id, param_substs);
-    match ccx.const_values().borrow().get(&key) {
-        Some(&val) => return Ok(val),
-        None => {}
+    if let Some(&val) = ccx.const_values().borrow().get(&key) {
+        return Ok(val);
     }
     let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
                                               &ccx.tcx().expr_ty(expr));
@@ -350,10 +349,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // references, even when only the latter are correct.
         try!(const_expr_unadjusted(ccx, expr, ty, param_substs, None, trueconst))
     } else {
-        match const_expr(ccx, expr, param_substs, None, trueconst) {
-            Err(err) => return Err(err),
-            Ok((ok, _)) => ok,
-        }
+        try!(const_expr(ccx, expr, param_substs, None, trueconst)).0
     };
 
     // boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -611,9 +607,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     };
     let _icx = push_ctxt("const_expr");
     Ok(match e.node {
-        hir::ExprLit(ref lit) => {
-            const_lit(cx, e, &**lit)
-        },
+        hir::ExprLit(ref lit) => const_lit(cx, e, &**lit),
         hir::ExprBinary(b, ref e1, ref e2) => {
             /* Neither type is bottom, and we expect them to be unified
              * already, so the following is safe. */
index d68959b99be0fee092346608b85510357499050e..0fbe83674931c2bbf89be4ba3107840afcb4b1b9 100644 (file)
@@ -17,7 +17,6 @@
 use middle::subst::{self, Subst};
 use middle::traits;
 use middle::ty::{self, Ty};
-use util::nodemap::FnvHashSet;
 
 use syntax::ast;
 use syntax::codemap::{self, Span};
@@ -280,7 +279,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
             rcx: rcx,
             span: span,
             parent_scope: parent_scope,
-            breadcrumbs: FnvHashSet()
+            breadcrumbs: Vec::new(),
         },
         TypeContext::Root,
         typ,
@@ -341,7 +340,7 @@ enum TypeContext {
 struct DropckContext<'a, 'b: 'a, 'tcx: 'b> {
     rcx: &'a mut Rcx<'b, 'tcx>,
     /// types that have already been traversed
-    breadcrumbs: FnvHashSet<Ty<'tcx>>,
+    breadcrumbs: Vec<Ty<'tcx>>,
     /// span for error reporting
     span: Span,
     /// the scope reachable dtorck types must outlive
@@ -356,6 +355,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     depth: usize) -> Result<(), Error<'tcx>>
 {
     let tcx = cx.rcx.tcx();
+    let ty = cx.rcx.infcx().resolve_type_and_region_vars_if_possible(&ty);
+
     // Issue #22443: Watch out for overflow. While we are careful to
     // handle regular types properly, non-regular ones cause problems.
     let recursion_limit = tcx.sess.recursion_limit.get();
@@ -366,13 +367,19 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
         return Err(Error::Overflow(context, ty))
     }
 
-    if !cx.breadcrumbs.insert(ty) {
-        debug!("iterate_over_potentially_unsafe_regions_in_type \
-               {}ty: {} scope: {:?} - cached",
-               (0..depth).map(|_| ' ').collect::<String>(),
-               ty, cx.parent_scope);
-        return Ok(()); // we already visited this type
+    for breadcrumb in &mut cx.breadcrumbs {
+        *breadcrumb =
+            cx.rcx.infcx().resolve_type_and_region_vars_if_possible(breadcrumb);
+        if *breadcrumb == ty {
+            debug!("iterate_over_potentially_unsafe_regions_in_type \
+                   {}ty: {} scope: {:?} - cached",
+                   (0..depth).map(|_| ' ').collect::<String>(),
+                   ty, cx.parent_scope);
+            return Ok(()); // we already visited this type
+        }
     }
+    cx.breadcrumbs.push(ty);
+
     debug!("iterate_over_potentially_unsafe_regions_in_type \
            {}ty: {} scope: {:?}",
            (0..depth).map(|_| ' ').collect::<String>(),
index a50213202b82c8cb94905f2ac3c65aa0c5f53683..a985e3552816f40bb3d9013573fec4ff5da197ef 100644 (file)
@@ -3156,12 +3156,13 @@ fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             !remaining_fields.is_empty()
         {
             span_err!(tcx.sess, span, E0063,
-                      "missing field{}: {}",
+                      "missing field{} {} in initializer of `{}`",
                       if remaining_fields.len() == 1 {""} else {"s"},
                       remaining_fields.keys()
                                       .map(|n| format!("`{}`", n))
                                       .collect::<Vec<_>>()
-                                      .join(", "));
+                                      .join(", "),
+                      adt_ty);
         }
 
     }
index 1ff8f572a7f571cf179e9a9b3412b74d7a624a13..1dd96f5ddfc0169af67bac30d21479c7097999b4 100644 (file)
@@ -311,9 +311,31 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl error::Error for Error {
+    #[allow(deprecated)] // remove with UnexpectedEOF
     fn description(&self) -> &str {
         match self.repr {
-            Repr::Os(..) => "os error",
+            Repr::Os(..) => match self.kind() {
+                ErrorKind::NotFound => "entity not found",
+                ErrorKind::PermissionDenied => "permission denied",
+                ErrorKind::ConnectionRefused => "connection refused",
+                ErrorKind::ConnectionReset => "connection reset",
+                ErrorKind::ConnectionAborted => "connection aborted",
+                ErrorKind::NotConnected => "not connected",
+                ErrorKind::AddrInUse => "address in use",
+                ErrorKind::AddrNotAvailable => "address not available",
+                ErrorKind::BrokenPipe => "broken pipe",
+                ErrorKind::AlreadyExists => "entity already exists",
+                ErrorKind::WouldBlock => "operation would block",
+                ErrorKind::InvalidInput => "invalid input parameter",
+                ErrorKind::InvalidData => "invalid data",
+                ErrorKind::TimedOut => "timed out",
+                ErrorKind::WriteZero => "write zero",
+                ErrorKind::Interrupted => "operation interrupted",
+                ErrorKind::Other => "other os error",
+                ErrorKind::UnexpectedEOF => "unexpected end of file",
+                ErrorKind::UnexpectedEof => "unexpected end of file",
+                ErrorKind::__Nonexhaustive => unreachable!()
+            },
             Repr::Custom(ref c) => c.error.description(),
         }
     }
index 1bf7f3933849de76ba2307357ba574ebc776b90c..bfc6a4ec9b85449dfe902959e13c2f605aed2649 100644 (file)
@@ -17,10 +17,6 @@ pub fn f() {}
 
 mod bar {
     use foo::bar::f as g; //~ ERROR unresolved import
-
-    use foo as f;
-    pub use foo::*;
 }
 
-use bar::f::f; //~ ERROR unresolved import
 fn main() {}
index 1fd9357cf2d4e3276e206b56bfc4d1dad4857117..d5ab13affafb1641df8bfa179252be37ae60ff40 100644 (file)
@@ -15,7 +15,7 @@ struct BuildData {
 }
 
 fn main() {
-    let foo = BuildData { //~ ERROR missing field: `bar`
+    let foo = BuildData { //~ ERROR missing field `bar` in initializer of `BuildData`
         foo: 0
     };
 }
diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs
new file mode 100644 (file)
index 0000000..9f8067f
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+struct Test<T: ?Sized>(T);
+
+fn main() {
+    let x = Test([1,2,3]);
+    let x : &Test<[i32]> = &x;
+
+    let & ref _y = x;
+
+    // Make sure binding to a fat pointer behind a reference
+    // still works
+    let slice = &[1,2,3];
+    let x = Test(&slice);
+    let Test(&_slice) = x;
+}
diff --git a/src/test/run-pass/issue-27889.rs b/src/test/run-pass/issue-27889.rs
new file mode 100644 (file)
index 0000000..3f7d040
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 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.
+
+// Test that a field can have the same name in different variants
+// of an enum
+// FIXME #27889
+
+pub enum Foo {
+    X { foo: u32 },
+    Y { foo: u32 }
+}
+
+pub fn foo(mut x: Foo) {
+    let mut y = None;
+    let mut z = None;
+    if let Foo::X { ref foo } = x {
+        z = Some(foo);
+    }
+    if let Foo::Y { ref mut foo } = x {
+        y = Some(foo);
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-29844.rs b/src/test/run-pass/issue-29844.rs
new file mode 100644 (file)
index 0000000..51df4d6
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 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::sync::Arc;
+
+pub struct DescriptorSet<'a> {
+    pub slots: Vec<AttachInfo<'a, Resources>>
+}
+
+pub trait ResourcesTrait<'r>: Sized {
+    type DescriptorSet: 'r;
+}
+
+pub struct Resources;
+
+impl<'a> ResourcesTrait<'a> for Resources {
+    type DescriptorSet = DescriptorSet<'a>;
+}
+
+pub enum AttachInfo<'a, R: ResourcesTrait<'a>> {
+    NextDescriptorSet(Arc<R::DescriptorSet>)
+}
+
+fn main() {
+    let _x = DescriptorSet {slots: Vec::new()};
+}