]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #42141 - ids1024:nobacktrace, r=aturon
authorMark Simulacrum <mark.simulacrum@gmail.com>
Thu, 25 May 2017 01:50:02 +0000 (19:50 -0600)
committerGitHub <noreply@github.com>
Thu, 25 May 2017 01:50:02 +0000 (19:50 -0600)
Fix building std without backtrace feature, which was broken in ca8b754

Fixes #42139

113 files changed:
src/bootstrap/lib.rs
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/language-features/attr-literals.md
src/doc/unstable-book/src/language-features/catch-expr.md
src/doc/unstable-book/src/language-features/loop-break-value.md [deleted file]
src/doc/unstable-book/src/language-features/on-unimplemented.md
src/doc/unstable-book/src/library-features/binary-heap-peek-mut-pop.md [deleted file]
src/doc/unstable-book/src/library-features/peek.md [deleted file]
src/doc/unstable-book/src/library-features/process-try-wait.md [deleted file]
src/doc/unstable-book/src/library-features/retain-hash-collection.md [deleted file]
src/libcollections/binary_heap.rs
src/libcollections/range.rs
src/libcollections/slice.rs
src/libcollections/tests/lib.rs
src/libcore/iter/range.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/tests/lib.rs
src/libcore/tests/ops.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/lowering.rs
src/librustc/infer/mod.rs
src/librustc/lib.rs
src/librustc/traits/README.md
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_driver/lib.rs
src/librustc_lint/builtin.rs
src/librustc_mir/build/expr/as_operand.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/consts.rs
src/librustc_trans/context.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/ffi/c_str.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/process.rs
src/libstd/thread/mod.rs
src/libsyntax/attr.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/lexer/unicode_chars.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/tokenstream.rs
src/test/compile-fail/E0277-2.rs
src/test/compile-fail/E0277.rs
src/test/compile-fail/const-unsized.rs
src/test/compile-fail/feature-gate-loop-break-value.rs [deleted file]
src/test/compile-fail/impl-trait/auto-trait-leak.rs
src/test/compile-fail/isssue-38821.rs [new file with mode: 0644]
src/test/compile-fail/loop-break-value.rs
src/test/compile-fail/on-unimplemented/multiple-impls.rs
src/test/compile-fail/on-unimplemented/on-impl.rs
src/test/compile-fail/on-unimplemented/on-trait.rs
src/test/compile-fail/on-unimplemented/slice-index.rs
src/test/compile-fail/partialeq_help.rs [new file with mode: 0644]
src/test/compile-fail/trait-suggest-where-clause.rs
src/test/mir-opt/storage_live_dead_in_statics.rs [new file with mode: 0644]
src/test/parse-fail/unicode-chars.rs
src/test/run-make/atomic-lock-free/atomic_lock_free.rs
src/test/run-pass/associated-const-outer-ty-refs.rs
src/test/run-pass/diverging-fallback-control-flow.rs
src/test/run-pass/loop-break-value.rs
src/test/run-pass/range_inclusive.rs
src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/renamed-via-module.rs [new file with mode: 0644]
src/test/ui/impl-trait/equality.stderr
src/test/ui/loop-break-value-no-repeat.rs
src/test/ui/loop-break-value-no-repeat.stderr
src/test/ui/mismatched_types/binops.stderr
src/test/ui/mismatched_types/cast-rfc0401.stderr
src/test/ui/resolve/issue-5035-2.stderr
src/test/ui/span/multiline-span-simple.stderr
src/tools/compiletest/src/runtest.rs

index 7eccc2a49c0ea230b2e6e6945f4fb6a9d5ec42a8..665b9ee49c02d5597ed3261be23f344007c7da65 100644 (file)
@@ -211,7 +211,7 @@ pub enum Mode {
     /// output in the "stageN-rustc" directory.
     Librustc,
 
-    /// This cargo is going to some build tool, placing output in the
+    /// This cargo is going to build some tool, placing output in the
     /// "stageN-tools" directory.
     Tool,
 }
@@ -424,7 +424,7 @@ fn cargo(&self,
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler));
         }
 
-        // There are two invariants we try must maintain:
+        // There are two invariants we must maintain:
         // * stable crates cannot depend on unstable crates (general Rust rule),
         // * crates that end up in the sysroot must be unstable (rustbuild rule).
         //
@@ -438,7 +438,7 @@ fn cargo(&self,
         // feature and opt-in to `rustc_private`.
         //
         // We can't always pass `rustbuild` because crates which are outside of
-        // the comipiler, libs, and tests are stable and we don't want to make
+        // the compiler, libs, and tests are stable and we don't want to make
         // their deps unstable (since this would break the first invariant
         // above).
         //
@@ -448,7 +448,7 @@ fn cargo(&self,
         }
 
         // Ignore incremental modes except for stage0, since we're
-        // not guaranteeing correctness acros builds if the compiler
+        // not guaranteeing correctness across builds if the compiler
         // is changing under your feet.`
         if self.flags.incremental && compiler.stage == 0 {
             let incr_dir = self.incremental_dir(compiler);
@@ -489,7 +489,7 @@ fn cargo(&self,
             cargo.env_remove("MAKEFLAGS");
         }
 
-        // Environment variables *required* needed throughout the build
+        // Environment variables *required* throughout the build
         //
         // FIXME: should update code to not require this env var
         cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
@@ -647,7 +647,7 @@ fn stage_out(&self, compiler: &Compiler, mode: Mode) -> PathBuf {
     }
 
     /// Returns the root output directory for all Cargo output in a given stage,
-    /// running a particular comipler, wehther or not we're building the
+    /// running a particular compiler, wehther or not we're building the
     /// standard library, and targeting the specified architecture.
     fn cargo_out(&self,
                  compiler: &Compiler,
index 39f800591483bdbf05528244bf24281e76c992d2..456a683dc33c89fcc53c5712c4510eec272028d0 100644 (file)
@@ -49,7 +49,6 @@
     - [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
     - [linkage](language-features/linkage.md)
     - [log_syntax](language-features/log-syntax.md)
-    - [loop_break_value](language-features/loop-break-value.md)
     - [macro_reexport](language-features/macro-reexport.md)
     - [macro_vis_matcher](language-features/macro-vis-matcher.md)
     - [main](language-features/main.md)
     - [alloc](library-features/alloc.md)
     - [as_c_str](library-features/as-c-str.md)
     - [ascii_ctype](library-features/ascii-ctype.md)
-    - [binary_heap_peek_mut_pop](library-features/binary-heap-peek-mut-pop.md)
     - [box_heap](library-features/box-heap.md)
     - [c_void_variant](library-features/c-void-variant.md)
     - [char_escape_debug](library-features/char-escape-debug.md)
     - [panic_abort](library-features/panic-abort.md)
     - [panic_unwind](library-features/panic-unwind.md)
     - [pattern](library-features/pattern.md)
-    - [peek](library-features/peek.md)
     - [placement_in](library-features/placement-in.md)
     - [placement_new_protocol](library-features/placement-new-protocol.md)
     - [print_internals](library-features/print-internals.md)
     - [proc_macro_internals](library-features/proc-macro-internals.md)
-    - [process_try_wait](library-features/process-try-wait.md)
     - [question_mark_carrier](library-features/question-mark-carrier.md)
     - [rand](library-features/rand.md)
     - [range_contains](library-features/range-contains.md)
     - [raw](library-features/raw.md)
-    - [retain_hash_collection](library-features/retain-hash-collection.md)
     - [reverse_cmp_key](library-features/reverse-cmp-key.md)
     - [rt](library-features/rt.md)
     - [rustc_private](library-features/rustc-private.md)
index 67eee214a4f247e4f012fe59dd0e5574d0b60519..60741a74400d2e50007610ab1ed27b291d56ee0a 100644 (file)
@@ -6,5 +6,25 @@ The tracking issue for this feature is: [#34981]
 
 ------------------------
 
+At present, literals are only accepted as the value of a key-value pair in
+attributes. What's more, only _string_ literals are accepted. This means that
+literals can only appear in forms of `#[attr(name = "value")]` or
+`#[attr = "value"]`.
 
+The `attr_literals` unstable feature allows other types of literals to be used
+in attributes. Here are some examples of attributes that can now be used with
+this feature enabled:
+
++```rust,ignore
++#[attr]
++#[attr(true)]
++#[attr(ident)]
++#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
++#[attr(100)]
++#[attr(enabled = true)]
++#[enabled(true)]
++#[attr("hello")]
++#[repr(C, align = 4)]
++#[repr(C, align(4))]
++```
 
index 44eb2a6dd4fdbda5f4ff346ddf8a36bbf7c85618..fbd213dca569949fc8b9e38c20f3a2de10f2778e 100644 (file)
@@ -5,3 +5,26 @@ The tracking issue for this feature is: [#31436]
 [#31436]: https://github.com/rust-lang/rust/issues/31436
 
 ------------------------
+
+The `catch_expr` feature adds support for a `catch` expression. The `catch`
+expression creates a new scope one can use the `?` operator in.
+
+```rust
+#![feature(catch_expr)]
+
+use std::num::ParseIntError;
+
+let result: Result<i32, ParseIntError> = do catch {
+    Ok("1".parse::<i32>()?
+        + "2".parse::<i32>()?
+        + "3".parse::<i32>()?)
+};
+assert_eq!(result, Ok(6));
+
+let result: Result<i32, ParseIntError> = do catch {
+    Ok("1".parse::<i32>()?
+        + "foo".parse::<i32>()?
+        + "3".parse::<i32>()?)
+};
+assert!(result.is_err());
+```
diff --git a/src/doc/unstable-book/src/language-features/loop-break-value.md b/src/doc/unstable-book/src/language-features/loop-break-value.md
deleted file mode 100644 (file)
index e8fefe3..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-# `loop_break_value`
-
-The tracking issue for this feature is: [#37339]
-
-[#37339]: https://github.com/rust-lang/rust/issues/37339
-
-Documentation to be appended to section G of the book.
-
-------------------------
-
-### Loops as expressions
-
-Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
-never exits.
-A `loop` can instead evaluate to a useful value via *break with value*:
-
-```rust
-#![feature(loop_break_value)]
-
-// Find the first square number over 1000:
-let mut n = 1;
-let square = loop {
-    if n * n > 1000 {
-        break n * n;
-    }
-    n += 1;
-};
-```
-
-The evaluation type may be specified externally:
-
-```rust
-#![feature(loop_break_value)]
-
-// Declare that value returned is unsigned 64-bit:
-let n: u64 = loop {
-    break 1;
-};
-```
-
-It is an error if types do not agree, either between a "break" value and an external requirement,
-or between multiple "break" values:
-
-```no_compile
-#![feature(loop_break_value)]
-
-loop {
-    if true {
-        break 1u32;
-    } else {
-        break 0u8;  // error: types do not agree
-    }
-};
-
-let n: i32 = loop {
-    break 0u32; // error: type does not agree with external requirement
-};
-```
-
-#### Break: label, value
-
-Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
-
-1.  `break;`
-2.  `break 'label;`
-3.  `break EXPR;`
-4.  `break 'label EXPR;`
-
-When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
-
-Using a label allows returning a value from an inner loop:
-
-```rust
-#![feature(loop_break_value)]
-
-let result = 'outer: loop {
-    for n in 1..10 {
-        if n > 4 {
-            break 'outer n;
-        }
-    }
-};
-```
index 81f284d0a6a3e0bb52573dd92ba162ea2ebb2d3a..9eea3fccbbc17e39ad591fb72f94893f0027d5f5 100644 (file)
@@ -6,5 +6,42 @@ The tracking issue for this feature is: [#29628]
 
 ------------------------
 
+The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
+attribute, which allows trait definitions to add specialized notes to error
+messages when an implementation was expected but not found.
 
+For example:
+
+```rust,compile_fail
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an \
+                          iterator over elements of type `{A}`"]
+trait MyIterator<A> {
+    fn next(&mut self) -> A;
+}
+
+fn iterate_chars<I: MyIterator<char>>(i: I) {
+    // ...
+}
+
+fn main() {
+    iterate_chars(&[1, 2, 3][..]);
+}
+```
+
+When the user compiles this, they will see the following;
+
+```txt
+error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
+  --> <anon>:14:5
+   |
+14 |     iterate_chars(&[1, 2, 3][..]);
+   |     ^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+   |
+   = note: a collection of type `&[{integer}]` cannot be built from an iterator over elements of type `char`
+   = note: required by `iterate_chars`
+
+error: aborting due to previous error
+```
 
diff --git a/src/doc/unstable-book/src/library-features/binary-heap-peek-mut-pop.md b/src/doc/unstable-book/src/library-features/binary-heap-peek-mut-pop.md
deleted file mode 100644 (file)
index f3863ab..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# `binary_heap_peek_mut_pop`
-
-The tracking issue for this feature is: [#38863]
-
-[#38863]: https://github.com/rust-lang/rust/issues/38863
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/peek.md b/src/doc/unstable-book/src/library-features/peek.md
deleted file mode 100644 (file)
index c42b4e9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# `peek`
-
-The tracking issue for this feature is: [#38980]
-
-[#38980]: https://github.com/rust-lang/rust/issues/38980
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/process-try-wait.md b/src/doc/unstable-book/src/library-features/process-try-wait.md
deleted file mode 100644 (file)
index 3593b64..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# `process_try_wait`
-
-The tracking issue for this feature is: [#38903]
-
-[#38903]: https://github.com/rust-lang/rust/issues/38903
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/retain-hash-collection.md b/src/doc/unstable-book/src/library-features/retain-hash-collection.md
deleted file mode 100644 (file)
index c9ba5ac..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# `retain_hash_collection`
-
-The tracking issue for this feature is: [#36648]
-
-[#36648]: https://github.com/rust-lang/rust/issues/36648
-
-------------------------
index 7d972403f65db47dd923dc257487de5a5b08ab9a..4e9dea09f79a0d0a654e882a9699dc12f27b9ce7 100644 (file)
@@ -268,7 +268,7 @@ fn deref_mut(&mut self) -> &mut T {
 
 impl<'a, T: Ord> PeekMut<'a, T> {
     /// Removes the peeked value from the heap and returns it.
-    #[unstable(feature = "binary_heap_peek_mut_pop", issue = "38863")]
+    #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")]
     pub fn pop(mut this: PeekMut<'a, T>) -> T {
         let value = this.heap.pop().unwrap();
         this.sift = false;
index 8f3209d015b159ad955f6a31ee7eac0109bd45b6..bc8566e8cbeb375b6b066b0ddd368eb7ee883dfb 100644 (file)
@@ -106,16 +106,10 @@ fn end(&self) -> Bound<&T> {
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<T> RangeArgument<T> for RangeInclusive<T> {
     fn start(&self) -> Bound<&T> {
-        match *self {
-            RangeInclusive::Empty{ ref at }            => Included(at),
-            RangeInclusive::NonEmpty { ref start, .. } => Included(start),
-        }
+        Included(&self.start)
     }
     fn end(&self) -> Bound<&T> {
-        match *self {
-            RangeInclusive::Empty{ ref at }            => Excluded(at),
-            RangeInclusive::NonEmpty { ref end, .. }   => Included(end),
-        }
+        Included(&self.end)
     }
 }
 
index 3efda1faa3b56405637a31019688775ffe8254fe..5696f5fe6a7ba80bdc6d15383dbd785db3547476 100644 (file)
@@ -1410,6 +1410,9 @@ pub fn to_vec(&self) -> Vec<T>
 
     /// Converts `self` into a vector without clones or allocation.
     ///
+    /// The resulting vector can be converted back into a box via
+    /// `Vec<T>`'s `into_boxed_slice` method.
+    ///
     /// # Examples
     ///
     /// ```
index eae3bf3915f60d1f40f30ab3203aafcc1363d4cf..cda8c6d59987efc42e652802aaa7f82e1f9ceee7 100644 (file)
@@ -10,7 +10,6 @@
 
 #![deny(warnings)]
 
-#![feature(binary_heap_peek_mut_pop)]
 #![feature(box_syntax)]
 #![feature(inclusive_range_syntax)]
 #![feature(collection_placement)]
index bd831d638c0c4cc24e8573501345ab809c489477..02d38ccea44eadcb2b95caee0450fbecd7d8d279 100644 (file)
@@ -403,61 +403,35 @@ impl<A: Step + Clone> Iterator for StepBy<A, ops::RangeInclusive<A>> {
 
     #[inline]
     fn next(&mut self) -> Option<A> {
-        use ops::RangeInclusive::*;
-
-        // this function has a sort of odd structure due to borrowck issues
-        // we may need to replace self.range, so borrows of start and end need to end early
-
-        let (finishing, n) = match self.range {
-            Empty { .. } => return None, // empty iterators yield no values
-
-            NonEmpty { ref mut start, ref mut end } => {
-                let rev = self.step_by.is_negative();
-
-                // march start towards (maybe past!) end and yield the old value
-                if (rev && start >= end) ||
-                   (!rev && start <= end)
-                {
-                    match start.step(&self.step_by) {
-                        Some(mut n) => {
-                            mem::swap(start, &mut n);
-                            (None, Some(n)) // yield old value, remain non-empty
-                        },
-                        None => {
-                            let mut n = end.clone();
-                            mem::swap(start, &mut n);
-                            (None, Some(n)) // yield old value, remain non-empty
-                        }
-                    }
-                } else {
-                    // found range in inconsistent state (start at or past end), so become empty
-                    (Some(end.replace_zero()), None)
-                }
-            }
-        };
+        let rev = self.step_by.is_negative();
 
-        // turn into an empty iterator if we've reached the end
-        if let Some(end) = finishing {
-            self.range = Empty { at: end };
+        if (rev && self.range.start >= self.range.end) ||
+           (!rev && self.range.start <= self.range.end)
+        {
+            match self.range.start.step(&self.step_by) {
+                Some(n) => {
+                    Some(mem::replace(&mut self.range.start, n))
+                },
+                None => {
+                    let last = self.range.start.replace_one();
+                    self.range.end.replace_zero();
+                    self.step_by.replace_one();
+                    Some(last)
+                },
+            }
+        }
+        else {
+            None
         }
-
-        n
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        use ops::RangeInclusive::*;
-
-        match self.range {
-            Empty { .. } => (0, Some(0)),
-
-            NonEmpty { ref start, ref end } =>
-                match Step::steps_between(start,
-                                          end,
-                                          &self.step_by) {
-                    Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
-                    None       => (0, None)
-                }
+        match Step::steps_between(&self.range.start,
+                                  &self.range.end,
+                                  &self.step_by) {
+            Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+            None       => (0, None)
         }
     }
 }
@@ -583,56 +557,31 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> where
 
     #[inline]
     fn next(&mut self) -> Option<A> {
-        use ops::RangeInclusive::*;
-
-        // this function has a sort of odd structure due to borrowck issues
-        // we may need to replace self, so borrows of self.start and self.end need to end early
-
-        let (finishing, n) = match *self {
-            Empty { .. } => (None, None), // empty iterators yield no values
-
-            NonEmpty { ref mut start, ref mut end } => {
-                if start == end {
-                    (Some(end.replace_one()), Some(start.replace_one()))
-                } else if start < end {
-                    let mut n = start.add_one();
-                    mem::swap(&mut n, start);
-
-                    // if the iterator is done iterating, it will change from
-                    // NonEmpty to Empty to avoid unnecessary drops or clones,
-                    // we'll reuse either start or end (they are equal now, so
-                    // it doesn't matter which) to pull out end, we need to swap
-                    // something back in
-
-                    (if n == *end { Some(end.replace_one()) } else { None },
-                    // ^ are we done yet?
-                    Some(n)) // < the value to output
-                } else {
-                    (Some(start.replace_one()), None)
-                }
-            }
-        };
-
-        // turn into an empty iterator if this is the last value
-        if let Some(end) = finishing {
-            *self = Empty { at: end };
+        use cmp::Ordering::*;
+
+        match self.start.partial_cmp(&self.end) {
+            Some(Less) => {
+                let n = self.start.add_one();
+                Some(mem::replace(&mut self.start, n))
+            },
+            Some(Equal) => {
+                let last = self.start.replace_one();
+                self.end.replace_zero();
+                Some(last)
+            },
+            _ => None,
         }
-
-        n
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        use ops::RangeInclusive::*;
-
-        match *self {
-            Empty { .. } => (0, Some(0)),
+        if !(self.start <= self.end) {
+            return (0, Some(0));
+        }
 
-            NonEmpty { ref start, ref end } =>
-                match Step::steps_between_by_one(start, end) {
-                    Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
-                    None => (0, None),
-                }
+        match Step::steps_between_by_one(&self.start, &self.end) {
+            Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+            None => (0, None),
         }
     }
 }
@@ -644,33 +593,20 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> where
 {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
-        use ops::RangeInclusive::*;
-
-        // see Iterator::next for comments
-
-        let (finishing, n) = match *self {
-            Empty { .. } => return None,
-
-            NonEmpty { ref mut start, ref mut end } => {
-                if start == end {
-                    (Some(start.replace_one()), Some(end.replace_one()))
-                } else if start < end {
-                    let mut n = end.sub_one();
-                    mem::swap(&mut n, end);
-
-                    (if n == *start { Some(start.replace_one()) } else { None },
-                     Some(n))
-                } else {
-                    (Some(end.replace_one()), None)
-                }
-            }
-        };
-
-        if let Some(start) = finishing {
-            *self = Empty { at: start };
+        use cmp::Ordering::*;
+
+        match self.start.partial_cmp(&self.end) {
+            Some(Less) => {
+                let n = self.end.sub_one();
+                Some(mem::replace(&mut self.end, n))
+            },
+            Some(Equal) => {
+                let last = self.end.replace_zero();
+                self.start.replace_one();
+                Some(last)
+            },
+            _ => None,
         }
-
-        n
     }
 }
 
index fc3af096b183880c4b3a61910e4fe5eae73e904d..59c3a9a8afa02ed2a0c6623a1aafb1a3078211b8 100644 (file)
@@ -2271,7 +2271,7 @@ pub fn contains(&self, item: Idx) -> bool {
 /// ```
 /// #![feature(inclusive_range,inclusive_range_syntax)]
 /// fn main() {
-///     assert_eq!((3...5), std::ops::RangeInclusive::NonEmpty{ start: 3, end: 5 });
+///     assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 });
 ///     assert_eq!(3+4+5, (3...5).sum());
 ///
 ///     let arr = [0, 1, 2, 3];
@@ -2281,45 +2281,23 @@ pub fn contains(&self, item: Idx) -> bool {
 /// ```
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-pub enum RangeInclusive<Idx> {
-    /// Empty range (iteration has finished)
+pub struct RangeInclusive<Idx> {
+    /// The lower bound of the range (inclusive).
     #[unstable(feature = "inclusive_range",
                reason = "recently added, follows RFC",
                issue = "28237")]
-    Empty {
-        /// The point at which iteration finished
-        #[unstable(feature = "inclusive_range",
-                   reason = "recently added, follows RFC",
-                   issue = "28237")]
-        at: Idx
-    },
-    /// Non-empty range (iteration will yield value(s))
+    pub start: Idx,
+    /// The upper bound of the range (inclusive).
     #[unstable(feature = "inclusive_range",
                reason = "recently added, follows RFC",
                issue = "28237")]
-    NonEmpty {
-        /// The lower bound of the range (inclusive).
-        #[unstable(feature = "inclusive_range",
-                   reason = "recently added, follows RFC",
-                   issue = "28237")]
-        start: Idx,
-        /// The upper bound of the range (inclusive).
-        #[unstable(feature = "inclusive_range",
-                   reason = "recently added, follows RFC",
-                   issue = "28237")]
-        end: Idx,
-    },
+    pub end: Idx,
 }
 
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        use self::RangeInclusive::*;
-
-        match *self {
-            Empty { ref at } => write!(fmt, "[empty range @ {:?}]", at),
-            NonEmpty { ref start, ref end } => write!(fmt, "{:?}...{:?}", start, end),
-        }
+        write!(fmt, "{:?}...{:?}", self.start, self.end)
     }
 }
 
@@ -2341,9 +2319,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     /// }
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
-        if let &RangeInclusive::NonEmpty{ref start, ref end} = self {
-            (*start <= item) && (item <= *end)
-        } else { false }
+        self.start <= item && item <= self.end
     }
 }
 
index 515f49d6f0bddc35aa41352a8675e3c8aa819572..e825acad4713e2a6973b242a0e5f11be102d266f 100644 (file)
@@ -174,7 +174,7 @@ impl<T> Option<T> {
     // Querying the contained values
     /////////////////////////////////////////////////////////////////////////
 
-    /// Returns `true` if the option is a `Some` value.
+    /// Returns `true` if the option is a [`Some`] value.
     ///
     /// # Examples
     ///
@@ -185,6 +185,8 @@ impl<T> Option<T> {
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_some(), false);
     /// ```
+    ///
+    /// [`Some`]: #variant.Some
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_some(&self) -> bool {
@@ -194,7 +196,7 @@ pub fn is_some(&self) -> bool {
         }
     }
 
-    /// Returns `true` if the option is a `None` value.
+    /// Returns `true` if the option is a [`None`] value.
     ///
     /// # Examples
     ///
@@ -205,6 +207,8 @@ pub fn is_some(&self) -> bool {
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_none(), true);
     /// ```
+    ///
+    /// [`None`]: #variant.None
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_none(&self) -> bool {
@@ -269,13 +273,14 @@ pub fn as_mut(&mut self) -> Option<&mut T> {
     // Getting to contained values
     /////////////////////////////////////////////////////////////////////////
 
-    /// Unwraps an option, yielding the content of a `Some`.
+    /// Unwraps an option, yielding the content of a [`Some`].
     ///
     /// # Panics
     ///
     /// Panics if the value is a [`None`] with a custom panic message provided by
     /// `msg`.
     ///
+    /// [`Some`]: #variant.Some
     /// [`None`]: #variant.None
     ///
     /// # Examples
@@ -298,16 +303,17 @@ pub fn expect(self, msg: &str) -> T {
         }
     }
 
-    /// Moves the value `v` out of the `Option<T>` if it is `Some(v)`.
+    /// Moves the value `v` out of the `Option<T>` if it is [`Some(v)`].
     ///
     /// In general, because this function may panic, its use is discouraged.
-    /// Instead, prefer to use pattern matching and handle the `None`
+    /// Instead, prefer to use pattern matching and handle the [`None`]
     /// case explicitly.
     ///
     /// # Panics
     ///
     /// Panics if the self value equals [`None`].
     ///
+    /// [`Some(v)`]: #variant.Some
     /// [`None`]: #variant.None
     ///
     /// # Examples
@@ -395,7 +401,9 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
     }
 
     /// Applies a function to the contained value (if any),
-    /// or returns a `default` (if not).
+    /// or returns a [`default`][] (if not).
+    ///
+    /// [`default`]: ../default/trait.Default.html#tymethod.default
     ///
     /// # Examples
     ///
@@ -416,7 +424,9 @@ pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
     }
 
     /// Applies a function to the contained value (if any),
-    /// or computes a `default` (if not).
+    /// or computes a [`default`][] (if not).
+    ///
+    /// [`default`]: ../default/trait.Default.html#tymethod.default
     ///
     /// # Examples
     ///
@@ -438,12 +448,14 @@ pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f:
         }
     }
 
-    /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
-    /// [`Ok(v)`] and `None` to [`Err(err)`][Err].
+    /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+    /// [`Ok(v)`] and [`None`] to [`Err(err)`].
     ///
     /// [`Result<T, E>`]: ../../std/result/enum.Result.html
     /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [Err]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`None`]: #variant.None
+    /// [`Some(v)`]: #variant.Some
     ///
     /// # Examples
     ///
@@ -463,12 +475,14 @@ pub fn ok_or<E>(self, err: E) -> Result<T, E> {
         }
     }
 
-    /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
-    /// [`Ok(v)`] and `None` to [`Err(err())`][Err].
+    /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+    /// [`Ok(v)`] and [`None`] to [`Err(err())`].
     ///
     /// [`Result<T, E>`]: ../../std/result/enum.Result.html
     /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [Err]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`None`]: #variant.None
+    /// [`Some(v)`]: #variant.Some
     ///
     /// # Examples
     ///
@@ -534,7 +548,9 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     // Boolean operations on the values, eager and lazy
     /////////////////////////////////////////////////////////////////////////
 
-    /// Returns `None` if the option is `None`, otherwise returns `optb`.
+    /// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
+    ///
+    /// [`None`]: #variant.None
     ///
     /// # Examples
     ///
@@ -564,11 +580,13 @@ pub fn and<U>(self, optb: Option<U>) -> Option<U> {
         }
     }
 
-    /// Returns `None` if the option is `None`, otherwise calls `f` with the
+    /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the
     /// wrapped value and returns the result.
     ///
     /// Some languages call this operation flatmap.
     ///
+    /// [`None`]: #variant.None
+    ///
     /// # Examples
     ///
     /// ```
@@ -645,9 +663,11 @@ pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
     // Entry-like operations to insert if None and return a reference
     /////////////////////////////////////////////////////////////////////////
 
-    /// Inserts `v` into the option if it is `None`, then
+    /// Inserts `v` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
+    /// [`None`]: #variant.None
+    ///
     /// # Examples
     ///
     /// ```
@@ -678,9 +698,11 @@ pub fn get_or_insert(&mut self, v: T) -> &mut T {
         }
     }
 
-    /// Inserts a value computed from `f` into the option if it is `None`, then
+    /// Inserts a value computed from `f` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
+    /// [`None`]: #variant.None
+    ///
     /// # Examples
     ///
     /// ```
@@ -715,7 +737,9 @@ pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
     // Misc
     /////////////////////////////////////////////////////////////////////////
 
-    /// Takes the value out of the option, leaving a `None` in its place.
+    /// Takes the value out of the option, leaving a [`None`] in its place.
+    ///
+    /// [`None`]: #variant.None
     ///
     /// # Examples
     ///
@@ -757,16 +781,16 @@ pub fn cloned(self) -> Option<T> {
 impl<T: Default> Option<T> {
     /// Returns the contained value or a default
     ///
-    /// Consumes the `self` argument then, if `Some`, returns the contained
-    /// value, otherwise if `None`, returns the default value for that
+    /// Consumes the `self` argument then, if [`Some`], returns the contained
+    /// value, otherwise if [`None`], returns the default value for that
     /// type.
     ///
     /// # Examples
     ///
     /// Convert a string to an integer, turning poorly-formed strings
-    /// into 0 (the default value for integers). `parse` converts
-    /// a string to any other type that implements `FromStr`, returning
-    /// `None` on error.
+    /// into 0 (the default value for integers). [`parse`] converts
+    /// a string to any other type that implements [`FromStr`], returning
+    /// [`None`] on error.
     ///
     /// ```
     /// let good_year_from_input = "1909";
@@ -777,6 +801,11 @@ impl<T: Default> Option<T> {
     /// assert_eq!(1909, good_year);
     /// assert_eq!(0, bad_year);
     /// ```
+    ///
+    /// [`Some`]: #variant.Some
+    /// [`None`]: #variant.None
+    /// [`parse`]: ../../std/primitive.str.html#method.parse
+    /// [`FromStr`]: ../../std/str/trait.FromStr.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_default(self) -> T {
@@ -801,7 +830,9 @@ fn expect_failed(msg: &str) -> ! {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Option<T> {
-    /// Returns None.
+    /// Returns [`None`].
+    ///
+    /// [`None`]: #variant.None
     #[inline]
     fn default() -> Option<T> { None }
 }
@@ -1020,8 +1051,8 @@ unsafe impl<A> TrustedLen for IntoIter<A> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
-    /// Takes each element in the `Iterator`: if it is `None`, no further
-    /// elements are taken, and the `None` is returned. Should no `None` occur, a
+    /// Takes each element in the [`Iterator`]: if it is [`None`], no further
+    /// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a
     /// container with the values of each `Option` is returned.
     ///
     /// Here is an example which increments every integer in a vector,
@@ -1037,6 +1068,9 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     /// ).collect();
     /// assert!(res == Some(vec![2, 3]));
     /// ```
+    ///
+    /// [`Iterator`]: ../iter/trait.Iterator.html
+    /// [`None`]: enum.Option.html#variant.None
     #[inline]
     fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
index 24ebfeb62e2eec23eec5fe573fa01ed819ace068..cef3682fd94d74859a69f0207b2796555520154a 100644 (file)
@@ -981,95 +981,82 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        match self {
-            ops::RangeInclusive::Empty { .. } => Some(&[]),
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get(slice),
-        }
+        if self.end == usize::max_value() { None }
+        else { (self.start..self.end + 1).get(slice) }
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        match self {
-            ops::RangeInclusive::Empty { .. } => Some(&mut []),
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_mut(slice),
-        }
+        if self.end == usize::max_value() { None }
+        else { (self.start..self.end + 1).get_mut(slice) }
     }
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &[],
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
-        }
+        (self.start..self.end + 1).get_unchecked(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &mut [],
-            ops::RangeInclusive::NonEmpty { start, end } => {
-                (start..end + 1).get_unchecked_mut(slice)
-            }
-        }
+        (self.start..self.end + 1).get_unchecked_mut(slice)
     }
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &[],
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
-                panic!("attempted to index slice up to maximum usize");
-            },
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
-        }
+        assert!(self.end != usize::max_value(),
+            "attempted to index slice up to maximum usize");
+        (self.start..self.end + 1).index(slice)
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        match self {
-            ops::RangeInclusive::Empty { .. } => &mut [],
-            ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
-                panic!("attempted to index slice up to maximum usize");
-            },
-            ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index_mut(slice),
-        }
+        assert!(self.end != usize::max_value(),
+            "attempted to index slice up to maximum usize");
+        (self.start..self.end + 1).index_mut(slice)
     }
 }
 
+#[cfg(stage0)] // The bootstrap compiler has a different `...` desugar
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+    ops::RangeInclusive { start, end }
+}
+#[cfg(not(stage0))]
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+    start...end
+}
+
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
     type Output = [T];
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        (0...self.end).get(slice)
+        inclusive(0, self.end).get(slice)
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (0...self.end).get_mut(slice)
+        inclusive(0, self.end).get_mut(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (0...self.end).get_unchecked(slice)
+        inclusive(0, self.end).get_unchecked(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).get_unchecked_mut(slice)
+        inclusive(0, self.end).get_unchecked_mut(slice)
     }
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        (0...self.end).index(slice)
+        inclusive(0, self.end).index(slice)
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).index_mut(slice)
+        inclusive(0, self.end).index_mut(slice)
     }
 }
 
