]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #39552 - zackmdavis:more_struct_aliases_stabilization_version, r...
authorCorey Farwell <coreyf@rwell.org>
Sun, 5 Feb 2017 14:14:57 +0000 (09:14 -0500)
committerGitHub <noreply@github.com>
Sun, 5 Feb 2017 14:14:57 +0000 (09:14 -0500)
correct version in which more_struct_aliases was/will be stable

The stabilizing commit is 5056a437, which is not in 1.14, but is (at
time of writing) on the 1.16 beta branch. [See discussion](https://github.com/rust-lang/rust/pull/39282#discussion_r99481687).

144 files changed:
src/bootstrap/bin/main.rs
src/bootstrap/bootstrap.py
src/bootstrap/dist.rs
src/doc/book/documentation.md
src/doc/book/using-rust-without-the-standard-library.md
src/libcollections/binary_heap.rs
src/libcore/char.rs
src/libcore/convert.rs
src/libcore/internal_macros.rs
src/libcore/iter/mod.rs
src/libcore/iter/traits.rs
src/libcore/num/int_macros.rs
src/libcore/num/uint_macros.rs
src/libcore/num/wrapping.rs
src/libcore/option.rs
src/libcore/slice.rs
src/libcore/sync/atomic.rs
src/libcoretest/iter.rs
src/liblibc
src/librustc/diagnostics.rs
src/librustc/lint/builtin.rs
src/librustc/middle/mem_categorization.rs
src/librustc/mir/tcx.rs
src/librustc/traits/select.rs
src/librustc/traits/util.rs
src/librustc/ty/contents.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/wasm32_unknown_emscripten.rs
src/librustc_borrowck/borrowck/fragments.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_const_eval/_match.rs
src/librustc_const_eval/pattern.rs
src/librustc_driver/test.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_metadata/creader.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/transform/type_check.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/abi.rs
src/librustc_trans/adt.rs
src/librustc_trans/back/link.rs
src/librustc_trans/callee.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/glue.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/libstd/ascii.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/env.rs
src/libstd/fs.rs
src/libstd/io/mod.rs
src/libstd/io/stdio.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/net/mod.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/os/raw.rs
src/libstd/panic.rs
src/libstd/process.rs
src/libstd/sync/barrier.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/unix/ext/process.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/net.rs
src/libstd/sys_common/net.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd_unicode/char.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/derive.rs [new file with mode: 0644]
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/parser.rs
src/libsyntax_ext/deriving/custom.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/test/compile-fail-fulldeps/proc-macro/derive-bad.rs
src/test/compile-fail-fulldeps/proc-macro/load-panic.rs
src/test/compile-fail-fulldeps/proc-macro/no-macro-use-attr.rs
src/test/compile-fail/defaulted-unit-warning.rs [new file with mode: 0644]
src/test/compile-fail/deriving-meta-unknown-trait.rs
src/test/compile-fail/deriving-primitive.rs
src/test/compile-fail/macro-error.rs
src/test/compile-fail/macros-nonfatal-errors.rs
src/test/compile-fail/no-link.rs
src/test/pretty/attr-derive.rs [new file with mode: 0644]
src/test/pretty/attr-variant-data.rs [deleted file]
src/test/pretty/auxiliary/derive-foo.rs [new file with mode: 0644]
src/test/run-make/atomic-lock-free/atomic_lock_free.rs
src/test/rustdoc/issue-38129.rs [new file with mode: 0644]
src/test/ui/custom-derive/issue-36935.stderr
src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr [new file with mode: 0644]

index c47f4fd8ec64b8f288855ae6638e56a3142bd68b..5ca5ce1648f2fc80ee0735f723dc5523333a2e26 100644 (file)
@@ -11,8 +11,8 @@
 //! rustbuild, the Rust build system
 //!
 //! This is the entry point for the build system used to compile the `rustc`
-//! compiler. Lots of documentation can be found in the `README.md` file next to
-//! this file, and otherwise documentation can be found throughout the `build`
+//! compiler. Lots of documentation can be found in the `README.md` file in the
+//! parent directory, and otherwise documentation can be found throughout the `build`
 //! directory in each respective module.
 
 #![deny(warnings)]
index 85e8dbce1a955000d839be8289a27069d4180dbf..bc8341102421b8f217311eca2903f5a92e217c4a 100644 (file)
@@ -438,14 +438,14 @@ def main():
     rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \
                               'CFG_ENABLE_VENDOR' in rb.config_mk
 
-    if 'SUDO_USER' in os.environ:
-        if os.environ['USER'] != os.environ['SUDO_USER']:
+    if 'SUDO_USER' in os.environ and not rb.use_vendored_sources:
+        if os.environ.get('USER') != os.environ['SUDO_USER']:
             rb.use_vendored_sources = True
             print('info: looks like you are running this command under `sudo`')
             print('      and so in order to preserve your $HOME this will now')
             print('      use vendored sources by default. Note that if this')
             print('      does not work you should run a normal build first')
-            print('      before running a command like `sudo make intall`')
+            print('      before running a command like `sudo make install`')
 
     if rb.use_vendored_sources:
         if not os.path.exists('.cargo'):
index 5fac142f777ff2b71893a93e3b8f8ce7fad95b81..9327cc0cf7faf63845940cbe6f113e4584cc4e9c 100644 (file)
@@ -381,7 +381,8 @@ pub fn rust_src(build: &Build) {
         "README.md",
         "RELEASES.md",
         "configure",
-        "Makefile.in"
+        "Makefile.in",
+        "x.py",
     ];
     let src_dirs = [
         "man",
index dafcffc39c802b0ff992fb4be06d8b9e5f86fcf2..d2402ddb2e957596c9edb506bbb42a06c4226d91 100644 (file)
@@ -601,7 +601,7 @@ is documented, especially when you are working on a library. Rust allows you to
 to generate warnings or errors, when an item is missing documentation.
 To generate warnings you use `warn`:
 
-```rust
+```rust,ignore
 #![warn(missing_docs)]
 ```
 
@@ -631,7 +631,7 @@ struct Hidden;
 You can control a few aspects of the HTML that `rustdoc` generates through the
 `#![doc]` version of the attribute:
 
-```rust
+```rust,ignore
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://www.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/")]
index 69958dd3e68a41c717527cc05347eb9d064705d1..e66e1d05fff73c7aea6f406280f88a2b3e66ff95 100644 (file)
@@ -13,7 +13,7 @@ don’t want to use the standard library via an attribute: `#![no_std]`.
 
 To use `#![no_std]`, add it to your crate root:
 
-```rust
+```rust,ignore
 #![no_std]
 
 fn plus_one(x: i32) -> i32 {
@@ -29,7 +29,7 @@ use its features without an explicit import. By the same token, when using
 prelude](../core/prelude/v1/index.html). This means that a lot of code will Just
 Work:
 
-```rust
+```rust,ignore
 #![no_std]
 
 fn may_fail(failure: bool) -> Result<(), &'static str> {
index b7c2a708baf492f91dfdc0976ac8d7dced7dbbbe..23e0295ba5401b998749699796088c25bae7cec2 100644 (file)
@@ -1088,7 +1088,7 @@ fn is_empty(&self) -> bool {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T: 'a> FusedIterator for Drain<'a, T> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
     fn from(vec: Vec<T>) -> BinaryHeap<T> {
         let mut heap = BinaryHeap { data: vec };
@@ -1097,7 +1097,7 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T> From<BinaryHeap<T>> for Vec<T> {
     fn from(heap: BinaryHeap<T>) -> Vec<T> {
         heap.data
index 367422f55364a997d5a83b85d7e94820b37bde69..78764091cf03275a3569dc30bae907ff275292d7 100644 (file)
@@ -588,7 +588,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for EscapeUnicode {}
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
 impl fmt::Display for EscapeUnicode {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for c in self.clone() {
@@ -701,7 +701,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for EscapeDefault {}
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
 impl fmt::Display for EscapeDefault {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for c in self.clone() {
@@ -735,7 +735,7 @@ impl ExactSizeIterator for EscapeDebug { }
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for EscapeDebug {}
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[unstable(feature = "char_escape_debug", issue = "35068")]
 impl fmt::Display for EscapeDebug {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&self.0, f)
index abd686b15e22b5f90a4603991b771a26d7007992..4e170794c1d6e411d57443a56c91e2ff7339f93b 100644 (file)
@@ -225,7 +225,7 @@ pub trait TryFrom<T>: Sized {
     type Err;
 
     /// Performs the conversion.
-    fn try_from(T) -> Result<Self, Self::Err>;
+    fn try_from(value: T) -> Result<Self, Self::Err>;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index f2cdc9d6a98c540de1c55271509687c2f0a89b71..9a7914064fdd56bb176fe19d1d811a288ff6ba79 100644 (file)
 // based on "op T" where T is expected to be `Copy`able
 macro_rules! forward_ref_unop {
     (impl $imp:ident, $method:ident for $t:ty) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
+        forward_ref_unop!(impl $imp, $method for $t,
+                #[stable(feature = "rust1", since = "1.0.0")]);
+    };
+    (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
+        #[$attr]
         impl<'a> $imp for &'a $t {
             type Output = <$t as $imp>::Output;
 
@@ -29,7 +33,11 @@ fn $method(self) -> <$t as $imp>::Output {
 // based on "T op U" where T and U are expected to be `Copy`able
 macro_rules! forward_ref_binop {
     (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
+        forward_ref_binop!(impl $imp, $method for $t, $u,
+                #[stable(feature = "rust1", since = "1.0.0")]);
+    };
+    (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
+        #[$attr]
         impl<'a> $imp<$u> for &'a $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -39,7 +47,7 @@ fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
             }
         }
 
-        #[stable(feature = "rust1", since = "1.0.0")]
+        #[$attr]
         impl<'a> $imp<&'a $u> for $t {
             type Output = <$t as $imp<$u>>::Output;
 
@@ -49,7 +57,7 @@ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
             }
         }
 
-        #[stable(feature = "rust1", since = "1.0.0")]
+        #[$attr]
         impl<'a, 'b> $imp<&'a $u> for &'b $t {
             type Output = <$t as $imp<$u>>::Output;
 
index 3999db0d63c99ac8770076f537e8807d5a8e33cc..d9b8c5ea589fd57aa74a840b889ae5aad9deb4de 100644 (file)
@@ -1086,7 +1086,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
-        for x in self.iter.by_ref() {
+        for x in &mut self.iter {
             if (self.predicate)(&x) {
                 return Some(x);
             }
@@ -1099,6 +1099,26 @@ fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
     }
+
+    // this special case allows the compiler to make `.filter(_).count()`
+    // branchless. Barring perfect branch prediction (which is unattainable in
+    // the general case), this will be much faster in >90% of cases (containing
+    // virtually all real workloads) and only a tiny bit slower in the rest.
+    //
+    // Having this specialization thus allows us to write `.filter(p).count()`
+    // where we would otherwise write `.map(|x| p(x) as usize).sum()`, which is
+    // less readable and also less backwards-compatible to Rust before 1.10.
+    //
+    // Using the branchless version will also simplify the LLVM byte code, thus
+    // leaving more budget for LLVM optimizations.
+    #[inline]
+    fn count(mut self) -> usize {
+        let mut count = 0;
+        for x in &mut self.iter {
+            count += (self.predicate)(&x) as usize;
+        }
+        count
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index a86ceb9ac0d370a469c8be4156a93d51ae93691f..cb180110d3cc0116159b137a1201c744ba677264 100644 (file)
@@ -661,29 +661,29 @@ pub trait Product<A = Self>: Sized {
 
 // NB: explicitly use Add and Mul here to inherit overflow checks
 macro_rules! integer_sum_product {
-    (@impls $zero:expr, $one:expr, $($a:ty)*) => ($(
-        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+    (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
+        #[$attr]
         impl Sum for $a {
             fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
                 iter.fold($zero, Add::add)
             }
         }
 
-        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+        #[$attr]
         impl Product for $a {
             fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
                 iter.fold($one, Mul::mul)
             }
         }
 
-        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+        #[$attr]
         impl<'a> Sum<&'a $a> for $a {
             fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
                 iter.fold($zero, Add::add)
             }
         }
 
-        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+        #[$attr]
         impl<'a> Product<&'a $a> for $a {
             fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
                 iter.fold($one, Mul::mul)
@@ -691,8 +691,12 @@ fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
         }
     )*);
     ($($a:ty)*) => (
-        integer_sum_product!(@impls 0, 1, $($a)+);
-        integer_sum_product!(@impls Wrapping(0), Wrapping(1), $(Wrapping<$a>)+);
+        integer_sum_product!(@impls 0, 1,
+                #[stable(feature = "iter_arith_traits", since = "1.12.0")],
+                $($a)+);
+        integer_sum_product!(@impls Wrapping(0), Wrapping(1),
+                #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
+                $(Wrapping<$a>)+);
     );
 }
 
index 04311d687ea92ad94e5f1a4bd9dcaa1f977e4fd1..3b1612a4ee29f8d051c0a8ec4b2cef9fa314c634 100644 (file)
 
 macro_rules! int_module {
     ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
-    ($T:ident, $($attr: tt)*) => (
+    ($T:ident, #[$attr:meta]) => (
         /// The smallest value that can be represented by this integer type.
-        $($attr)*
+        #[$attr]
         pub const MIN: $T = $T::min_value();
         /// The largest value that can be represented by this integer type.
-        $($attr)*
+        #[$attr]
         pub const MAX: $T = $T::max_value();
     )
 }
index 2e59b39278ab6a9716b57b6bb21d3eba105ced19..f7e1f78d69ebf64396ae21e6cbff0323b4056b5b 100644 (file)
 
 macro_rules! uint_module {
     ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]););
-    ($T:ident, $($attr: tt)*) => (
+    ($T:ident, #[$attr:meta]) => (
         /// The smallest value that can be represented by this integer type.
-        $($attr)*
+        #[$attr]
         pub const MIN: $T = $T::min_value();
         /// The largest value that can be represented by this integer type.
-        $($attr)*
+        #[$attr]
         pub const MAX: $T = $T::max_value();
     )
 }
index 50007c7d9b01a6a0f8270dbe5bc9299c795b30c5..013f02685bad117149951d86e56b9c3f662d6f71 100644 (file)
@@ -131,7 +131,8 @@ fn add(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_add(other.0))
             }
         }
-        forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl AddAssign for Wrapping<$t> {
@@ -150,7 +151,8 @@ fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_sub(other.0))
             }
         }
-        forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl SubAssign for Wrapping<$t> {
@@ -169,7 +171,8 @@ fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_mul(other.0))
             }
         }
-        forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl MulAssign for Wrapping<$t> {
@@ -188,7 +191,8 @@ fn div(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_div(other.0))
             }
         }
-        forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl DivAssign for Wrapping<$t> {
@@ -207,7 +211,8 @@ fn rem(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0.wrapping_rem(other.0))
             }
         }
-        forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl RemAssign for Wrapping<$t> {
@@ -226,7 +231,8 @@ fn not(self) -> Wrapping<$t> {
                 Wrapping(!self.0)
             }
         }
-        forward_ref_unop! { impl Not, not for Wrapping<$t> }
+        forward_ref_unop! { impl Not, not for Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl BitXor for Wrapping<$t> {
@@ -237,7 +243,8 @@ fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 ^ other.0)
             }
         }
-        forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitXorAssign for Wrapping<$t> {
@@ -256,7 +263,8 @@ fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 | other.0)
             }
         }
-        forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitOrAssign for Wrapping<$t> {
@@ -275,7 +283,8 @@ fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
                 Wrapping(self.0 & other.0)
             }
         }
-        forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t> }
+        forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
 
         #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitAndAssign for Wrapping<$t> {
@@ -293,7 +302,8 @@ fn neg(self) -> Self {
                 Wrapping(0) - self
             }
         }
-        forward_ref_unop! { impl Neg, neg for Wrapping<$t> }
+        forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
+                #[stable(feature = "wrapping_ref", since = "1.14.0")] }
     )*)
 }
 
index c4d7b2dcf96fb258f38a88754387d2e4cda4ba9c..9df8350d90ffdc8cb864ed4899b57018e390139f 100644 (file)
@@ -632,6 +632,76 @@ 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
+    /// returns a mutable reference to the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_entry)]
+    ///
+    /// let mut x = None;
+    ///
+    /// {
+    ///     let y: &mut u32 = x.get_or_insert(5);
+    ///     assert_eq!(y, &5);
+    ///
+    ///     *y = 7;
+    /// }
+    ///
+    /// assert_eq!(x, Some(7));
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_entry", issue = "39288")]
+    pub fn get_or_insert(&mut self, v: T) -> &mut T {
+        match *self {
+            None => *self = Some(v),
+            _ => (),
+        }
+
+        match *self {
+            Some(ref mut v) => v,
+            _ => unreachable!(),
+        }
+    }
+
+    /// Inserts a value computed from `f` into the option if it is `None`, then
+    /// returns a mutable reference to the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_entry)]
+    ///
+    /// let mut x = None;
+    ///
+    /// {
+    ///     let y: &mut u32 = x.get_or_insert_with(|| 5);
+    ///     assert_eq!(y, &5);
+    ///
+    ///     *y = 7;
+    /// }
+    ///
+    /// assert_eq!(x, Some(7));
+    /// ```
+    #[inline]
+    #[unstable(feature = "option_entry", issue = "39288")]
+    pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
+        match *self {
+            None => *self = Some(f()),
+            _ => (),
+        }
+
+        match *self {
+            Some(ref mut v) => v,
+            _ => unreachable!(),
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Misc
     /////////////////////////////////////////////////////////////////////////
index b942d85f9808bd8147b8dd5d79ecf36c3559bde4..1a482b75731c102fc36b1e92d772822f2e8a07fd 100644 (file)
@@ -616,7 +616,7 @@ pub trait SliceIndex<T> {
     fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
 impl<T> SliceIndex<T> for usize {
     type Output = T;
 
@@ -665,7 +665,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut T {
     }
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
 impl<T> SliceIndex<T> for  ops::Range<usize> {
     type Output = [T];
 
@@ -726,7 +726,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
     }
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
 impl<T> SliceIndex<T> for ops::RangeTo<usize> {
     type Output = [T];
 
@@ -761,7 +761,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
     }
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
 impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
     type Output = [T];
 
@@ -796,7 +796,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
     }
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
 impl<T> SliceIndex<T> for ops::RangeFull {
     type Output = [T];
 
@@ -832,7 +832,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
 }
 
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
     type Output = [T];
 
@@ -895,7 +895,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
     }
 }
 