index 7fb941c091fbc4fab90ed623b90ff54db4bb3142..547a4899c7118c85e9bf6ceffaaab190401ac988 100644 (file)
@@ -1724,15 +1724,12 @@ impl ops::Index<ops::RangeInclusive<usize>> for str {
 
         #[inline]
         fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
-            match index {
-                ops::RangeInclusive::Empty { .. } => "",
-                ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
-                    panic!("attempted to index slice up to maximum usize"),
-                ops::RangeInclusive::NonEmpty { start, end } =>
-                    self.index(start .. end+1)
-            }
+            assert!(index.end != usize::max_value(),
+                "attempted to index str up to maximum usize");
+            self.index(index.start .. index.end+1)
         }
     }
+
     #[unstable(feature = "inclusive_range",
                reason = "recently added, follows RFC",
                issue = "28237")]
@@ -1741,7 +1738,9 @@ impl ops::Index<ops::RangeToInclusive<usize>> for str {
 
         #[inline]
         fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
-            self.index(0...index.end)
+            assert!(index.end != usize::max_value(),
+                "attempted to index str up to maximum usize");
+            self.index(.. index.end+1)
         }
     }
 
@@ -1751,13 +1750,9 @@ fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
     impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
         #[inline]
         fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
-            match index {
-                ops::RangeInclusive::Empty { .. } => &mut self[0..0], // `&mut ""` doesn't work
-                ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
-                    panic!("attempted to index str up to maximum usize"),
-                    ops::RangeInclusive::NonEmpty { start, end } =>
-                        self.index_mut(start .. end+1)
-            }
+            assert!(index.end != usize::max_value(),
+                "attempted to index str up to maximum usize");
+            self.index_mut(index.start .. index.end+1)
         }
     }
     #[unstable(feature = "inclusive_range",
@@ -1766,7 +1761,9 @@ fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
     impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
         #[inline]
         fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
-            self.index_mut(0...index.end)
+            assert!(index.end != usize::max_value(),
+                "attempted to index str up to maximum usize");
+            self.index_mut(.. index.end+1)
         }
     }
 
@@ -1948,45 +1945,27 @@ impl SliceIndex<str> for ops::RangeInclusive<usize> {
         type Output = str;
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.get(slice)
+            (self.start..self.end+1).get(slice)
         }
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.get_mut(slice)
+            (self.start..self.end+1).get_mut(slice)
         }
         #[inline]
         unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.get_unchecked(slice)
+            (self.start..self.end+1).get_unchecked(slice)
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.get_unchecked_mut(slice)
+            (self.start..self.end+1).get_unchecked_mut(slice)
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.index(slice)
+            (self.start..self.end+1).index(slice)
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            match self {
-                ops::RangeInclusive::Empty { .. } => 0..0,
-                ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
-            }.index_mut(slice)
+            (self.start..self.end+1).index_mut(slice)
         }
     }
 
index c52155ead4f0b2774fe73db9cb4f73048a475dc4..8c4cd1d0c84583b20e961f9151c0e363686dbcac 100644 (file)
@@ -22,6 +22,7 @@
 #![feature(fmt_internals)]
 #![feature(iterator_step_by)]
 #![feature(i128_type)]
+#![feature(inclusive_range)]
 #![feature(iter_rfind)]
 #![feature(libc)]
 #![feature(nonzero)]
index 1c6c13b0d02e8b6e5417bbfbc900d4ca78f21f67..b81b3878c9d6e1d4c82a117f46107a17cf170b0b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};
 
 // Test the Range structs without the syntactic sugar.
 
@@ -47,3 +47,24 @@ fn test_full_range() {
     // Not much to test.
     let _ = RangeFull;
 }
+
+#[test]
+fn test_range_inclusive() {
+    let mut r = RangeInclusive { start: 1i8, end: 2 };
+    assert_eq!(r.next(), Some(1));
+    assert_eq!(r.next(), Some(2));
+    assert_eq!(r.next(), None);
+
+    r = RangeInclusive { start: 127i8, end: 127 };
+    assert_eq!(r.next(), Some(127));
+    assert_eq!(r.next(), None);
+
+    r = RangeInclusive { start: -128i8, end: -128 };
+    assert_eq!(r.next_back(), Some(-128));
+    assert_eq!(r.next_back(), None);
+
+    // degenerate
+    r = RangeInclusive { start: 1, end: -1 };
+    assert_eq!(r.size_hint(), (0, Some(0)));
+    assert_eq!(r.next(), None);
+}
\ No newline at end of file
index 15c4469b74694c98d3108c0002a9840329f6b53f..291d0d7c937ed6a3a15621ee013ab8952161d449 100644 (file)
@@ -108,6 +108,10 @@ pub enum DepNode<D: Clone + Debug> {
     SymbolName(D),
     SpecializationGraph(D),
     ObjectSafety(D),
+    IsCopy(D),
+    IsSized(D),
+    IsFreeze(D),
+    NeedsDrop(D),
 
     // The set of impls for a given trait. Ultimately, it would be
     // nice to get more fine-grained here (e.g., to include a
@@ -159,6 +163,7 @@ pub enum DepNode<D: Clone + Debug> {
     // not a hotspot.
     ProjectionCache { def_ids: Vec<D> },
 
+    ParamEnv(D),
     DescribeDef(D),
     DefSpan(D),
     Stability(D),
@@ -233,6 +238,10 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             // they are always absolute.
             WorkProduct(ref id) => Some(WorkProduct(id.clone())),
 
+            IsCopy(ref d) => op(d).map(IsCopy),
+            IsSized(ref d) => op(d).map(IsSized),
+            IsFreeze(ref d) => op(d).map(IsFreeze),
+            NeedsDrop(ref d) => op(d).map(NeedsDrop),
             Hir(ref d) => op(d).map(Hir),
             HirBody(ref d) => op(d).map(HirBody),
             MetaData(ref d) => op(d).map(MetaData),
@@ -284,6 +293,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
                 let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
                 def_ids.map(|d| ProjectionCache { def_ids: d })
             }
+            ParamEnv(ref d) => op(d).map(ParamEnv),
             DescribeDef(ref d) => op(d).map(DescribeDef),
             DefSpan(ref d) => op(d).map(DefSpan),
             Stability(ref d) => op(d).map(Stability),
index 8f4dce5a78303d51d2c5850fd4fceb6af612df39..d359c69d3a092842e8868c63b03d9c3fa43b9d9d 100644 (file)
@@ -1934,13 +1934,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             ExprKind::Range(ref e1, ref e2, lims) => {
                 use syntax::ast::RangeLimits::*;
 
-                let (path, variant) = match (e1, e2, lims) {
-                    (&None, &None, HalfOpen) => ("RangeFull", None),
-                    (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
-                    (&None, &Some(..), HalfOpen) => ("RangeTo", None),
-                    (&Some(..), &Some(..), HalfOpen) => ("Range", None),
-                    (&None, &Some(..), Closed) => ("RangeToInclusive", None),
-                    (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+                let path = match (e1, e2, lims) {
+                    (&None, &None, HalfOpen) => "RangeFull",
+                    (&Some(..), &None, HalfOpen) => "RangeFrom",
+                    (&None, &Some(..), HalfOpen) => "RangeTo",
+                    (&Some(..), &Some(..), HalfOpen) => "Range",
+                    (&None, &Some(..), Closed) => "RangeToInclusive",
+                    (&Some(..), &Some(..), Closed) => "RangeInclusive",
                     (_, &None, Closed) =>
                         panic!(self.diagnostic().span_fatal(
                             e.span, "inclusive range with no end")),
@@ -1957,7 +1957,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let is_unit = fields.is_empty();
                 let unstable_span = self.allow_internal_unstable("...", e.span);
                 let struct_path =
-                    iter::once("ops").chain(iter::once(path)).chain(variant)
+                    iter::once("ops").chain(iter::once(path))
                     .collect::<Vec<_>>();
                 let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
                 let struct_path = hir::QPath::Resolved(None, P(struct_path));
index 1ecc277c7ca4d27dd407cfc9ff39b1f910c5ecdb..270430f40df02d145ed68321d5c50f35d0516126 100644 (file)
@@ -161,7 +161,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // For region variables.
     region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
 
-    pub parameter_environment: ty::ParameterEnvironment<'gcx>,
+    pub param_env: ty::ParamEnv<'gcx>,
 
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
@@ -406,41 +406,41 @@ pub trait InferEnv<'a, 'tcx> {
     fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>);
+                    Option<ty::ParamEnv<'tcx>>);
 }
 
 impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
+                    Option<ty::ParamEnv<'tcx>>) {
         (None, None, None)
     }
 }
 
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParamEnv<'tcx> {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
+                    Option<ty::ParamEnv<'tcx>>) {
         (None, None, Some(self))
     }
 }
 
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
+                    Option<ty::ParamEnv<'tcx>>) {
         (Some(self.0), None, Some(self.1))
     }
 }
 
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
+                    Option<ty::ParamEnv<'tcx>>) {
         (None, Some(self.0), Some(self.1))
     }
 }
@@ -449,11 +449,11 @@ impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
     fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
                     Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
+                    Option<ty::ParamEnv<'tcx>>) {
         let def_id = tcx.hir.body_owner_def_id(self);
         (Some(tcx.typeck_tables_of(def_id)),
          None,
-         Some(tcx.parameter_environment(def_id)))
+         Some(tcx.param_env(def_id)))
     }
 }
 
@@ -465,7 +465,7 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     arena: DroplessArena,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
     tables: Option<&'a ty::TypeckTables<'gcx>>,
-    param_env: Option<ty::ParameterEnvironment<'gcx>>,
+    param_env: Option<ty::ParamEnv<'gcx>>,
     projection_mode: Reveal,
 }
 
@@ -498,7 +498,7 @@ pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
             int_unification_table: RefCell::new(UnificationTable::new()),
             float_unification_table: RefCell::new(UnificationTable::new()),
             region_vars: RegionVarBindings::new(self),
-            parameter_environment: param_env.unwrap(),
+            param_env: param_env.unwrap(),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             projection_cache: RefCell::new(traits::ProjectionCache::new()),
@@ -526,9 +526,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
         let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
             fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
         });
-        let param_env = param_env.take().unwrap_or_else(|| {
-            global_tcx.empty_parameter_environment()
-        });
+        let param_env = param_env.take().unwrap_or_else(|| ty::ParamEnv::empty());
         global_tcx.enter_local(arena, |tcx| f(InferCtxt {
             tcx: tcx,
             tables: tables,
@@ -537,7 +535,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
             int_unification_table: RefCell::new(UnificationTable::new()),
             float_unification_table: RefCell::new(UnificationTable::new()),
             region_vars: RegionVarBindings::new(tcx),
-            parameter_environment: param_env,
+            param_env: param_env,
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             reported_trait_errors: RefCell::new(FxHashSet()),
@@ -650,7 +648,7 @@ pub fn normalize_associated_type<T>(self, value: &T) -> T
     }
 
     pub fn normalize_associated_type_in_env<T>(
-        self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
+        self, value: &T, env: ty::ParamEnv<'tcx>
     ) -> T
         where T: TransNormalize<'tcx>
     {
@@ -662,7 +660,7 @@ pub fn normalize_associated_type_in_env<T>(
             return value;
         }
 
-        self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
+        self.infer_ctxt(env, Reveal::All).enter(|infcx| {
             value.trans_normalize(&infcx)
        })
     }
@@ -1674,8 +1672,8 @@ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'t
         self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
     }
 
-    pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
-        &self.parameter_environment
+    pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
+        self.param_env
     }
 
     pub fn closure_kind(&self,
index f32ee7900646b0e4f1c82e9b415362e85dbc533d..2b4b5cc73337b7306dc5d6a9d3c3bda7ce9fd7a9 100644 (file)
@@ -30,7 +30,6 @@
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![feature(libc)]
-#![feature(loop_break_value)]
 #![feature(never_type)]
 #![feature(nonzero)]
 #![feature(quote)]
@@ -45,6 +44,7 @@
 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![cfg_attr(stage0, feature(rustc_private))]
 #![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
 
 #![recursion_limit="128"]
 
index ff72f9dd07e36096819e2244644099a136cc63c4..c49df4b1ad9ea8bd6f564ccb08a9eb546a3cea44 100644 (file)
@@ -418,16 +418,16 @@ before, and hence the cache lookup would succeed, yielding
 One subtle interaction is that the results of trait lookup will vary
 depending on what where clauses are in scope. Therefore, we actually
 have *two* caches, a local and a global cache. The local cache is
-attached to the `ParameterEnvironment` and the global cache attached
-to the `tcx`. We use the local cache whenever the result might depend
-on the where clauses that are in scope. The determination of which
-cache to use is done by the method `pick_candidate_cache` in
-`select.rs`. At the moment, we use a very simple, conservative rule:
-if there are any where-clauses in scope, then we use the local cache.
-We used to try and draw finer-grained distinctions, but that led to a
-serious of annoying and weird bugs like #22019 and #18290. This simple
-rule seems to be pretty clearly safe and also still retains a very
-high hit rate (~95% when compiling rustc).
+attached to the `ParamEnv` and the global cache attached to the
+`tcx`. We use the local cache whenever the result might depend on the
+where clauses that are in scope. The determination of which cache to
+use is done by the method `pick_candidate_cache` in `select.rs`. At
+the moment, we use a very simple, conservative rule: if there are any
+where-clauses in scope, then we use the local cache.  We used to try
+and draw finer-grained distinctions, but that led to a serious of
+annoying and weird bugs like #22019 and #18290. This simple rule seems
+to be pretty clearly safe and also still retains a very high hit rate
+(~95% when compiling rustc).
 
 # Specialization
 
index 152e3353994b3b32315d8591d4e482f2792b461d..3c7761c6cd3bcf338373f2a5c278e5af96666048 100644 (file)
@@ -559,6 +559,23 @@ pub fn report_selection_error(&self,
                             trait_ref.to_predicate(),
                             post_message);
 
+                        let unimplemented_note = self.on_unimplemented_note(trait_ref, obligation);
+                        if let Some(ref s) = unimplemented_note {
+                            // If it has a custom "#[rustc_on_unimplemented]"
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&format!("{}the trait `{}` is not implemented for `{}`",
+                                              pre_message,
+                                              trait_ref,
+                                              trait_ref.self_ty()));
+                        } else {
+                            err.span_label(span,
+                                           &*format!("{}the trait `{}` is not implemented for `{}`",
+                                                     pre_message,
+                                                     trait_ref,
+                                                     trait_ref.self_ty()));
+                        }
+
                         // Try to report a help message
                         if !trait_ref.has_infer_types() &&
                             self.predicate_can_apply(trait_ref) {
@@ -571,21 +588,12 @@ pub fn report_selection_error(&self,
                             // which is somewhat confusing.
                             err.help(&format!("consider adding a `where {}` bound",
                                                 trait_ref.to_predicate()));
-                        } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) {
-                            // If it has a custom "#[rustc_on_unimplemented]"
-                            // error message, let's display it!
-                            err.note(&s);
-                        } else {
+                        } else if unimplemented_note.is_none() {
                             // Can't show anything else useful, try to find similar impls.
                             let impl_candidates = self.find_similar_impl_candidates(trait_ref);
                             self.report_similar_impl_candidates(impl_candidates, &mut err);
                         }
 
-                        err.span_label(span,
-                                       format!("{}the trait `{}` is not implemented for `{}`",
-                                                pre_message,
-                                                trait_ref,
-                                                trait_ref.self_ty()));
                         err
                     }
 
index 1823373348badfb8ef177602d852f4ed29ff0217..e358f39bd9a3a1356fb2130b3ea15cb1b382bcb9 100644 (file)
@@ -437,9 +437,9 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
 /// Normalizes the parameter environment, reporting errors if they occur.
 pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               region_context: DefId,
-                                              unnormalized_env: ty::ParameterEnvironment<'tcx>,
+                                              unnormalized_env: ty::ParamEnv<'tcx>,
                                               cause: ObligationCause<'tcx>)
-                                              -> ty::ParameterEnvironment<'tcx>
+                                              -> ty::ParamEnv<'tcx>
 {
     // I'm not wild about reporting errors here; I'd prefer to
     // have the errors get reported at a defined place (e.g.,
@@ -477,15 +477,15 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
            predicates);
 
-    let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
+    let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
 
     tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
         let predicates = match fully_normalize(
                 &infcx, cause,
-                // You would really want to pass infcx.parameter_environment.caller_bounds here,
+                // You would really want to pass infcx.param_env.caller_bounds here,
                 // but that is an interned slice, and fully_normalize takes &T and returns T, so
                 // without further refactoring, a slice can't be used. Luckily, we still have the
-                // predicate vector from which we created the ParameterEnvironment in infcx, so we
+                // predicate vector from which we created the ParamEnv in infcx, so we
                 // can pass that instead. It's roundabout and a bit brittle, but this code path
                 // ought to be refactored anyway, and until then it saves us from having to copy.
                 &predicates,
@@ -494,7 +494,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             Err(errors) => {
                 infcx.report_fulfillment_errors(&errors);
                 // An unnormalized env is better than nothing.
-                return infcx.parameter_environment;
+                return infcx.param_env;
             }
         };
 
@@ -516,19 +516,19 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // all things considered.
                 tcx.sess.span_err(span, &fixup_err.to_string());
                 // An unnormalized env is better than nothing.
-                return infcx.parameter_environment;
+                return infcx.param_env;
             }
         };
 
         let predicates = match tcx.lift_to_global(&predicates) {
             Some(predicates) => predicates,
-            None => return infcx.parameter_environment
+            None => return infcx.param_env
         };
 
         debug!("normalize_param_env_or_error: resolved predicates={:?}",
             predicates);
 
-        infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates))
     })
 }
 
index cccc20e5b296bd692fdd23ec52144512fd942582..7366ed45f31bd514f96279377cbd36433dfe1e26 100644 (file)
@@ -315,7 +315,7 @@ pub fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
+    pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
         self.infcx.param_env()
     }
 
index 0e5779f9d17935b291fc1d72aec74fd879166c0f..e0f28e3b49e919832a56b8bc738e0b2f6d983fe2 100644 (file)
@@ -180,7 +180,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     // create a parameter environment corresponding to a (skolemized) instantiation of impl1
-    let penv = tcx.parameter_environment(impl1_def_id);
+    let penv = tcx.param_env(impl1_def_id);
     let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
 
     // Create a infcx, taking the predicates of impl1 as assumptions:
@@ -250,7 +250,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                        source_trait_ref,
                        target_trait_ref,
                        errors,
-                       infcx.parameter_environment.caller_bounds);
+                       infcx.param_env.caller_bounds);
                 Err(())
             }
 
index b9355c264b3ef49d85c7f1d392645d7b3c6ef3ee..5ee0b1c9e5ea44ba421bc9a29b03e29e84135709 100644 (file)
@@ -138,7 +138,7 @@ fn intern_ty(&self, st: TypeVariants<'tcx>,
             let flags = super::flags::FlagComputation::for_sty(&st);
             let ty_struct = TyS {
                 sty: st,
-                flags: Cell::new(flags.flags),
+                flags: flags.flags,
                 region_depth: flags.depth,
             };
 
@@ -978,8 +978,8 @@ pub fn go(tcx: TyCtxt) {
                         ty::TyError => /* unimportant */ continue,
                         $(ty::$variant(..) => &mut $variant,)*
                     };
-                    let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
-                    let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
+                    let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+                    let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
 
                     variant.total += 1;
                     total.total += 1;
index 686b99ba680942eb734f8c1578b7ca648d849eac..46afa6ee7d011d48053d892c02cd4cdc1ec65b83 100644 (file)
@@ -167,7 +167,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
     }
 
     fn add_ty(&mut self, ty: Ty) {
-        self.add_flags(ty.flags.get());
+        self.add_flags(ty.flags);
         self.add_depth(ty.region_depth);
     }
 
index 6de3c018bda0ebe8223760d6d7eb282553712540..c17a54f4f69bbb98717992d487c0d0c8a1e7afba 100644 (file)
@@ -625,9 +625,8 @@ struct HasTypeFlagsVisitor {
 
 impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
     fn visit_ty(&mut self, t: Ty) -> bool {
-        let flags = t.flags.get();
-        debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, flags, self.flags);
-        flags.intersects(self.flags)
+        debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags, self.flags);
+        t.flags.intersects(self.flags)
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
index bd38a6c3fd39a6edad843f3053b95fe8b4325ea4..1a8c74ff1f94323db427711be1617d01c1100a48 100644 (file)
@@ -1079,7 +1079,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
         let ptr_layout = |pointee: Ty<'gcx>| {
             let non_zero = !ty.is_unsafe_ptr();
             let pointee = infcx.normalize_projections(pointee);
-            if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
+            if pointee.is_sized(tcx, infcx.param_env, DUMMY_SP) {
                 Ok(Scalar { value: Pointer, non_zero: non_zero })
             } else {
                 let unsized_part = tcx.struct_tail(pointee);
@@ -1268,11 +1268,11 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
                         StructKind::AlwaysSizedUnivariant
                     } else {
-                        let param_env = tcx.parameter_environment(def.did);
+                        let param_env = tcx.param_env(def.did);
                         let fields = &def.variants[0].fields;
                         let last_field = &fields[fields.len()-1];
                         let always_sized = tcx.type_of(last_field.did)
-                          .is_sized(tcx, &param_env, DUMMY_SP);
+                          .is_sized(tcx, param_env, DUMMY_SP);
                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
                         else { StructKind::AlwaysSizedUnivariant }
                     };
index 85462bd9b1273ca2a40946ace10c0355abcb9212..fb352e5be89383c4743522ba1abe85ab54217aea 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use hir::def::Def;
 use hir;
 use middle::const_val;
@@ -136,6 +136,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
+impl<'tcx, T: Clone + Hash + Eq + Debug> Key for ty::ParamEnvAnd<'tcx, T> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 trait Value<'tcx>: Sized {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
 }