-#[stable(feature = "slice-get-slice-impls", since = "1.13.0")]
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
     type Output = [T];
 
index 743e3c41170a34d0c99ef3575cd234811eb3deb2..58cd0af7ee38752618f90bff1524d6dfe2b99524 100644 (file)
@@ -1318,6 +1318,24 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     u64 AtomicU64 ATOMIC_U64_INIT
 }
+#[cfg(not(stage0))]
+#[cfg(target_has_atomic = "128")]
+atomic_int! {
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    i128 AtomicI128 ATOMIC_I128_INIT
+}
+#[cfg(not(stage0))]
+#[cfg(target_has_atomic = "128")]
+atomic_int! {
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    unstable(feature = "i128", issue = "35118"),
+    u128 AtomicU128 ATOMIC_U128_INIT
+}
 #[cfg(target_has_atomic = "ptr")]
 atomic_int!{
     stable(feature = "rust1", since = "1.0.0"),
index 6d02f76c33d162ed628f2c9a93488f2b1790c1eb..c7833dbd15629431504d6b9935a5334022926bc4 100644 (file)
@@ -191,6 +191,12 @@ fn test_iterator_enumerate_count() {
     assert_eq!(xs.iter().count(), 6);
 }
 
+#[test]
+fn test_iterator_filter_count() {
+    let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(xs.iter().filter(|&&x| x % 2 == 0).count(), 5);
+}
+
 #[test]
 fn test_iterator_peekable() {
     let xs = vec![0, 1, 2, 3, 4, 5];
index 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc..cb7f66732175e6171587ed69656b7aae7dd2e6ec 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7d57bdcdbb56540f37afe5a934ce12d33a6ca7fc
+Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec
index b51a7d4104ab92865a5f76d3ba2c3f542a32f690..cf51dad5142eea278649b6da04897c03292744ce 100644 (file)
@@ -620,7 +620,7 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
 You can build a free-standing crate by adding `#![no_std]` to the crate
 attributes:
 
-```
+```ignore
 #![no_std]
 ```
 
index e1605959922c0530e64e1a2b1ab299282afc6639..70f03e02f46d9b9c6a8dd7c22c7afaa2cd4f31ae 100644 (file)
     "lifetimes or labels named `'_` were erroneously allowed"
 }
 
+declare_lint! {
+    pub RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
+    Warn,
+    "attempt to resolve a trait on an expression whose type cannot be inferred but which \
+     currently defaults to ()"
+}
+
 declare_lint! {
     pub SAFE_EXTERN_STATICS,
     Warn,
@@ -272,6 +279,7 @@ fn get_lints(&self) -> LintArray {
             SUPER_OR_SELF_IN_GLOBAL_PATH,
             HR_LIFETIME_IN_ASSOC_TYPE,
             LIFETIME_UNDERSCORE,
+            RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
             SAFE_EXTERN_STATICS,
             PATTERNS_IN_FNS_WITHOUT_BODY,
             EXTRA_REQUIREMENT_IN_IMPL,
index 0e8e1921de700fc1f7a77161bbb9162d1c051c5f..9d1bcb8164a9e08c477ef02cab8e6f6f7bb700de 100644 (file)
@@ -1199,7 +1199,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul
           PatKind::Tuple(ref subpats, ddpos) => {
             // (p1, ..., pN)
             let expected_len = match self.pat_ty(&pat)?.sty {
-                ty::TyTuple(ref tys) => tys.len(),
+                ty::TyTuple(ref tys, _) => tys.len(),
                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
index 03530945e046df3651199a4438ffed8f80610f3d..f1268521d67086781de6701def629e40d4ab251e 100644 (file)
@@ -163,7 +163,7 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Opti
                 let lhs_ty = lhs.ty(mir, tcx);
                 let rhs_ty = rhs.ty(mir, tcx);
                 let ty = op.ty(tcx, lhs_ty, rhs_ty);
-                let ty = tcx.intern_tup(&[ty, tcx.types.bool]);
+                let ty = tcx.intern_tup(&[ty, tcx.types.bool], false);
                 Some(ty)
             }
             &Rvalue::UnaryOp(_, ref operand) => {
@@ -184,7 +184,8 @@ pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Opti
                     }
                     AggregateKind::Tuple => {
                         Some(tcx.mk_tup(
-                            ops.iter().map(|op| op.ty(mir, tcx))
+                            ops.iter().map(|op| op.ty(mir, tcx)),
+                            false
                         ))
                     }
                     AggregateKind::Adt(def, _, substs, _) => {
index d51332f833d77cfdbefddc812c1092da8d7177c6..41f3f825c3d191e16770527fd80819af4ef77719 100644 (file)
@@ -52,6 +52,7 @@
 use std::rc::Rc;
 use syntax::abi::Abi;
 use hir;
+use lint;
 use util::nodemap::FxHashMap;
 
 struct InferredObligationsSnapshotVecDelegate<'tcx> {
@@ -407,19 +408,62 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
         debug!("select({:?})", obligation);
         assert!(!obligation.predicate.has_escaping_regions());
 
+        let tcx = self.tcx();
         let dep_node = obligation.predicate.dep_node();
-        let _task = self.tcx().dep_graph.in_task(dep_node);
+        let _task = tcx.dep_graph.in_task(dep_node);
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
-        match self.candidate_from_obligation(&stack)? {
-            None => Ok(None),
+        let ret = match self.candidate_from_obligation(&stack)? {
+            None => None,
             Some(candidate) => {
                 let mut candidate = self.confirm_candidate(obligation, candidate)?;
                 let inferred_obligations = (*self.inferred_obligations).into_iter().cloned();
                 candidate.nested_obligations_mut().extend(inferred_obligations);
-                Ok(Some(candidate))
+                Some(candidate)
             },
+        };
+
+        // Test whether this is a `()` which was produced by defaulting a
+        // diverging type variable with `!` disabled. If so, we may need
+        // to raise a warning.
+        if obligation.predicate.skip_binder().self_ty().is_defaulted_unit() {
+            let mut raise_warning = true;
+            // Don't raise a warning if the trait is implemented for ! and only
+            // permits a trivial implementation for !. This stops us warning
+            // about (for example) `(): Clone` becoming `!: Clone` because such
+            // a switch can't cause code to stop compiling or execute
+            // differently.
+            let mut never_obligation = obligation.clone();
+            let def_id = never_obligation.predicate.skip_binder().trait_ref.def_id;
+            never_obligation.predicate = never_obligation.predicate.map_bound(|mut trait_pred| {
+                // Swap out () with ! so we can check if the trait is impld for !
+                {
+                    let mut trait_ref = &mut trait_pred.trait_ref;
+                    let unit_substs = trait_ref.substs;
+                    let mut never_substs = Vec::with_capacity(unit_substs.len());
+                    never_substs.push(From::from(tcx.types.never));
+                    never_substs.extend(&unit_substs[1..]);
+                    trait_ref.substs = tcx.intern_substs(&never_substs);
+                }
+                trait_pred
+            });
+            if let Ok(Some(..)) = self.select(&never_obligation) {
+                if !tcx.trait_relevant_for_never(def_id) {
+                    // The trait is also implemented for ! and the resulting
+                    // implementation cannot actually be invoked in any way.
+                    raise_warning = false;
+                }
+            }
+
+            if raise_warning {
+                tcx.sess.add_lint(lint::builtin::RESOLVE_TRAIT_ON_DEFAULTED_UNIT,
+                                  obligation.cause.body_id,
+                                  obligation.cause.span,
+                                  format!("code relies on type inference rules which are likely \
+                                           to change"));
+            }
         }
+        Ok(ret)
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -1744,7 +1788,7 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
 
             ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
 
-            ty::TyTuple(tys) => {
+            ty::TyTuple(tys, _) => {
                 Where(ty::Binder(tys.last().into_iter().cloned().collect()))
             }
 
@@ -1752,7 +1796,7 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
                 Where(ty::Binder(match sized_crit.sty {
-                    ty::TyTuple(tys) => tys.to_vec().subst(self.tcx(), substs),
+                    ty::TyTuple(tys, _) => tys.to_vec().subst(self.tcx(), substs),
                     ty::TyBool => vec![],
                     _ => vec![sized_crit.subst(self.tcx(), substs)]
                 }))
@@ -1799,7 +1843,7 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(vec![element_ty]))
             }
 
-            ty::TyTuple(tys) => {
+            ty::TyTuple(tys, _) => {
                 // (*) binder moved here
                 Where(ty::Binder(tys.to_vec()))
             }
@@ -1874,7 +1918,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
                 vec![element_ty]
             }
 
-            ty::TyTuple(ref tys) => {
+            ty::TyTuple(ref tys, _) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
                 tys.to_vec()
             }
index cebd8bf87d736cca88ae75bcf5917a22d5193da3..7b2882bb64f2cb97a13825a6e66ae7eefcf0b877 100644 (file)
@@ -489,7 +489,7 @@ pub fn closure_trait_ref_and_return_type(self,
         let arguments_tuple = match tuple_arguments {
             TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
             TupleArgumentsFlag::Yes =>
-                self.intern_tup(sig.skip_binder().inputs()),
+                self.intern_tup(sig.skip_binder().inputs(), false),
         };
         let trait_ref = ty::TraitRef {
             def_id: fn_trait_def_id,
index 00c6dca21b1ef4f5f2a031973b1008498785b420..56621c57eb8f7bed86f3b7c10f99b6fbd565acc1 100644 (file)
@@ -201,7 +201,7 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         |ty| tc_ty(tcx, &ty, cache))
                 }
 
-                ty::TyTuple(ref tys) => {
+                ty::TyTuple(ref tys, _) => {
                     TypeContents::union(&tys[..],
                                         |ty| tc_ty(tcx, *ty, cache))
                 }
index 7dcbe04caf82bcc9d93db94f9ec17a3469a879f5..a0eae33c4402b20c5a03478840ae208efe05bc54 100644 (file)
@@ -1384,23 +1384,24 @@ pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         self.mk_ty(TySlice(ty))
     }
 
-    pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
-        self.mk_ty(TyTuple(self.intern_type_list(ts)))
+    pub fn intern_tup(self, ts: &[Ty<'tcx>], defaulted: bool) -> Ty<'tcx> {
+        self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted))
     }
 
-    pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
-        iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts))))
+    pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I,
+                                                     defaulted: bool) -> I::Output {
+        iter.intern_with(|ts| self.mk_ty(TyTuple(self.intern_type_list(ts), defaulted)))
     }
 
     pub fn mk_nil(self) -> Ty<'tcx> {
-        self.intern_tup(&[])
+        self.intern_tup(&[], false)
     }
 
     pub fn mk_diverging_default(self) -> Ty<'tcx> {
         if self.sess.features.borrow().never_type {
             self.types.never
         } else {
-            self.mk_nil()
+            self.intern_tup(&[], true)
         }
     }
 
index 29d855a7fcb78ebf9cc3362bc7e100060243b610..3ab3fc899e78c6754305f18f307f6534c3cc5378 100644 (file)
@@ -178,7 +178,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
         match self.sty {
             ty::TyBool | ty::TyChar | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
-            ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
+            ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
 
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
             ty::TyArray(_, n) => format!("array of {} elements", n),
@@ -209,7 +209,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
                     |p| format!("trait {}", tcx.item_path_str(p.def_id())))
             }
             ty::TyClosure(..) => "closure".to_string(),
-            ty::TyTuple(_) => "tuple".to_string(),
+            ty::TyTuple(..) => "tuple".to_string(),
             ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
             ty::TyInfer(ty::IntVar(_)) => "integral variable".to_string(),
             ty::TyInfer(ty::FloatVar(_)) => "floating-point variable".to_string(),
index 94b9abc72025faed7f33357bdcd25610416ed7d8..981cf0897a034f2f68e1d600bdaac3e4448bbe31 100644 (file)
@@ -72,7 +72,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             Some(ClosureSimplifiedType(def_id))
         }
         ty::TyNever => Some(NeverSimplifiedType),
-        ty::TyTuple(ref tys) => {
+        ty::TyTuple(ref tys, _) => {
             Some(TupleSimplifiedType(tys.len()))
         }
         ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
index 0de77526b5a46a2e934c36ee239a200f441ab05f..2012917f93a87e91669d74d8b61442ee97763e9f 100644 (file)
@@ -151,7 +151,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_ty(m.ty);
             }
 
-            &ty::TyTuple(ref ts) => {
+            &ty::TyTuple(ref ts, _) => {
                 self.add_tys(&ts[..]);
             }
 
index 6c49493a655597abb1b95ec23aeba408ea0bcffa..18a3f1a218d854e00d9e2f4204152234b08ba18f 100644 (file)
@@ -178,7 +178,7 @@ fn uninhabited_from_inner(
             },
 
             TyNever => DefIdForest::full(tcx),
-            TyTuple(ref tys) => {
+            TyTuple(ref tys, _) => {
                 DefIdForest::union(tcx, tys.iter().map(|ty| {
                     ty.uninhabited_from(visited, tcx)
                 }))
index b719911d18cf8706113805f6ccba94fe49f00b21..f45f00b4dec96bbf20590469c44687b98858a625 100644 (file)
@@ -319,9 +319,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         ty::TyRawPtr(mt) |
         ty::TyRef(_, mt) => characteristic_def_id_of_type(mt.ty),
 
-        ty::TyTuple(ref tys) => tys.iter()
-                                   .filter_map(|ty| characteristic_def_id_of_type(ty))
-                                   .next(),
+        ty::TyTuple(ref tys, _) => tys.iter()
+                                      .filter_map(|ty| characteristic_def_id_of_type(ty))
+                                      .next(),
 
         ty::TyFnDef(def_id, ..) |
         ty::TyClosure(def_id, _) => Some(def_id),
index b5efd2cfc686af457f4fc3f0b5aa9bc679a0cacd..ff3ac3586a78778b69a84b0bbd9b8ec9b2347f27 100644 (file)
@@ -791,7 +791,7 @@ fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                     Some(&variant.memory_index[..]))
             }
             // Can we use one of the fields in this tuple?
-            (&Univariant { ref variant, .. }, &ty::TyTuple(tys)) => {
+            (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
                 Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
                     Some(&variant.memory_index[..]))
             }
@@ -1157,7 +1157,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 Univariant { variant: st, non_zero: false }
             }
 