@@ -244,6 +253,30 @@ impl<M: DepTrackingMapConfig<Key=DefId>> QueryDescription for M {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is `Copy`", env.value)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is `Sized`", env.value)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` is freeze", env.value)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
+    fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+        format!("computing whether `{}` needs drop", env.value)
+    }
+}
+
 impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
     fn describe(tcx: TyCtxt, def_id: DefId) -> String {
         format!("computing the supertraits of `{}`",
@@ -856,6 +889,15 @@ fn default() -> Self {
         -> ty::trait_def::TraitImpls,
     [] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
     [] is_object_safe: ObjectSafety(DefId) -> bool,
+
+    [] param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
+
+    // Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
+    // `ty.is_copy()`, etc, since that will prune the environment where possible.
+    [] is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+    [] is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+    [] is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+    [] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
 }
 
 fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -899,3 +941,27 @@ fn crate_variances(_: CrateNum) -> DepNode<DefId> {
 fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
     DepNode::TraitImpls(def_id)
 }
+
+fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+        .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+    DepNode::IsCopy(def_id)
+}
+
+fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+        .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+    DepNode::IsSized(def_id)
+}
+
+fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+        .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+    DepNode::IsFreeze(def_id)
+}
+
+fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+    let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+        .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+    DepNode::NeedsDrop(def_id)
+}
index 359722ce96ec9786f0131c197805fac38806bfe7..fa731f6dde638f6fb97f3ff4acf282ad5e5239c9 100644 (file)
@@ -35,7 +35,6 @@
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
 
 use serialize::{self, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
 use std::collections::BTreeMap;
 use std::cmp;
 use std::fmt;
@@ -503,22 +502,12 @@ pub enum FragmentInfo {
                                   TypeFlags::HAS_TY_CLOSURE.bits |
                                   TypeFlags::HAS_LOCAL_NAMES.bits |
                                   TypeFlags::KEEP_IN_LOCAL_TCX.bits,
-
-        // Caches for type_is_sized, type_moves_by_default
-        const SIZEDNESS_CACHED  = 1 << 16,
-        const IS_SIZED          = 1 << 17,
-        const MOVENESS_CACHED   = 1 << 18,
-        const MOVES_BY_DEFAULT  = 1 << 19,
-        const FREEZENESS_CACHED = 1 << 20,
-        const IS_FREEZE         = 1 << 21,
-        const NEEDS_DROP_CACHED = 1 << 22,
-        const NEEDS_DROP        = 1 << 23,
     }
 }
 
 pub struct TyS<'tcx> {
     pub sty: TypeVariants<'tcx>,
-    pub flags: Cell<TypeFlags>,
+    pub flags: TypeFlags,
 
     // the maximal depth of any bound regions appearing in this type.
     region_depth: u32,
@@ -1249,46 +1238,58 @@ pub fn is_empty(&self) -> bool {
     }
 }
 
-/// When type checking, we use the `ParameterEnvironment` to track
-/// details about the type/lifetime parameters that are in scope.
-/// It primarily stores the bounds information.
-///
-/// Note: This information might seem to be redundant with the data in
-/// `tcx.ty_param_defs`, but it is not. That table contains the
-/// parameter definitions from an "outside" perspective, but this
-/// struct will contain the bounds for a parameter as seen from inside
-/// the function body. Currently the only real distinction is that
-/// bound lifetime parameters are replaced with free ones, but in the
-/// future I hope to refine the representation of types so as to make
-/// more distinctions clearer.
-#[derive(Clone)]
-pub struct ParameterEnvironment<'tcx> {
+/// When type checking, we use the `ParamEnv` to track
+/// details about the set of where-clauses that are in scope at this
+/// particular point.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnv<'tcx> {
     /// Obligations that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
     /// into Obligations, and elaborated and normalized.
-    pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
-
-    /// A cache for `moves_by_default`.
-    pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+    pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
+}
 
-    /// A cache for `type_is_sized`
-    pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+impl<'tcx> ParamEnv<'tcx> {
+    /// Creates a suitable environment in which to perform trait
+    /// queries on the given value. This will either be `self` *or*
+    /// the empty environment, depending on whether `value` references
+    /// type parameters that are in scope. (If it doesn't, then any
+    /// judgements should be completely independent of the context,
+    /// and hence we can safely use the empty environment so as to
+    /// enable more sharing across functions.)
+    ///
+    /// NB: This is a mildly dubious thing to do, in that a function
+    /// (or other environment) might have wacky where-clauses like
+    /// `where Box<u32>: Copy`, which are clearly never
+    /// satisfiable. The code will at present ignore these,
+    /// effectively, when type-checking the body of said
+    /// function. This preserves existing behavior in any
+    /// case. --nmatsakis
+    pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+        assert!(!value.needs_infer());
+        if value.has_param_types() || value.has_self_ty() {
+            ParamEnvAnd {
+                param_env: self,
+                value: value,
+            }
+        } else {
+            ParamEnvAnd {
+                param_env: ParamEnv::empty(),
+                value: value,
+            }
+        }
+    }
+}
 
-    /// A cache for `type_is_freeze`
-    pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnvAnd<'tcx, T> {
+    pub param_env: ParamEnv<'tcx>,
+    pub value: T,
 }
 
-impl<'a, 'tcx> ParameterEnvironment<'tcx> {
-    pub fn with_caller_bounds(&self,
-                              caller_bounds: &'tcx [ty::Predicate<'tcx>])
-                              -> ParameterEnvironment<'tcx>
-    {
-        ParameterEnvironment {
-            caller_bounds: caller_bounds,
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        }
+impl<'tcx, T> ParamEnvAnd<'tcx, T> {
+    pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
+        (self.param_env, self.value)
     }
 }
 
@@ -2357,54 +2358,6 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         }
     }
 
-    /// Construct a parameter environment suitable for static contexts or other contexts where there
-    /// are no free type/lifetime parameters in scope.
-    pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
-        ty::ParameterEnvironment {
-            caller_bounds: Slice::empty(),
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        }
-    }
-
-    /// See `ParameterEnvironment` struct def'n for details.
-    pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
-        //
-        // Compute the bounds on Self and the type parameters.
-        //
-
-        let tcx = self.global_tcx();
-        let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
-        let predicates = bounds.predicates;
-
-        // Finally, we have to normalize the bounds in the environment, in
-        // case they contain any associated type projections. This process
-        // can yield errors if the put in illegal associated types, like
-        // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
-        // report these errors right here; this doesn't actually feel
-        // right to me, because constructing the environment feels like a
-        // kind of a "idempotent" action, but I'm not sure where would be
-        // a better place. In practice, we construct environments for
-        // every fn once during type checking, and we'll abort if there
-        // are any errors at that point, so after type checking you can be
-        // sure that this will succeed without errors anyway.
-        //
-
-        let unnormalized_env = ty::ParameterEnvironment {
-            caller_bounds: tcx.intern_predicates(&predicates),
-            is_copy_cache: RefCell::new(FxHashMap()),
-            is_sized_cache: RefCell::new(FxHashMap()),
-            is_freeze_cache: RefCell::new(FxHashMap()),
-        };
-
-        let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
-            self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
-        });
-        let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
-        traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
-    }
-
     pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
         self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
     }
@@ -2564,14 +2517,45 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
         })
 }
 
+/// See `ParamEnv` struct def'n for details.
+fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   def_id: DefId)
+                                   -> ParamEnv<'tcx> {
+    // Compute the bounds on Self and the type parameters.
+
+    let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
+    let predicates = bounds.predicates;
+
+    // Finally, we have to normalize the bounds in the environment, in
+    // case they contain any associated type projections. This process
+    // can yield errors if the put in illegal associated types, like
+    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+    // report these errors right here; this doesn't actually feel
+    // right to me, because constructing the environment feels like a
+    // kind of a "idempotent" action, but I'm not sure where would be
+    // a better place. In practice, we construct environments for
+    // every fn once during type checking, and we'll abort if there
+    // are any errors at that point, so after type checking you can be
+    // sure that this will succeed without errors anyway.
+
+    let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
+
+    let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+        tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+    });
+    let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+    traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
 
 pub fn provide(providers: &mut ty::maps::Providers) {
+    util::provide(providers);
     *providers = ty::maps::Providers {
         associated_item,
         associated_item_def_ids,
         adt_sized_constraint,
         adt_dtorck_constraint,
         def_span,
+        param_env,
         trait_of_item,
         trait_impls_of: trait_def::trait_impls_of_provider,
         relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
@@ -2585,6 +2569,7 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
         adt_dtorck_constraint,
         trait_impls_of: trait_def::trait_impls_of_provider,
         relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
+        param_env,
         ..*providers
     };
 }
index c6c6a0e47003dbb40777d056b2ade638c6259eb7..01fed11fc97affd7e8ad22cb0f275e7b5ec1faef 100644 (file)
 use infer::InferCtxt;
 use ich::{StableHashingContext, NodeIdHashingMode};
 use traits::{self, Reveal};
-use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
-use ty::ParameterEnvironment;
+use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::TypeVisitor;
 use ty::layout::{Layout, LayoutError};
 use ty::subst::{Subst, Kind};
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
-use util::nodemap::{FxHashMap, FxHashSet};
 use middle::lang_items;
 
 use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
-use std::cell::RefCell;
 use std::cmp;
 use std::hash::Hash;
 use std::intrinsics;
@@ -36,8 +33,6 @@
 use syntax::attr::{self, SignedInt, UnsignedInt};
 use syntax_pos::{Span, DUMMY_SP};
 
-use hir;
-
 type Disr = ConstInt;
 
 pub trait IntTypeExt {
@@ -152,7 +147,18 @@ pub enum Representability {
     SelfRecursive(Vec<Span>),
 }
 
-impl<'tcx> ParameterEnvironment<'tcx> {
+impl<'tcx> ty::ParamEnv<'tcx> {
+    /// Construct a trait environment suitable for contexts where
+    /// there are no where clauses in scope.
+    pub fn empty() -> Self {
+        Self::new(ty::Slice::empty())
+    }
+
+    /// Construct a trait environment with the given set of predicates.
+    pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>) -> Self {
+        ty::ParamEnv { caller_bounds }
+    }
+
     pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(), CopyImplementationError> {
@@ -711,152 +717,28 @@ fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, x: &ty::Binder<T>) -> bool {
 }
 
 impl<'a, 'tcx> ty::TyS<'tcx> {
-    fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                   param_env: &ParameterEnvironment<'tcx>,
-                   def_id: DefId,
-                   cache: &RefCell<FxHashMap<Ty<'tcx>, bool>>,
-                   span: Span) -> bool
-    {
-        if self.has_param_types() || self.has_self_ty() {
-            if let Some(result) = cache.borrow().get(self) {
-                return *result;
-            }
-        }
-        let result =
-            tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing)
-            .enter(|infcx| {
-                traits::type_known_to_meet_bound(&infcx, self, def_id, span)
-            });
-        if self.has_param_types() || self.has_self_ty() {
-            cache.borrow_mut().insert(self, result);
-        }
-        return result;
-    }
-
-    // FIXME (@jroesch): I made this public to use it, not sure if should be private
-    pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            param_env: &ParameterEnvironment<'tcx>,
-                            span: Span) -> bool {
-        if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
-        }
-
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
-            TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
-                mutbl: hir::MutImmutable, ..
-            }) => Some(false),
-
-            TyStr | TyRef(_, TypeAndMut {
-                mutbl: hir::MutMutable, ..
-            }) => Some(true),
-
-            TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
-            TyClosure(..) | TyAdt(..) | TyAnon(..) |
-            TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
-        }.unwrap_or_else(|| {
-            !self.impls_bound(tcx, param_env,
-                              tcx.require_lang_item(lang_items::CopyTraitLangItem),
-                              &param_env.is_copy_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
-            } else {
-                TypeFlags::MOVENESS_CACHED
-            });
-        }
-
-        result
+    pub fn moves_by_default(&'tcx self,
+                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            param_env: ty::ParamEnv<'tcx>,
+                            span: Span)
+                            -> bool {
+        !tcx.at(span).is_copy_raw(param_env.and(self))
     }
 
-    #[inline]
-    pub fn is_sized(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    param_env: &ParameterEnvironment<'tcx>,
-                    span: Span) -> bool
+    pub fn is_sized(&'tcx self,
+                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    param_env: ty::ParamEnv<'tcx>,
+                    span: Span)-> bool
     {
-        if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::IS_SIZED);
-        }
-
-        self.is_sized_uncached(tcx, param_env, span)
-    }
-
-    fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                         param_env: &ParameterEnvironment<'tcx>,
-                         span: Span) -> bool {
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
-            TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
-
-            TyStr | TyDynamic(..) | TySlice(_) => Some(false),
-
-            TyAdt(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyAnon(..) | TyError => None
-        }.unwrap_or_else(|| {
-            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                              &param_env.is_sized_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
-            } else {
-                TypeFlags::SIZEDNESS_CACHED
-            });
-        }
-
-        result
+        tcx.at(span).is_sized_raw(param_env.and(self))
     }
 
-    /// Returns `true` if and only if there are no `UnsafeCell`s
-    /// nested within the type (ignoring `PhantomData` or pointers).
-    #[inline]
-    pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                     param_env: &ParameterEnvironment<'tcx>,
-                     span: Span) -> bool
+    pub fn is_freeze(&'tcx self,
+                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                     param_env: ty::ParamEnv<'tcx>,
+                     span: Span)-> bool
     {
-        if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
-            return self.flags.get().intersects(TypeFlags::IS_FREEZE);
-        }
-
-        self.is_freeze_uncached(tcx, param_env, span)
-    }
-
-    fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          param_env: &ParameterEnvironment<'tcx>,
-                          span: Span) -> bool {
-        assert!(!self.needs_infer());
-
-        // Fast-path for primitive types
-        let result = match self.sty {
-            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
-            TyStr | TyNever => Some(true),
-
-            TyArray(..) | TySlice(_) |
-            TyTuple(..) | TyClosure(..) | TyAdt(..) |
-            TyDynamic(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyAnon(..) | TyError => None
-        }.unwrap_or_else(|| {
-            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
-                              &param_env.is_freeze_cache, span) });
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
-            } else {
-                TypeFlags::FREEZENESS_CACHED
-            });
-        }
-
-        result
+        tcx.at(span).is_freeze_raw(param_env.and(self))
     }
 
     /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
@@ -866,112 +748,11 @@ fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     /// (Note that this implies that if `ty` has a destructor attached,
     /// then `needs_drop` will definitely return `true` for `ty`.)
     #[inline]
-    pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
-        if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
-            return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
-        }
-
-        self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
-    }
-
-    fn needs_drop_inner(&'tcx self,
-                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: &ty::ParameterEnvironment<'tcx>,
-                        stack: &mut FxHashSet<Ty<'tcx>>)
-                        -> bool {
-        if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
-            return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
-        }
-
-        // This should be reported as an error by `check_representable`.
-        //
-        // Consider the type as not needing drop in the meanwhile to avoid
-        // further errors.
-        if let Some(_) = stack.replace(self) {
-            return false;
-        }
-
-        let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
-
-        // "Pop" the cycle detection "stack".
-        stack.remove(self);
-
-        needs_drop
-    }
-
-    fn needs_drop_uncached(&'tcx self,
-                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           param_env: &ty::ParameterEnvironment<'tcx>,
-                           stack: &mut FxHashSet<Ty<'tcx>>)
-                           -> bool {
-        assert!(!self.needs_infer());
-
-        let result = match self.sty {
-            // Fast-path for primitive types
-            ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
-            ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
-            ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
-            ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
-
-            // Issue #22536: We first query type_moves_by_default.  It sees a
-            // normalized version of the type, and therefore will definitely
-            // know whether the type implements Copy (and thus needs no
-            // cleanup/drop/zeroing) ...
-            _ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
-
-            // ... (issue #22536 continued) but as an optimization, still use
-            // prior logic of asking for the structural "may drop".
-
-            // FIXME(#22815): Note that this is a conservative heuristic;
-            // it may report that the type "may drop" when actual type does
-            // not actually have a destructor associated with it. But since
-            // the type absolutely did not have the `Copy` bound attached
-            // (see above), it is sound to treat it as having a destructor.
-
-            // User destructors are the only way to have concrete drop types.
-            ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
-
-            // Can refer to a type which may drop.
-            // FIXME(eddyb) check this against a ParameterEnvironment.
-            ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
-            ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
-
-            // Structural recursion.
-            ty::TyArray(ty, _) | ty::TySlice(ty) => {
-                ty.needs_drop_inner(tcx, param_env, stack)
-            }
-
-            ty::TyClosure(def_id, ref substs) => {
-                substs.upvar_tys(def_id, tcx)
-                    .any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
-            }
-
-            ty::TyTuple(ref tys, _) => {
-                tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
-            }
-
-            // unions don't have destructors regardless of the child types
-            ty::TyAdt(def, _) if def.is_union() => false,
-
-            ty::TyAdt(def, substs) => {
-                def.variants.iter().any(|v| {
-                    v.fields.iter().any(|f| {
-                        f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
-                    })
-                })
-            }
-        };
-
-        if !self.has_param_types() && !self.has_self_ty() {
-            self.flags.set(self.flags.get() | if result {
-                TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
-            } else {
-                TypeFlags::NEEDS_DROP_CACHED
-            });
-        }
-
-        result
+    pub fn needs_drop(&'tcx self,
+                      tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                      param_env: ty::ParamEnv<'tcx>)
+                      -> bool {
+        tcx.needs_drop_raw(param_env.and(self))
     }
 
     #[inline]
@@ -1158,3 +939,112 @@ fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         r
     }
 }
+
+fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                         -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                          -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                           -> bool
+{
+    let (param_env, ty) = query.into_parts();
+    let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
+    tcx.infer_ctxt(param_env, Reveal::UserFacing)
+       .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                            -> bool
+{
+    let (param_env, ty) = query.into_parts();
+
+    let needs_drop = |ty: Ty<'tcx>| -> bool {
+        match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
+            Ok(v) => v,
+            Err(_) => {
+                // Cycles should be reported as an error by `check_representable`.
+                //
+                // Consider the type as not needing drop in the meanwhile to avoid
+                // further errors.
+                false
+            }
+        }
+    };
+
+    assert!(!ty.needs_infer());
+
+    match ty.sty {
+        // Fast-path for primitive types
+        ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
+        ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
+        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+        ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
+
+        // Issue #22536: We first query type_moves_by_default.  It sees a
+        // normalized version of the type, and therefore will definitely
+        // know whether the type implements Copy (and thus needs no
+        // cleanup/drop/zeroing) ...
+        _ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false,
+
+        // ... (issue #22536 continued) but as an optimization, still use
+        // prior logic of asking for the structural "may drop".
+
+        // FIXME(#22815): Note that this is a conservative heuristic;
+        // it may report that the type "may drop" when actual type does
+        // not actually have a destructor associated with it. But since
+        // the type absolutely did not have the `Copy` bound attached
+        // (see above), it is sound to treat it as having a destructor.
+
+        // User destructors are the only way to have concrete drop types.
+        ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
+
+        // Can refer to a type which may drop.
+        // FIXME(eddyb) check this against a ParamEnv.
+        ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
+        ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
+
+        // Structural recursion.
+        ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty),
+
+        ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
+
+        ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
+
+        // unions don't have destructors regardless of the child types
+        ty::TyAdt(def, _) if def.is_union() => false,
+
+        ty::TyAdt(def, substs) =>
+            def.variants.iter().any(
+                |variant| variant.fields.iter().any(
+                    |field| needs_drop(field.ty(tcx, substs)))),
+    }
+}
+
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        is_copy_raw,
+        is_sized_raw,
+        is_freeze_raw,
+        needs_drop_raw,
+        ..*providers
+    };
+}
index 8ca699339d36ecedca7a92a3e785b51fffb248bf..340e4f2cfccbcdba96cacd9f1e35f786fcfad6e3 100644 (file)
@@ -504,13 +504,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
-    }
-}
-
-impl<'tcx> fmt::Display for ty::RegionKind {
+impl fmt::Display for ty::RegionKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if verbose() {
             return write!(f, "{:?}", *self);
index eeb5a3fb957fa481f7a2ad4dc15f80b77f529950..722ec6424fecec3dc9c0393b1df4989b022e16f2 100644 (file)
@@ -90,7 +90,7 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> {
     dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
     move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
     all_loans: &'a [Loan<'tcx>],
-    param_env: &'a ty::ParameterEnvironment<'tcx>,
+    param_env: &'a ty::ParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
@@ -197,7 +197,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         dfcx_loans: dfcx_loans,
         move_data: move_data,
         all_loans: all_loans,
-        param_env: &infcx.parameter_environment
+        param_env: &infcx.param_env
     };
     euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx).consume_body(body);
 }
index 520a90d940b3912d292448891e569244063cefef..e0d86ff23f8621a6aae97415ee2919e2990055f8 100644 (file)
@@ -44,8 +44,8 @@ fn run_pass<'a, 'tcx>(&self,
             _ => return
         }
         let id = src.item_id();
-        let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
-        let move_data = MoveData::gather_moves(mir, tcx, &param_env);
+        let param_env = tcx.param_env(tcx.hir.local_def_id(id));
+        let move_data = MoveData::gather_moves(mir, tcx, param_env);
         let elaborate_patch = {
             let mir = &*mir;
             let env = MoveDataParamEnv {
@@ -196,7 +196,7 @@ fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
         self.ctxt.tcx
     }
 
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.ctxt.param_env()
     }
 
@@ -289,8 +289,9 @@ struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
 
 impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
-    fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
-        &self.env.param_env
+
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.env.param_env
     }
 
     fn initialization_data_at(&self, loc: Location) -> InitializationData {
index ed5e539f245f10fb2280d4821e8bf39f38166796..931cdf4f6861208d048fad342af8256c502ae442 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-use rustc::ty::{self, TyCtxt, ParameterEnvironment};
+use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::{IndexVec};
@@ -191,7 +191,7 @@ pub struct MovePathLookup<'tcx> {
 struct MoveDataBuilder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: &'a ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     data: MoveData<'tcx>,
 }
 
@@ -203,7 +203,7 @@ pub enum MovePathError {
 impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     fn new(mir: &'a Mir<'tcx>,
            tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: &'a ParameterEnvironment<'tcx>)
+           param_env: ty::ParamEnv<'tcx>)
            -> Self {
         let mut move_paths = IndexVec::new();
         let mut path_map = IndexVec::new();
@@ -370,7 +370,7 @@ pub fn find(&self, lval: &Lvalue<'tcx>) -> LookupResult {
 impl<'a, 'tcx> MoveData<'tcx> {
     pub fn gather_moves(mir: &Mir<'tcx>,
                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: &ParameterEnvironment<'tcx>)
+                        param_env: ty::ParamEnv<'tcx>)
                         -> Self {
         gather_moves(mir, tcx, param_env)
     }
@@ -378,7 +378,7 @@ pub fn gather_moves(mir: &Mir<'tcx>,
 
 fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          param_env: &ParameterEnvironment<'tcx>)
+                          param_env: ty::ParamEnv<'tcx>)
                           -> MoveData<'tcx> {
     let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
 
index fbaa60f84450b26f4596bb99728af967f47344ba..2eb064305e87c0626999e4951acf956089148332 100644 (file)
@@ -51,7 +51,7 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem>
 
 pub struct MoveDataParamEnv<'tcx> {
     move_data: MoveData<'tcx>,
-    param_env: ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
 }
 
 pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
@@ -65,8 +65,8 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     // steals it, but it forces the `borrowck` query.
     let mir = &tcx.mir_validated(def_id).borrow();
 
-    let param_env = tcx.parameter_environment(def_id);
-    let move_data = MoveData::gather_moves(mir, tcx, &param_env);
+    let param_env = tcx.param_env(def_id);
+    let move_data = MoveData::gather_moves(mir, tcx, param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let flow_inits =
@@ -325,7 +325,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
         let ty = lvalue.ty(mir, tcx).to_ty(tcx);
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
 
-        if ty.needs_drop(tcx, &ctxt.param_env) {
+        if ty.needs_drop(tcx, ctxt.param_env) {
             each_child(child);
         } else {
             debug!("on_all_drop_children_bits - skipping")
@@ -359,7 +359,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
     where F: FnMut(MovePathIndex, DropFlagState)
 {
     let move_data = &ctxt.move_data;
-    let param_env = &ctxt.param_env;
+    let param_env = ctxt.param_env;
     debug!("drop_flag_effects_for_location({:?})", loc);
 
     // first, move out of the RHS
index c28d45be18d9e754ec9cdd7a93b20064f22de517..f7c20542cbf2e98c685bd4b56166d7efb22e2529 100644 (file)
@@ -535,7 +535,7 @@ pub fn report_use_of_moved_value(&self,
                                      lp: &LoanPath<'tcx>,
                                      the_move: &move_data::Move,
                                      moved_lp: &LoanPath<'tcx>,
-                                     _param_env: &ty::ParameterEnvironment<'tcx>) {
+                                     _param_env: &ty::ParamEnv<'tcx>) {
         let (verb, verb_participle) = match use_kind {
             MovedInUse => ("use", "used"),
             MovedInCapture => ("capture", "captured"),
index a18f91a9ee391408f069981f119d09ead357e618..7ed5f620816e11d5cca9c3ddf10fdabf3fdcb47c 100644 (file)
@@ -52,7 +52,7 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
             tcx: self.tcx,
             tables: self.tcx.body_tables(b),
             region_maps: &self.tcx.region_maps(def_id),
-            param_env: &self.tcx.parameter_environment(def_id)
+            param_env: self.tcx.param_env(def_id)
         }.visit_body(self.tcx.hir.body(b));
     }
 }
@@ -69,7 +69,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn
 struct MatchVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     region_maps: &'a RegionMaps,
 }
 
@@ -518,7 +518,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
 ///
 /// FIXME: this should be done by borrowck.
 fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
-    cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| {
+    cx.tcx.infer_ctxt((cx.tables, cx.param_env), Reveal::UserFacing).enter(|infcx| {
         let mut checker = MutationChecker {
             cx: cx,
         };
index 18a57f78a503719e7bcc48fb26362977f8a79bcd..7ecd7c5412e03920a8297674fa07f8c596b4988f 100644 (file)
@@ -23,7 +23,6 @@
 #![deny(warnings)]
 
 #![feature(box_syntax)]
-#![feature(loop_break_value)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
@@ -32,6 +31,7 @@
 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![cfg_attr(stage0, feature(rustc_private))]
 #![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
 
 extern crate arena;
 extern crate getopts;
index 6423d65a4c23fc7175ee598ef365ae7ed90c3ce1..39b8e568ab48d959f5a1e1a5a573c7b0a3b59a36 100644 (file)
@@ -527,13 +527,11 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         if def.has_dtor(cx.tcx) {
             return;
         }
-        let parameter_environment = cx.tcx.empty_parameter_environment();
-        // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
-        // method
-        if !ty.moves_by_default(cx.tcx, &parameter_environment, item.span) {
+        let param_env = ty::ParamEnv::empty();
+        if !ty.moves_by_default(cx.tcx, param_env, item.span) {
             return;
         }
-        if parameter_environment.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+        if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
             cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
                          item.span,
                          "type could implement `Copy`; consider adding `impl \
@@ -990,7 +988,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
                                                 trait_ref.to_poly_trait_predicate());
 
-                    let param_env = tcx.parameter_environment(method.def_id);
+                    let param_env = tcx.param_env(method.def_id);
                     tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
                         let mut selcx = traits::SelectionContext::new(&infcx);
                         match selcx.select(&obligation) {
@@ -1258,7 +1256,8 @@ fn get_lints(&self) -> LintArray {
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
         if let hir::ItemUnion(ref vdata, _) = item.node {
-            let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
+            let item_def_id = ctx.tcx.hir.local_def_id(item.id);
+            let param_env = ctx.tcx.param_env(item_def_id);
             for field in vdata.fields() {
                 let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
                 if field_ty.needs_drop(ctx.tcx, param_env) {
index a368021443292b36a844039ab75b37333721c6c5..5178963179d6f80d1bf90e33e6c244ddfcc6bb00 100644 (file)
@@ -27,8 +27,8 @@ pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M)
                              -> BlockAnd<Operand<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
-        let topmost_scope = self.topmost_scope(); // FIXME(#6393)
-        self.as_operand(block, Some(topmost_scope), expr)
+        let local_scope = self.local_scope();
+        self.as_operand(block, local_scope, expr)
     }
 
     /// Compile `expr` into a value that can be used as an operand.
index 7b29cd970d7d4447c852d0feaa39542afc77d0a6..e1832e0a0af347614978ad0db3a66db2a330d707 100644 (file)
@@ -33,8 +33,8 @@ pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M)
                              -> BlockAnd<Rvalue<'tcx>>
         where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
-        let topmost_scope = self.topmost_scope(); // FIXME(#6393)
-        self.as_rvalue(block, Some(topmost_scope), expr)
+        let local_scope = self.local_scope();
+        self.as_rvalue(block, local_scope, expr)
     }
 
     /// Compile `expr`, yielding an rvalue.
@@ -51,7 +51,7 @@ fn expr_as_rvalue(&mut self,
                       scope: Option<CodeExtent>,
                       expr: Expr<'tcx>)
                       -> BlockAnd<Rvalue<'tcx>> {
-        debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
+        debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
 
         let this = self;
         let expr_span = expr.span;
index a334923546fb2df76a8c4ccb73cd242bf11ae6ab..ab27a1a9c24bc2a92c5bfea8e22d56348cd37b77 100644 (file)
@@ -35,7 +35,8 @@ fn expr_as_temp(&mut self,
                     temp_lifetime: Option<CodeExtent>,
                     expr: Expr<'tcx>)
                     -> BlockAnd<Lvalue<'tcx>> {
-        debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
+        debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
+               block, temp_lifetime, expr);
         let this = self;
 
         if let ExprKind::Scope { extent, value } = expr.kind {
index fb173e2487bff0c5091fb68566f4a5975f16b9f3..407b08d2831497b3456a2fdf0a7f9795c2f9d348 100644 (file)
@@ -172,7 +172,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     let span = tcx.hir.span(ctor_id);
     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
-        let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
+        let pe = tcx.param_env(tcx.hir.local_def_id(ctor_id));
         tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
             let (mut mir, src) =
                 shim::build_adt_ctor(&infcx, ctor_id, fields, span);
@@ -392,9 +392,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     mir
 }
 
-pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
-                                       body_id: hir::BodyId)
-                                       -> Mir<'tcx> {
+fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+                                   body_id: hir::BodyId)
+                                   -> Mir<'tcx> {
     let tcx = hir.tcx();
     let ast_expr = &tcx.hir.body(body_id).value;
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
@@ -415,7 +415,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     builder.finish(vec![], ty)
 }
 
-pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
                                        body_id: hir::BodyId)
                                        -> Mir<'tcx> {
     let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
index ae47f4c42442041fe47241444d4c796fb5a91c39..a99e7b4be5768b81c9a5c06851b3dc20ed28c104 100644 (file)
@@ -93,6 +93,7 @@
 use rustc::ty::subst::{Kind, Subst};
 use rustc::ty::{Ty, TyCtxt};
 use rustc::mir::*;
+use rustc::mir::transform::MirSource;
 use syntax_pos::Span;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::fx::FxHashMap;
@@ -428,6 +429,41 @@ pub fn topmost_scope(&self) -> CodeExtent {
         self.scopes.last().expect("topmost_scope: no scopes present").extent
     }
 
+    /// Returns the scope that we should use as the lifetime of an
+    /// operand. Basically, an operand must live until it is consumed.
+    /// This is similar to, but not quite the same as, the temporary
+    /// scope (which can be larger or smaller).
+    ///
+    /// Consider:
+    ///
+    ///     let x = foo(bar(X, Y));
+    ///
+    /// We wish to pop the storage for X and Y after `bar()` is
+    /// called, not after the whole `let` is completed.
+    ///
+    /// As another example, if the second argument diverges:
+    ///
+    ///     foo(Box::new(2), panic!())
+    ///
+    /// We would allocate the box but then free it on the unwinding
+    /// path; we would also emit a free on the 'success' path from
+    /// panic, but that will turn out to be removed as dead-code.
+    ///
+    /// When building statics/constants, returns `None` since
+    /// intermediate values do not have to be dropped in that case.
+    pub fn local_scope(&self) -> Option<CodeExtent> {
+        match self.hir.src {
+            MirSource::Const(_) |
+            MirSource::Static(..) =>
+                // No need to free storage in this context.
+                None,
+            MirSource::Fn(_) =>
+                Some(self.topmost_scope()),
+            MirSource::Promoted(..) =>
+                bug!(),
+        }
+    }
+
     // Scheduling drops
     // ================
     /// Indicates that `lvalue` should be dropped on exit from
index 9ffce18fe150e0c8b52ac54df9164910d5631345..581a403fb6dee848861860711fca541722b9fa5b 100644 (file)
@@ -36,8 +36,14 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     pub region_maps: Rc<RegionMaps>,
+
+    /// This is `Constness::Const` if we are compiling a `static`,
+    /// `const`, or the body of a `const fn`.
     constness: hir::Constness,
 
+    /// What are we compiling?
+    pub src: MirSource,
+
     /// True if this constant/function needs overflow checks.
     check_overflow: bool,
 }
@@ -74,7 +80,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx,
         // Constants and const fn's always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
 
-        Cx { tcx, infcx, region_maps, constness, check_overflow }
+        Cx { tcx, infcx, region_maps, constness, src, check_overflow }
     }
 }
 
@@ -168,7 +174,7 @@ pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
                   type with inference types/regions",
                  ty);
         });
-        ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
+        ty.needs_drop(self.tcx.global_tcx(), self.infcx.param_env)
     }
 
     pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