-            ty::TyTuple(tys) => {
+            ty::TyTuple(tys, _) => {
                 // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
                 // See the univariant case below to learn how.
                 let st = Struct::new(dl,
index 5ab45e746e7f25e67763af997ff915812cf60631..c9ae3b3df028c80ddb07bf7034087ed4f0c36dc5 100644 (file)
@@ -197,6 +197,17 @@ pub fn def(&self) -> Def {
             AssociatedKind::Type => Def::AssociatedTy(self.def_id),
         }
     }
+
+    /// Tests whether the associated item admits a non-trivial implementation
+    /// for !
+    pub fn relevant_for_never<'tcx>(&self) -> bool {
+        match self.kind {
+            AssociatedKind::Const => true,
+            AssociatedKind::Type => true,
+            // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
+            AssociatedKind::Method => !self.method_has_self_argument,
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)]
@@ -1603,7 +1614,7 @@ fn calculate_sized_constraint_inner(&self,
             _ if tys.references_error() => tcx.types.err,
             0 => tcx.types.bool,
             1 => tys[0],
-            _ => tcx.intern_tup(&tys[..])
+            _ => tcx.intern_tup(&tys[..], false)
         };
 
         let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned();
@@ -1638,7 +1649,7 @@ fn sized_constraint_for_ty(&self,
                 vec![ty]
             }
 
-            TyTuple(ref tys) => {
+            TyTuple(ref tys, _) => {
                 match tys.last() {
                     None => vec![],
                     Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
@@ -1652,7 +1663,7 @@ fn sized_constraint_for_ty(&self,
                        .subst(tcx, substs);
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
                        ty, adt_ty);
-                if let ty::TyTuple(ref tys) = adt_ty.sty {
+                if let ty::TyTuple(ref tys, _) = adt_ty.sty {
                     tys.iter().flat_map(|ty| {
                         self.sized_constraint_for_ty(tcx, stack, ty)
                     }).collect()
@@ -2010,6 +2021,12 @@ pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
         }
     }
 
+    pub fn trait_relevant_for_never(self, did: DefId) -> bool {
+        self.associated_items(did).any(|item| {
+            item.relevant_for_never()
+        })
+    }
+
     pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
         self.custom_coerce_unsized_kinds.memoize(did, || {
             let (kind, src) = if did.krate != LOCAL_CRATE {
index 89514085e1c78601d1efd4582387df06ef1b4fff..adedf78bba7c013e922cbc40cb89fcbaf67e9ced 100644 (file)
@@ -447,10 +447,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_slice(t))
         }
 
-        (&ty::TyTuple(as_), &ty::TyTuple(bs)) =>
+        (&ty::TyTuple(as_, a_defaulted), &ty::TyTuple(bs, b_defaulted)) =>
         {
             if as_.len() == bs.len() {
-                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
+                let defaulted = a_defaulted || b_defaulted;
+                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)), defaulted)?)
             } else if !(as_.is_empty() || bs.is_empty()) {
                 Err(TypeError::TupleSize(
                     expected_found(relation, &as_.len(), &bs.len())))
index 05f4abad469213f41347de0013a71ae28d3423ff..aa74e7cc0d0430c809f0195b34fcf98a4bdc2170 100644 (file)
@@ -474,7 +474,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
             ty::TyDynamic(ref trait_ty, ref region) =>
                 ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
-            ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
+            ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
             ty::TyFnDef(def_id, substs, f) => {
                 ty::TyFnDef(def_id,
                             substs.fold_with(folder),
@@ -511,7 +511,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyAdt(_, substs) => substs.visit_with(visitor),
             ty::TyDynamic(ref trait_ty, ref reg) =>
                 trait_ty.visit_with(visitor) || reg.visit_with(visitor),
-            ty::TyTuple(ts) => ts.visit_with(visitor),
+            ty::TyTuple(ts, _) => ts.visit_with(visitor),
             ty::TyFnDef(_, substs, ref f) => {
                 substs.visit_with(visitor) || f.visit_with(visitor)
             }
index 113534e4529cdc6c87c8855cbd11c366b392bd76..9bba4c6e37a69dda4b77460bd6a0f5e5fd4b6d22 100644 (file)
@@ -151,7 +151,11 @@ pub enum TypeVariants<'tcx> {
     TyNever,
 
     /// A tuple type.  For example, `(i32, bool)`.
-    TyTuple(&'tcx Slice<Ty<'tcx>>),
+    /// The bool indicates whether this is a unit tuple and was created by
+    /// defaulting a diverging type variable with feature(never_type) disabled.
+    /// It's only purpose is for raising future-compatibility warnings for when
+    /// diverging type variables start defaulting to ! instead of ().
+    TyTuple(&'tcx Slice<Ty<'tcx>>, bool),
 
     /// The projection of an associated type.  For example,
     /// `<T as Trait<..>>::N`.
@@ -961,7 +965,7 @@ pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
 
     pub fn is_nil(&self) -> bool {
         match self.sty {
-            TyTuple(ref tys) => tys.is_empty(),
+            TyTuple(ref tys, _) => tys.is_empty(),
             _ => false
         }
     }
@@ -973,6 +977,15 @@ pub fn is_never(&self) -> bool {
         }
     }
 
+    // Test whether this is a `()` which was produced by defaulting a
+    // diverging type variable with feature(never_type) disabled.
+    pub fn is_defaulted_unit(&self) -> bool {
+        match self.sty {
+            TyTuple(_, true) => true,
+            _ => false,
+        }
+    }
+
     /// Checks whether a type is visibly uninhabited from a particular module.
     /// # Example
     /// ```rust
@@ -1355,7 +1368,7 @@ pub fn regions(&self) -> Vec<&'tcx ty::Region> {
             TySlice(_) |
             TyRawPtr(_) |
             TyNever |
-            TyTuple(_) |
+            TyTuple(..) |
             TyParam(_) |
             TyInfer(_) |
             TyError => {
index ba49aa1ef4866b97c8ffc5c211130ae5775a99a2..b01b77bbcf8a5c5e184b9a03ab06df54e037f2b9 100644 (file)
@@ -207,7 +207,7 @@ pub fn positional_element_ty(self,
                 // Don't use `struct_variant`, this may be a univariant enum.
                 adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
             }
-            (&TyTuple(ref v), None) => v.get(i).cloned(),
+            (&TyTuple(ref v, _), None) => v.get(i).cloned(),
             _ => None
         }
     }
@@ -466,8 +466,9 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                     self.def_id(d);
                 }
             }
-            TyTuple(tys) => {
+            TyTuple(tys, defaulted) => {
                 self.hash(tys.len());
+                self.hash(defaulted);
             }
             TyParam(p) => {
                 self.hash(p.idx);
@@ -675,7 +676,7 @@ fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span,
                                                seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
                                                -> Representability {
             match ty.sty {
-                TyTuple(ref ts) => {
+                TyTuple(ref ts, _) => {
                     find_nonrepresentable(tcx, sp, seen, ts.iter().cloned())
                 }
                 // Fixed-length vectors.
index 0d1dc2e4d7c218c8ed3dabc3dcafca6d176eef87..01f31e5024c0dfeaf258100b77b17e136193a493 100644 (file)
@@ -112,7 +112,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyClosure(_, ref substs) => {
             stack.extend(substs.substs.types().rev());
         }
-        ty::TyTuple(ts) => {
+        ty::TyTuple(ts, _) => {
             stack.extend(ts.iter().cloned().rev());
         }
         ty::TyFnDef(_, substs, ref ft) => {
index 33b70b09dcb7b6d742ae1932e77079384fe574ae..8a5bd6862cf4552c099b431fa344c81142dc7876 100644 (file)
@@ -315,7 +315,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     self.require_sized(subty, traits::SliceOrArrayElem);
                 }
 
-                ty::TyTuple(ref tys) => {
+                ty::TyTuple(ref tys, _) => {
                     if let Some((_last, rest)) = tys.split_last() {
                         for elem in rest {
                             self.require_sized(elem, traits::TupleElem);
index aa2eb2955debe69cbd278e39cb3b7319de362c7e..5d6ee1a277a5f88049c9d68a33dc1f462a76066a 100644 (file)
@@ -156,7 +156,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
 
     if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
         let projection_ty = projections[0].ty;
-        if let TyTuple(ref args) = substs.type_at(1).sty {
+        if let TyTuple(ref args, _) = substs.type_at(1).sty {
             return fn_sig(f, args, false, projection_ty);
         }
     }
@@ -724,7 +724,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "{}", tm)
             }
             TyNever => write!(f, "!"),
-            TyTuple(ref tys) => {
+            TyTuple(ref tys, _) => {
                 write!(f, "(")?;
                 let mut tys = tys.iter();
                 if let Some(&ty) = tys.next() {
index 2dbaeaf26e970f68cf15d27859324e6c94b88245..4d38b0d1705962afa24e58c81801073ea0569d67 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Result<Target, String> {
         linker_is_gnu: true,
         allow_asm: false,
         obj_is_bitcode: true,
+        is_like_emscripten: true,
         max_atomic_width: Some(32),
         post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
         target_family: Some("unix".to_string()),
index 5afa85d155279e17a905edf5885a32d677209914..d2b76b1d55a984c8d3abf9e476822ae698dee54e 100644 (file)
@@ -330,6 +330,10 @@ pub struct TargetOptions {
     /// Whether the target toolchain is like Android's. Only useful for compiling against Android.
     /// Defaults to false.
     pub is_like_android: bool,
+    /// Whether the target toolchain is like Emscripten's. Only useful for compiling with
+    /// Emscripten toolchain.
+    /// Defaults to false.
+    pub is_like_emscripten: bool,
     /// Whether the linker support GNU-like arguments such as -O. Defaults to false.
     pub linker_is_gnu: bool,
     /// The MinGW toolchain has a known issue that prevents it from correctly
@@ -428,6 +432,7 @@ fn default() -> TargetOptions {
             is_like_solaris: false,
             is_like_windows: false,
             is_like_android: false,
+            is_like_emscripten: false,
             is_like_msvc: false,
             linker_is_gnu: false,
             allows_weak_linkage: true,
@@ -603,6 +608,7 @@ macro_rules! key {
         key!(is_like_solaris, bool);
         key!(is_like_windows, bool);
         key!(is_like_msvc, bool);
+        key!(is_like_emscripten, bool);
         key!(is_like_android, bool);
         key!(linker_is_gnu, bool);
         key!(allows_weak_linkage, bool);
@@ -767,6 +773,7 @@ macro_rules! target_option_val {
         target_option_val!(is_like_solaris);
         target_option_val!(is_like_windows);
         target_option_val!(is_like_msvc);
+        target_option_val!(is_like_emscripten);
         target_option_val!(is_like_android);
         target_option_val!(linker_is_gnu);
         target_option_val!(allows_weak_linkage);
index a06980767fd75cd58baded41b2fabe298191e15a..b1967fa8f37a7aea5c3052d48d45e24bfbbf4098 100644 (file)
@@ -24,6 +24,7 @@ pub fn target() -> Result<Target, String> {
         linker_is_gnu: true,
         allow_asm: false,
         obj_is_bitcode: true,
+        is_like_emscripten: true,
         max_atomic_width: Some(32),
         post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(),
                              "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()],
index 285f3ab9047c85c5379abf9171f886cbfb7aab56..dbab3bca52b4eccc5caba872e2d2d476de468cdf 100644 (file)
@@ -423,7 +423,7 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
     };
 
     match parent_ty.sty {
-        ty::TyTuple(ref v) => {
+        ty::TyTuple(ref v, _) => {
             let tuple_idx = match *origin_field_name {
                 mc::PositionalField(tuple_idx) => tuple_idx,
                 mc::NamedField(_) =>
index 9e89a3689c7acd23c7894a16270052336813d430..d2f744bde2d63d33444202a38a1515d3fec1ae50 100644 (file)
@@ -713,7 +713,7 @@ fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
                 let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx).collect();
                 self.open_drop_for_tuple(c, &tys)
             }
-            ty::TyTuple(tys) => {
+            ty::TyTuple(tys, _) => {
                 self.open_drop_for_tuple(c, tys)
             }
             ty::TyAdt(def, _) if def.is_box() => {
index 94b2ba58c9aa539c776df5978597f95658365b93..7a64ff7114a7eaba36871218c566db2e58c54c2e 100644 (file)
@@ -721,7 +721,7 @@ fn pat_constructors(_cx: &mut MatchCheckCtxt,
 fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize {
     debug!("constructor_arity({:?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs) => fs.len(),
+        ty::TyTuple(ref fs, _) => fs.len(),
         ty::TySlice(..) | ty::TyArray(..) => match *ctor {
             Slice(length) => length,
             ConstantValue(_) => 0,
@@ -745,7 +745,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
 {
     debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::TyTuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
+        ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(),
         ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
             Slice(length) => repeat(ty).take(length).collect(),
             ConstantValue(_) => vec![],
index c6272613f4d09fd3695222e4523e40dde99e6f37..609fb3e39d62cc8406987ca1ebd8e6fffb3d0e03 100644 (file)
@@ -342,7 +342,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
             PatKind::Tuple(ref subpatterns, ddpos) => {
                 let ty = self.tables.node_id_to_type(pat.id);
                 match ty.sty {
-                    ty::TyTuple(ref tys) => {
+                    ty::TyTuple(ref tys, _) => {
                         let subpatterns =
                             subpatterns.iter()
                                        .enumerate_and_adjust(tys.len(), ddpos)
index 1086d75f02cb4055c030b85c0077eb55fb349804..5481de1811d78b91b411b6b470b288bec54dc154 100644 (file)
@@ -280,7 +280,7 @@ pub fn t_nil(&self) -> Ty<'tcx> {
     }
 
     pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
-        self.infcx.tcx.intern_tup(&[ty1, ty2])
+        self.infcx.tcx.intern_tup(&[ty1, ty2], false)
     }
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
@@ -803,8 +803,8 @@ fn walk_ty() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let uint_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
+        let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false);
+        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false);
         let walked: Vec<_> = tup2_ty.walk().collect();
         assert_eq!(walked,
                    [tup2_ty, tup1_ty, int_ty, uint_ty, int_ty, uint_ty, tup1_ty, int_ty,
@@ -818,8 +818,8 @@ fn walk_ty_skip_subtree() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let uint_ty = tcx.types.usize;
-        let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty]);
-        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty]);
+        let tup1_ty = tcx.intern_tup(&[int_ty, uint_ty, int_ty, uint_ty], false);
+        let tup2_ty = tcx.intern_tup(&[tup1_ty, tup1_ty, uint_ty], false);
 
         // types we expect to see (in order), plus a boolean saying
         // whether to skip the subtree.
index d1ad3730aa2b3b716ba6eae742ec1401aa7010cb..8fb1740e66eacbfccf65cd8991bcd67aaea28130 100644 (file)
@@ -219,6 +219,10 @@ macro_rules! add_lint_group {
             id: LintId::of(LIFETIME_UNDERSCORE),
             reference: "issue #36892 <https://github.com/rust-lang/rust/issues/36892>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
+            reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
+        },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue #36247 <https://github.com/rust-lang/rust/issues/35112>",
index 2c3d71cd8de1d691b0fda1ffcf048835a70c9f1f..e42e038ea4d6c5a53779943ccb140522a9e3f442 100644 (file)
@@ -532,7 +532,7 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
                            consider using a `*const libc::c_char`")
             }
 
-            ty::TyTuple(_) => {
+            ty::TyTuple(..) => {
                 FfiUnsafe("found Rust tuple type in foreign module; \
                            consider using a struct instead")
             }
index a85b47c8ada7a2c6c533567ed8ec160cfa9436af..28ce9126019ebdebb86da7436e62674b52e30474 100644 (file)
@@ -141,7 +141,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
 
         let t = cx.tables.expr_ty(&expr);
         let warned = match t.sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => return,
+            ty::TyTuple(ref tys, _) if tys.is_empty() => return,
             ty::TyNever => return,
             ty::TyBool => return,
             ty::TyAdt(def, _) => {
index f0d056b96f150ab88063111053d2796bb49352a1..81a4f7c93b6e91abe2eec44da15ef705b8dbccb9 100644 (file)
@@ -584,7 +584,7 @@ fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span:
         use proc_macro::TokenStream;
         use proc_macro::__internal::Registry;
         use rustc_back::dynamic_lib::DynamicLibrary;
-        use syntax_ext::deriving::custom::CustomDerive;
+        use syntax_ext::deriving::custom::ProcMacroDerive;
         use syntax_ext::proc_macro_impl::AttrProcMacro;
 
         let path = match dylib {
@@ -616,8 +616,8 @@ fn register_custom_derive(&mut self,
                                       expand: fn(TokenStream) -> TokenStream,
                                       attributes: &[&'static str]) {
                 let attrs = attributes.iter().cloned().map(Symbol::intern).collect();
-                let derive = SyntaxExtension::CustomDerive(
-                    Box::new(CustomDerive::new(expand, attrs))
+                let derive = SyntaxExtension::ProcMacroDerive(
+                    Box::new(ProcMacroDerive::new(expand, attrs))
                 );
                 self.0.push((Symbol::intern(trait_name), Rc::new(derive)));
             }
index b1e1e75912da33f1605d4f2e904ee96aa25f9351..dad1d713168cd43e39c66608a1909ba8440d9f4c 100644 (file)
@@ -257,7 +257,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
         let source_info = self.source_info(span);
         let bool_ty = self.hir.bool_ty();
         if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() {
-            let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]);
+            let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false);
             let result_value = self.temp(result_tup);
 
             self.cfg.push_assign(block, source_info,
index c9195f29f1784481e0774d8b23ccfaba7d61a523..529fe564af02bc54e4dce16e0e046298fe381816 100644 (file)
@@ -282,7 +282,7 @@ fn field_ty(&mut self,
                         })
                     }
                 }
-                ty::TyTuple(tys) => {
+                ty::TyTuple(tys, _) => {
                     return match tys.get(field.index()) {
                         Some(&ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
index eb6c7f4bed5deaddb2cdeec5528afc97a4f3d2b0..4679b6be88b6f0835a06e410c37af1082423455a 100644 (file)
@@ -559,7 +559,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expa
                       "an `extern crate` loading macros must be at the crate root");
         } else if !self.use_extern_macros && !used &&
                   self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() {
-            let msg = "custom derive crates and `#[no_link]` crates have no effect without \
+            let msg = "proc macro crates and `#[no_link]` crates have no effect without \
                        `#[macro_use]`";
             self.session.span_warn(item.span, msg);
             used = true; // Avoid the normal unused extern crate warning
index 682b3ff834fad1eca4ddb76284ed08d12881cf97..ea3112b2463f8ba27007e6e14405c475ef93e153 100644 (file)
@@ -250,6 +250,32 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
         }
         result
     }
+
+    fn resolve_builtin_macro(&mut self, tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy> {
+        match self.builtin_macros.get(&tname).cloned() {
+            Some(binding) => Ok(binding.get_macro(self)),
+            None => Err(Determinacy::Undetermined),
+        }
+    }
+
+    fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
+                            -> Result<Rc<SyntaxExtension>, Determinacy> {
+        let ast::Path { span, .. } = *path;
+        match self.resolve_macro(scope, path, false) {
+            Ok(ext) => match *ext {
+                SyntaxExtension::BuiltinDerive(..) |
+                SyntaxExtension::ProcMacroDerive(..) => Ok(ext),
+                _ => Err(Determinacy::Determined),
+            },
+            Err(Determinacy::Undetermined) if force => {
+                let msg = format!("cannot find derive macro `{}` in this scope", path);
+                let mut err = self.session.struct_span_err(span, &msg);
+                err.emit();
+                Err(Determinacy::Determined)
+            },
+            Err(err) => Err(err),
+        }
+    }
 }
 
 impl<'a> Resolver<'a> {
index 65cdeb9253d89ed4c1d2ab79d2d6cd75756be10e..dbc8bca548b769a1334f15facf53288a0a7e8845 100644 (file)
@@ -639,7 +639,19 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
                 let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
                     if *i == ident { return None; } // Never suggest the same name
                     match *resolution.borrow() {
-                        NameResolution { binding: Some(_), .. } => Some(&i.name),
+                        NameResolution { binding: Some(name_binding), .. } => {
+                            match name_binding.kind {
+                                NameBindingKind::Import { binding, .. } => {
+                                    match binding.kind {
+                                        // Never suggest the name that has binding error
+                                        // i.e. the name that cannot be previously resolved
+                                        NameBindingKind::Def(Def::Err) => return None,
+                                        _ => Some(&i.name),
+                                    }
+                                },
+                                _ => Some(&i.name),
+                            }
+                        },
                         NameResolution { single_imports: SingleImports::None, .. } => None,
                         _ => Some(&i.name),
                     }
index f128167bbf621b50e074a27a3d34bd2227ddaf70..41f91a1d2acc17ac234f00824cd88655868bde26 100644 (file)
@@ -1440,7 +1440,7 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                             }.lower(self.tcx));
                         }
                     }
-                    ty::TyTuple(_) => {}
+                    ty::TyTuple(..) => {}
                     _ => span_bug!(ex.span,
                                    "Expected struct or tuple type, found {:?}",
                                    ty),
index 8d0cdd1678c730a39c19175cc9dc3f943aef4fc9..ebb33a12c870397fe2dbd2331cb95de79cd0f67d 100644 (file)
@@ -430,6 +430,9 @@ pub fn get_trait_ref_data(&self,
                               -> Option<TypeRefData> {
         self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| {
             let span = trait_ref.path.span;
+            if generated_code(span) {
+                return None;
+            }
             let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
             filter!(self.span_utils, sub_span, span, None);
             Some(TypeRefData {
index d392ebaa33d422dfb045ee80a01f67155bdbd96f..a476b1d29e5fb823ef8ffb9a605c2ab474210ba5 100644 (file)
@@ -367,7 +367,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             assert!(!sig.variadic && extra_args.is_empty());
 
             match sig.inputs().last().unwrap().sty {
-                ty::TyTuple(ref tupled_arguments) => {
+                ty::TyTuple(ref tupled_arguments, _) => {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                     &tupled_arguments[..]
                 }
index c3b9a56ac9778569b4d1e4e835ff2571fbcae58d..bc1e07e708c248e5dc051b450ec4fa6d5230ff85 100644 (file)
@@ -72,7 +72,7 @@ pub fn compute_fields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
                 monomorphize::field_ty(cx.tcx(), substs, f)
             }).collect::<Vec<_>>()
         },
-        ty::TyTuple(fields) => fields.to_vec(),
+        ty::TyTuple(fields, _) => fields.to_vec(),
         ty::TyClosure(def_id, substs) => {
             if variant_index > 0 { bug!("{} is a closure, which only has one variant", t);}
             substs.upvar_tys(def_id, cx.tcx()).collect()
index 20842ea3fe54d4f1cda93a3a5de7995ea42a3a9b..4ddf8a883bc488781efd48a31d5758eefb7460b0 100644 (file)
@@ -29,6 +29,7 @@
 use rustc::hir::def_id::CrateNum;
 use rustc::hir::svh::Svh;
 use rustc_back::tempdir::TempDir;
+use rustc_back::PanicStrategy;
 use rustc_incremental::IncrementalHashesMap;
 
 use std::ascii;
@@ -714,6 +715,11 @@ fn link_natively(sess: &Session,
         cmd.arg(root.join(obj));
     }
 
+    if sess.target.target.options.is_like_emscripten &&
+       sess.panic_strategy() == PanicStrategy::Abort {
+        cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]);
+    }
+
     {
         let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
         link_args(&mut *linker, sess, crate_type, tmpdir,
index 58d0c46850353697ddf9d908ac330ef682e438ff..c6b86c6ba48deed1ee9f5a775409b5e0c8f6fbb2 100644 (file)
@@ -485,7 +485,7 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
         }
     };
     let sig = tcx.erase_late_bound_regions_and_normalize(sig);
-    let tuple_input_ty = tcx.intern_tup(sig.inputs());
+    let tuple_input_ty = tcx.intern_tup(sig.inputs(), false);
     let sig = tcx.mk_fn_sig(
         [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
         sig.output(),
index 392c270c130a857b09886bc64e51ad349a910fb2..89f5c00e9c11a6c6bf1e911f6c6e3e61880a75f9 100644 (file)
@@ -823,7 +823,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                 output.push(TransItem::DropGlue(DropGlueKind::Ty(inner_type)));
             }
         }
-        ty::TyTuple(args) => {
+        ty::TyTuple(args, _) => {
             for arg in args {
                 let arg = glue::get_drop_glue_type(scx, arg);
                 if scx.type_needs_drop(arg) {
index 01b2aeef004db6f3f16a7be771fe13369379b18e..725b0e06e30888fbbab359915defb8c38da90169 100644 (file)
@@ -93,7 +93,7 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
                 }
             }))
         }
-        ty::TyTuple(tys) => {
+        ty::TyTuple(tys, _) => {
             if tys.len() != 2 {
                 return None;
             }
index b7e319f2de43431cf9ef8190611dc227b9aab659..c83e2f4854bf5cda8cbfd195df2b58d6462b0a84 100644 (file)
@@ -383,7 +383,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     // return type
     signature_metadata.push(match signature.output().sty {
-        ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
+        ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
         _ => type_metadata(cx, signature.output(), span)
     });
 
@@ -528,7 +528,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyFloat(_) => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
-        ty::TyTuple(ref elements) if elements.is_empty() => {
+        ty::TyTuple(ref elements, _) if elements.is_empty() => {
             MetadataCreationResult::new(basic_type_metadata(cx, t), false)
         }
         ty::TyArray(typ, len) => {
@@ -603,7 +603,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                     usage_site_span).finalize(cx)
             }
         },
-        ty::TyTuple(ref elements) => {
+        ty::TyTuple(ref elements, _) => {
             prepare_tuple_metadata(cx,
                                    t,
                                    &elements[..],
@@ -706,7 +706,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let (name, encoding) = match t.sty {
         ty::TyNever => ("!", DW_ATE_unsigned),
-        ty::TyTuple(ref elements) if elements.is_empty() =>
+        ty::TyTuple(ref elements, _) if elements.is_empty() =>
             ("()", DW_ATE_unsigned),
         ty::TyBool => ("bool", DW_ATE_boolean),
         ty::TyChar => ("char", DW_ATE_unsigned_char),
index e9468e56637d22cf1859fe79ebc91a72c666bb08..501f891befa8dafa279002972a0610e9571ac39d 100644 (file)
@@ -295,7 +295,7 @@ fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
         // Return type -- llvm::DIBuilder wants this at index 0
         signature.push(match sig.output().sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
+            ty::TyTuple(ref tys, _) if tys.is_empty() => ptr::null_mut(),
             _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)
         });
 
@@ -311,7 +311,7 @@ fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
 
         if abi == Abi::RustCall && !sig.inputs().is_empty() {
-            if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
+            if let ty::TyTuple(args, _) = sig.inputs()[sig.inputs().len() - 1].sty {
                 for &argument_type in args {
                     signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP));
                 }
index 8e11bf6b8976a8c3c822c18cec94de6966458fbc..018bbb6e97d345167e46c9edfec272fa803f58f4 100644 (file)
@@ -48,7 +48,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             push_item_name(cx, def.did, qualified, output);
             push_type_params(cx, substs, output);
         },
-        ty::TyTuple(component_types) => {
+        ty::TyTuple(component_types, _) => {
             output.push('(');
             for &component_type in component_types {
                 push_debuginfo_type_name(cx, component_type, true, output);
index 1415ca6029f530f885a8f469243db2aaf4dc6dac..fdefd37549ced1251245822615473da33c8f46ab 100644 (file)
@@ -442,7 +442,7 @@ fn iter_variant_fields<'a, 'tcx>(
             cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra,
                 |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty)));
         }
-        ty::TyTuple(ref args) => {
+        ty::TyTuple(ref args, _) => {
             for (i, arg) in args.iter().enumerate() {
                 let llfld_a = ptr.trans_field_ptr(&cx, i);
                 drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
index 7d4a1ab5ae70e1f7b991934c94d1e0dbf036f60a..027779aca63e4e03f1432873278301674aedebc2 100644 (file)
@@ -695,7 +695,7 @@ fn trans_arguments_untupled(&mut self,
         let tuple = self.trans_operand(bcx, operand);
 
         let arg_types = match tuple.ty.sty {
-            ty::TyTuple(ref tys) => tys,
+            ty::TyTuple(ref tys, _) => tys,
             _ => span_bug!(self.mir.span,
                            "bad final argument to \"rust-call\" fn {:?}", tuple.ty)
         };
index 3d5e1694355b3f2fd40592581c827ba9ff026728..c8a680d25195a023d823328b35b0325892ccec61 100644 (file)
@@ -735,7 +735,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                 let rhs = self.const_operand(rhs, span)?;
                 let ty = lhs.ty;
                 let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
-                let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool]);
+                let binop_ty = tcx.intern_tup(&[val_ty, tcx.types.bool], false);
                 let (lhs, rhs) = (lhs.llval, rhs.llval);
                 assert!(!ty.is_fp());
 
index 30c138310da9c501d158ba856ecd2b6890540a82..8a0a97a56343955c8fd258b09097da0b76912171 100644 (file)
@@ -384,7 +384,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             // individual LLVM function arguments.
 
             let tupled_arg_tys = match arg_ty.sty {
-                ty::TyTuple(ref tys) => tys,
+                ty::TyTuple(ref tys, _) => tys,
                 _ => bug!("spread argument isn't a tuple?!")
             };
 
index 1b97a8d010cfeafbe13f12ae03c000505beec03c..81b241b4851756a2441c572254900f3a1331afd3 100644 (file)
@@ -402,7 +402,7 @@ pub fn trans_rvalue_operand(&mut self,
                                                              lhs.immediate(), rhs.immediate(),
                                                              lhs.ty);
                 let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty);
-                let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool]);
+                let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false);
                 let operand = OperandRef {
                     val: result,
                     ty: operand_ty
index d58a93e3cb71c47d4ee758e7887b8648dc10ac28..04a6cb27501b3eab4000d02358d4d2103ca67948 100644 (file)
@@ -409,7 +409,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 self.push_def_path(adt_def.did, output);
                 self.push_type_params(substs, iter::empty(), output);
             },
-            ty::TyTuple(component_types) => {
+            ty::TyTuple(component_types, _) => {
                 output.push('(');
                 for &component_type in component_types {
                     self.push_type_name(component_type, output);
index 4df0e989ada9975040bbe9eea3e350838f1f92af..87af3b6c5e1535bc4748624e367d36b73deb446b 100644 (file)
@@ -74,7 +74,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             Type::array(&llty, size)
         }
 
-        ty::TyTuple(ref tys) if tys.is_empty() => {
+        ty::TyTuple(ref tys, _) if tys.is_empty() => {
             Type::nil(cx)
         }
 
@@ -276,7 +276,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
         let sig = cx.tcx().erase_late_bound_regions_and_normalize(&f.sig);
         FnType::new(cx, f.abi, &sig, &[]).llvm_type(cx).ptr_to()
       }
-      ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
+      ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx),
       ty::TyTuple(..) => {
           adt::type_of(cx, t)
       }
index bb9a487802e7b686c207cdff0ed41be19a7ac154..a3373f6da28526b17e2ae4f1bc65777404ad689e 100644 (file)
@@ -421,7 +421,7 @@ fn convert_parenthesized_parameters(&self,
             span: output_span
         };
 
-        (self.tcx().mk_ty(ty::TyTuple(inputs)), output_binding)
+        (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
     }
 
     /// Instantiates the path for the given trait reference, assuming that it's
@@ -1170,7 +1170,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 tcx.types.never
             },
             hir::TyTup(ref fields) => {
-                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)))
+                tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t)), false)
             }
             hir::TyBareFn(ref bf) => {
                 require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
index 932e7ae1dd4266ffa480e092fbae9cf3e44033e7..feed5752cf8fb6c3b92bbeb8dd7ccfb0eb93229a 100644 (file)
@@ -164,7 +164,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
                 let mut expected_len = elements.len();
                 if ddpos.is_some() {
                     // Require known type only when `..` is present
-                    if let ty::TyTuple(ref tys) =
+                    if let ty::TyTuple(ref tys, _) =
                             self.structurally_resolved_type(pat.span, expected).sty {
                         expected_len = tys.len();
                     }
@@ -176,7 +176,7 @@ pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: boo
                     //       from all tuple elements isn't trivial.
                     TypeVariableOrigin::TypeInference(pat.span)));
                 let element_tys = tcx.mk_type_list(element_tys_iter);
-                let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys));
+                let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
                 self.demand_eqtype(pat.span, expected, pat_ty);
                 for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
                     self.check_pat(elem, &element_tys[i]);
index 2e6592b55017961034aff71eb3398c012209e428..7979edbf5e27a1c7c78536a1e8272b6662680db0 100644 (file)
@@ -89,7 +89,7 @@ fn check_closure(&self,
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
         fn_ty.sig.0 = self.tcx.mk_fn_sig(
-            iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs())),
+            iter::once(self.tcx.intern_tup(fn_ty.sig.skip_binder().inputs(), false)),
             fn_ty.sig.skip_binder().output(),
             fn_ty.sig.variadic()
         );
@@ -218,7 +218,7 @@ fn deduce_sig_from_projection(&self,
                arg_param_ty);
 
         let input_tys = match arg_param_ty.sty {
-            ty::TyTuple(tys) => tys.into_iter(),
+            ty::TyTuple(tys, _) => tys.into_iter(),
             _ => {
                 return None;
             }
index 34aa4eda772ada2b1904be85f40ca05612a29648..f701bc3220848d452b0b51aa913751d676ab9137 100644 (file)
@@ -489,7 +489,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
             Ok(())
         }
 
-        ty::TyTuple(tys) => {
+        ty::TyTuple(tys, _) => {
             for ty in tys {
                 iterate_over_potentially_unsafe_regions_in_type(cx, context, ty, depth+1)?
             }
index 7ead7ada893d7bccdb2e284a13d19c300ee21c83..cb4e85e842c2a8f3727cfad82a312fcfb7a3aecf 100644 (file)
@@ -87,7 +87,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
             "cxchg" | "cxchgweak" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)),
                                               param(ccx, 0),
                                               param(ccx, 0)],
-                                      tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
+                                      tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)),
             "load" => (1, vec![tcx.mk_imm_ptr(param(ccx, 0))],
                        param(ccx, 0)),
             "store" => (1, vec![tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)],
@@ -272,7 +272,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
 
             "add_with_overflow" | "sub_with_overflow"  | "mul_with_overflow" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)],
-                tcx.intern_tup(&[param(ccx, 0), tcx.types.bool])),
+                tcx.intern_tup(&[param(ccx, 0), tcx.types.bool], false)),
 
             "unchecked_div" | "unchecked_rem" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
@@ -420,7 +420,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
 
     match *expected {
         Void => match t.sty {
-            ty::TyTuple(ref v) if v.is_empty() => {},
+            ty::TyTuple(ref v, _) if v.is_empty() => {},
             _ => simple_error(&format!("`{}`", t), "()"),
         },
         // (The width we pass to LLVM doesn't concern the type checker.)
@@ -494,7 +494,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
         }
         Aggregate(_flatten, ref expected_contents) => {
             match t.sty {
-                ty::TyTuple(contents) => {
+                ty::TyTuple(contents, _) => {
                     if contents.len() != expected_contents.len() {
                         simple_error(&format!("tuple with length {}", contents.len()),
                                      &format!("tuple with length {}", expected_contents.len()));
index 1d9913cd96dc310383f1a348745eba0f3945687c..c4a366c2f17fe1ed336ac4bab56cd6c31a68551e 100644 (file)
@@ -1947,7 +1947,9 @@ fn check_casts(&self) {
     }
 
     /// Apply "fallbacks" to some types
-    /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
+    /// unconstrained types get replaced with ! or  () (depending on whether
+    /// feature(never_type) is enabled), unconstrained ints with i32, and
+    /// unconstrained floats with f64.
     fn default_type_parameters(&self) {
         use rustc::ty::error::UnconstrainedNumeric::Neither;
         use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
@@ -2408,7 +2410,7 @@ fn check_method_argument_types(&self,
 
             let err_inputs = match tuple_arguments {
                 DontTupleArguments => err_inputs,
-                TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])],
+                TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)],
             };
 
             self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
@@ -2505,16 +2507,16 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
         let formal_tys = if tuple_arguments == TupleArguments {
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
-                ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
+                ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => {
                     parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(),
                                           "E0057", false, def_span);
                     expected_arg_tys = &[];
                     self.err_args(args.len())
                 }
-                ty::TyTuple(arg_types) => {
+                ty::TyTuple(arg_types, _) => {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
-                            ty::TyTuple(ref tys) => &tys,
+                            ty::TyTuple(ref tys, _) => &tys,
                             _ => &[]
                         },
                         None => &[]
@@ -3072,7 +3074,7 @@ fn check_tup_field(&self,
                         }
                     })
                 }
-                ty::TyTuple(ref v) => {
+                ty::TyTuple(ref v, _) => {
                     tuple_like = true;
                     v.get(idx.node).cloned()
                 }
@@ -3864,7 +3866,7 @@ fn check_expr_kind(&self,
           hir::ExprTup(ref elts) => {
             let flds = expected.only_has_type(self).and_then(|ty| {
                 match ty.sty {
-                    ty::TyTuple(ref flds) => Some(&flds[..]),
+                    ty::TyTuple(ref flds, _) => Some(&flds[..]),
                     _ => None
                 }
             });
@@ -3882,7 +3884,7 @@ fn check_expr_kind(&self,
                 };
                 t
             });
-            let tuple = tcx.mk_tup(elt_ts_iter);
+            let tuple = tcx.mk_tup(elt_ts_iter, false);
             if tuple.references_error() {
                 tcx.types.err
             } else {
@@ -3923,7 +3925,7 @@ fn check_expr_kind(&self,
                               },
                               base_t);
                           // Try to give some advice about indexing tuples.
-                          if let ty::TyTuple(_) = base_t.sty {
+                          if let ty::TyTuple(..) = base_t.sty {
                               let mut needs_note = true;
                               // If the index is an integer, we can show the actual
                               // fixed expression:
index 40e82959336de4e654ecc7a95f0ee075a5232f0e..860f6d98370ad1926a192e20b1c164c1f99f9c0b 100644 (file)
@@ -338,7 +338,7 @@ fn add_constraints_from_ty(&mut self,
                 self.add_constraints_from_mt(generics, mt, variance);
             }
 
-            ty::TyTuple(subtys) => {
+            ty::TyTuple(subtys, _) => {
                 for &subty in subtys {
                     self.add_constraints_from_ty(generics, subty, variance);
                 }
index fe2edcad25c20d84bdea3f08805e483231f8f4e5..dc2aa1f138d62d04eb74b385b1875aa9feb02c75 100644 (file)
@@ -655,7 +655,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
         Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => {
             assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
-                ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
+                ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return PathParameters::AngleBracketed {
                         lifetimes: lifetimes,
@@ -667,7 +667,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
             let output = None;
             // FIXME(#20299) return type comes from a projection now
             // match types[1].sty {
-            //     ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
+            //     ty::TyTuple(ref v, _) if v.is_empty() => None, // -> ()
             //     _ => Some(types[1].clean(cx))
             // };
             PathParameters::Parenthesized {
@@ -710,7 +710,7 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
         // collect any late bound regions
         let mut late_bounds = vec![];
         for ty_s in self.input_types().skip(1) {
-            if let ty::TyTuple(ts) = ty_s.sty {
+            if let ty::TyTuple(ts, _) = ty_s.sty {
                 for &ty_s in ts {
                     if let ty::TyRef(ref reg, _) = ty_s.sty {
                         if let &ty::Region::ReLateBound(..) = *reg {
@@ -1895,7 +1895,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     Never
                 }
             }
-            ty::TyTuple(ref t) => Tuple(t.clean(cx)),
+            ty::TyTuple(ref t, _) => Tuple(t.clean(cx)),
 
             ty::TyProjection(ref data) => data.clean(cx),
 
index 503ef4c3183d2aa2ca543501b3bd6d329d54efa1..84f69cd35045c91fd833f4dce04235ecd14048d6 100644 (file)
@@ -193,7 +193,7 @@ pub fn main_args(args: &[String]) -> isize {
     nightly_options::check_nightly_options(&matches, &opts());
 
     if matches.opt_present("h") || matches.opt_present("help") {
-        usage(&args[0]);
+        usage("rustdoc");
         return 0;
     } else if matches.opt_present("version") {
         rustc_driver::version("rustdoc", &matches);
index 6b6330ef12a94dea6a53da36ebbaa08dfbae69df..6f38da4f24b0d5a2196fa96d19c8a6883e1b04d9 100644 (file)
@@ -354,6 +354,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool,
     prog
 }
 
+// FIXME(aburka): use a real parser to deal with multiline attributes
 fn partition_source(s: &str) -> (String, String) {
     use std_unicode::str::UnicodeStr;
 
@@ -364,7 +365,7 @@ fn partition_source(s: &str) -> (String, String) {
     for line in s.lines() {
         let trimline = line.trim();
         let header = trimline.is_whitespace() ||
-            trimline.starts_with("#![feature");
+            trimline.starts_with("#![");
         if !header || after_header {
             after_header = true;
             after.push_str(line);
index b220504d2b4f5c6eb246303009a99aaec9292d3f..35c388ba076cef69d9c2eb32608275ff884d3a79 100644 (file)
@@ -399,7 +399,7 @@ impl ExactSizeIterator for EscapeDefault {}
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for EscapeDefault {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for EscapeDefault {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("EscapeDefault { .. }")
index 8058972e7509310bc8914ba1fef45d83844afd17..ffb7a1a1fc15f2b0acd6ad439c9d407fce602259 100644 (file)
@@ -1283,7 +1283,7 @@ fn clone(&self) -> Iter<'a, K, V> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_list()
@@ -1318,7 +1318,7 @@ fn clone(&self) -> Keys<'a, K, V> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_list()
@@ -1341,7 +1341,7 @@ fn clone(&self) -> Values<'a, K, V> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_list()
@@ -1591,7 +1591,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K, V> fmt::Debug for IterMut<'a, K, V>
     where K: fmt::Debug,
           V: fmt::Debug,
@@ -1626,7 +1626,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<K, V> FusedIterator for IntoIter<K, V> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_list()
@@ -1704,7 +1704,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V>
     where K: fmt::Debug,
           V: fmt::Debug,
@@ -1739,7 +1739,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
     where K: fmt::Debug,
           V: fmt::Debug,
@@ -2227,7 +2227,7 @@ fn default() -> RandomState {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for RandomState {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("RandomState { .. }")
index 341b050862f5c455520c25d6496c7a264782fb0b..a3f7e13bbf9131615f369a5ee328947e1cdfc8b2 100644 (file)
@@ -948,7 +948,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Iter<'a, K> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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()
@@ -977,7 +977,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<K> FusedIterator for IntoIter<K> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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);
@@ -1007,7 +1007,7 @@ fn len(&self) -> usize {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Drain<'a, K> {}
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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);
@@ -1050,7 +1050,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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,
@@ -1109,7 +1109,7 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S>
 {
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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,
@@ -1150,7 +1150,7 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
 {
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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,
@@ -1176,7 +1176,7 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S>
 {
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[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,
index c3a6b2433ed8815acb1460ba3800a2a13857738b..29f2ac6ab444c05463ac2eb6d87ded54ade44121 100644 (file)
@@ -145,7 +145,7 @@ fn next(&mut self) -> Option<(String, String)> {
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Vars {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Vars { .. }")
@@ -159,7 +159,7 @@ fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for VarsOs {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("VarsOs { .. }")
@@ -382,7 +382,7 @@ fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a> fmt::Debug for SplitPaths<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("SplitPaths { .. }")
@@ -665,7 +665,7 @@ fn next_back(&mut self) -> Option<String> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Args {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Args { .. }")
@@ -690,7 +690,7 @@ impl DoubleEndedIterator for ArgsOs {
     fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ArgsOs {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("ArgsOs { .. }")
index 249627c430cb7d49299b5cda6a3c4b1d9da91384..e5562d05f10ae92472aebb2a3fbe2c114f82f372 100644 (file)
@@ -869,7 +869,7 @@ pub fn created(&self) -> io::Result<SystemTime> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Metadata {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("Metadata")
index de5fc5bfad13761297fb0af88c96737c020e99f6..8cb7b2bda7554239a9e2684f51843ad96aae8167 100644 (file)
@@ -1450,7 +1450,7 @@ pub struct Chain<T, U> {
     done_first: bool,
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("Chain")
index 83a675eb512e5c7faf34b5389199a6c3df2fdbcd..e16e8019b5f735fb6e2af5192363d2941bf6b869 100644 (file)
@@ -282,7 +282,7 @@ pub fn read_line(&self, buf: &mut String) -> io::Result<usize> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdin {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Stdin { .. }")
@@ -321,7 +321,7 @@ fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
     fn consume(&mut self, n: usize) { self.inner.consume(n) }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a> fmt::Debug for StdinLock<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("StdinLock { .. }")
@@ -438,7 +438,7 @@ pub fn lock(&self) -> StdoutLock {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdout {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Stdout { .. }")
@@ -470,7 +470,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a> fmt::Debug for StdoutLock<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("StdoutLock { .. }")
@@ -573,7 +573,7 @@ pub fn lock(&self) -> StderrLock {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stderr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Stderr { .. }")
@@ -605,7 +605,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a> fmt::Debug for StderrLock<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("StderrLock { .. }")
index e50665120eb47c1de435a873ac4ef5ef4667b378..4163187488e6544d378808bde18689977623edf3 100644 (file)
@@ -98,7 +98,7 @@ fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
     fn consume(&mut self, _n: usize) {}
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Empty {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Empty { .. }")
@@ -141,7 +141,7 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Repeat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Repeat { .. }")
@@ -180,7 +180,7 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Sink {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Sink { .. }")
index 181694dead03c1d9ca0de6c5578de3c46afaa202..9bcecebf693d2e73265285260c3e9317bde5a7b6 100644 (file)
 #![feature(oom)]
 #![feature(optin_builtin_traits)]
 #![feature(panic_unwind)]
+#![feature(peek)]
 #![feature(placement_in_syntax)]
 #![feature(prelude_import)]
 #![feature(pub_restricted)]
index 2b60fc38198ec3c090c365fc43dc36a96b9f85ae..b0d2e3e4687b44c24e4fee5cf64a14b9109261c0 100644 (file)
@@ -106,7 +106,10 @@ impl Iterator for LookupHost {
     fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+                                              iterator and returning socket \
+                                              addresses",
+           issue = "27705")]
 impl fmt::Debug for LookupHost {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("LookupHost { .. }")
index cbc672c28bc6aa858f7a5b1c90f0f7aec8eafa91..9bead22ef7f5e0516267712a326b3c465671e159 100644 (file)
@@ -296,6 +296,29 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         self.0.write_timeout()
     }
 
+    /// Receives data on the socket from the remote adress to which it is
+    /// connected, without removing that data from the queue. On success,
+    /// returns the number of bytes peeked.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(peek)]
+    /// use std::net::TcpStream;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8000")
+    ///                        .expect("couldn't bind to address");
+    /// let mut buf = [0; 10];
+    /// let len = stream.peek(&mut buf).expect("peek failed");
+    /// ```
+    #[unstable(feature = "peek", issue = "38980")]
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.peek(buf)
+    }
+
     /// Sets the value of the `TCP_NODELAY` option on this socket.
     ///
     /// If set, this option disables the Nagle algorithm. This means that
@@ -1406,4 +1429,35 @@ fn set_nonblocking() {
             Err(e) => panic!("unexpected error {}", e),
         }
     }
+
+    #[test]
+    fn peek() {
+        each_ip(&mut |addr| {
+            let (txdone, rxdone) = channel();
+
+            let srv = t!(TcpListener::bind(&addr));
+            let _t = thread::spawn(move|| {
+                let mut cl = t!(srv.accept()).0;
+                cl.write(&[1,3,3,7]).unwrap();
+                t!(rxdone.recv());
+            });
+
+            let mut c = t!(TcpStream::connect(&addr));
+            let mut b = [0; 10];
+            for _ in 1..3 {
+                let len = c.peek(&mut b).unwrap();
+                assert_eq!(len, 4);
+            }
+            let len = c.read(&mut b).unwrap();
+            assert_eq!(len, 4);
+
+            t!(c.set_nonblocking(true));
+            match c.peek(&mut b) {
+                Ok(_) => panic!("expected error"),
+                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
+                Err(e) => panic!("unexpected error {}", e),
+            }
+            t!(txdone.send(()));
+        })
+    }
 }
index 492e57f6e44e51f1047de23c4a48f238a11465a8..f452c75d389664ed90bf0da30aa2066ec12a7086 100644 (file)
@@ -83,6 +83,30 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.0.recv_from(buf)
     }
 
+    /// Receives data from the socket, without removing it from the queue.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
+    ///
+    /// On success, returns the number of bytes peeked and the address from
+    /// whence the data came.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(peek)]
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// let mut buf = [0; 10];
+    /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
+    ///                                         .expect("Didn't receive data");
+    /// ```
+    #[unstable(feature = "peek", issue = "38980")]
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.0.peek_from(buf)
+    }
+
     /// Sends data on the socket to the given address. On success, returns the
     /// number of bytes written.
     ///
@@ -579,6 +603,37 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.recv(buf)
     }
 
+    /// Receives data on the socket from the remote adress to which it is
+    /// connected, without removing that data from the queue. On success,
+    /// returns the number of bytes peeked.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+    ///
+    /// # Errors
+    ///
+    /// This method will fail if the socket is not connected. The `connect` method
+    /// will connect this socket to a remote address.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(peek)]
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("127.0.0.1:8080").expect("connect function failed");
+    /// let mut buf = [0; 10];
+    /// match socket.peek(&mut buf) {
+    ///     Ok(received) => println!("received {} bytes", received),
+    ///     Err(e) => println!("peek function failed: {:?}", e),
+    /// }
+    /// ```
+    #[unstable(feature = "peek", issue = "38980")]
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.peek(buf)
+    }
+
     /// Moves this UDP socket into or out of nonblocking mode.
     ///
     /// On Unix this corresponds to calling fcntl, and on Windows this
@@ -869,6 +924,48 @@ fn connect_send_recv() {
         assert_eq!(b"hello world", &buf[..]);
     }
 
+    #[test]
+    fn connect_send_peek_recv() {
+        each_ip(&mut |addr, _| {
+            let socket = t!(UdpSocket::bind(&addr));
+            t!(socket.connect(addr));
+
+            t!(socket.send(b"hello world"));
+
+            for _ in 1..3 {
+                let mut buf = [0; 11];
+                let size = t!(socket.peek(&mut buf));
+                assert_eq!(b"hello world", &buf[..]);
+                assert_eq!(size, 11);
+            }
+
+            let mut buf = [0; 11];
+            let size = t!(socket.recv(&mut buf));
+            assert_eq!(b"hello world", &buf[..]);
+            assert_eq!(size, 11);
+        })
+    }
+
+    #[test]
+    fn peek_from() {
+        each_ip(&mut |addr, _| {
+            let socket = t!(UdpSocket::bind(&addr));
+            t!(socket.send_to(b"hello world", &addr));
+
+            for _ in 1..3 {
+                let mut buf = [0; 11];
+                let (size, _) = t!(socket.peek_from(&mut buf));
+                assert_eq!(b"hello world", &buf[..]);
+                assert_eq!(size, 11);
+            }
+
+            let mut buf = [0; 11];
+            let (size, _) = t!(socket.recv_from(&mut buf));
+            assert_eq!(b"hello world", &buf[..]);
+            assert_eq!(size, 11);
+        })
+    }
+
     #[test]
     fn ttl() {
         let ttl = 100;
index cc154f7ab413b4341307d9eb127b91eb696f86f2..68d4ca900195c5ed8c3161eaa5d9853942fb5500 100644 (file)
@@ -73,7 +73,7 @@ pub enum c_void {
     #[doc(hidden)] __variant2,
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for c_void {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("c_void")
index faf4949e86192e2d76ba2cc7199f9a6a7a67ead7..ac0d0d2afb80328042a8a3109c7cffa366e520b5 100644 (file)
@@ -297,7 +297,7 @@ extern "rust-call" fn call_once(self, _args: ()) -> R {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("AssertUnwindSafe")
index 5af4ba53bf9a57e2d79325c68f5a8df60e54f5f6..c16b97ebda5e3c2bd4a1d4a4ca055c6101077c50 100644 (file)
@@ -114,7 +114,7 @@ impl IntoInner<imp::Process> for Child {
     fn into_inner(self) -> imp::Process { self.handle }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Child {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("Child")
@@ -160,7 +160,7 @@ fn from_inner(pipe: AnonPipe) -> ChildStdin {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdin {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("ChildStdin { .. }")
@@ -201,7 +201,7 @@ fn from_inner(pipe: AnonPipe) -> ChildStdout {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdout {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("ChildStdout { .. }")
@@ -242,7 +242,7 @@ fn from_inner(pipe: AnonPipe) -> ChildStderr {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStderr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("ChildStderr { .. }")
@@ -696,7 +696,7 @@ fn from_inner(inner: imp::Stdio) -> Stdio {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdio {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Stdio { .. }")
@@ -959,10 +959,27 @@ pub fn wait_with_output(mut self) -> io::Result<Output> {
 ///
 /// # Examples
 ///
+/// Due to this function’s behavior regarding destructors, a conventional way
+/// to use the function is to extract the actual computation to another
+/// function and compute the exit code from its return value:
+///
 /// ```
-/// use std::process;
+/// use std::io::{self, Write};
+///
+/// fn run_app() -> Result<(), ()> {
+///     // Application logic here
+///     Ok(())
+/// }
 ///
-/// process::exit(0);
+/// fn main() {
+///     ::std::process::exit(match run_app() {
+///        Ok(_) => 0,
+///        Err(err) => {
+///            writeln!(io::stderr(), "error: {:?}", err).unwrap();
+///            1
+///        }
+///     });
+/// }
 /// ```
 ///
 /// Due to [platform-specific behavior], the exit code for this example will be
index b8e83dced8d4b100bae84db8804628bb78bef740..fc4fd4ce92b1b6fbe6f37e8fc3d998e90d68b8e4 100644 (file)
@@ -55,7 +55,7 @@ struct BarrierState {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BarrierWaitResult(bool);
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Barrier {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Barrier { .. }")
@@ -110,7 +110,7 @@ pub fn wait(&self) -> BarrierWaitResult {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for BarrierWaitResult {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("BarrierWaitResult")
index 5c85c4879a8396770805b4aa4904bb583f21d32b..7ee1c98565cfd5525fd3afba2cdfba2e4743ac69 100644 (file)
@@ -240,7 +240,7 @@ fn verify(&self, mutex: &sys_mutex::Mutex) {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Condvar {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Condvar { .. }")
index 2efddeb4610dd6211cb7ea06b5c2ae91073cde85..0d6ad5e38e98b0bcdec7b57e691a3675359e546f 100644 (file)
@@ -428,7 +428,7 @@ fn drop(&mut self) {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("MutexGuard")
index a9747639aacd797381e8df74d4eb2b44ecbf13a4..ba99375139139c7d2a1cd71ed5e9c3961e8233df 100644 (file)
@@ -330,7 +330,7 @@ fn call_inner(&'static self,
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Once {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("Once { .. }")
index adbb98e4b1f4f664a99ab278c06a517639e091de..a3db0adeda00dc6042c2c8f26dc77d6c3b65162c 100644 (file)
@@ -361,7 +361,7 @@ unsafe fn new(lock: &'rwlock RwLock<T>)
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("RwLockReadGuard")
@@ -370,7 +370,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("RwLockWriteGuard")
index 585dcbb9a34a1e2330ae5f9450f1128d9fc93df2..2961c4ec58245588d1592ef7d0799702852383c7 100644 (file)
@@ -67,10 +67,20 @@ fn before_exec<F>(&mut self, f: F) -> &mut process::Command
     /// an error indicating why the exec (or another part of the setup of the
     /// `Command`) failed.
     ///
+    /// `exec` not returning has the same implications as calling
+    /// [`process::exit`] â€“ no destructors on the current stack or any other
+    /// thread’s stack will be run. Therefore, it is recommended to only call
+    /// `exec` at a point where it is fine to not run any destructors. Note,
+    /// that the `execvp` syscall independently guarantees that all memory is
+    /// freed and all file descriptors with the `CLOEXEC` option (set by default
+    /// on all file descriptors opened by the standard library) are closed.
+    ///
     /// This function, unlike `spawn`, will **not** `fork` the process to create
     /// a new child. Like spawn, however, the default behavior for the stdio
     /// descriptors will be to inherited from the current process.
     ///
+    /// [`process::exit`]: ../../../process/fn.exit.html
+    ///
     /// # Notes
     ///
     /// The process may be in a "broken state" if this function returns in
index ad287bbec3889b276c5292c7fa6efa082600b472..5efddca110f0506a048828e4611ddd2aac2eb723 100644 (file)
 
 use ffi::CStr;
 use io;
-use libc::{self, c_int, size_t, sockaddr, socklen_t, EAI_SYSTEM};
+use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+use mem;
 use net::{SocketAddr, Shutdown};
 use str;
 use sys::fd::FileDesc;
 use sys_common::{AsInner, FromInner, IntoInner};
-use sys_common::net::{getsockopt, setsockopt};
+use sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
 use time::Duration;
 
 pub use sys::{cvt, cvt_r};
@@ -155,8 +156,46 @@ pub fn duplicate(&self) -> io::Result<Socket> {
         self.0.duplicate().map(Socket)
     }
 
+    fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::recv(self.0.raw(),
+                       buf.as_mut_ptr() as *mut c_void,
+                       buf.len(),
+                       flags)
+        })?;
+        Ok(ret as usize)
+    }
+
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
+        self.recv_with_flags(buf, 0)
+    }
+
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_with_flags(buf, MSG_PEEK)
+    }
+
+    fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int)
+                            -> io::Result<(usize, SocketAddr)> {
+        let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
+        let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t;
+
+        let n = cvt(unsafe {
+            libc::recvfrom(self.0.raw(),
+                        buf.as_mut_ptr() as *mut c_void,
+                        buf.len(),
+                        flags,
+                        &mut storage as *mut _ as *mut _,
+                        &mut addrlen)
+        })?;
+        Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+    }
+
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, 0)
+    }
+
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, MSG_PEEK)
     }
 
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
index 1b29bf73c7aec09794eff3830c87df9842c2c53c..850d6f49612ee3b7626e6f11bd9d5972c8050aea 100644 (file)
@@ -167,6 +167,7 @@ fn clone(&self) -> Self { *self }
 pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
 
 pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
+pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
 
 // Note that these are not actually HANDLEs, just values to pass to GetStdHandle
 pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
@@ -245,6 +246,7 @@ fn clone(&self) -> Self { *self }
 pub const IP_DROP_MEMBERSHIP: c_int = 13;
 pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
 pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
+pub const MSG_PEEK: c_int = 0x2;
 
 #[repr(C)]
 pub struct ip_mreq {
index c410fcd1ee0ed59f0c2533172541f3cd64a89a17..4efc68afdc4c74f6387f359c788f30eb42b20fbe 100644 (file)
@@ -646,9 +646,25 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
     let src = to_u16s(src)?;
     let dst = to_u16s(dst)?;
     let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
-    cvt(unsafe {
-        c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL
-    })?;
+    // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10
+    // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the
+    // computer is in Developer Mode, but SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE must be
+    // added to dwFlags to opt into this behaviour.
+    let result = cvt(unsafe {
+        c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(),
+                               flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) as c::BOOL
+    });
+    if let Err(err) = result {
+        if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) {
+            // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
+            // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag.
+            cvt(unsafe {
+                c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL
+            })?;
+        } else {
+            return Err(err);
+        }
+    }
     Ok(())
 }
 
index aca6994503ff8aa46495e32747fda5c7c1e8a127..adf6210d82e897542d990bd43bcfb7b4cf2bf807 100644 (file)
@@ -147,12 +147,12 @@ pub fn duplicate(&self) -> io::Result<Socket> {
         Ok(socket)
     }
 
-    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+    fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
         let len = cmp::min(buf.len(), i32::max_value() as usize) as i32;
         unsafe {
-            match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) {
+            match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
                 -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
                 -1 => Err(last_error()),
                 n => Ok(n as usize)
@@ -160,6 +160,46 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         }
     }
 
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_with_flags(buf, 0)
+    }
+
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.recv_with_flags(buf, c::MSG_PEEK)
+    }
+
+    fn recv_from_with_flags(&self, buf: &mut [u8], flags: c_int)
+                            -> io::Result<(usize, SocketAddr)> {
+        let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() };
+        let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+
+        // On unix when a socket is shut down all further reads return 0, so we
+        // do the same on windows to map a shut down socket to returning EOF.
+        unsafe {
+            match c::recvfrom(self.0,
+                              buf.as_mut_ptr() as *mut c_void,
+                              len,
+                              flags,
+                              &mut storage as *mut _ as *mut _,
+                              &mut addrlen) {
+                -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => {
+                    Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?))
+                },
+                -1 => Err(last_error()),
+                n => Ok((n as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)),
+            }
+        }
+    }
+
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, 0)
+    }
+
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_with_flags(buf, c::MSG_PEEK)
+    }
+
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
         let mut me = self;
         (&mut me).read_to_end(buf)
index 10ad61f4c800c26b9593a7979edbf2f5cac55ce1..3cdeb511945756d7d8c451ad4ff89ff6aac8f164 100644 (file)
@@ -91,7 +91,7 @@ fn sockname<F>(f: F) -> io::Result<SocketAddr>
     }
 }
 
-fn sockaddr_to_addr(storage: &c::sockaddr_storage,
+pub fn sockaddr_to_addr(storage: &c::sockaddr_storage,
                     len: usize) -> io::Result<SocketAddr> {
     match storage.ss_family as c_int {
         c::AF_INET => {
@@ -222,6 +222,10 @@ pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         self.inner.timeout(c::SO_SNDTIMEO)
     }
 
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.peek(buf)
+    }
+
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
@@ -441,17 +445,11 @@ pub fn socket_addr(&self) -> io::Result<SocketAddr> {
     }
 
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
-        let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+        self.inner.recv_from(buf)
+    }
 
-        let n = cvt(unsafe {
-            c::recvfrom(*self.inner.as_inner(),
-                        buf.as_mut_ptr() as *mut c_void,
-                        len, 0,
-                        &mut storage as *mut _ as *mut _, &mut addrlen)
-        })?;
-        Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.inner.peek_from(buf)
     }
 
     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
@@ -578,6 +576,10 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
 
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.peek(buf)
+    }
+
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
         let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
         let ret = cvt(unsafe {
index 01584979aabaae59c57e769cee73dd8e25e49477..5166ddf8a21b620bc516150da11ae1dd51926055 100644 (file)
@@ -99,7 +99,7 @@ pub struct LocalKey<T: 'static> {
     init: fn() -> T,
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: 'static> fmt::Debug for LocalKey<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("LocalKey { .. }")
@@ -332,7 +332,6 @@ pub struct Key<T> {
         marker: marker::PhantomData<Cell<T>>,
     }
 
-    #[stable(feature = "std_debug", since = "1.15.0")]
     impl<T> fmt::Debug for Key<T> {
         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             f.pad("Key { .. }")
index 8789006436c0c7baa2cfe93a0960b3ea1b4faa57..93e320c45223c5978b06f523002e01be941b889b 100644 (file)
@@ -698,7 +698,7 @@ fn new() -> ThreadId {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[unstable(feature = "thread_id", issue = "21507")]
 impl fmt::Debug for ThreadId {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("ThreadId { .. }")
@@ -1002,7 +1002,7 @@ impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
     fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
 }
 
-#[stable(feature = "std_debug", since = "1.15.0")]
+#[stable(feature = "std_debug", since = "1.16.0")]
 impl<T> fmt::Debug for JoinHandle<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("JoinHandle { .. }")
index f2c53efda173700e9e00e5c03151d4b66654aabf..4269ce8534bd032e056a76dabec6fd88359e1669 100644 (file)
@@ -131,7 +131,6 @@ fn next(&mut self) -> Option<char> {
     }
 }
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
 impl fmt::Display for CaseMappingIter {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -152,14 +151,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
 impl fmt::Display for ToLowercase {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&self.0, f)
     }
 }
 
-#[stable(feature = "char_struct_display", since = "1.17.0")]
+#[stable(feature = "char_struct_display", since = "1.16.0")]
 impl fmt::Display for ToUppercase {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&self.0, f)
index edf74e1fe19f155d0a19075f42d50f4fb45ef801..9a717b86d091ed6682cd67427c89bda2baadf850 100644 (file)
@@ -10,7 +10,7 @@
 
 pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
 
-use ast::{self, Attribute, Name, PatKind};
+use ast::{self, Attribute, Name, PatKind, MetaItem};
 use attr::HasAttrs;
 use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
 use syntax_pos::{Span, ExpnId, NO_EXPANSION};
@@ -471,6 +471,9 @@ fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
     }
 }
 
+pub type BuiltinDeriveFn =
+    for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
+
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
     /// A syntax extension that is attached to an item and creates new items
@@ -507,7 +510,14 @@ pub enum SyntaxExtension {
     ///
     IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
 
-    CustomDerive(Box<MultiItemModifier>),
+    /// An attribute-like procedural macro. TokenStream -> TokenStream.
+    /// The input is the annotated item.
+    /// Allows generating code to implement a Trait for a given struct
+    /// or enum item.
+    ProcMacroDerive(Box<MultiItemModifier>),
+
+    /// An attribute-like procedural macro that derives a builtin trait.
+    BuiltinDerive(BuiltinDeriveFn),
 }
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
@@ -526,6 +536,9 @@ pub trait Resolver {
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn resolve_builtin_macro(&mut self, tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
+                            -> Result<Rc<SyntaxExtension>, Determinacy>;
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -552,6 +565,13 @@ fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
     }
+    fn resolve_builtin_macro(&mut self, _tname: Name) -> Result<Rc<SyntaxExtension>, Determinacy> {
+        Err(Determinacy::Determined)
+    }
+    fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
+                            -> Result<Rc<SyntaxExtension>, Determinacy> {
+        Err(Determinacy::Determined)
+    }
 }
 
 #[derive(Clone)]
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
new file mode 100644 (file)
index 0000000..946448e
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright 2012-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.
+
+use ast::Name;
+use attr;
+use ast::{self, NestedMetaItem}; use ext::base::{ExtCtxt, SyntaxExtension};
+use codemap;
+use ext::build::AstBuilder;
+use feature_gate;
+use symbol::Symbol;
+use syntax_pos::Span;
+
+pub fn derive_attr_trait<'a>(cx: &mut ExtCtxt, attr: &'a ast::Attribute)
+                             -> Option<&'a NestedMetaItem> {
+    if attr.name() != "derive" {
+        return None;
+    }
+    if attr.value_str().is_some() {
+        cx.span_err(attr.span, "unexpected value in `derive`");
+        return None;
+    }
+
+    let traits = attr.meta_item_list().unwrap_or(&[]);
+
+    if traits.is_empty() {
+        cx.span_warn(attr.span, "empty trait list in `derive`");
+        return None;
+    }
+
+    return traits.get(0);
+}
+
+pub fn verify_derive_attrs(cx: &mut ExtCtxt, attrs: &[ast::Attribute]) {
+    for attr in attrs {
+        if attr.name() != "derive" {
+            continue;
+        }
+
+        if attr.value_str().is_some() {
+            cx.span_err(attr.span, "unexpected value in `derive`");
+        }
+
+        let traits = attr.meta_item_list().unwrap_or(&[]).to_owned();
+
+        if traits.is_empty() {
+            cx.span_warn(attr.span, "empty trait list in `derive`");
+            attr::mark_used(&attr);
+            continue;
+        }
+        for titem in traits {
+            if titem.word().is_none() {
+                cx.span_err(titem.span, "malformed `derive` entry");
+            }
+        }
+    }
+}
+
+#[derive(PartialEq, Debug, Clone, Copy)]
+pub enum DeriveType {
+    Legacy,
+    ProcMacro,
+    Builtin
+}
+
+impl DeriveType {
+    // Classify a derive trait name by resolving the macro.
+    pub fn classify(cx: &mut ExtCtxt, tname: Name) -> DeriveType {
+        let legacy_derive_name = Symbol::intern(&format!("derive_{}", tname));
+
+        if let Ok(_) = cx.resolver.resolve_builtin_macro(legacy_derive_name) {
+            return DeriveType::Legacy;
+        }
+
+        match cx.resolver.resolve_builtin_macro(tname) {
+            Ok(ext) => match *ext {
+                SyntaxExtension::BuiltinDerive(..) => DeriveType::Builtin,
+                _ => DeriveType::ProcMacro,
+            },
+            Err(_) => DeriveType::ProcMacro,
+        }
+    }
+}
+
+pub fn get_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>,
+                       derive_type: DeriveType) -> Option<ast::Attribute> {
+    for i in 0..attrs.len() {
+        if attrs[i].name() != "derive" {
+            continue;
+        }
+
+        if attrs[i].value_str().is_some() {
+            continue;
+        }
+
+        let mut traits = attrs[i].meta_item_list().unwrap_or(&[]).to_owned();
+
+        // First, weed out malformed #[derive]
+        traits.retain(|titem| titem.word().is_some());
+
+        let mut titem = None;
+
+        // See if we can find a matching trait.
+        for j in 0..traits.len() {
+            let tname = match traits[j].name() {
+                Some(tname) => tname,
+                _ => continue,
+            };
+
+            if DeriveType::classify(cx, tname) == derive_type {
+                titem = Some(traits.remove(j));
+                break;
+            }
+        }
+
+        // If we find a trait, remove the trait from the attribute.
+        if let Some(titem) = titem {
+            if traits.len() == 0 {
+                attrs.remove(i);
+            } else {
+                let derive = Symbol::intern("derive");
+                let mitem = cx.meta_list(titem.span, derive, traits);
+                attrs[i] = cx.attribute(titem.span, mitem);
+            }
+            let derive = Symbol::intern("derive");
+            let mitem = cx.meta_list(titem.span, derive, vec![titem]);
+            return Some(cx.attribute(mitem.span, mitem));
+        }
+    }
+    return None;
+}
+
+fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span {
+    Span {
+        expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
+            call_site: span,
+            callee: codemap::NameAndSpan {
+                format: codemap::MacroAttribute(Symbol::intern(attr_name)),
+                span: Some(span),
+                allow_internal_unstable: true,
+            },
+        }),
+        ..span
+    }
+}
+
+pub fn add_derived_markers(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) {
+    if attrs.is_empty() {
+        return;
+    }
+
+    let titems = attrs.iter().filter(|a| {
+        a.name() == "derive"
+    }).flat_map(|a| {
+        a.meta_item_list().unwrap_or(&[]).iter()
+    }).filter_map(|titem| {
+        titem.name()
+    }).collect::<Vec<_>>();
+
+    let span = attrs[0].span;
+
+    if !attrs.iter().any(|a| a.name() == "structural_match") &&
+       titems.iter().any(|t| *t == "PartialEq") && titems.iter().any(|t| *t == "Eq") {
+        let structural_match = Symbol::intern("structural_match");
+        let span = allow_unstable(cx, span, "derive(PartialEq, Eq)");
+        let meta = cx.meta_word(span, structural_match);
+        attrs.push(cx.attribute(span, meta));
+    }
+
+    if !attrs.iter().any(|a| a.name() == "rustc_copy_clone_marker") &&
+       titems.iter().any(|t| *t == "Copy") && titems.iter().any(|t| *t == "Clone") {
+        let structural_match = Symbol::intern("rustc_copy_clone_marker");
+        let span = allow_unstable(cx, span, "derive(Copy, Clone)");
+        let meta = cx.meta_word(span, structural_match);
+        attrs.push(cx.attribute(span, meta));
+    }
+}
+
+pub fn find_derive_attr(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>)
+                        -> Option<ast::Attribute> {
+    verify_derive_attrs(cx, attrs);
+    get_derive_attr(cx, attrs, DeriveType::Legacy).and_then(|a| {
+        let titem = derive_attr_trait(cx, &a);
+        titem.and_then(|titem| {
+            let tword = titem.word().unwrap();
+            let tname = tword.name();
+            if !cx.ecfg.enable_custom_derive() {
+                feature_gate::emit_feature_err(
+                    &cx.parse_sess,
+                    "custom_derive",
+                    titem.span,
+                    feature_gate::GateIssue::Language,
+                    feature_gate::EXPLAIN_CUSTOM_DERIVE
+                );
+                None
+            } else {
+                let name = Symbol::intern(&format!("derive_{}", tname));
+                if !cx.resolver.is_whitelisted_legacy_custom_derive(name) {
+                    cx.span_warn(titem.span,
+                                 feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
+                }
+                let mitem = cx.meta_word(titem.span, name);
+                Some(cx.attribute(mitem.span, mitem))
+            }
+        })
+    }).or_else(|| {
+        get_derive_attr(cx, attrs, DeriveType::ProcMacro)
+    }).or_else(|| {
+        add_derived_markers(cx, attrs);
+        get_derive_attr(cx, attrs, DeriveType::Builtin)
+    })
+}
index 226625ebc8e5e4fd0cf501ac92ca1145e7029506..8e7f8830eafbc586d2b2c04ad60d44487cc12dc9 100644 (file)
@@ -8,26 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{Block, Ident, Mac_, PatKind};
+use ast::{self, Block, Ident, Mac_, PatKind};
 use ast::{Name, MacStmtStyle, StmtKind, ItemKind};
-use ast;
-use ext::hygiene::Mark;
-use ext::placeholders::{placeholder, PlaceholderExpander};
 use attr::{self, HasAttrs};
 use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
-use syntax_pos::{self, Span, ExpnId};
 use config::{is_test_or_bench, StripUnconfigured};
 use ext::base::*;
+use ext::derive::{find_derive_attr, derive_attr_trait};
+use ext::hygiene::Mark;
+use ext::placeholders::{placeholder, PlaceholderExpander};
 use feature_gate::{self, Features};
 use fold;
 use fold::*;
-use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts};
 use parse::parser::Parser;
 use parse::token;
+use parse::{ParseSess, DirectoryOwnership, PResult, filemap_to_tts};
 use print::pprust;
 use ptr::P;
 use std_inject;
+use symbol::Symbol;
 use symbol::keywords;
+use syntax_pos::{self, Span, ExpnId};
 use tokenstream::{TokenTree, TokenStream};
 use util::small_vector::SmallVector;
 use visit::Visitor;
@@ -166,6 +167,10 @@ pub enum InvocationKind {
         attr: ast::Attribute,
         item: Annotatable,
     },
+    Derive {
+        attr: ast::Attribute,
+        item: Annotatable,
+    },
 }
 
 impl Invocation {
@@ -173,6 +178,7 @@ fn span(&self) -> Span {
         match self.kind {
             InvocationKind::Bang { span, .. } => span,
             InvocationKind::Attr { ref attr, .. } => attr.span,
+            InvocationKind::Derive { ref attr, .. } => attr.span,
         }
     }
 }
@@ -250,6 +256,13 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
                     let path = ast::Path::from_ident(attr.span, ident);
                     self.cx.resolver.resolve_macro(scope, &path, force)
                 }
+                InvocationKind::Derive { ref attr, .. } => {
+                    let titem = derive_attr_trait(self.cx, &attr).unwrap();
+                    let tname = titem.name().expect("Expected derive macro name");
+                    let ident = Ident::with_empty_ctxt(tname);
+                    let path = ast::Path::from_ident(attr.span, ident);
+                    self.cx.resolver.resolve_derive_macro(scope, &path, force)
+                }
             };
             let ext = match resolution {
                 Ok(ext) => Some(ext),
@@ -330,6 +343,7 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expan
         match invoc.kind {
             InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
             InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext),
+            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext),
         }
     }
 
@@ -370,7 +384,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
                 self.parse_expansion(tok_result, kind, name, attr.span)
             }
-            SyntaxExtension::CustomDerive(_) => {
+            SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
                 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
                 kind.dummy(attr.span)
             }
@@ -440,7 +454,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 return kind.dummy(span);
             }
 
-            SyntaxExtension::CustomDerive(..) => {
+            SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
                 self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname));
                 return kind.dummy(span);
             }
@@ -486,6 +500,71 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
         })
     }
 
+    /// Expand a derive invocation. Returns the result of expansion.
+    fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
+        let Invocation { expansion_kind: kind, .. } = invoc;
+        let (attr, item) = match invoc.kind {
+            InvocationKind::Derive { attr, item } => (attr, item),
+            _ => unreachable!(),
+        };
+
+        attr::mark_used(&attr);
+        let titem = derive_attr_trait(self.cx, &attr).unwrap();
+        let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap());
+        let name = Symbol::intern(&format!("derive({})", tname));
+        let mitem = &attr.value;
+
+        self.cx.bt_push(ExpnInfo {
+            call_site: attr.span,
+            callee: NameAndSpan {
+                format: MacroAttribute(attr.name()),
+                span: Some(attr.span),
+                allow_internal_unstable: false,
+            }
+        });
+
+        match *ext {
+            SyntaxExtension::ProcMacroDerive(ref ext) => {
+                let span = Span {
+                    expn_id: self.cx.codemap().record_expansion(ExpnInfo {
+                        call_site: mitem.span,
+                        callee: NameAndSpan {
+                            format: MacroAttribute(Symbol::intern(&format!("derive({})", tname))),
+                            span: None,
+                            allow_internal_unstable: false,
+                        },
+                    }),
+                    ..mitem.span
+                };
+                return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item));
+            }
+            SyntaxExtension::BuiltinDerive(func) => {
+                let span = Span {
+                    expn_id: self.cx.codemap().record_expansion(ExpnInfo {
+                        call_site: titem.span,
+                        callee: NameAndSpan {
+                            format: MacroAttribute(name),
+                            span: None,
+                            allow_internal_unstable: true,
+                        },
+                    }),
+                    ..titem.span
+                };
+                let mut items = Vec::new();
+                func(self.cx, span, &mitem, &item, &mut |a| {
+                    items.push(a)
+                });
+                items.insert(0, item);
+                return kind.expect_from_annotatables(items);
+            }
+            _ => {
+                let msg = &format!("macro `{}` may not be used for derive attributes", name);
+                self.cx.span_err(attr.span, &msg);
+                kind.dummy(attr.span)
+            }
+        }
+    }
+
     fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span)
                        -> Expansion {
         let mut parser = self.cx.new_parser_from_tts(&toks.trees().cloned().collect::<Vec<_>>());
@@ -595,16 +674,31 @@ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Ex
 
     fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind)
                     -> Expansion {
-        self.collect(kind, InvocationKind::Attr { attr: attr, item: item })
+        let invoc_kind = if attr.name() == "derive" {
+            if kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems {
+                self.cx.span_err(attr.span, "`derive` can be only be applied to items");
+                return kind.expect_from_annotatables(::std::iter::once(item));
+            }
+            InvocationKind::Derive { attr: attr, item: item }
+        } else {
+            InvocationKind::Attr { attr: attr, item: item }
+        };
+
+        self.collect(kind, invoc_kind)
     }
 
     // If `item` is an attr invocation, remove and return the macro attribute.
     fn classify_item<T: HasAttrs>(&mut self, mut item: T) -> (T, Option<ast::Attribute>) {
         let mut attr = None;
+
         item = item.map_attrs(|mut attrs| {
-            attr = self.cx.resolver.find_attr_invoc(&mut attrs);
+            attr = self.cx.resolver.find_attr_invoc(&mut attrs).or_else(|| {
+                find_derive_attr(self.cx, &mut attrs)
+            });
+
             attrs
         });
+
         (item, attr)
     }
 
index cc04727b698085042a502c255f1d9e9b02da9ab9..52ef2a05fcf195fa93fb1e72a875aff95ae47de2 100644 (file)
@@ -318,7 +318,7 @@ pub fn new() -> Features {
     (active, abi_unadjusted, "1.16.0", None),
 
     // Macros 1.1
-    (active, proc_macro, "1.16.0", Some(35900)),
+    (active, proc_macro, "1.16.0", Some(38356)),
 
     // Allows attributes on struct literal fields.
     (active, struct_field_attributes, "1.16.0", Some(38814)),
index 25be9e91a6ac92a70cedb6573d161c42e631df25..87a03adf6b77c018784aa535a3939f0ba1db4a2c 100644 (file)
@@ -128,6 +128,7 @@ pub mod print {
 pub mod ext {
     pub mod base;
     pub mod build;
+    pub mod derive;
     pub mod expand;
     pub mod placeholders;
     pub mod hygiene;
index fd7c56f136f48fe48b1e22ae02a2046dd23e933b..45d8354d317dc5949959ebbdef94b67cfb157f6b 100644 (file)
@@ -1691,6 +1691,7 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
         }
 
         // Assemble the span.
+        // FIXME(#39450) This is bogus if part of the path is macro generated.
         let span = mk_sp(lo, self.prev_span.hi);
 
         // Assemble the result.
index 2ce6fc03f7731a5d85f230b4c167d6cacc01fa6a..974e86a57412446d0b2457b48704e8e46a91f927 100644 (file)
@@ -32,18 +32,18 @@ fn visit_attribute(&mut self, attr: &Attribute) {
     fn visit_mac(&mut self, _mac: &Mac) {}
 }
 
-pub struct CustomDerive {
+pub struct ProcMacroDerive {
     inner: fn(TokenStream) -> TokenStream,
     attrs: Vec<ast::Name>,
 }
 
-impl CustomDerive {
-    pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> CustomDerive {
-        CustomDerive { inner: inner, attrs: attrs }
+impl ProcMacroDerive {
+    pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> ProcMacroDerive {
+        ProcMacroDerive { inner: inner, attrs: attrs }
     }
 }
 
-impl MultiItemModifier for CustomDerive {
+impl MultiItemModifier for ProcMacroDerive {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               span: Span,
@@ -54,7 +54,7 @@ fn expand(&self,
             Annotatable::Item(item) => item,
             Annotatable::ImplItem(_) |
             Annotatable::TraitItem(_) => {
-                ecx.span_err(span, "custom derive attributes may only be \
+                ecx.span_err(span, "proc-macro derives may only be \
                                     applied to struct/enum items");
                 return Vec::new()
             }
@@ -63,7 +63,7 @@ fn expand(&self,
             ItemKind::Struct(..) |
             ItemKind::Enum(..) => {},
             _ => {
-                ecx.span_err(span, "custom derive attributes may only be \
+                ecx.span_err(span, "proc-macro derives may only be \
                                     applied to struct/enum items");
                 return Vec::new()
             }
@@ -81,7 +81,7 @@ fn expand(&self,
         let stream = match res {
             Ok(stream) => stream,
             Err(e) => {
-                let msg = "custom derive attribute panicked";
+                let msg = "proc-macro derive panicked";
                 let mut err = ecx.struct_span_fatal(span, msg);
                 if let Some(s) = e.downcast_ref::<String>() {
                     err.help(&format!("message: {}", s));
@@ -100,7 +100,7 @@ fn expand(&self,
                 Ok(new_items) => new_items,
                 Err(_) => {
                     // FIXME: handle this better
-                    let msg = "custom derive produced unparseable tokens";
+                    let msg = "proc-macro derive produced unparseable tokens";
                     ecx.struct_span_fatal(span, msg).emit();
                     panic!(FatalError);
                 }
index e2634c60dcaad0cd8f16ab3e824c8a54e8b7ccbb..498f2348b80f109157f55992e684e7e91111b864 100644 (file)
@@ -13,6 +13,7 @@
 use deriving;
 use deriving::generic::*;
 use deriving::generic::ty::*;
+use deriving::warn_if_deprecated;
 
 use syntax::ast;
 use syntax::ast::{Expr, MetaItem, Mutability};
@@ -35,6 +36,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable)) {
+    warn_if_deprecated(cx, span, "Decodable");
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
index 092738ab8a03d372333f6272ae608e775cc9d617..9d155c22ad031d86f4f3508d4195c5c051b5a5d8 100644 (file)
@@ -91,6 +91,7 @@
 use deriving;
 use deriving::generic::*;
 use deriving::generic::ty::*;
+use deriving::warn_if_deprecated;
 
 use syntax::ast::{Expr, ExprKind, MetaItem, Mutability};
 use syntax::ext::base::{Annotatable, ExtCtxt};
@@ -112,6 +113,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable)) {
+    warn_if_deprecated(cx, span, "Encodable");
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
index 096f6dfd5d8d86cbae0dc18d3c8a640ec70d1c04..3bceb02f3d6c5af6a2e2cff0a5cb9c452ce275c5 100644 (file)
 
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use syntax::ast::{self, MetaItem};
-use syntax::attr::HasAttrs;
+use std::rc::Rc;
+use syntax::ast;
 use syntax::codemap;
-use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
 use syntax::ext::build::AstBuilder;
-use syntax::feature_gate;
 use syntax::ptr::P;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
@@ -89,234 +88,6 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span {
     }
 }
 
-pub fn expand_derive(cx: &mut ExtCtxt,
-                     span: Span,
-                     mitem: &MetaItem,
-                     annotatable: Annotatable)
-                     -> Vec<Annotatable> {
-    debug!("expand_derive: span = {:?}", span);
-    debug!("expand_derive: mitem = {:?}", mitem);
-    debug!("expand_derive: annotatable input  = {:?}", annotatable);
-    let mut item = match annotatable {
-        Annotatable::Item(item) => item,
-        other => {
-            cx.span_err(span, "`derive` can only be applied to items");
-            return vec![other]
-        }
-    };
-
-    let derive = Symbol::intern("derive");
-    let mut derive_attrs = Vec::new();
-    item = item.map_attrs(|attrs| {
-        let partition = attrs.into_iter().partition(|attr| attr.name() == derive);
-        derive_attrs = partition.0;
-        partition.1
-    });
-
-    // Expand `#[derive]`s after other attribute macro invocations.
-    if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() {
-        return vec![Annotatable::Item(item.map_attrs(|mut attrs| {
-            attrs.push(cx.attribute(span, mitem.clone()));
-            attrs.extend(derive_attrs);
-            attrs
-        }))];
-    }
-
-    let get_traits = |mitem: &MetaItem, cx: &ExtCtxt| {
-        if mitem.value_str().is_some() {
-            cx.span_err(mitem.span, "unexpected value in `derive`");
-        }
-
-        let traits = mitem.meta_item_list().unwrap_or(&[]).to_owned();
-        if traits.is_empty() {
-            cx.span_warn(mitem.span, "empty trait list in `derive`");
-        }
-        traits
-    };
-
-    let mut traits = get_traits(mitem, cx);
-    for derive_attr in derive_attrs {
-        traits.extend(get_traits(&derive_attr.value, cx));
-    }
-
-    // First, weed out malformed #[derive]
-    traits.retain(|titem| {
-        if titem.word().is_none() {
-            cx.span_err(titem.span, "malformed `derive` entry");
-            false
-        } else {
-            true
-        }
-    });
-
-    // Next, check for old-style #[derive(Foo)]
-    //
-    // These all get expanded to `#[derive_Foo]` and will get expanded first. If
-    // we actually add any attributes here then we return to get those expanded
-    // and then eventually we'll come back to finish off the other derive modes.
-    let mut new_attributes = Vec::new();
-    traits.retain(|titem| {
-        let tword = titem.word().unwrap();
-        let tname = tword.name();
-
-        if is_builtin_trait(tname) || {
-            let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname));
-            cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| {
-                if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false }
-            }).unwrap_or(false)
-        } {
-            return true;
-        }
-
-        if !cx.ecfg.enable_custom_derive() {
-            feature_gate::emit_feature_err(&cx.parse_sess,
-                                           "custom_derive",
-                                           titem.span,
-                                           feature_gate::GateIssue::Language,
-                                           feature_gate::EXPLAIN_CUSTOM_DERIVE);
-        } else {
-            let name = Symbol::intern(&format!("derive_{}", tname));
-            if !cx.resolver.is_whitelisted_legacy_custom_derive(name) {
-                cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
-            }
-            let mitem = cx.meta_word(titem.span, name);
-            new_attributes.push(cx.attribute(mitem.span, mitem));
-        }
-        false
-    });
-    if new_attributes.len() > 0 {
-        item = item.map(|mut i| {
-            i.attrs.extend(new_attributes);
-            if traits.len() > 0 {
-                let list = cx.meta_list(mitem.span, derive, traits);
-                i.attrs.push(cx.attribute(mitem.span, list));
-            }
-            i
-        });
-        return vec![Annotatable::Item(item)]
-    }
-
-    // Now check for macros-1.1 style custom #[derive].
-    //
-    // Expand each of them in order given, but *before* we expand any built-in
-    // derive modes. The logic here is to:
-    //
-    // 1. Collect the remaining `#[derive]` annotations into a list. If
-    //    there are any left, attach a `#[derive]` attribute to the item
-    //    that we're currently expanding with the remaining derive modes.
-    // 2. Manufacture a `#[derive(Foo)]` attribute to pass to the expander.
-    // 3. Expand the current item we're expanding, getting back a list of
-    //    items that replace it.
-    // 4. Extend the returned list with the current list of items we've
-    //    collected so far.
-    // 5. Return everything!
-    //
-    // If custom derive extensions end up threading through the `#[derive]`
-    // attribute, we'll get called again later on to continue expanding
-    // those modes.
-    let macros_11_derive = traits.iter()
-                                 .cloned()
-                                 .enumerate()
-                                 .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap()))
-                                 .next();
-    if let Some((i, titem)) = macros_11_derive {
-        let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap());
-        let path = ast::Path::from_ident(titem.span, tname);
-        let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
-
-        traits.remove(i);
-        if traits.len() > 0 {
-            item = item.map(|mut i| {
-                let list = cx.meta_list(mitem.span, derive, traits);
-                i.attrs.push(cx.attribute(mitem.span, list));
-                i
-            });
-        }
-        let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap());
-        let mitem = cx.meta_list(titem.span, derive, vec![titem]);
-        let item = Annotatable::Item(item);
-
-        let span = Span {
-            expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
-                call_site: mitem.span,
-                callee: codemap::NameAndSpan {
-                    format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))),
-                    span: None,
-                    allow_internal_unstable: false,
-                },
-            }),
-            ..mitem.span
-        };
-
-        if let SyntaxExtension::CustomDerive(ref ext) = *ext {
-            return ext.expand(cx, span, &mitem, item);
-        } else {
-            unreachable!()
-        }
-    }
-
-    // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor
-    // any macros-1.1 style `#[derive(Foo)]`. Expand all built-in traits here.
-
-    // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
-    // `#[structural_match]` attribute.
-    let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq"));
-    if traits.iter().any(|t| t.name() == Some(partial_eq)) &&
-       traits.iter().any(|t| t.name() == Some(eq)) {
-        let structural_match = Symbol::intern("structural_match");
-        let span = allow_unstable(cx, span, "derive(PartialEq, Eq)");
-        let meta = cx.meta_word(span, structural_match);
-        item = item.map(|mut i| {
-            i.attrs.push(cx.attribute(span, meta));
-            i
-        });
-    }
-
-    // RFC #1521. `Clone` can assume that `Copy` types' clone implementation is
-    // the same as the copy implementation.
-    //
-    // Add a marker attribute here picked up during #[derive(Clone)]
-    let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone"));
-    if traits.iter().any(|t| t.name() == Some(clone)) &&
-       traits.iter().any(|t| t.name() == Some(copy)) {
-        let marker = Symbol::intern("rustc_copy_clone_marker");
-        let span = allow_unstable(cx, span, "derive(Copy, Clone)");
-        let meta = cx.meta_word(span, marker);
-        item = item.map(|mut i| {
-            i.attrs.push(cx.attribute(span, meta));
-            i
-        });
-    }
-
-    let mut items = Vec::new();
-    for titem in traits.iter() {
-        let tname = titem.word().unwrap().name();
-        let name = Symbol::intern(&format!("derive({})", tname));
-        let mitem = cx.meta_word(titem.span, name);
-
-        let span = Span {
-            expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
-                call_site: titem.span,
-                callee: codemap::NameAndSpan {
-                    format: codemap::MacroAttribute(name),
-                    span: None,
-                    allow_internal_unstable: true,
-                },
-            }),
-            ..titem.span
-        };
-
-        let my_item = Annotatable::Item(item);
-        expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
-            items.push(a);
-        });
-        item = my_item.expect_item();
-    }
-
-    items.insert(0, Annotatable::Item(item));
-    return items
-}
-
 macro_rules! derive_traits {
     ($( $name:expr => $func:path, )+) => {
         pub fn is_builtin_trait(name: ast::Name) -> bool {
@@ -326,21 +97,13 @@ pub fn is_builtin_trait(name: ast::Name) -> bool {
             }
         }
 
-        fn expand_builtin(name: &str,
-                          ecx: &mut ExtCtxt,
-                          span: Span,
-                          mitem: &MetaItem,
-                          item: &Annotatable,
-                          push: &mut FnMut(Annotatable)) {
-            match name {
-                $(
-                    $name => {
-                        warn_if_deprecated(ecx, span, $name);
-                        $func(ecx, span, mitem, item, push);
-                    }
-                )*
-                _ => panic!("not a builtin derive mode: {}", name),
-            }
+        pub fn register_builtin_derives(resolver: &mut Resolver) {
+            $(
+                resolver.add_ext(
+                    ast::Ident::with_empty_ctxt(Symbol::intern($name)),
+                    Rc::new(SyntaxExtension::BuiltinDerive($func))
+                );
+            )*
         }
     }
 }
index ebec23d0901a0409ea705cf3db7cbe7fa1275204..7533171b08556df082f2fcabfd27dbcb11e3e3d0 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(staged_api)]
 
 extern crate fmt_macros;
-#[macro_use]
 extern crate log;
 #[macro_use]
 extern crate syntax;
 
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension};
+use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension};
 use syntax::symbol::Symbol;
 
 pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
                          user_exts: Vec<NamedSyntaxExtension>,
                          enable_quotes: bool) {
+    deriving::register_builtin_derives(resolver);
+
     let mut register = |name, ext| {
         resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };
@@ -112,8 +113,6 @@ macro_rules! register {
     register(Symbol::intern("format_args"),
              NormalTT(Box::new(format::expand_format_args), None, true));
 
-    register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive)));
-
     for (name, ext) in user_exts {
         register(name, ext);
     }
index c8af16e9242f05c8277578b04576d11c13d08b04..325f09a83ddab80860afd3524f7937ab23cd2e7c 100644 (file)
@@ -27,7 +27,7 @@
 
 use deriving;
 
-struct CustomDerive {
+struct ProcMacroDerive {
     trait_name: ast::Name,
     function_name: Ident,
     span: Span,
@@ -40,7 +40,7 @@ struct AttrProcMacro {
 }
 
 struct CollectProcMacros<'a> {
-    derives: Vec<CustomDerive>,
+    derives: Vec<ProcMacroDerive>,
     attr_macros: Vec<AttrProcMacro>,
     in_root: bool,
     handler: &'a errors::Handler,
@@ -176,7 +176,7 @@ fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribut
         };
 
         if self.in_root && item.vis == ast::Visibility::Public {
-            self.derives.push(CustomDerive {
+            self.derives.push(ProcMacroDerive {
                 span: item.span,
                 trait_name: trait_name,
                 function_name: item.ident,
@@ -319,7 +319,7 @@ fn visit_mac(&mut self, mac: &ast::Mac) {
 //          }
 //      }
 fn mk_registrar(cx: &mut ExtCtxt,
-                custom_derives: &[CustomDerive],
+                custom_derives: &[ProcMacroDerive],
                 custom_attrs: &[AttrProcMacro]) -> P<ast::Item> {
     let eid = cx.codemap().record_expansion(ExpnInfo {
         call_site: DUMMY_SP,
index a5359946c09c2626557ba7fbb023b39f9c7db5e2..42fad803bfa68ae345d5643ff0ae3b0e99fbdadb 100644 (file)
@@ -16,7 +16,7 @@
 #[derive(
     A
 )]
-//~^^ ERROR: custom derive produced unparseable tokens
+//~^^ ERROR: proc-macro derive produced unparseable tokens
 struct A;
 
 fn main() {}
index f9906b650fb878c2b7c4340025b2719c15d9bd6b..c483c048b418f11f437a37a8f13a03200cd472a6 100644 (file)
@@ -14,7 +14,7 @@
 extern crate derive_panic;
 
 #[derive(A)]
-//~^ ERROR: custom derive attribute panicked
+//~^ ERROR: proc-macro derive panicked
 //~| HELP: message: nope!
 struct Foo;
 
index f61b8b4073b6f51aa0275e66645290284014744d..e47a4aefb5e0b67447dde7a118477e45622574ba 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(rustc_attrs)]
 
 extern crate derive_a;
-//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]`
+//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
 
 #[rustc_error]
 fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/defaulted-unit-warning.rs b/src/test/compile-fail/defaulted-unit-warning.rs
new file mode 100644 (file)
index 0000000..5213a18
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![deny(resolve_trait_on_defaulted_unit)]
+
+trait Deserialize: Sized {
+    fn deserialize() -> Result<Self, String>;
+}
+
+impl Deserialize for () {
+    fn deserialize() -> Result<(), String> {
+        Ok(())
+    }
+}
+
+fn doit() -> Result<(), String> {
+    let _ = match Deserialize::deserialize() {
+        //~^ ERROR code relies on type
+        //~| WARNING previously accepted
+        Ok(x) => x,
+        Err(e) => return Err(e),
+    };
+    Ok(())
+}
+
+trait ImplementedForUnitButNotNever {}
+
+impl ImplementedForUnitButNotNever for () {}
+
+fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+
+fn smeg() {
+    let _x = return;
+    foo(_x);
+    //~^ ERROR code relies on type
+    //~| WARNING previously accepted
+}
+
+fn main() {
+    let _ = doit();
+}
+
index 596cc1e7d58163e8af3b843089e08092e1ccc43b..d388ece084417160ce98517533942f71e0387ca5 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-tidy-linelength
 
 #[derive(Eqr)]
-//~^ ERROR `#[derive]` for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644)
+//~^ ERROR cannot find derive macro `Eqr` in this scope
 struct Foo;
 
 pub fn main() {}
index be822a173ab5821053a21d7b05abb6eb24562f55..97a39a46c19a81774f5e06f1b45118b65c7253da 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable
+#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope
 enum Foo {}
 
 fn main() {}
index 4a6dbf014a1cace35ae973c1daa5cf77ca3bade8..f467ba3b1e19521a8e161573ea538c494ea5e34a 100644 (file)
@@ -16,5 +16,5 @@ fn main() {
     foo!(0); // Check that we report errors at macro definition, not expansion.
 
     let _: cfg!(foo) = (); //~ ERROR non-type macro in type position
-    derive!(); //~ ERROR `derive` can only be used in attributes
+    derive!(); //~ ERROR macro undefined: 'derive!'
 }
index 723e936212a5b76efa3a82765c1ba03df7b906c8..3f710af8ac9a883f0c31ac5161e2828b3998771f 100644 (file)
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
 
-#[derive(Default, //~ ERROR
-           Zero)] //~ ERROR
-enum CantDeriveThose {}
+#[derive(Zero)] //~ ERROR
+struct CantDeriveThis;
+
+#[derive(Default)] //~ ERROR
+enum OrDeriveThis {}
 
 fn main() {
     doesnt_exist!(); //~ ERROR
index d8e7411bded2cbfcaa1baa91a805c5ac0d460d6e..f74ff55e2c08e406399443b2c7a4ca49a3a3c7c1 100644 (file)
@@ -12,7 +12,7 @@
 
 #[no_link]
 extern crate empty_struct;
-//~^ WARN custom derive crates and `#[no_link]` crates have no effect without `#[macro_use]`
+//~^ WARN proc macro crates and `#[no_link]` crates have no effect without `#[macro_use]`
 
 fn main() {
     empty_struct::XEmpty1; //~ ERROR cannot find value `XEmpty1` in module `empty_struct`
diff --git a/src/test/pretty/attr-derive.rs b/src/test/pretty/attr-derive.rs
new file mode 100644 (file)
index 0000000..a1c581a
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2012 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:derive-foo.rs
+// ignore-stage1
+// pp-exact
+// Testing that both the inner item and next outer item are
+// preserved, and that the first outer item parsed in main is not
+// accidentally carried over to each inner function
+
+#[macro_use]
+extern crate derive_foo;
+
+#[derive(Foo)]
+struct X;
+
+#[derive(Foo)]
+#[Bar]
+struct Y;
+
+#[derive(Foo)]
+struct WithRef {
+    x: X,
+    #[Bar]
+    y: Y,
+}
+
+#[derive(Foo)]
+enum Enum {
+
+    #[Bar]
+    Asdf,
+    Qwerty,
+}
+
+fn main() { }
diff --git a/src/test/pretty/attr-variant-data.rs b/src/test/pretty/attr-variant-data.rs
deleted file mode 100644 (file)
index 1ffacaa..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2012 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.
-
-// pp-exact
-// Testing that both the inner item and next outer item are
-// preserved, and that the first outer item parsed in main is not
-// accidentally carried over to each inner function
-
-#![feature(custom_attribute)]
-#![feature(custom_derive)]
-
-#[derive(Serialize, Deserialize)]
-struct X;
-
-#[derive(Serialize, Deserialize)]
-struct WithRef<'a, T: 'a> {
-    #[serde(skip_deserializing)]
-    t: Option<&'a T>,
-    #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
-    x: X,
-}
-
-#[derive(Serialize, Deserialize)]
-enum EnumWith<T> {
-    Unit,
-    Newtype(
-            #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
-            X),
-    Tuple(T,
-          #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
-          X),
-    Struct {
-        t: T,
-        #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
-        x: X,
-    },
-}
-
-#[derive(Serialize, Deserialize)]
-struct Tuple<T>(T,
-                #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
-                X);
-
-fn main() { }
diff --git a/src/test/pretty/auxiliary/derive-foo.rs b/src/test/pretty/auxiliary/derive-foo.rs
new file mode 100644 (file)
index 0000000..bd81d3e
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo, attributes(Bar))]
+pub fn derive(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
index 023f2218b87ae7e7afaf853e5d953b53363da95e..5ac50e04b8d2fc81e3e1991a5f682f9d1d89232b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items)]
+#![feature(cfg_target_has_atomic, no_core, intrinsics, lang_items, i128_type)]
 #![crate_type="rlib"]
 #![no_core]
 
@@ -54,6 +54,14 @@ pub unsafe fn atomic_u64(x: *mut u64) {
 pub unsafe fn atomic_i64(x: *mut i64) {
     atomic_xadd(x, 1);
 }
+#[cfg(target_has_atomic = "128")]
+pub unsafe fn atomic_u128(x: *mut u128) {
+    atomic_xadd(x, 1);
+}
+#[cfg(target_has_atomic = "128")]
+pub unsafe fn atomic_i128(x: *mut i128) {
+    atomic_xadd(x, 1);
+}
 #[cfg(target_has_atomic = "ptr")]
 pub unsafe fn atomic_usize(x: *mut usize) {
     atomic_xadd(x, 1);
diff --git a/src/test/rustdoc/issue-38129.rs b/src/test/rustdoc/issue-38129.rs
new file mode 100644 (file)
index 0000000..00ccc74
--- /dev/null
@@ -0,0 +1,110 @@
+// 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.
+
+// compile-flags:--test
+
+// This file tests the source-partitioning behavior of rustdoc.
+// Each test contains some code that should be put into the generated
+// `fn main` and some attributes should be left outside (except the first
+// one, which has no attributes).
+// If the #![recursion_limit] attribute is incorrectly left inside,
+// then the tests will fail because the macro recurses 128 times.
+
+/// ```
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn simple() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+///     (()) => {};
+///     (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn non_feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn feature_attr() {}
+
+/// ```
+/// #![feature(core_intrinsics)]
+/// #![recursion_limit = "1024"]
+/// macro_rules! recurse {
+///     (()) => {};
+///     (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs() {}
+
+/// ```
+/// #![recursion_limit = "1024"]
+/// #![feature(core_intrinsics)]
+/// macro_rules! recurse {
+///     (()) => {};
+///     (() $($rest:tt)*) => { recurse!($($rest)*); }
+/// }
+/// recurse!(() () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ()
+///          () () () () () () () ());
+/// assert_eq!(1 + 1, 2);
+/// ```
+pub fn both_attrs_reverse() {}
+
index 213366a307d40decb9165d209add3f94c337a99e..9a5e2de14e3b0788754bee7982778fea7adb0253 100644 (file)
@@ -1,4 +1,4 @@
-error: custom derive attribute panicked
+error: proc-macro derive panicked
   --> $DIR/issue-36935.rs:17:15
    |
 17 | #[derive(Foo, Bar)]
diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs
new file mode 100644 (file)
index 0000000..1938d33
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+use Foo;
+
+use Foo1;
+
+fn main() {}
diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
new file mode 100644 (file)
index 0000000..325f55e
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0432]: unresolved import `Foo`
+  --> $DIR/issue-38054-do-not-show-unresolved-names.rs:11:5
+   |
+11 | use Foo;
+   |     ^^^ no `Foo` in the root
+
+error[E0432]: unresolved import `Foo1`
+  --> $DIR/issue-38054-do-not-show-unresolved-names.rs:13:5
+   |
+13 | use Foo1;
+   |     ^^^^ no `Foo1` in the root
+
+error: aborting due to 2 previous errors
+