index 6f4480bf6dd16d525bdb54dc8ba02a9f66b2ffa7..428685d7f5058cf1dbdaeabb0251eb9096352e3d 100644 (file)
@@ -40,8 +40,6 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                        -> &'tcx Mir<'tcx>
 {
     debug!("make_shim({:?})", instance);
-    let did = instance.def_id();
-    let param_env = tcx.parameter_environment(did);
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) =>
@@ -98,7 +96,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             )
         }
         ty::InstanceDef::DropGlue(def_id, ty) => {
-            build_drop_shim(tcx, &param_env, def_id, ty)
+            build_drop_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::Intrinsic(_) => {
             bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
@@ -144,7 +142,6 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
 }
 
 fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-                             param_env: &ty::ParameterEnvironment<'tcx>,
                              def_id: DefId,
                              ty: Option<Ty<'tcx>>)
                              -> Mir<'tcx>
@@ -189,10 +186,12 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(..) = ty {
         let patch = {
+            let param_env = tcx.param_env(def_id);
             let mut elaborator = DropShimElaborator {
                 mir: &mir,
                 patch: MirPatch::new(&mir),
-                tcx, param_env
+                tcx,
+                param_env
             };
             let dropee = Lvalue::Local(Local::new(1+0)).deref();
             let resume_block = elaborator.patch.resume_block();
@@ -218,7 +217,7 @@ pub struct DropShimElaborator<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     patch: MirPatch<'tcx>,
     tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
 }
 
 impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
@@ -233,7 +232,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
     fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
     fn mir(&self) -> &'a Mir<'tcx> { self.mir }
     fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> { self.param_env }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
 
     fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
         if let DropFlagMode::Shallow = mode {
index e6d62dc6460726365dc560edb3492f74964f5f44..edb2f44d18e35423afe37ec1bebed8a9bca2f5d8 100644 (file)
@@ -220,7 +220,7 @@ fn should_inline(&self,
         // FIXME: Give a bonus to functions with only a single caller
 
         let def_id = tcx.hir.local_def_id(self.source.item_id());
-        let param_env = tcx.parameter_environment(def_id);
+        let param_env = tcx.param_env(def_id);
 
         let mut first_block = true;
         let mut cost = 0;
@@ -253,7 +253,7 @@ fn should_inline(&self,
                     // a regular goto.
                     let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
                     let ty = ty.to_ty(tcx);
-                    if ty.needs_drop(tcx, &param_env) {
+                    if ty.needs_drop(tcx, param_env) {
                         cost += CALL_PENALTY;
                         if let Some(unwind) = unwind {
                             work_list.push(unwind);
@@ -545,7 +545,7 @@ fn make_call_args(&self, args: Vec<Operand<'tcx>>,
     }
 }
 
-fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>,
+fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>,
                           ty: Ty<'tcx>) -> Option<u64> {
     tcx.infer_ctxt(param_env, traits::Reveal::All).enter(|infcx| {
         ty.layout(&infcx).ok().map(|layout| {
index 72edf68f4034c47121332cf54b57d7647115ed56..4e84cbe6fecb130bfd268a39cdfab4c0edc345d2 100644 (file)
@@ -78,7 +78,7 @@ impl<'a, 'tcx> Qualif {
     /// Remove flags which are impossible for the given type.
     fn restrict(&mut self, ty: Ty<'tcx>,
                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                param_env: &ty::ParameterEnvironment<'tcx>) {
+                param_env: ty::ParamEnv<'tcx>) {
         if ty.is_freeze(tcx, param_env, DUMMY_SP) {
             *self = *self - Qualif::MUTABLE_INTERIOR;
         }
@@ -128,7 +128,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     rpo: ReversePostorder<'a, 'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    param_env: ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     temp_qualif: IndexVec<Local, Option<Qualif>>,
     return_qualif: Option<Qualif>,
     qualif: Qualif,
@@ -139,7 +139,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
 impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: ty::ParameterEnvironment<'tcx>,
+           param_env: ty::ParamEnv<'tcx>,
            def_id: DefId,
            mir: &'a Mir<'tcx>,
            mode: Mode)
@@ -193,7 +193,7 @@ fn add(&mut self, qualif: Qualif) {
     /// Add the given type's qualification to self.qualif.
     fn add_type(&mut self, ty: Ty<'tcx>) {
         self.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
-        self.qualif.restrict(ty, self.tcx, &self.param_env);
+        self.qualif.restrict(ty, self.tcx, self.param_env);
     }
 
     /// Within the provided closure, self.qualif will start
@@ -544,7 +544,7 @@ fn visit_lvalue(&mut self,
                                            static, use a constant instead");
                             }
                             let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
-                            this.qualif.restrict(ty, this.tcx, &this.param_env);
+                            this.qualif.restrict(ty, this.tcx, this.param_env);
                         }
 
                         ProjectionElem::ConstantIndex {..} |
@@ -937,7 +937,7 @@ fn mir_const_qualif<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return Qualif::NOT_CONST.bits();
     }
 
-    let param_env = tcx.parameter_environment(def_id);
+    let param_env = tcx.param_env(def_id);
 
     let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
     qualifier.qualify_const().bits()
@@ -965,7 +965,7 @@ fn run_pass<'a, 'tcx>(&self,
             MirSource::Const(_) |
             MirSource::Promoted(..) => return
         };
-        let param_env = tcx.parameter_environment(def_id);
+        let param_env = tcx.param_env(def_id);
 
         if mode == Mode::Fn || mode == Mode::ConstFn {
             // This is ugly because Qualifier holds onto mir,
index 82c0d2c1b01c6ab3f52f688538c4e87b9d7476f1..6d9603ea459d40941bc1225945f8d55ace1b1eef 100644 (file)
@@ -751,7 +751,7 @@ fn run_pass<'a, 'tcx>(&self,
             // broken MIR, so try not to report duplicate errors.
             return;
         }
-        let param_env = tcx.parameter_environment(def_id);
+        let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
             let mut checker = TypeChecker::new(&infcx, item_id);
             {
index 9d7c7ec63cfc57afbc32eccfa5dfb5cee46185c2..585840ce1e509f17df1558be01671169b234710d 100644 (file)
@@ -56,7 +56,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
     fn patch(&mut self) -> &mut MirPatch<'tcx>;
     fn mir(&self) -> &'a Mir<'tcx>;
     fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
-    fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx>;
+    fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
     fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>>;
index a0998b1bd1bfb3fd7cd3a54da70b140d3987da0a..25845c5768e8c8629a12efee4bccc4d9894ef8c0 100644 (file)
@@ -58,7 +58,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
     in_fn: bool,
     promotable: bool,
     mut_rvalue_borrows: NodeSet,
-    param_env: ty::ParameterEnvironment<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
 }
 
@@ -85,11 +85,11 @@ fn check_const_eval(&self, expr: &'gcx hir::Expr) {
 
     // Adds the worst effect out of all the values of one type.
     fn add_type(&mut self, ty: Ty<'gcx>) {
-        if !ty.is_freeze(self.tcx, &self.param_env, DUMMY_SP) {
+        if !ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
             self.promotable = false;
         }
 
-        if ty.needs_drop(self.tcx, &self.param_env) {
+        if ty.needs_drop(self.tcx, self.param_env) {
             self.promotable = false;
         }
     }
@@ -139,7 +139,7 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         }
 
         let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
-            let param_env = infcx.parameter_environment.clone();
+            let param_env = infcx.param_env.clone();
             let outer_penv = mem::replace(&mut self.param_env, param_env);
             let region_maps = &self.tcx.region_maps(item_def_id);;
             euv::ExprUseVisitor::new(self, region_maps, &infcx).consume_body(body);
@@ -466,7 +466,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         in_fn: false,
         promotable: false,
         mut_rvalue_borrows: NodeSet(),
-        param_env: tcx.empty_parameter_environment(),
+        param_env: ty::ParamEnv::empty(),
     }.as_deep_visitor());
     tcx.sess.abort_if_errors();
 }
index c2f2c63790a4c64d04ec9e9ca93ffb175364fc24..0dece586c930dabfd39226e4ec8e817161049536 100644 (file)
@@ -79,7 +79,6 @@ pub fn extend(&mut self, stats: Stats) {
 pub struct SharedCrateContext<'a, 'tcx: 'a> {
     exported_symbols: NodeSet,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    empty_param_env: ty::ParameterEnvironment<'tcx>,
     check_overflow: bool,
 
     use_dll_storage_attrs: bool,
@@ -315,7 +314,6 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
 
         SharedCrateContext {
             exported_symbols: exported_symbols,
-            empty_param_env: tcx.empty_parameter_environment(),
             tcx: tcx,
             check_overflow: check_overflow,
             use_dll_storage_attrs: use_dll_storage_attrs,
@@ -323,15 +321,15 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
     }
 
     pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(self.tcx, &self.empty_param_env)
+        ty.needs_drop(self.tcx, ty::ParamEnv::empty())
     }
 
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
+        ty.is_sized(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
     }
 
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(self.tcx, &self.empty_param_env, DUMMY_SP)
+        ty.is_freeze(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
     }
 
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
index d9f77e8f04f1ccbfa595b19195f286a8a942b34a..767cf8f48cfeabfc3989661bebb1ad150e7ed358 100644 (file)
@@ -165,10 +165,6 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Finally we register each of these predicates as an obligation in
     // a fresh FulfillmentCtxt, and invoke select_all_or_error.
 
-    // Create a parameter environment that represents the implementation's
-    // method.
-    let impl_param_env = tcx.parameter_environment(impl_m.def_id);
-
     // Create mapping from impl to skolemized.
     let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
 
@@ -216,19 +212,18 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
-    let trait_param_env = impl_param_env.with_caller_bounds(
-        tcx.intern_predicates(&hybrid_preds.predicates));
-    let trait_param_env = traits::normalize_param_env_or_error(tcx,
-                                                               impl_m.def_id,
-                                                               trait_param_env,
-                                                               normalize_cause.clone());
-
-    tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
+    let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates));
+    let param_env = traits::normalize_param_env_or_error(tcx,
+                                                         impl_m.def_id,
+                                                         param_env,
+                                                         normalize_cause.clone());
+
+    tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
         let inh = Inherited::new(infcx, impl_m.def_id);
         let infcx = &inh.infcx;
 
         debug!("compare_impl_method: caller_bounds={:?}",
-               infcx.parameter_environment.caller_bounds);
+               infcx.param_env.caller_bounds);
 
         let mut selcx = traits::SelectionContext::new(&infcx);
 
@@ -350,7 +345,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let region_maps = RegionMaps::new();
             let mut free_regions = FreeRegionMap::new();
             free_regions.relate_free_regions_from_predicates(
-                &infcx.parameter_environment.caller_bounds);
+                &infcx.param_env.caller_bounds);
             infcx.resolve_regions_and_report_errors(impl_m.def_id, &region_maps, &free_regions);
         } else {
             let fcx = FnCtxt::new(&inh, impl_m_node_id);
index e029332559635663b46b12b696e9a466aa25dea2..3ed0da05dc2c2f800e8916017a22e047de4e2069 100644 (file)
@@ -79,7 +79,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
 
     // check that the impl type can be made to match the trait type.
 
-    let impl_param_env = tcx.parameter_environment(self_type_did);
+    let impl_param_env = tcx.param_env(self_type_did);
     tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
         let tcx = infcx.tcx;
         let mut fulfillment_cx = traits::FulfillmentContext::new();
index c1cf5192877c0d45246e5b003c4d63c1a5a20d9a..9ad72b2a137ea2ea10112bfb7ddb61ed1a0b9f23 100644 (file)
@@ -566,7 +566,7 @@ fn assemble_inherent_candidates_from_param(&mut self,
                                                param_ty: ty::ParamTy) {
         // FIXME -- Do we want to commit to this behavior for param bounds?
 
-        let bounds: Vec<_> = self.parameter_environment
+        let bounds: Vec<_> = self.param_env
             .caller_bounds
             .iter()
             .filter_map(|predicate| {
@@ -893,7 +893,7 @@ fn assemble_where_clause_candidates(&mut self,
         debug!("assemble_where_clause_candidates(trait_def_id={:?})",
                trait_def_id);
 
-        let caller_predicates = self.parameter_environment.caller_bounds.to_vec();
+        let caller_predicates = self.param_env.caller_bounds.to_vec();
         for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
             .filter_map(|p| p.to_opt_poly_trait_ref())
             .filter(|b| b.def_id() == trait_def_id) {
index d304d79bc52c8342b8ce1ad65cf1226f2cfb277a..24a88140cf041014af2370a1c5345beb4404f29d 100644 (file)
@@ -539,7 +539,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
     pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
                  -> InheritedBuilder<'a, 'gcx, 'tcx> {
         let tables = ty::TypeckTables::empty();
-        let param_env = tcx.parameter_environment(def_id);
+        let param_env = tcx.param_env(def_id);
         InheritedBuilder {
             infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
             def_id,
@@ -1561,7 +1561,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
         let index = generics.type_param_to_index[&def_id.index];
         ty::GenericPredicates {
             parent: None,
-            predicates: self.parameter_environment.caller_bounds.iter().filter(|predicate| {
+            predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
                 match **predicate {
                     ty::Predicate::Trait(ref data) => {
                         data.0.self_ty().is_param(index)
index 754bd288bfaa70c995624c1358dbc3ffcd7e284f..b29bf01ba1996d472aba27ff1226c376583f2645 100644 (file)
@@ -138,7 +138,7 @@ pub fn regionck_item(&self,
         let subject = self.tcx.hir.local_def_id(item_id);
         let mut rcx = RegionCtxt::new(self, RepeatingScope(item_id), item_id, Subject(subject));
         rcx.free_region_map.relate_free_regions_from_predicates(
-            &self.parameter_environment.caller_bounds);
+            &self.param_env.caller_bounds);
         rcx.relate_free_regions(wf_tys, item_id, span);
         rcx.visit_region_obligations(item_id);
         rcx.resolve_regions_and_report_errors();
@@ -158,7 +158,7 @@ pub fn regionck_fn(&self,
         }
 
         rcx.free_region_map.relate_free_regions_from_predicates(
-            &self.parameter_environment.caller_bounds);
+            &self.param_env.caller_bounds);
 
         rcx.resolve_regions_and_report_errors();
 
@@ -1682,7 +1682,7 @@ fn recursive_type_bound(&self, span: Span, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
     fn declared_generic_bounds_from_env(&self, generic: GenericKind<'tcx>)
                                         -> Vec<ty::Region<'tcx>>
     {
-        let param_env = &self.parameter_environment;
+        let param_env = &self.param_env;
 
         // To start, collect bounds from user:
         let mut param_bounds = self.tcx.required_region_bounds(generic.to_ty(self.tcx),
index 556bd618c78cbb22e49b90b503f1daad2577d4a6..ff5599fb1bdbf46c24a1dd0c8474360787035b79 100644 (file)
@@ -105,7 +105,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            self_type);
 
     let span = tcx.hir.span(impl_node_id);
-    let param_env = tcx.parameter_environment(impl_did);
+    let param_env = tcx.param_env(impl_did);
     assert!(!self_type.has_escaping_regions());
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
@@ -199,7 +199,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            target);
 
     let span = tcx.hir.span(impl_node_id);
-    let param_env = tcx.parameter_environment(impl_did);
+    let param_env = tcx.param_env(impl_did);
     assert!(!source.has_escaping_regions());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
@@ -387,7 +387,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Finally, resolve all regions.
         let region_maps = RegionMaps::new();
         let mut free_regions = FreeRegionMap::new();
-        free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
+        free_regions.relate_free_regions_from_predicates(&infcx.param_env
             .caller_bounds);
         infcx.resolve_regions_and_report_errors(impl_did, &region_maps, &free_regions);
 
index 99ee1cff7fd22ab9c2883eb49ac6346931c71c89..6f2c73b892567f343f174113bc6ee49b29d7029a 100644 (file)
@@ -76,7 +76,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
-#![feature(loop_break_value)]
 #![feature(never_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
@@ -84,6 +83,7 @@
 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![cfg_attr(stage0, feature(rustc_private))]
 #![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index 9dea0e3d83088451b551acc35da723395105e5e4..141efe471af5fe1cdae32198ed4ea7add4d767e7 100644 (file)
 ///
 /// The returned value is `None` if the definition could not be inlined,
 /// and `Some` of a vector of items if it was successfully expanded.
-pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
+pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
                   -> Option<Vec<clean::Item>> {
     if def == Def::Err { return None }
     let did = def.def_id();
     if did.is_local() { return None }
-    try_inline_def(cx, def).map(|vec| {
-        vec.into_iter().map(|mut item| {
-            match into {
-                Some(into) if item.name.is_some() => {
-                    item.name = Some(into.clean(cx));
-                }
-                _ => {}
-            }
-            item
-        }).collect()
-    })
-}
-
-fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
-    let tcx = cx.tcx;
     let mut ret = Vec::new();
     let inner = match def {
         Def::Trait(did) => {
@@ -112,16 +97,15 @@ fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
         }
         _ => return None,
     };
-    let did = def.def_id();
     cx.renderinfo.borrow_mut().inlined.insert(did);
     ret.push(clean::Item {
-        source: tcx.def_span(did).clean(cx),
-        name: Some(tcx.item_name(did).to_string()),
+        source: cx.tcx.def_span(did).clean(cx),
+        name: Some(name.clean(cx)),
         attrs: load_attrs(cx, did),
         inner: inner,
         visibility: Some(clean::Public),
-        stability: tcx.lookup_stability(did).clean(cx),
-        deprecation: tcx.lookup_deprecation(did).clean(cx),
+        stability: cx.tcx.lookup_stability(did).clean(cx),
+        deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
         def_id: did,
     });
     Some(ret)
@@ -463,7 +447,7 @@ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
             let def_id = item.def.def_id();
             if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
                 if !visited.insert(def_id) { continue }
-                if let Some(i) = try_inline_def(cx, item.def) {
+                if let Some(i) = try_inline(cx, item.def, item.name) {
                     items.extend(i)
                 }
             }
index 61f941e57b2d8c6a61481e6ba7c819d0ded0604d..48d387f812d2548df1868fe197a082531d4ccdd4 100644 (file)
@@ -2618,7 +2618,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
         } else {
             let name = self.name;
             if !denied {
-                if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
+                if let Some(items) = inline::try_inline(cx, path.def, name) {
                     return items;
                 }
             }
index 51d127f8ba79a246c33745356c94ab0888f4bf98..8c4cbb66b454d2e52a5d1989efc745998d5b6593 100644 (file)
@@ -1231,14 +1231,13 @@ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
     /// # Examples
     ///
     /// ```
-    /// #![feature(retain_hash_collection)]
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<isize, isize> = (0..8).map(|x|(x, x*10)).collect();
     /// map.retain(|&k, _| k % 2 == 0);
     /// assert_eq!(map.len(), 4);
     /// ```
-    #[unstable(feature = "retain_hash_collection", issue = "36648")]
+    #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, mut f: F)
         where F: FnMut(&K, &mut V) -> bool
     {
index 7215e1bde8503e1988f14e3bcbcde373a58ab4a1..d80df5f18b610ba3f6df437aba1ac522371aa7f1 100644 (file)
 /// [`HashMap`]: struct.HashMap.html
 /// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
 /// [`RefCell`]: ../../std/cell/struct.RefCell.html
-
-
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct HashSet<T, S = RandomState> {
@@ -658,7 +656,6 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     /// # Examples
     ///
     /// ```
-    /// #![feature(retain_hash_collection)]
     /// use std::collections::HashSet;
     ///
     /// let xs = [1,2,3,4,5,6];
@@ -666,7 +663,7 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
     /// ```
-    #[unstable(feature = "retain_hash_collection", issue = "36648")]
+    #[stable(feature = "retain_hash_collection", since = "1.18.0")]
     pub fn retain<F>(&mut self, mut f: F)
         where F: FnMut(&T) -> bool
     {
@@ -1041,9 +1038,7 @@ impl<'a, K> FusedIterator for Iter<'a, K> {}
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1070,10 +1065,11 @@ impl<K> FusedIterator for IntoIter<K> {}
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
-        f.debug_list()
-            .entries(entries_iter)
-            .finish()
+        let entries_iter = self.iter
+            .inner
+            .iter()
+            .map(|(k, _)| k);
+        f.debug_list().entries(entries_iter).finish()
     }
 }
 
@@ -1100,10 +1096,11 @@ impl<'a, K> FusedIterator for Drain<'a, K> {}
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
-        f.debug_list()
-            .entries(entries_iter)
-            .finish()
+        let entries_iter = self.iter
+            .inner
+            .iter()
+            .map(|(k, _)| k);
+        f.debug_list().entries(entries_iter).finish()
     }
 }
 
@@ -1143,12 +1140,10 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
     where T: fmt::Debug + Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1202,12 +1197,10 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S>
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T, S> fmt::Debug for Difference<'a, T, S>
     where T: fmt::Debug + Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1243,12 +1236,10 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S>
     where T: fmt::Debug + Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1269,12 +1260,10 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S>
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T, S> fmt::Debug for Union<'a, T, S>
     where T: fmt::Debug + Eq + Hash,
-          S: BuildHasher,
+          S: BuildHasher
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_list()
-            .entries(self.clone())
-            .finish()
+        f.debug_list().entries(self.clone()).finish()
     }
 }
 
@@ -1698,7 +1687,7 @@ fn test_extend_ref() {
 
     #[test]
     fn test_retain() {
-        let xs = [1,2,3,4,5,6];
+        let xs = [1, 2, 3, 4, 5, 6];
         let mut set: HashSet<isize> = xs.iter().cloned().collect();
         set.retain(|&k| k % 2 == 0);
         assert_eq!(set.len(), 3);
index f40475a41422bb9dc726480c3db4fbc9ea5459f4..1167c39dba8eef63c9589777b6a0928b4de61029 100644 (file)
 use slice;
 use str::{self, Utf8Error};
 
-/// A type representing an owned C-compatible string
+/// A type representing an owned C-compatible string.
 ///
 /// This type serves the primary purpose of being able to safely generate a
 /// C-compatible string from a Rust byte slice or vector. An instance of this
 /// type is a static guarantee that the underlying bytes contain no interior 0
 /// bytes and the final byte is 0.
 ///
-/// A `CString` is created from either a byte slice or a byte vector.  A `u8`
-/// slice can be obtained with the `as_bytes` method.  Slices produced from a
+/// A `CString` is created from either a byte slice or a byte vector. A [`u8`]
+/// slice can be obtained with the `as_bytes` method. Slices produced from a
 /// `CString` do *not* contain the trailing nul terminator unless otherwise
 /// specified.
 ///
+/// [`u8`]: ../primitive.u8.html
+///
 /// # Examples
 ///
 /// ```no_run
@@ -81,12 +83,14 @@ pub struct CString {
 ///
 /// Note that this structure is **not** `repr(C)` and is not recommended to be
 /// placed in the signatures of FFI functions. Instead safe wrappers of FFI
-/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
+/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
 /// interface to other consumers.
 ///
+/// [`from_ptr`]: #method.from_ptr
+///
 /// # Examples
 ///
-/// Inspecting a foreign C string
+/// Inspecting a foreign C string:
 ///
 /// ```no_run
 /// use std::ffi::CStr;
@@ -100,7 +104,7 @@ pub struct CString {
 /// }
 /// ```
 ///
-/// Passing a Rust-originating C string
+/// Passing a Rust-originating C string:
 ///
 /// ```no_run
 /// use std::ffi::{CString, CStr};
@@ -116,7 +120,9 @@ pub struct CString {
 /// work(&s);
 /// ```
 ///
-/// Converting a foreign C string into a Rust `String`
+/// Converting a foreign C string into a Rust [`String`]:
+///
+/// [`String`]: ../string/struct.String.html
 ///
 /// ```no_run
 /// use std::ffi::CStr;
@@ -142,14 +148,18 @@ pub struct CStr {
     inner: [c_char]
 }
 
-/// An error returned from `CString::new` to indicate that a nul byte was found
+/// An error returned from [`CString::new`] to indicate that a nul byte was found
 /// in the vector provided.
+///
+/// [`CString::new`]: struct.CString.html#method.new
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct NulError(usize, Vec<u8>);
 
-/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
+/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul
 /// byte was found too early in the slice provided or one wasn't found at all.
+///
+/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
 pub struct FromBytesWithNulError {
@@ -175,8 +185,10 @@ fn not_nul_terminated() -> FromBytesWithNulError {
     }
 }
 
-/// An error returned from `CString::into_string` to indicate that a UTF-8 error
+/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error
 /// was encountered during the conversion.
+///
+/// [`CString::into_string`]: struct.CString.html#method.into_string
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstring_into", since = "1.7.0")]
 pub struct IntoStringError {
@@ -224,10 +236,12 @@ fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
     /// Creates a C-compatible string from a byte vector without checking for
     /// interior 0 bytes.
     ///
-    /// This method is equivalent to `new` except that no runtime assertion
+    /// This method is equivalent to [`new`] except that no runtime assertion
     /// is made that `v` contains no 0 bytes, and it requires an actual
     /// byte vector, not anything that can be converted to one with Into.
     ///
+    /// [`new`]: #method.new
+    ///
     /// # Examples
     ///
     /// ```
@@ -252,9 +266,11 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
     /// # Safety
     ///
     /// This should only ever be called with a pointer that was earlier
-    /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
+    /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take
     /// ownership of a string that was allocated by foreign code) is likely to lead
     /// to undefined behavior or allocator corruption.
+    ///
+    /// [`into_raw`]: #method.into_raw
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
         let len = libc::strlen(ptr) + 1; // Including the NUL byte
@@ -265,19 +281,23 @@ pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
     /// Transfers ownership of the string to a C caller.
     ///
     /// The pointer must be returned to Rust and reconstituted using
-    /// `from_raw` to be properly deallocated. Specifically, one
+    /// [`from_raw`] to be properly deallocated. Specifically, one
     /// should *not* use the standard C `free` function to deallocate
     /// this string.
     ///
-    /// Failure to call `from_raw` will lead to a memory leak.
+    /// Failure to call [`from_raw`] will lead to a memory leak.
+    ///
+    /// [`from_raw`]: #method.from_raw
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub fn into_raw(self) -> *mut c_char {
         Box::into_raw(self.into_inner()) as *mut c_char
     }
 
-    /// Converts the `CString` into a `String` if it contains valid Unicode data.
+    /// Converts the `CString` into a [`String`] if it contains valid Unicode data.
     ///
     /// On failure, ownership of the original `CString` is returned.
+    ///
+    /// [`String`]: ../string/struct.String.html
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_string(self) -> Result<String, IntoStringError> {
         String::from_utf8(self.into_bytes())
@@ -299,8 +319,10 @@ pub fn into_bytes(self) -> Vec<u8> {
         vec
     }
 
-    /// Equivalent to the `into_bytes` function except that the returned vector
+    /// Equivalent to the [`into_bytes`] function except that the returned vector
     /// includes the trailing nul byte.
+    ///
+    /// [`into_bytes`]: #method.into_bytes
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_bytes_with_nul(self) -> Vec<u8> {
         self.into_inner().into_vec()
@@ -315,26 +337,34 @@ pub fn as_bytes(&self) -> &[u8] {
         &self.inner[..self.inner.len() - 1]
     }
 
-    /// Equivalent to the `as_bytes` function except that the returned slice
+    /// Equivalent to the [`as_bytes`] function except that the returned slice
     /// includes the trailing nul byte.
+    ///
+    /// [`as_bytes`]: #method.as_bytes
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_bytes_with_nul(&self) -> &[u8] {
         &self.inner
     }
 
-    /// Extracts a `CStr` slice containing the entire string.
+    /// Extracts a [`CStr`] slice containing the entire string.
+    ///
+    /// [`CStr`]: struct.CStr.html
     #[unstable(feature = "as_c_str", issue = "40380")]
     pub fn as_c_str(&self) -> &CStr {
         &*self
     }
 
-    /// Converts this `CString` into a boxed `CStr`.
+    /// Converts this `CString` into a boxed [`CStr`].
+    ///
+    /// [`CStr`]: struct.CStr.html
     #[unstable(feature = "into_boxed_c_str", issue = "40380")]
     pub fn into_boxed_c_str(self) -> Box<CStr> {
         unsafe { mem::transmute(self.into_inner()) }
     }
 
-    // Bypass "move out of struct which implements `Drop` trait" restriction.
+    // Bypass "move out of struct which implements [`Drop`] trait" restriction.
+    ///
+    /// [`Drop`]: ../ops/trait.Drop.html
     fn into_inner(self) -> Box<[u8]> {
         unsafe {
             let result = ptr::read(&self.inner);
@@ -443,7 +473,9 @@ fn default() -> Box<CStr> {
 
 impl NulError {
     /// Returns the position of the nul byte in the slice that was provided to
-    /// `CString::new`.
+    /// [`CString::new`].
+    ///
+    /// [`CString::new`]: struct.CString.html#method.new
     ///
     /// # Examples
     ///
@@ -518,8 +550,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl IntoStringError {
-    /// Consumes this error, returning original `CString` which generated the
+    /// Consumes this error, returning original [`CString`] which generated the
     /// error.
+    ///
+    /// [`CString`]: struct.CString.html
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_cstring(self) -> CString {
         self.inner
@@ -557,9 +591,9 @@ impl CStr {
     /// allows inspection and interoperation of non-owned C strings. This method
     /// is unsafe for a number of reasons:
     ///
-    /// * There is no guarantee to the validity of `ptr`
+    /// * There is no guarantee to the validity of `ptr`.
     /// * The returned lifetime is not guaranteed to be the actual lifetime of
-    ///   `ptr`
+    ///   `ptr`.
     /// * There is no guarantee that the memory pointed to by `ptr` contains a
     ///   valid nul terminator byte at the end of the string.
     ///
@@ -703,26 +737,30 @@ pub fn to_bytes(&self) -> &[u8] {
 
     /// Converts this C string to a byte slice containing the trailing 0 byte.
     ///
-    /// This function is the equivalent of `to_bytes` except that it will retain
+    /// This function is the equivalent of [`to_bytes`] except that it will retain
     /// the trailing nul instead of chopping it off.
     ///
     /// > **Note**: This method is currently implemented as a 0-cost cast, but
     /// > it is planned to alter its definition in the future to perform the
     /// > length calculation whenever this method is called.
+    ///
+    /// [`to_bytes`]: #method.to_bytes
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_bytes_with_nul(&self) -> &[u8] {
         unsafe { mem::transmute(&self.inner) }
     }
 
-    /// Yields a `&str` slice if the `CStr` contains valid UTF-8.
+    /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
     ///
     /// This function will calculate the length of this string and check for
-    /// UTF-8 validity, and then return the `&str` if it's valid.
+    /// UTF-8 validity, and then return the [`&str`] if it's valid.
     ///
     /// > **Note**: This method is currently implemented to check for validity
     /// > after a 0-cost cast, but it is planned to alter its definition in the
     /// > future to perform the length calculation in addition to the UTF-8
     /// > check whenever this method is called.
+    ///
+    /// [`&str`]: ../primitive.str.html
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
     pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
         // NB: When CStr is changed to perform the length check in .to_bytes()
@@ -732,23 +770,29 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
         str::from_utf8(self.to_bytes())
     }
 
-    /// Converts a `CStr` into a `Cow<str>`.
+    /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
     ///
     /// This function will calculate the length of this string (which normally
     /// requires a linear amount of work to be done) and then return the
-    /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
+    /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences
     /// with `U+FFFD REPLACEMENT CHARACTER`.
     ///
     /// > **Note**: This method is currently implemented to check for validity
     /// > after a 0-cost cast, but it is planned to alter its definition in the
     /// > future to perform the length calculation in addition to the UTF-8
     /// > check whenever this method is called.
+    ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`str`]: ../primitive.str.html
     #[stable(feature = "cstr_to_str", since = "1.4.0")]
     pub fn to_string_lossy(&self) -> Cow<str> {
         String::from_utf8_lossy(self.to_bytes())
     }
 
-    /// Converts a `Box<CStr>` into a `CString` without copying or allocating.
+    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: struct.CString.html
     #[unstable(feature = "into_boxed_c_str", issue = "40380")]
     pub fn into_c_string(self: Box<CStr>) -> CString {
         unsafe { mem::transmute(self) }
index 34229f80769aba8108f10553346af51b271cab35..c1493c9c6f4ff43a56b37baebe91f8e6a367a5c6 100644 (file)
@@ -343,7 +343,6 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(peek)]
     /// use std::net::TcpStream;
     ///
     /// let stream = TcpStream::connect("127.0.0.1:8000")
@@ -351,7 +350,7 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
     /// let mut buf = [0; 10];
     /// let len = stream.peek(&mut buf).expect("peek failed");
     /// ```
-    #[unstable(feature = "peek", issue = "38980")]
+    #[stable(feature = "peek", since = "1.18.0")]
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.peek(buf)
     }
index cdf04f7f1a484bb02f5f257000060fe82d98b7b8..80151dc2b4455a758c9be39ac379db73f7979bb1 100644 (file)
@@ -112,7 +112,6 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(peek)]
     /// use std::net::UdpSocket;
     ///
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
@@ -120,7 +119,7 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
     /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
     ///                                         .expect("Didn't receive data");
     /// ```
-    #[unstable(feature = "peek", issue = "38980")]
+    #[stable(feature = "peek", since = "1.18.0")]
     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.0.peek_from(buf)
     }
@@ -638,7 +637,6 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
     /// # Examples
     ///
     /// ```no_run
-    /// #![feature(peek)]
     /// use std::net::UdpSocket;
     ///
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
@@ -649,7 +647,7 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
     ///     Err(e) => println!("peek function failed: {:?}", e),
     /// }
     /// ```
-    #[unstable(feature = "peek", issue = "38980")]
+    #[stable(feature = "peek", since = "1.18.0")]
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.peek(buf)
     }
index d0e7defbbbb9a15f0b9af79925d319c8d8e22d59..da64704efbaa9452ec78a3976b9c043803bbb170 100644 (file)
@@ -928,8 +928,6 @@ pub fn wait(&mut self) -> io::Result<ExitStatus> {
     /// Basic usage:
     ///
     /// ```no_run
-    /// #![feature(process_try_wait)]
-    ///
     /// use std::process::Command;
     ///
     /// let mut child = Command::new("ls").spawn().unwrap();
@@ -944,7 +942,7 @@ pub fn wait(&mut self) -> io::Result<ExitStatus> {
     ///     Err(e) => println!("error attempting to wait: {}", e),
     /// }
     /// ```
-    #[unstable(feature = "process_try_wait", issue = "38903")]
+    #[stable(feature = "process_try_wait", since = "1.18.0")]
     pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
         Ok(self.handle.try_wait()?.map(ExitStatus))
     }
index 75717abb4ad28612c0c806d23361342d3dfe2986..d0e3b00d75fac43fdf2ad5f869e0f1add11be067 100644 (file)
@@ -397,6 +397,26 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
 /// want to specify the stack size or the name of the thread, use this API
 /// instead.
 ///
+/// As you can see in the signature of `spawn` there are two constraints on
+/// both the closure given to `spawn` and its return value, let's explain them:
+///
+/// - The `'static` constraint means that the closure and its return value
+///   must have a lifetime of the whole program execution. The reason for this
+///   is that threads can `detach` and outlive the lifetime they have been
+///   created in.
+///   Indeed if the thread, and by extension its return value, can outlive their
+///   caller, we need to make sure that they will be valid afterwards, and since
+///   we *can't* know when it will return we need to have them valid as long as
+///   possible, that is until the end of the program, hence the `'static`
+///   lifetime.
+/// - The [`Send`] constraint is because the closure will need to be passed
+///   *by value* from the thread where it is spawned to the new thread. Its
+///   return value will need to be passed from the new thread to the thread
+///   where it is `join`ed.
+///   As a reminder, the [`Send`] marker trait, expresses that it is safe to be
+///   passed from thread to thread. [`Sync`] expresses that it is safe to have a
+///   reference be passed from thread to thread.
+///
 /// # Panics
 ///
 /// Panics if the OS fails to create a thread; use [`Builder::spawn`]
@@ -463,6 +483,8 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
 /// [`panic`]: ../../std/macro.panic.html
 /// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
 /// [`Builder`]: ../../std/thread/struct.Builder.html
+/// [`Send`]: ../../std/marker/trait.Send.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
     F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
index 45f891d8dc56db911f325fd6ff90b4034066e834..8e63e219c42c19924914ce01bf1661dc9cfb68aa 100644 (file)
@@ -320,7 +320,7 @@ pub fn meta(&self) -> Option<MetaItem> {
     pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
         where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     {
-        let mut parser = Parser::new(sess, self.tokens.clone(), None, false);
+        let mut parser = Parser::new(sess, self.tokens.clone(), None, false, false);
         let result = f(&mut parser)?;
         if parser.token != token::Eof {
             parser.unexpected()?;
index bf66aa0f00bed42409ffbdc7ffe8cc3341d2a787..0b6a2eb536a20d7769721ee16a07f4de716ebefd 100644 (file)
@@ -418,9 +418,13 @@ fn inner_parse_loop(sess: &ParseSess,
     Success(())
 }
 
-pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Option<Directory>)
+pub fn parse(sess: &ParseSess,
+             tts: TokenStream,
+             ms: &[TokenTree],
+             directory: Option<Directory>,
+             recurse_into_modules: bool)
              -> NamedParseResult {
-    let mut parser = Parser::new(sess, tts, directory, true);
+    let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
     let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), parser.span.lo));
     let mut next_eis = Vec::new(); // or proceed normally
 
index a208f530602a5f0b05677e27c261e29971871e78..73494d47fee9b9a59dee95d448e95e43de1e55ca 100644 (file)
@@ -121,7 +121,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
                     path: cx.current_expansion.module.directory.clone(),
                     ownership: cx.current_expansion.directory_ownership,
                 };
-                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
+                let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
                 p.root_module_name = cx.current_expansion.module.mod_path.last()
                     .map(|id| id.name.as_str().to_string());
 
@@ -192,7 +192,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
         ast::ItemKind::MacroDef(ref body) => body.clone().into(),
         _ => unreachable!(),
     };
-    let argument_map = match parse(sess, body, &argument_gram, None) {
+    let argument_map = match parse(sess, body, &argument_gram, None, true) {
         Success(m) => m,
         Failure(sp, tok) => {
             let s = parse_failure_msg(tok);
index bebb26afb540f10f8a069fa4cab94031acf1c820..e1b7d4681ad160c38c613af52e931c48b0a5ff49 100644 (file)
@@ -297,9 +297,6 @@ pub fn new() -> Features {
 
     (active, use_extern_macros, "1.15.0", Some(35896)),
 
-    // Allows `break {expr}` with a value inside `loop`s.
-    (active, loop_break_value, "1.14.0", Some(37339)),
-
     // Allows #[target_feature(...)]
     (active, target_feature, "1.15.0", None),
 
@@ -423,6 +420,8 @@ pub fn new() -> Features {
     (accepted, pub_restricted, "1.18.0", Some(32409)),
     // The #![windows_subsystem] attribute
     (accepted, windows_subsystem, "1.18.0", Some(37499)),
+    // Allows `break {expr}` with a value inside `loop`s.
+    (accepted, loop_break_value, "1.19.0", Some(37339)),
 );
 // If you change this, please modify src/doc/unstable-book as well. You must
 // move that documentation into the relevant place in the other docs, and
@@ -1301,10 +1300,6 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
                     }
                 }
             }
-            ast::ExprKind::Break(_, Some(_)) => {
-                gate_feature_post!(&self, loop_break_value, e.span,
-                                   "`break` with a value is experimental");
-            }
             ast::ExprKind::Lit(ref lit) => {
                 if let ast::LitKind::Int(_, ref ty) = lit.node {
                     match *ty {
index 4df23da3c9ce3464bf1cb760352e5bd7df68b144..83a164bdb9693c66b67cd46300331d0839f703a4 100644 (file)
@@ -238,7 +238,7 @@ pub fn check_for_substitution<'a>(reader: &StringReader<'a>,
         match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
             Some(&(ascii_char, ascii_name)) => {
                 let msg =
-                    format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
+                    format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not",
                             ch, u_name, ascii_char, ascii_name);
                 err.span_help(span, &msg);
             },
index 1eff819d755493f33f713b6281100591bab78413..3a68a6ba7646c98de89a8cd8354b4db1fab175ef 100644 (file)
@@ -149,7 +149,9 @@ pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSe
 // Create a new parser from a source string
 pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
                                       -> Parser {
-    filemap_to_parser(sess, sess.codemap().new_filemap(name, source))
+    let mut parser = filemap_to_parser(sess, sess.codemap().new_filemap(name, source));
+    parser.recurse_into_file_modules = false;
+    parser
 }
 
 /// Create a new parser, handling errors as appropriate
@@ -218,7 +220,7 @@ pub fn filemap_to_stream(sess: &ParseSess, filemap: Rc<FileMap>) -> TokenStream
 
 /// Given stream and the `ParseSess`, produce a parser
 pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
-    Parser::new(sess, stream, None, false)
+    Parser::new(sess, stream, None, true, false)
 }
 
 /// Parse a string representing a character literal into its final form.
@@ -1032,4 +1034,23 @@ fn ttdelim_span() {
             Err(_) => panic!("could not get snippet"),
         }
     }
+
+    // This tests that when parsing a string (rather than a file) we don't try
+    // and read in a file for a module declaration and just parse a stub.
+    // See `recurse_into_file_modules` in the parser.
+    #[test]
+    fn out_of_line_mod() {
+        let sess = ParseSess::new(FilePathMapping::empty());
+        let item = parse_item_from_source_str(
+            "foo".to_owned(),
+            "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
+            &sess,
+        ).unwrap().unwrap();
+
+        if let ast::ItemKind::Mod(ref m) = item.node {
+            assert!(m.items.len() == 2);
+        } else {
+            panic!();
+        }
+    }
 }
index 4741f896d3cc0c8c6ce38501dd2e1cb1a7dcfe0e..c28f678cb5197a84f62426c4bdfc5f8fdfb3d485 100644 (file)
@@ -179,6 +179,8 @@ pub struct Parser<'a> {
     pub obsolete_set: HashSet<ObsoleteSyntax>,
     /// Used to determine the path to externally loaded source files
     pub directory: Directory,
+    /// Whether to parse sub-modules in other files.
+    pub recurse_into_file_modules: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
     /// into modules, and sub-parsers have new values for this name.
@@ -190,6 +192,7 @@ pub struct Parser<'a> {
     pub cfg_mods: bool,
 }
 
+
 struct TokenCursor {
     frame: TokenCursorFrame,
     stack: Vec<TokenCursorFrame>,
@@ -439,6 +442,7 @@ impl<'a> Parser<'a> {
     pub fn new(sess: &'a ParseSess,
                tokens: TokenStream,
                directory: Option<Directory>,
+               recurse_into_file_modules: bool,
                desugar_doc_comments: bool)
                -> Self {
         let mut parser = Parser {
@@ -450,6 +454,7 @@ pub fn new(sess: &'a ParseSess,
             prev_token_kind: PrevTokenKind::Other,
             restrictions: Restrictions::empty(),
             obsolete_set: HashSet::new(),
+            recurse_into_file_modules: recurse_into_file_modules,
             directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
             root_module_name: None,
             expected_tokens: Vec::new(),
@@ -467,12 +472,14 @@ pub fn new(sess: &'a ParseSess,
         let tok = parser.next_tok();
         parser.token = tok.tok;
         parser.span = tok.sp;
+
         if let Some(directory) = directory {
             parser.directory = directory;
         } else if parser.span != syntax_pos::DUMMY_SP {
             parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
             parser.directory.path.pop();
         }
+
         parser.process_potential_macro_variable();
         parser
     }
@@ -3921,6 +3928,7 @@ fn parse_stmt_without_recovery(&mut self,
                 mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
             let item = self.parse_item_(attrs.clone(), false, true)?;
             self.directory.ownership = old_directory_ownership;
+
             match item {
                 Some(i) => Stmt {
                     id: ast::DUMMY_NODE_ID,
@@ -5254,7 +5262,7 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
         let id = self.parse_ident()?;
         if self.check(&token::Semi) {
             self.bump();
-            if in_cfg {
+            if in_cfg && self.recurse_into_file_modules {
                 // This mod is in an external file. Let's go get it!
                 let ModulePathSuccess { path, directory_ownership, warn } =
                     self.submod_path(id, &outer_attrs, id_span)?;
@@ -5281,10 +5289,12 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
         } else {
             let old_directory = self.directory.clone();
             self.push_directory(id, &outer_attrs);
+
             self.expect(&token::OpenDelim(token::Brace))?;
             let mod_inner_lo = self.span;
             let attrs = self.parse_inner_attributes()?;
             let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
+
             self.directory = old_directory;
             Ok((id, ItemKind::Mod(module), Some(attrs)))
         }
@@ -5347,7 +5357,8 @@ pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -
     fn submod_path(&mut self,
                    id: ast::Ident,
                    outer_attrs: &[ast::Attribute],
-                   id_sp: Span) -> PResult<'a, ModulePathSuccess> {
+                   id_sp: Span)
+                   -> PResult<'a, ModulePathSuccess> {
         if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
             return Ok(ModulePathSuccess {
                 directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
index 9c1371a31fec7a9287f9f874c5d59defe042056e..339e7c0b628adcf5a9c9298cd93423c138ae20a5 100644 (file)
@@ -109,7 +109,7 @@ pub fn parse(cx: &base::ExtCtxt, mtch: &[quoted::TokenTree], tts: TokenStream)
             path: cx.current_expansion.module.directory.clone(),
             ownership: cx.current_expansion.directory_ownership,
         };
-        macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory))
+        macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true)
     }
 
     /// Check if this TokenTree is equal to the other, regardless of span information.
index 211c0e6f890313130583ac8d7796ddd6a6403a2d..816d35295542785cc0c5ac9fb8c8c75299c2ca88 100644 (file)
@@ -25,7 +25,6 @@ fn is_send<T: Send>() { }
 fn main() {
     is_send::<Foo>();
     //~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
-    //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8`
     //~| NOTE: `*const u8` cannot be sent between threads safely
     //~| NOTE: required because it appears within the type `Baz`
     //~| NOTE: required because it appears within the type `Bar`
index e31fea1e45863205e40132d17162e04a9fbe9e85..8b34936419db587c2bf844fa54cb23069ccf38b2 100644 (file)
@@ -20,7 +20,6 @@ fn some_func<T: Foo>(foo: T) {
 
 fn f(p: Path) { }
 //~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
-//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
 //~| NOTE `[u8]` does not have a constant size known at compile-time
 //~| NOTE required because it appears within the type `std::path::Path`
 //~| NOTE all local variables must have a statically known size
index 23cff4ac6ad6c219b55eae24f8c8d515c4d30523..4b212814ded2985249dcb8b004a70b1c2f462aa9 100644 (file)
 
 const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
 //~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
 //~| NOTE does not have a constant size known at compile-time
 //~| NOTE constant expressions must have a statically known size
 
 const CONST_FOO: str = *"foo";
 //~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
 //~| NOTE does not have a constant size known at compile-time
 //~| NOTE constant expressions must have a statically known size
 
 static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
 //~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
 //~| NOTE does not have a constant size known at compile-time
 //~| NOTE constant expressions must have a statically known size
 
 static STATIC_BAR: str = *"bar";
 //~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
 //~| NOTE does not have a constant size known at compile-time
 //~| NOTE constant expressions must have a statically known size
 
diff --git a/src/test/compile-fail/feature-gate-loop-break-value.rs b/src/test/compile-fail/feature-gate-loop-break-value.rs
deleted file mode 100644 (file)
index 1632c40..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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.
-
-fn main() {
-    loop {
-        break 123; //~ ERROR `break` with a value is experimental
-    }
-}
index 13e53cab17226d385107b551928608cb95c56a1a..8a5033e76478ba90e0347ff01578f9d25889a381 100644 (file)
@@ -26,7 +26,6 @@ fn send<T: Send>(_: T) {}
 fn main() {
     send(before());
     //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
-    //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
     //~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
     //~| NOTE required because it appears within the type `[closure
     //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
@@ -34,7 +33,6 @@ fn main() {
 
     send(after());
     //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
-    //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
     //~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
     //~| NOTE required because it appears within the type `[closure
     //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
diff --git a/src/test/compile-fail/isssue-38821.rs b/src/test/compile-fail/isssue-38821.rs
new file mode 100644 (file)
index 0000000..63de780
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2017 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.
+
+pub struct Nullable<T: NotNull>(T);
+
+pub trait NotNull {}
+
+pub trait IntoNullable {
+    type Nullable;
+}
+
+impl<T: NotNull> IntoNullable for T {
+    type Nullable = Nullable<T>;
+}
+
+impl<T: NotNull> IntoNullable for Nullable<T> {
+    type Nullable = Nullable<T>;
+}
+
+pub trait Expression {
+    type SqlType;
+}
+
+pub trait Column: Expression {}
+
+#[derive(Debug, Copy, Clone)]
+//~^ ERROR the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+pub enum ColumnInsertValue<Col, Expr> where
+    Col: Column,
+    Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
+{
+    Expression(Col, Expr),
+    Default(Col),
+}
+
+fn main() {}
index a414321899203d17b0f16642a9e8fc0e67170d18..938f7fba2a0324320b3616e4b68e8acc66ec5ce9 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(loop_break_value)]
 #![feature(never_type)]
 
 fn main() {
index 0ad9f21e0983f491bc079f65dfec4e4e76656f5f..0df8c41ffe1a8e52ae7fa2f710305af478c78348 100644 (file)
@@ -42,17 +42,14 @@ fn index(&self, _index: Bar<usize>) -> &i32 {
 fn main() {
     Index::index(&[] as &[i32], 2u32);
     //~^ ERROR E0277
-    //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
     //~| NOTE trait message
     //~| NOTE required by
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
-    //~| NOTE the trait `Index<Foo<u32>>` is not implemented for `[i32]`
     //~| NOTE on impl for Foo
     //~| NOTE required by
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
-    //~| NOTE the trait `Index<Bar<u32>>` is not implemented for `[i32]`
     //~| NOTE on impl for Bar
     //~| NOTE required by
 }
index a7c599330a070e70051a8b9b7771bcefb7c26b12..79021cd03ccc13e6fa12f35d6f1ab23c28338252 100644 (file)
@@ -31,7 +31,6 @@ fn index(&self, index: usize) -> &i32 {
 fn main() {
     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
     //~^ ERROR E0277
-    //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
     //~| NOTE a usize is required
     //~| NOTE required by
 }
index 0f4b0919b6500842c7566ceefa0f099fb0a05bf5..a8daef356a5ccb809565bac96259e955ece9d11a 100644 (file)
@@ -35,9 +35,8 @@ pub fn main() {
     //~^ ERROR
     //~^^ NOTE a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
     //~^^^ NOTE required by `collect`
-    //~| NOTE the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
+
     let x: String = foobar(); //~ ERROR
     //~^ NOTE test error `std::string::String` with `u8` `_` `u32`
     //~^^ NOTE required by `foobar`
-    //~| NOTE the trait `Foo<u8, _, u32>` is not implemented for `std::string::String`
 }
index 1a9ed2dd6e4dcd957c4350c44b1af6ed61bec546..5d30c2e982ef719e30a0894788cf32af3fa8bf4c 100644 (file)
@@ -20,10 +20,8 @@ fn main() {
     let x = &[1, 2, 3] as &[i32];
     x[1i32]; //~ ERROR E0277
              //~| NOTE slice indices are of type `usize` or ranges of `usize`
-             //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
              //~| NOTE required because of the requirements on the impl of `std::ops::Index<i32>`
     x[..1i32]; //~ ERROR E0277
                //~| NOTE slice indices are of type `usize` or ranges of `usize`
-               //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
                //~| NOTE requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>`
 }
diff --git a/src/test/compile-fail/partialeq_help.rs b/src/test/compile-fail/partialeq_help.rs
new file mode 100644 (file)
index 0000000..52c2447
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+fn foo<T: PartialEq>(a: &T, b: T) {
+    a == b; //~ ERROR E0277
+            //~| NOTE can't compare `&T` with `T`
+            //~| HELP the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
+            //~| HELP consider adding a `where &T: std::cmp::PartialEq<T>` bound
+}
+
+fn main() {
+    foo(&1, 1);
+}
index 7530d8890b98c9397f45e10bb23fab948959ecf7..2c38d8d2e28ba2e3e1f6355a79df3e80b8883d2d 100644 (file)
@@ -16,51 +16,53 @@ fn check<T: Iterator, U: ?Sized>() {
     // suggest a where-clause, if needed
     mem::size_of::<U>();
     //~^ ERROR `U: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
     //~| HELP consider adding a `where U: std::marker::Sized` bound
     //~| NOTE required by `std::mem::size_of`
+    //~| NOTE `U` does not have a constant size known at compile-time
+    //~| HELP the trait `std::marker::Sized` is not implemented for `U`
 
     mem::size_of::<Misc<U>>();
     //~^ ERROR `U: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
     //~| HELP consider adding a `where U: std::marker::Sized` bound
     //~| NOTE required because it appears within the type `Misc<U>`
     //~| NOTE required by `std::mem::size_of`
+    //~| NOTE `U` does not have a constant size known at compile-time
+    //~| HELP within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
 
     // ... even if T occurs as a type parameter
 
     <u64 as From<T>>::from;
     //~^ ERROR `u64: std::convert::From<T>` is not satisfied
-    //~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
     //~| HELP consider adding a `where u64: std::convert::From<T>` bound
     //~| NOTE required by `std::convert::From::from`
+    //~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
 
     <u64 as From<<T as Iterator>::Item>>::from;
     //~^ ERROR `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
-    //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
     //~| HELP consider adding a `where u64:
     //~| NOTE required by `std::convert::From::from`
+    //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
 
     // ... but not if there are inference variables
 
     <Misc<_> as From<T>>::from;
     //~^ ERROR `Misc<_>: std::convert::From<T>` is not satisfied
-    //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
     //~| NOTE required by `std::convert::From::from`
+    //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
 
     // ... and also not if the error is not related to the type
 
     mem::size_of::<[T]>();
     //~^ ERROR `[T]: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `[T]`
     //~| NOTE `[T]` does not have a constant size
     //~| NOTE required by `std::mem::size_of`
+    //~| HELP the trait `std::marker::Sized` is not implemented for `[T]`
 
     mem::size_of::<[&U]>();
     //~^ ERROR `[&U]: std::marker::Sized` is not satisfied
-    //~| NOTE the trait `std::marker::Sized` is not implemented for `[&U]`
     //~| NOTE `[&U]` does not have a constant size
     //~| NOTE required by `std::mem::size_of`
+    //~| HELP the trait `std::marker::Sized` is not implemented for `[&U]`
 }
 
 fn main() {
diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs
new file mode 100644 (file)
index 0000000..9fb725a
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2017 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.
+
+// Check that when we compile the static `XXX` into MIR, we do not
+// generate `StorageStart` or `StorageEnd` statements.
+
+// ignore-tidy-linelength
+
+static XXX: &'static Foo = &Foo {
+    tup: "hi",
+    data: &[
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+        (0, 1), (0, 2), (0, 3),
+    ]
+};
+
+#[derive(Debug)]
+struct Foo {
+    tup: &'static str,
+    data: &'static [(u32, u32)]
+}
+
+fn main() {
+    println!("{:?}", XXX);
+}
+
+// END RUST SOURCE
+// START rustc.node4.mir_map.0.mir
+//    bb0: {
+//        _7 = (const 0u32, const 1u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15
+//        _8 = (const 0u32, const 2u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23
+//        _9 = (const 0u32, const 3u32);   // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31
+//        _10 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15
+//        _11 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23
+//        _12 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31
+//        _13 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15
+//        _14 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23
+//        _15 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31
+//        _16 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15
+//        _17 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23
+//        _18 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31
+//        _19 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15
+//        _20 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23
+//        _21 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31
+//        _22 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15
+//        _23 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23
+//        _24 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31
+//        _25 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15
+//        _26 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23
+//        _27 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31
+//        _28 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15
+//        _29 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23
+//        _30 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31
+//        _31 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15
+//        _32 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23
+//        _33 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31
+//        _34 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15
+//        _35 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23
+//        _36 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31
+//        _37 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15
+//        _38 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23
+//        _39 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31
+//        _40 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15
+//        _41 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23
+//        _42 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31
+//        _43 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15
+//        _44 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23
+//        _45 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31
+//        _46 = (const 0u32, const 1u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15
+//        _47 = (const 0u32, const 2u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23
+//        _48 = (const 0u32, const 3u32);  // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31
+//        _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6
+//        _5 = &_6;                        // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _4 = &(*_5);                     // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+//        _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2
+//        _1 = &_2;                        // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+//        _0 = &(*_1);                     // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+//        return;                          // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3
+//    }
+// END rustc.node4.mir_map.0.mir
index adfaf62b5d3cc04aa203f3ee2810725f63d45450..1bdeb121a55d5ed555246cdf69d2d4a1448dc694 100644 (file)
@@ -9,10 +9,9 @@
 // except according to those terms.
 
 // compile-flags: -Z parse-only
-// ignore-tidy-linelength
 
 fn main() {
     let y = 0;
     //~^ ERROR unknown start of token: \u{37e}
-    //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not
+    //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not
 }
index 023f2218b87ae7e7afaf853e5d953b53363da95e..b41e8e9226b326e43f87d5eacf0d83f2d27064c0 100644 (file)
@@ -20,6 +20,8 @@
 trait Sized {}
 #[lang = "copy"]
 trait Copy {}
+#[lang = "freeze"]
+trait Freeze {}
 
 #[cfg(target_has_atomic = "8")]
 pub unsafe fn atomic_u8(x: *mut u8) {
index a603b225132d45ecfade7dd0abf54f1141eaa5a6..2e6fb11a12d6bb6cae799208fd617aa85f4bb35c 100644 (file)
@@ -13,8 +13,7 @@ trait Lattice {
     const BOTTOM: Self;
 }
 
-// FIXME(#33573): this should work without the 'static lifetime bound.
-impl<T: 'static> Lattice for Option<T> {
+impl<T> Lattice for Option<T> {
     const BOTTOM: Option<T> = None;
 }
 
index 656e90d2d52d7e0f57cf3f1d1add2791df92bd7a..723a98bcdfa0d85a894e7aea8d20739afdc0aff0 100644 (file)
@@ -15,7 +15,6 @@
 // like to revisit these and potentially change them. --nmatsakis
 
 #![feature(never_type)]
-#![feature(loop_break_value)]
 
 trait BadDefault {
     fn default() -> Self;
index 4906a8e71d7a4fad61a4d5b57bbedb7e4d5f7500..1d5c83bc20d9554c3244eaa3d7513d1982d7f255 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(loop_break_value)]
 #![feature(never_type)]
 
 #[allow(unused)]
index cfa9f6e36e9bcb37fce6b735ed61b6e3d925ff08..372d4a8b732acfb44151cd560e3d489653ffd179 100644 (file)
@@ -82,7 +82,7 @@ pub fn main() {
     short.next();
     assert_eq!(long.size_hint(), (255, Some(255)));
     assert_eq!(short.size_hint(), (0, Some(0)));
-    assert_eq!(short, RangeInclusive::Empty { at: 42 });
+    assert_eq!(short, 1...0);
 
     assert_eq!(long.len(), 255);
     assert_eq!(short.len(), 0);
@@ -97,28 +97,28 @@ pub fn main() {
     for i in 3...251 {
         assert_eq!(long.next(), Some(i));
     }
-    assert_eq!(long, RangeInclusive::Empty { at: 251 });
+    assert_eq!(long, 1...0);
 
     // check underflow
     let mut narrow = 1...0;
     assert_eq!(narrow.next_back(), None);
-    assert_eq!(narrow, RangeInclusive::Empty { at: 0 });
+    assert_eq!(narrow, 1...0);
     let mut zero = 0u8...0;
     assert_eq!(zero.next_back(), Some(0));
     assert_eq!(zero.next_back(), None);
-    assert_eq!(zero, RangeInclusive::Empty { at: 0 });
+    assert_eq!(zero, 1...0);
     let mut high = 255u8...255;
     assert_eq!(high.next_back(), Some(255));
     assert_eq!(high.next_back(), None);
-    assert_eq!(high, RangeInclusive::Empty { at: 255 });
+    assert_eq!(high, 1...0);
 
     // what happens if you have a nonsense range?
     let mut nonsense = 10...5;
     assert_eq!(nonsense.next(), None);
-    assert_eq!(nonsense, RangeInclusive::Empty { at: 10 });
+    assert_eq!(nonsense, 10...5);
 
     // output
     assert_eq!(format!("{:?}", 0...10), "0...10");
     assert_eq!(format!("{:?}", ...10), "...10");
-    assert_eq!(format!("{:?}", long), "[empty range @ 251]");
+    assert_eq!(format!("{:?}", long), "1...0");
 }
diff --git a/src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs b/src/test/rustdoc/inline_cross/auxiliary/renamed-via-module.rs
new file mode 100644 (file)
index 0000000..9f7a259
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 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.
+
+#![crate_name = "foo"]
+
+pub mod iter {
+    mod range {
+        pub struct StepBy;
+    }
+    pub use self::range::StepBy as DeprecatedStepBy;
+    pub struct StepBy;
+}
diff --git a/src/test/rustdoc/inline_cross/renamed-via-module.rs b/src/test/rustdoc/inline_cross/renamed-via-module.rs
new file mode 100644 (file)
index 0000000..a4e0154
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2017 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.
+
+// aux-build:renamed-via-module.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "bar"]
+
+extern crate foo;
+
+// @has foo/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has foo/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct foo::iter::DeprecatedStepBy"
+// @has foo/iter/struct.StepBy.html
+// @has - '//h1' "Struct foo::iter::StepBy"
+
+// @has bar/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has bar/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct bar::iter::DeprecatedStepBy"
+// @has bar/iter/struct.StepBy.html
+// @has - '//h1' "Struct bar::iter::StepBy"
+pub use foo::iter;
index bd024d6766eda590a809243fed7daa8407a51714..08d9043f65ecd9d4a5e47b854e0629dbd149ca98 100644 (file)
@@ -11,9 +11,9 @@ error[E0277]: the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
   --> $DIR/equality.rs:34:9
    |
 34 |         n + sum_to(n - 1)
-   |         ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+   |         ^^^^^^^^^^^^^^^^^ no implementation for `u32 + impl Foo`
    |
-   = note: no implementation for `u32 + impl Foo`
+   = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
 
 error[E0308]: mismatched types
   --> $DIR/equality.rs:53:18
index 790f796fae07f787a64fba8266b46ede5ed7bb65..b52d540fd75119dc5d24c87f7ca06f9888f5a4ab 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(loop_break_value)]
 #![allow(unused_variables)]
 
 use std::ptr;
index 0d99abd3907d81b40a67e8959a1d9edf747db9f5..c154ea6f8c2d68e76a7ff04e24ad6b2a5b2b5017 100644 (file)
@@ -1,7 +1,7 @@
 error[E0571]: `break` with value from a `for` loop
-  --> $DIR/loop-break-value-no-repeat.rs:23:9
+  --> $DIR/loop-break-value-no-repeat.rs:22:9
    |
-23 |         break 22
+22 |         break 22
    |         ^^^^^^^^ can only break with a value inside `loop`
 
 error: aborting due to previous error
index a0f7ff6587097bedc2ed08f3bc2e22af36f918ce..773bf0593c51390f2ca205b19d14dac6425c0957 100644 (file)
@@ -2,57 +2,57 @@ error[E0277]: the trait bound `{integer}: std::ops::Add<std::option::Option<{int
   --> $DIR/binops.rs:12:5
    |
 12 |     1 + Some(1);
-   |     ^^^^^^^^^^^ the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+   |     ^^^^^^^^^^^ no implementation for `{integer} + std::option::Option<{integer}>`
    |
-   = note: no implementation for `{integer} + std::option::Option<{integer}>`
+   = help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
 
 error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
   --> $DIR/binops.rs:13:5
    |
 13 |     2 as usize - Some(1);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+   |     ^^^^^^^^^^^^^^^^^^^^ no implementation for `usize - std::option::Option<{integer}>`
    |
-   = note: no implementation for `usize - std::option::Option<{integer}>`
+   = help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
 
 error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
   --> $DIR/binops.rs:14:5
    |
 14 |     3 * ();
-   |     ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+   |     ^^^^^^ no implementation for `{integer} * ()`
    |
-   = note: no implementation for `{integer} * ()`
+   = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
 
 error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
   --> $DIR/binops.rs:15:5
    |
 15 |     4 / "";
-   |     ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+   |     ^^^^^^ no implementation for `{integer} / &str`
    |
-   = note: no implementation for `{integer} / &str`
+   = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
 
 error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
   --> $DIR/binops.rs:16:5
    |
 16 |     5 < String::new();
-   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
+   |     ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
    |
-   = note: can't compare `{integer}` with `std::string::String`
+   = help: the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
 
 error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
   --> $DIR/binops.rs:16:5
    |
 16 |     5 < String::new();
-   |     ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+   |     ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
    |
-   = note: can't compare `{integer}` with `std::string::String`
+   = help: the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
 
 error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
   --> $DIR/binops.rs:17:5
    |
 17 |     6 == Ok(1);
-   |     ^^^^^^^^^^ the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+   |     ^^^^^^^^^^ can't compare `{integer}` with `std::result::Result<{integer}, _>`
    |
-   = note: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+   = help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
 
 error: aborting due to 7 previous errors
 
index 7fd10f3cb689176f9c23ac53a4c5ee3fee518352..8853b35eb8b33d67ac4b266b14831426be5bda59 100644 (file)
@@ -210,18 +210,18 @@ error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
   --> $DIR/cast-rfc0401.rs:63:13
    |
 63 |     let _ = fat_v as *const Foo;
-   |             ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]`
+   |             ^^^^^ `[u8]` does not have a constant size known at compile-time
    |
-   = note: `[u8]` does not have a constant size known at compile-time
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: required for the cast to the object type `Foo`
 
 error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
   --> $DIR/cast-rfc0401.rs:72:13
    |
 72 |     let _ = a as *const Foo;
-   |             ^ the trait `std::marker::Sized` is not implemented for `str`
+   |             ^ `str` does not have a constant size known at compile-time
    |
-   = note: `str` does not have a constant size known at compile-time
+   = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: required for the cast to the object type `Foo`
 
 error: casting `&{float}` as `f32` is invalid
index 72b1578e0d020f055fe12c5d5019aaaa159e40cb..791b20725f3bcbb5d11ac164da22aa02812e56bf 100644 (file)
@@ -2,9 +2,9 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied
   --> $DIR/issue-5035-2.rs:14:8
    |
 14 | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
-   |        ^^ the trait `std::marker::Sized` is not implemented for `I + 'static`
+   |        ^^ `I + 'static` does not have a constant size known at compile-time
    |
-   = note: `I + 'static` does not have a constant size known at compile-time
+   = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
    = note: all local variables must have a statically known size
 
 error: aborting due to previous error
index 843c1e811d578393ea375cc42338d38a773e7749..44d5379648d5b7e6eceadc7bb1041f16cb107462 100644 (file)
@@ -7,9 +7,9 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
 25 | |         bar(x,
 26 | |
 27 | |             y),
-   | |______________^ the trait `std::ops::Add<()>` is not implemented for `u32`
+   | |______________^ no implementation for `u32 + ()`
    |
-   = note: no implementation for `u32 + ()`
+   = help: the trait `std::ops::Add<()>` is not implemented for `u32`
 
 error: aborting due to previous error
 
index 911f3c51f5f6005f4181f023f67218ca72bd2111..1bec6f6af83814c6f725ff3b529602c040b36a59 100644 (file)
@@ -2415,11 +2415,11 @@ fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
         println!("expected {}:\n{}\n", kind, expected);
         println!("diff of {}:\n", kind);
 
-        for diff in diff::lines(actual, expected) {
+        for diff in diff::lines(expected, actual) {
             match diff {
-                diff::Result::Left(l)    => println!("+{}", l),
+                diff::Result::Left(l)    => println!("-{}", l),
                 diff::Result::Both(l, _) => println!(" {}", l),
-                diff::Result::Right(r)   => println!("-{}", r),
+                diff::Result::Right(r)   => println!("+{}", r),
             }
         }